Compare commits

..

No commits in common. "master" and "francisco/logger" have entirely different histories.

30 changed files with 473 additions and 1554 deletions

View File

@ -20,15 +20,10 @@ DB_MONGO_PASS=password
SMTP_HOST=smtp-mail.outlook.com SMTP_HOST=smtp-mail.outlook.com
SMTP_PORT=587 SMTP_PORT=587
SMTP_PROTOCOL=tls SMTP_PROTOCOL=tls
SMTP_USER=francisco.sandoval@outlook.cl
SMTP_PASS=aigdvnrbueitklry
SMTP_FROM='"Sistema Transporte" <francisco.sandoval@outlook.cl>' SMTP_FROM='"Sistema Transporte" <francisco.sandoval@outlook.cl>'
# PATH UPLOAD # PATH UPLOAD
GTFS_UPLOADS=/uploads/gtfs GTFS_UPLOADS=/uploads/gtfs
PHOTOS_UPLOADS=/uploads/photos PHOTOS_UPLOADS=/uploads/photos
# URL INFO PARADERO
URL_PARADERO='http://localhost:3001/rutaParadero/?id='
#COORDENADAS DE INICIO PARA EL MAPA
COORDINI_LAT=-36.8270
COORDINI_LNG=-73.0503

View File

@ -14,6 +14,8 @@ DB_REDIS_PORT=6379
SMTP_HOST=smtp-mail.outlook.com SMTP_HOST=smtp-mail.outlook.com
SMTP_PORT=587 SMTP_PORT=587
SMTP_PROTOCOL=tls SMTP_PROTOCOL=tls
SMTP_USER=francisco.sandoval@outlook.cl
SMTP_PASS=aigdvnrbueitklry
SMTP_FROM='"Sistema Transporte" <francisco.sandoval@outlook.cl>' SMTP_FROM='"Sistema Transporte" <francisco.sandoval@outlook.cl>'
# PATH UPLOAD # PATH UPLOAD

View File

@ -68,20 +68,6 @@ Content-Type: application/json
} }
###
# @name get_info_device2
POST {{server}}/dispositivos/getInfoDevice/
Authorization: Bearer {{token}}
Content-Type: application/json
{
"GetInfoDevice": {
"idDispositivo": "00000000160f3b42b8:27:eb:0f:3b:42",
"KeyAutorizacion":"token"
}
}
### ###

View File

@ -8,8 +8,8 @@ POST {{server}}/auth/
Content-Type: application/json Content-Type: application/json
{ {
"rut": "11111111-1", "rut": "22222222-2",
"password": "usuario1" "password": "usuario2"
} }
### ###

View File

@ -1,214 +1,80 @@
DO $$
DECLARE
inicio_vigencia DATE;
v_error TEXT := '';
BEGIN
-- Verificar agency_id único ALTER TABLE rol_linea drop CONSTRAINT IF EXISTS rol_linea_id_linea_fkey;
IF (SELECT COUNT(*) FROM (SELECT agency_id FROM z_agency GROUP BY agency_id HAVING COUNT(*) > 1) AS duplicated) > 0 THEN
update gtfs_archivo
set status = 'Error - Agency_id duplicados'
where trim(upper(status))='PROCESANDO' ;
v_error:= '1 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar route_id único -----
IF (SELECT COUNT(*) FROM (SELECT route_id FROM z_routes GROUP BY route_id HAVING COUNT(*) > 1) AS duplicated) > 0 THEN
update gtfs_archivo
set status = 'Error - Route_id duplicados'
where trim(upper(status))='PROCESANDO' ;
v_error:= '2 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar service_id único en calendar ALTER TABLE linea_paradero drop CONSTRAINT IF EXISTS linea_paradero_id_linea_fkey;
IF (SELECT COUNT(*) FROM (SELECT service_id FROM z_calendar GROUP BY service_id HAVING COUNT(*) > 1) AS duplicated) > 0 THEN
update gtfs_archivo
set status = 'Error - service_id duplicados en calendar'
where trim(upper(status))='PROCESANDO' ;
v_error:= '3 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar trip_id único -----
IF (SELECT COUNT(*) FROM (SELECT trip_id FROM z_trips GROUP BY trip_id HAVING COUNT(*) > 1) AS duplicated) > 0 THEN
update gtfs_archivo
set status = 'Error - Trip_id duplicados '
where trim(upper(status))='PROCESANDO' ;
v_error:= '4 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar stop_id único ALTER TABLE gtfs_stop_times drop CONSTRAINT IF EXISTS fk_gtfs_sto_reference_gtfs_tri;
IF (SELECT COUNT(*) FROM (SELECT stop_id FROM z_stops GROUP BY stop_id HAVING COUNT(*) > 1) AS duplicated) > 0 THEN
update gtfs_archivo
set status = 'Error - Stop_id duplicados'
where trim(upper(status))='PROCESANDO' ;
v_error:= '5 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar referencias cruzadas entre trips y routes -----
IF (SELECT COUNT(*) FROM z_trips WHERE route_id NOT IN (SELECT route_id FROM z_routes)) > 0 THEN
update gtfs_archivo
set status = 'Error - Trips_id con route_id que no existen'
where trim(upper(status))='PROCESANDO' ;
v_error:= '6 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar referencias cruzadas entre stop_times y trips ALTER TABLE gtfs_frequencie drop CONSTRAINT IF EXISTS fk_gtfs_fre_reference_gtfs_tri;
IF (SELECT COUNT(*) FROM z_stop_times WHERE trip_id NOT IN (SELECT trip_id FROM z_trips)) > 0 THEN
update gtfs_archivo
set status = 'Error - Stop_times con trips_id que no existen'
where trim(upper(status))='PROCESANDO' ;
v_error:= '7 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
-- Verificar referencias cruzadas entre stop_times y stops -----
IF (SELECT COUNT(*) FROM z_stop_times WHERE stop_id NOT IN (SELECT stop_id FROM z_stops)) > 0 THEN
update gtfs_archivo
set status = 'Error - stop_time con stop_id que no existen'
where trim(upper(status))='PROCESANDO' ;
v_error:= '8 La validacion de archivos detecto errores en los archivos GTFS';
END IF;
/*WITH inicio_calendar AS ( DELETE FROM gtfs_calendar;
SELECT MIN(start_date) AS inicio FROM z_calendar
), inicio_calendar_dates AS (
SELECT MIN(date) AS inicio FROM z_calendar_dates WHERE exception_type = 1
)
SELECT LEAST(
COALESCE((SELECT inicio FROM inicio_calendar), CURRENT_DATE),
COALESCE((SELECT inicio FROM inicio_calendar_dates), CURRENT_DATE)
) INTO inicio_vigencia;*/
SELECT MIN(start_date) INTO inicio_vigencia FROM z_calendar; -----
update gtfs_archivo
set valid_from= inicio_vigencia
where trim(upper(status))='PROCESANDO' ;
IF CURRENT_DATE < inicio_vigencia THEN insert into gtfs_calendar
update gtfs_archivo select service_id, monday::bool , tuesday::bool , wednesday::bool , thursday::bool ,friday::bool ,saturday::bool ,sunday::bool
set status = 'PENDIENTE' from z_calendar zc;
where trim(upper(status))='PROCESANDO' ;
v_error:= '9 EL ARCHIVO AUN NO ESTA VIGENTE POR FECHA';
END IF;
if v_error = '' THEN -----
/* ASEGURA QUE CADA TRIPS TENGA UN SOLO GUION EN SU DESCRIPCION */ update paradero
UPDATE z_trips set vigente = true,
SET trip_headsign = stop_name= (select stop_name from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
CASE stop_desc=(select stop_desc from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
WHEN (LENGTH(trip_headsign) - LENGTH(REPLACE(trip_headsign, '-', '')) = 2) THEN stop_lat =(select stop_lat from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
regexp_replace(trip_headsign, '^(.*)-(.*)-(.*)$', '\1-\2~\3') stop_lon =(select stop_lon from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
ELSE stop_code=(select stop_code from z_stops where stop_id=paradero.id_paradero::text limit 1)
trip_headsign where id_paradero::text in (select stop_id from z_stops );
end
WHERE trip_headsign LIKE '%-%-%';
-----
update gtfs_archivo insert into paradero
set vigente = False select
where vigente = true and id_red in stop_id, null as id_comuna, null as id_tipo_paradero, true,
(select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' ); stop_code , stop_name , stop_desc , stop_lat::float(8) , stop_lon::float(8) , zone_id ,
stop_url , location_type ,
parent_station ,null as stop_time_zone , wheelchair_boarding::numeric
from z_stops zs
where stop_id not in (select id_paradero::text from paradero);
-----
ALTER TABLE linea_paradero drop CONSTRAINT IF EXISTS linea_paradero_id_linea_fkey; delete from linea_paradero;
----- -----
ALTER TABLE gtfs_stop_times drop CONSTRAINT IF EXISTS fk_gtfs_sto_reference_gtfs_tri; update linea
set vigente = false
----- where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' )
and id_linea not in (
ALTER TABLE gtfs_frequencie drop CONSTRAINT IF EXISTS fk_gtfs_fre_reference_gtfs_tri;
-----
DELETE FROM gtfs_calendar;
-----
insert into gtfs_calendar
select service_id, monday::bool , tuesday::bool , wednesday::bool , thursday::bool ,friday::bool ,saturday::bool ,sunday::bool
from z_calendar zc;
-----
update paradero
set vigente = true,
stop_name= (select stop_name from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
stop_desc=(select stop_desc from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
stop_lat =(select stop_lat from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
stop_lon =(select stop_lon from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
stop_code=(select stop_code from z_stops where stop_id=paradero.id_paradero::text limit 1)
where id_paradero::text in (select stop_id from z_stops );
-----
insert into paradero
select
stop_id, null as id_comuna, null as id_tipo_paradero, true,
stop_code , stop_name , stop_desc , stop_lat::float(8) , stop_lon::float(8) , zone_id ,
stop_url , location_type ,
parent_station ,null as stop_time_zone , wheelchair_boarding::numeric
from z_stops zs
where stop_id not in (select id_paradero::text from paradero);
-----
delete from linea_paradero;
-----
CREATE TABLE IF NOT EXISTS z_verifica_route (
route_id text NULL,
route_short_name text NULL
);
delete from linea l
where id_linea in
(
select route_id||'-0' from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
union
select route_id||'-1' from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
union
select route_id from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
) ;
delete from z_verifica_route ;
insert into z_verifica_route
select route_id, route_short_name from z_routes ;
-----
update linea
set vigente = false
where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' )
and id_linea not in (
select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar)
from z_routes zr from z_routes zr
inner join z_trips zt on zr.route_id =zt.route_id inner join z_trips zt on zr.route_id =zt.route_id
); );
----- -----
update linea update linea
set vigente = true set vigente = true
where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' ) where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' )
and id_linea in ( and id_linea in (
select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar)
from z_routes zr from z_routes zr
inner join z_trips zt on zr.route_id =zt.route_id inner join z_trips zt on zr.route_id =zt.route_id
); );
----- -----
insert into linea insert into linea
select distinct select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id , null,--zr.agency_id ,
substring(zt.trip_headsign FROM '(\S+) -') as route_short_name , substring(zt.trip_headsign FROM '(\S+) -') as route_short_name ,
@ -223,11 +89,11 @@ if v_error = '' THEN
inner join z_trips zt inner join z_trips zt
on zr.route_id =zt.route_id on zr.route_id =zt.route_id
and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 1)||'-'||SPLIT_PART(route_long_name, '-', 2)),' ','') and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 1)||'-'||SPLIT_PART(route_long_name, '-', 2)),' ','')
where route_long_name not like '%'||route_short_name ||'%' where route_long_name not like '%'||route_short_name ||'%'
and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea ) and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
union union
select distinct select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id , null,--zr.agency_id ,
substring(zt.trip_headsign FROM '(\S+) -') as route_short_name , substring(zt.trip_headsign FROM '(\S+) -') as route_short_name ,
zr.route_desc , zr.route_desc ,
@ -241,10 +107,10 @@ if v_error = '' THEN
inner join z_trips zt inner join z_trips zt
on zr.route_id =zt.route_id on zr.route_id =zt.route_id
and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 3)||'-'||SPLIT_PART(route_long_name, '-', 4)),' ','') and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 3)||'-'||SPLIT_PART(route_long_name, '-', 4)),' ','')
where route_long_name not like '%'||route_short_name ||'%' where route_long_name not like '%'||route_short_name ||'%'
and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea ) and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
union union
select distinct select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id, trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id , null,--zr.agency_id ,
route_short_name , route_short_name ,
@ -263,62 +129,62 @@ if v_error = '' THEN
or or
route_long_name like '%'||route_short_name ||'%' route_long_name like '%'||route_short_name ||'%'
) )
where (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea ) where (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
order by 1; order by 1;
----- -----
truncate table gtfs_shape; truncate table gtfs_shape;
----- -----
insert into gtfs_shape insert into gtfs_shape
select shape_id,shape_pt_lat::float8,shape_pt_lon::float8, select shape_id::numeric,shape_pt_lat::float8,shape_pt_lon::float8,
shape_pt_sequence::numeric,shape_dist_traveled::float8 shape_pt_sequence::numeric,shape_dist_traveled::float8
from z_shapes zs; from z_shapes zs;
----- -----
truncate table gtfs_stop_times; truncate table gtfs_stop_times;
----- -----
truncate table gtfs_frequencie; truncate table gtfs_frequencie;
----- -----
truncate table gtfs_trips; truncate table gtfs_trips;
----- -----
insert into gtfs_trips insert into gtfs_trips
select select
trip_id, trip_id,
trim(route_id)||'-'||trim(direction_id::varchar) as route_id, trim(route_id)||'-'||trim(direction_id::varchar) as route_id,
shape_id ,null as regreso, trip_headsign,trip_short_name,direction_id::numeric,service_id::varchar,block_id shape_id::numeric ,null as regreso, trip_headsign,trip_short_name,direction_id::numeric,service_id::varchar,block_id
from z_trips zt; from z_trips zt;
----- -----
insert into gtfs_stop_times insert into gtfs_stop_times
select stop_id,trip_id,arrival_time,stop_sequence::numeric,stop_headsign,departure_time,drop_off_type::numeric,null as shape_dist_traveled , select stop_id,trip_id,arrival_time,stop_sequence::numeric,stop_headsign,departure_time,drop_off_type::numeric,null as shape_dist_traveled ,
timepoint::numeric , pickup_type::numeric timepoint::numeric , pickup_type::numeric
from z_stop_times zst ; from z_stop_times zst ;
----- -----
insert into linea_paradero (id_linea , id_paradero ) insert into linea_paradero (id_linea , id_paradero )
SELECT DISTINCT SELECT DISTINCT
l.id_linea , p.id_paradero l.id_linea , p.id_paradero
FROM linea l FROM linea l
JOIN gtfs_trips t ON l.id_linea =t.id_linea JOIN gtfs_trips t ON l.id_linea =t.id_linea
JOIN gtfs_stop_times st ON t.id_trip = st.id_trip JOIN gtfs_stop_times st ON t.id_trip = st.id_trip
JOIN paradero p ON st.id_paradero = p.id_paradero; JOIN paradero p ON st.id_paradero = p.id_paradero;
----- -----
UPDATE paradero UPDATE paradero
SET stop_name = REGEXP_REPLACE( SET stop_name = REGEXP_REPLACE(
REGEXP_REPLACE( REGEXP_REPLACE(
stop_name, stop_name,
'\yentre\y', '\yentre\y',
@ -328,66 +194,30 @@ if v_error = '' THEN
'\yesq\y', '\yesq\y',
'-esq', '-esq',
'gi' 'gi'
); );
----- -----
update paradero update paradero
set id_comuna = (select id_comuna from comuna_georeferencia as c where ST_Contains(c.geom, ST_SetSRID(ST_MakePoint(paradero.stop_lon, paradero.stop_lat), 4326)) limit 1) set id_comuna = (select id_comuna from comuna_georeferencia as c where ST_Contains(c.geom, ST_SetSRID(ST_MakePoint(paradero.stop_lon, paradero.stop_lat), 4326)) limit 1)
where id_comuna is not null; where id_comuna is not null;
----- -----
insert into dispositivo delete from rol_linea where id_linea not in (select id_linea from linea);
select 'QRCode-'||id_paradero , id_paradero , true, null, 3
from paradero as p where id_paradero
not in (select id_paradero from dispositivo as d where id_tipo_dispositivo=3 and d.id_paradero = p.id_paradero);
----- -----
ALTER TABLE linea_paradero ADD CONSTRAINT linea_paradero_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea); ALTER TABLE rol_linea ADD CONSTRAINT rol_linea_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea);
----- -----
ALTER TABLE gtfs_stop_times ADD CONSTRAINT fk_gtfs_sto_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT; ALTER TABLE linea_paradero ADD CONSTRAINT linea_paradero_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea);
----- -----
ALTER TABLE gtfs_frequencie ADD CONSTRAINT fk_gtfs_fre_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT; ALTER TABLE gtfs_stop_times ADD CONSTRAINT fk_gtfs_sto_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT;
----- -----
ALTER TABLE gtfs_frequencie ADD CONSTRAINT fk_gtfs_fre_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT;
update paradero p set id_comuna = ( -----
select id_comuna from comuna_georeferencia cg
where st_contains(cg.geom, st_setsrid(st_makepoint(p.stop_lon, p.stop_lat) ,4326))
limit 1)
where id_comuna is null;
CREATE TABLE IF NOT EXISTS gtfs_validaciones (
id_gtfs int4 not null,
route_id text NULL,
route_long_name text NULL,
observacion text NULL
);
insert into gtfs_validaciones
select (select id_gtfs from gtfs_archivo where trim(upper(status))='PROCESANDO' ),
route_id, route_long_name,
'Ruta sin Trips Asociados'
from z_routes
where route_id not in
(select route_id from z_trips ) ;
update gtfs_archivo
set vigente = true , status = case when
(
select count(*) from gtfs_validaciones where id_gtfs =(select id_gtfs from gtfs_archivo where trim(upper(status))='PROCESANDO' )
) =0 then 'GTFS CARGADO' else 'GTFS CARGADO CON REPAROS' END
where trim(upper(status))='PROCESANDO' ;
END IF;
END$$;

View File

@ -1,252 +0,0 @@
ALTER TABLE linea_paradero drop CONSTRAINT IF EXISTS linea_paradero_id_linea_fkey;
-----
ALTER TABLE gtfs_stop_times drop CONSTRAINT IF EXISTS fk_gtfs_sto_reference_gtfs_tri;
-----
ALTER TABLE gtfs_frequencie drop CONSTRAINT IF EXISTS fk_gtfs_fre_reference_gtfs_tri;
-----
DELETE FROM gtfs_calendar;
-----
insert into gtfs_calendar
select service_id, monday::bool , tuesday::bool , wednesday::bool , thursday::bool ,friday::bool ,saturday::bool ,sunday::bool
from z_calendar zc;
-----
update paradero
set vigente = true,
stop_name= (select stop_name from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
stop_desc=(select stop_desc from z_stops where stop_id=paradero.id_paradero::text limit 1 ),
stop_lat =(select stop_lat from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
stop_lon =(select stop_lon from z_stops where stop_id=paradero.id_paradero::text limit 1)::float(8),
stop_code=(select stop_code from z_stops where stop_id=paradero.id_paradero::text limit 1)
where id_paradero::text in (select stop_id from z_stops );
-----
insert into paradero
select
stop_id, null as id_comuna, null as id_tipo_paradero, true,
stop_code , stop_name , stop_desc , stop_lat::float(8) , stop_lon::float(8) , zone_id ,
stop_url , location_type ,
parent_station ,null as stop_time_zone , wheelchair_boarding::numeric
from z_stops zs
where stop_id not in (select id_paradero::text from paradero);
-----
delete from linea_paradero;
-----
CREATE TABLE IF NOT EXISTS z_verifica_route (
route_id text NULL,
route_short_name text NULL
);
delete from linea l
where id_linea in
(
select route_id||'-0' from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
union
select route_id||'-1' from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
union
select route_id from z_verifica_route as v
where coalesce((select count(*) from z_routes as r where r.route_id=v.route_id and r.route_short_name = v.route_short_name),0)=0
) ;
delete from z_verifica_route ;
insert into z_verifica_route
select route_id, route_short_name from z_routes ;
-----
update linea
set vigente = false
where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' )
and id_linea not in (
select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar)
from z_routes zr
inner join z_trips zt on zr.route_id =zt.route_id
);
-----
update linea
set vigente = true
where id_red in (select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' )
and id_linea in (
select trim(zr.route_id)||'-'||trim(zt.direction_id::varchar)
from z_routes zr
inner join z_trips zt on zr.route_id =zt.route_id
);
-----
insert into linea
select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id ,
substring(zt.trip_headsign FROM '(\S+) -') as route_short_name ,
zr.route_desc ,
zr.route_type::numeric ,
zr.route_url,
zr.route_color ,
zr.route_text_color ,
zt.trip_headsign as route_long_name , true ,
(select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' limit 1) as id_red
from z_routes zr
inner join z_trips zt
on zr.route_id =zt.route_id
and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 1)||'-'||SPLIT_PART(route_long_name, '-', 2)),' ','')
where route_long_name not like '%'||route_short_name ||'%'
and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
union
select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id ,
substring(zt.trip_headsign FROM '(\S+) -') as route_short_name ,
zr.route_desc ,
zr.route_type::numeric ,
zr.route_url,
zr.route_color ,
zr.route_text_color ,
zt.trip_headsign as route_long_name , true ,
(select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' limit 1) as id_red
from z_routes zr
inner join z_trips zt
on zr.route_id =zt.route_id
and replace (zt.trip_headsign,' ','') =replace ((SPLIT_PART(route_long_name, '-', 3)||'-'||SPLIT_PART(route_long_name, '-', 4)),' ','')
where route_long_name not like '%'||route_short_name ||'%'
and (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
union
select distinct
trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) as route_id,
null,--zr.agency_id ,
route_short_name ,
zr.route_desc ,
zr.route_type::numeric ,
zr.route_url,
zr.route_color ,
zr.route_text_color ,
zt.trip_headsign as route_long_name , true ,
(select id_red from gtfs_archivo where trim(upper(status))='PROCESANDO' limit 1) as id_red
from z_routes zr
inner join z_trips zt
on zr.route_id =zt.route_id
and
( position('-' in zt.trip_headsign) = 0
or
route_long_name like '%'||route_short_name ||'%'
)
where (trim(zr.route_id)||'-'||trim(zt.direction_id::varchar) ) not in (select id_linea from linea )
order by 1;
-----
truncate table gtfs_shape;
-----
insert into gtfs_shape
select shape_id::numeric,shape_pt_lat::float8,shape_pt_lon::float8,
shape_pt_sequence::numeric,shape_dist_traveled::float8
from z_shapes zs;
-----
truncate table gtfs_stop_times;
-----
truncate table gtfs_frequencie;
-----
truncate table gtfs_trips;
-----
insert into gtfs_trips
select
trip_id,
trim(route_id)||'-'||trim(direction_id::varchar) as route_id,
shape_id::numeric ,null as regreso, trip_headsign,trip_short_name,direction_id::numeric,service_id::varchar,block_id
from z_trips zt;
-----
insert into gtfs_stop_times
select stop_id,trip_id,arrival_time,stop_sequence::numeric,stop_headsign,departure_time,drop_off_type::numeric,null as shape_dist_traveled ,
timepoint::numeric , pickup_type::numeric
from z_stop_times zst ;
-----
insert into linea_paradero (id_linea , id_paradero )
SELECT DISTINCT
l.id_linea , p.id_paradero
FROM linea l
JOIN gtfs_trips t ON l.id_linea =t.id_linea
JOIN gtfs_stop_times st ON t.id_trip = st.id_trip
JOIN paradero p ON st.id_paradero = p.id_paradero;
-----
UPDATE paradero
SET stop_name = REGEXP_REPLACE(
REGEXP_REPLACE(
stop_name,
'\yentre\y',
'-entre',
'gi'
),
'\yesq\y',
'-esq',
'gi'
);
-----
update paradero
set id_comuna = (select id_comuna from comuna_georeferencia as c where ST_Contains(c.geom, ST_SetSRID(ST_MakePoint(paradero.stop_lon, paradero.stop_lat), 4326)) limit 1)
where id_comuna is not null;
-----
insert into dispositivo
select 'QRCode-'||id_paradero , id_paradero , true, null, 3
from paradero as p where id_paradero
not in (select id_paradero from dispositivo as d where id_tipo_dispositivo=3 and d.id_paradero = p.id_paradero);
-----
ALTER TABLE linea_paradero ADD CONSTRAINT linea_paradero_id_linea_fkey FOREIGN KEY (id_linea) REFERENCES linea(id_linea);
-----
ALTER TABLE gtfs_stop_times ADD CONSTRAINT fk_gtfs_sto_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT;
-----
ALTER TABLE gtfs_frequencie ADD CONSTRAINT fk_gtfs_fre_reference_gtfs_tri FOREIGN KEY (id_trip) REFERENCES gtfs_trips(id_trip) ON DELETE RESTRICT ON UPDATE RESTRICT;
-----
update paradero p set id_comuna = (
select id_comuna from comuna_georeferencia cg
where st_contains(cg.geom, st_setsrid(st_makepoint(p.stop_lon, p.stop_lat) ,4326))
limit 1)
where id_comuna is null;

View File

@ -13,7 +13,7 @@ class Command(BaseCommand):
help = 'Procesa los archivos gtfs en formato comprimido (zip)' help = 'Procesa los archivos gtfs en formato comprimido (zip)'
def handle(self, *args, **options): def handle(self, *args, **options):
# Lógica de tu comando aquí
folder = config('GTFS_UPLOADS','/tmp') folder = config('GTFS_UPLOADS','/tmp')
redes = RedTransporte.objects.filter(vigente=True) redes = RedTransporte.objects.filter(vigente=True)
@ -33,14 +33,14 @@ class Command(BaseCommand):
print(f'procesa: {filepath}') print(f'procesa: {filepath}')
procesa_zip(filepath) procesa_zip(filepath)
#registro_anterior = GtfsArchivo.objects.filter(vigente=True, id_red = red.id_red).first() registro_anterior = GtfsArchivo.objects.filter(vigente=True, id_red = red.id_red).first()
#if registro_anterior: if registro_anterior:
# registro_anterior.vigente = False registro_anterior.vigente = False
# registro_anterior.save() registro_anterior.save()
#gtfs_archivo.status = 'GTFS CARGADO' gtfs_archivo.status = 'GTFS CARGADO'
#gtfs_archivo.vigente = True gtfs_archivo.vigente = True
#gtfs_archivo.save() gtfs_archivo.save()
self.stdout.write(self.style.SUCCESS('¡Comando ejecutado con éxito!')) self.stdout.write(self.style.SUCCESS('¡Comando ejecutado con éxito!'))
@ -129,10 +129,7 @@ def procesa_tablas_z(cursor):
current_folder = os.path.dirname(os.path.abspath(__file__)) current_folder = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(current_folder, 'actualiza_GTFS.sql'),'r') as file: with open(os.path.join(current_folder, 'actualiza_GTFS.sql'),'r') as file:
sqlFile = file.read() content = ''.join(file.readlines())
cursor.execute(sqlFile)
#cursor.commit()
""" content = ''.join(file.readlines())
arr_sql = content.split('-----') arr_sql = content.split('-----')
for sql in arr_sql: for sql in arr_sql:
@ -140,4 +137,4 @@ def procesa_tablas_z(cursor):
if sql > ' ': if sql > ' ':
print(f'SQL> {sql}', flush=True) print(f'SQL> {sql}', flush=True)
cursor.execute(sql) cursor.execute(sql)
print('', flush=True) """ print('', flush=True)

View File

@ -16,7 +16,7 @@ class ApiMiddleware:
return response return response
match = resolve(request.path) match = resolve(request.path)
logging.info(match) logging.error(match)
# se omite esta regla al mostrar imagen de paradero # se omite esta regla al mostrar imagen de paradero
if match.url_name == 'paradero_imagen-detail' and request.method == 'GET': if match.url_name == 'paradero_imagen-detail' and request.method == 'GET':

View File

@ -8,6 +8,7 @@
from django.db import models from django.db import models
from .validaciones import rut_valido from .validaciones import rut_valido
class Aplicacion(models.Model): class Aplicacion(models.Model):
id_aplicacion = models.IntegerField(primary_key=True) id_aplicacion = models.IntegerField(primary_key=True)
nombre_app = models.CharField(max_length=100, blank=False, null=False) nombre_app = models.CharField(max_length=100, blank=False, null=False)
@ -18,6 +19,7 @@ class Aplicacion(models.Model):
managed = True managed = True
db_table = 'aplicacion' db_table = 'aplicacion'
class Comuna(models.Model): class Comuna(models.Model):
id_comuna = models.IntegerField(primary_key=True) id_comuna = models.IntegerField(primary_key=True)
id_region = models.ForeignKey('Region', models.DO_NOTHING, db_column='id_region', blank=True, null=True) id_region = models.ForeignKey('Region', models.DO_NOTHING, db_column='id_region', blank=True, null=True)
@ -27,6 +29,7 @@ class Comuna(models.Model):
managed = False managed = False
db_table = 'comuna' db_table = 'comuna'
class Conductor(models.Model): class Conductor(models.Model):
patente = models.OneToOneField('Vehiculo', models.DO_NOTHING, db_column='patente', primary_key=True) patente = models.OneToOneField('Vehiculo', models.DO_NOTHING, db_column='patente', primary_key=True)
rut = models.ForeignKey('Persona', models.DO_NOTHING, db_column='rut', blank=True, null=True) rut = models.ForeignKey('Persona', models.DO_NOTHING, db_column='rut', blank=True, null=True)
@ -36,9 +39,10 @@ class Conductor(models.Model):
managed = False managed = False
db_table = 'conductor' db_table = 'conductor'
class Dispositivo(models.Model): class Dispositivo(models.Model):
id_dispositivo = models.CharField(primary_key=True, max_length=100) id_dispositivo = models.CharField(primary_key=True, max_length=100)
id_paradero = models.ForeignKey('Paradero', models.DO_NOTHING, db_column='id_paradero', blank=False, null=False) id_paradero = models.ForeignKey('Paradero', models.DO_NOTHING, db_column='id_paradero', blank=True, null=True)
vigente = models.BooleanField(blank=True, null=True) vigente = models.BooleanField(blank=True, null=True)
ultima_conexion = models.DateField(blank=True, null=True) ultima_conexion = models.DateField(blank=True, null=True)
id_tipo_dispositivo = models.ForeignKey('TipoDispositivo', models.DO_NOTHING, db_column='id_tipo_dispositivo') id_tipo_dispositivo = models.ForeignKey('TipoDispositivo', models.DO_NOTHING, db_column='id_tipo_dispositivo')
@ -47,6 +51,18 @@ class Dispositivo(models.Model):
managed = False managed = False
db_table = 'dispositivo' db_table = 'dispositivo'
class Funcionario(models.Model):
rut = models.OneToOneField('Persona', models.DO_NOTHING, db_column='rut', primary_key=True)
id_operador = models.ForeignKey('Operador', models.DO_NOTHING, db_column='id_operador', blank=True, null=True)
desde = models.DateField(blank=True, null=True)
hasta = models.DateField(blank=True, null=True)
class Meta:
managed = False
db_table = 'funcionario'
class GtfsFrequencie(models.Model): class GtfsFrequencie(models.Model):
id_trip = models.ForeignKey('GtfsTrips', models.DO_NOTHING, db_column='id_trip', blank=True, null=True) id_trip = models.ForeignKey('GtfsTrips', models.DO_NOTHING, db_column='id_trip', blank=True, null=True)
start_time = models.TimeField(blank=True, null=True) start_time = models.TimeField(blank=True, null=True)
@ -58,6 +74,7 @@ class GtfsFrequencie(models.Model):
managed = False managed = False
db_table = 'gtfs_frequencie' db_table = 'gtfs_frequencie'
class GtfsPosiciones(models.Model): class GtfsPosiciones(models.Model):
id = models.UUIDField(primary_key=True) id = models.UUIDField(primary_key=True)
trip_id = models.UUIDField() trip_id = models.UUIDField()
@ -92,7 +109,7 @@ class GtfsRouteType(models.Model):
class GtfsShape(models.Model): class GtfsShape(models.Model):
id_shape = models.CharField(max_length=150) id_shape = models.DecimalField(max_digits=18, decimal_places=0)
shape_pt_lat = models.FloatField(blank=True, null=True) shape_pt_lat = models.FloatField(blank=True, null=True)
shape_pt_lon = models.FloatField(blank=True, null=True) shape_pt_lon = models.FloatField(blank=True, null=True)
shape_pt_sequence = models.IntegerField(blank=True, null=True) shape_pt_sequence = models.IntegerField(blank=True, null=True)
@ -126,7 +143,7 @@ class GtfsStopTimes(models.Model):
class GtfsTrips(models.Model): class GtfsTrips(models.Model):
id_trip = models.CharField(primary_key=True, max_length=150) id_trip = models.CharField(primary_key=True, max_length=150)
id_linea = models.CharField(max_length=150, blank=True, null=True) id_linea = models.CharField(max_length=150, blank=True, null=True)
id_shape = models.CharField(max_length=150,blank=True, null=True) id_shape = models.IntegerField(blank=True, null=True)
id_trip_regreso = models.ForeignKey('self', models.DO_NOTHING, db_column='id_trip_regreso', blank=True, null=True) id_trip_regreso = models.ForeignKey('self', models.DO_NOTHING, db_column='id_trip_regreso', blank=True, null=True)
trip_headsign = models.CharField(max_length=100, blank=True, null=True) trip_headsign = models.CharField(max_length=100, blank=True, null=True)
trip_short_name = models.CharField(max_length=100, blank=True, null=True) trip_short_name = models.CharField(max_length=100, blank=True, null=True)
@ -171,6 +188,7 @@ class Linea(models.Model):
managed = False managed = False
db_table = 'linea' db_table = 'linea'
class LineaParadero(models.Model): class LineaParadero(models.Model):
id_linea_paradero = models.AutoField(primary_key=True) id_linea_paradero = models.AutoField(primary_key=True)
id_linea = models.ForeignKey(Linea, models.DO_NOTHING, db_column='id_linea') id_linea = models.ForeignKey(Linea, models.DO_NOTHING, db_column='id_linea')
@ -180,13 +198,6 @@ class LineaParadero(models.Model):
managed = False managed = False
db_table = 'linea_paradero' db_table = 'linea_paradero'
class Rol(models.Model):
id_rol = models.IntegerField(primary_key=True)
nombre_rol = models.CharField(max_length=100)
class Meta:
managed = False
db_table = 'rol'
class Operador(models.Model): class Operador(models.Model):
id_operador = models.CharField(primary_key=True, max_length=150) id_operador = models.CharField(primary_key=True, max_length=150)
@ -198,12 +209,12 @@ class Operador(models.Model):
agency_lang = models.CharField(max_length=50, blank=True, null=True) agency_lang = models.CharField(max_length=50, blank=True, null=True)
agency_phone = models.CharField(max_length=50, blank=True, null=True) agency_phone = models.CharField(max_length=50, blank=True, null=True)
agency_fare_url = models.CharField(max_length=50, blank=True, null=True) agency_fare_url = models.CharField(max_length=50, blank=True, null=True)
id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=True)
class Meta: class Meta:
managed = False managed = False
db_table = 'operador' db_table = 'operador'
class Paradero(models.Model): class Paradero(models.Model):
id_paradero = models.CharField(primary_key=True, max_length=50) id_paradero = models.CharField(primary_key=True, max_length=50)
id_comuna = models.ForeignKey(Comuna, models.DO_NOTHING, db_column='id_comuna', blank=True, null=True) id_comuna = models.ForeignKey(Comuna, models.DO_NOTHING, db_column='id_comuna', blank=True, null=True)
@ -225,6 +236,7 @@ class Paradero(models.Model):
managed = False managed = False
db_table = 'paradero' db_table = 'paradero'
class ParaderoImagen(models.Model): class ParaderoImagen(models.Model):
id_paradero_imagen = models.AutoField(primary_key=True) id_paradero_imagen = models.AutoField(primary_key=True)
id_paradero = models.ForeignKey(Paradero, models.DO_NOTHING, db_column='id_paradero') id_paradero = models.ForeignKey(Paradero, models.DO_NOTHING, db_column='id_paradero')
@ -235,6 +247,7 @@ class ParaderoImagen(models.Model):
managed = False managed = False
db_table = 'paradero_imagen' db_table = 'paradero_imagen'
class Persona(models.Model): class Persona(models.Model):
rut = models.DecimalField(primary_key=True, max_digits=12, decimal_places=0) rut = models.DecimalField(primary_key=True, max_digits=12, decimal_places=0)
id_tipo_tratamiento = models.ForeignKey('TipoTratamientoPersona', models.DO_NOTHING, db_column='id_tipo_tratamiento', blank=True, null=True) id_tipo_tratamiento = models.ForeignKey('TipoTratamientoPersona', models.DO_NOTHING, db_column='id_tipo_tratamiento', blank=True, null=True)
@ -261,6 +274,7 @@ class Persona(models.Model):
super().save(*args, **kwargs) super().save(*args, **kwargs)
class Region(models.Model): class Region(models.Model):
id_region = models.IntegerField(primary_key=True) id_region = models.IntegerField(primary_key=True)
nombre_region = models.CharField(max_length=100) nombre_region = models.CharField(max_length=100)
@ -269,10 +283,20 @@ class Region(models.Model):
managed = False managed = False
db_table = 'region' db_table = 'region'
class Rol(models.Model):
id_rol = models.IntegerField(primary_key=True)
nombre_rol = models.CharField(max_length=100)
class Meta:
managed = False
db_table = 'rol'
class RolAplicacion(models.Model): class RolAplicacion(models.Model):
id_rol_app = models.AutoField(primary_key=True) id_rol_app = models.AutoField(primary_key=True)
id_aplicacion = models.ForeignKey(Aplicacion, models.DO_NOTHING, db_column='id_aplicacion', blank=False, null=False) id_aplicacion = models.ForeignKey(Aplicacion, models.DO_NOTHING, db_column='id_aplicacion', blank=False, null=False)
id_rol = models.ForeignKey(Rol, on_delete=models.CASCADE, db_column='id_rol', blank=False, null=False) id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=False)
solo_visualizar = models.BooleanField(blank=True, null=True) solo_visualizar = models.BooleanField(blank=True, null=True)
class Meta: class Meta:
@ -283,7 +307,7 @@ class RolAplicacion(models.Model):
class RolOperador(models.Model): class RolOperador(models.Model):
id_rol_operador = models.AutoField(primary_key=True) id_rol_operador = models.AutoField(primary_key=True)
id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol') id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol')
id_operador = models.ForeignKey(Operador, on_delete=models.CASCADE, db_column='id_operador') id_operador = models.ForeignKey(Operador, models.DO_NOTHING, db_column='id_operador')
class Meta: class Meta:
managed = True managed = True
@ -310,6 +334,7 @@ class TipoDispositivo(models.Model):
managed = False managed = False
db_table = 'tipo_dispositivo' db_table = 'tipo_dispositivo'
class TipoParadero(models.Model): class TipoParadero(models.Model):
id_tipo_paradero = models.IntegerField(primary_key=True) id_tipo_paradero = models.IntegerField(primary_key=True)
descripcion = models.CharField(max_length=100, blank=True, null=True) descripcion = models.CharField(max_length=100, blank=True, null=True)
@ -318,6 +343,7 @@ class TipoParadero(models.Model):
managed = False managed = False
db_table = 'tipo_paradero' db_table = 'tipo_paradero'
class TipoTransporte(models.Model): class TipoTransporte(models.Model):
id_tipo_transporte = models.IntegerField(primary_key=True) id_tipo_transporte = models.IntegerField(primary_key=True)
descripcion = models.CharField(max_length=50, blank=True, null=True) descripcion = models.CharField(max_length=50, blank=True, null=True)
@ -326,14 +352,6 @@ class TipoTransporte(models.Model):
managed = False managed = False
db_table = 'tipo_transporte' db_table = 'tipo_transporte'
class TipoCargo(models.Model):
id_cargo = models.IntegerField(primary_key=True)
descripcion = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'tipo_cargo'
db_table_comment = 'Registro de los cargos que se pueden asociar a un contrato'
class TipoTratamientoPersona(models.Model): class TipoTratamientoPersona(models.Model):
id_tipo_tratamiento = models.IntegerField(primary_key=True) id_tipo_tratamiento = models.IntegerField(primary_key=True)
@ -344,6 +362,7 @@ class TipoTratamientoPersona(models.Model):
db_table = 'tipo_tratamiento_persona' db_table = 'tipo_tratamiento_persona'
db_table_comment = 'Establece el tratamiento de como dirigirse hacia una persona:\r\nEjemplo\r\nSeñor\r\nSeñora\r\nSrta' db_table_comment = 'Establece el tratamiento de como dirigirse hacia una persona:\r\nEjemplo\r\nSeñor\r\nSeñora\r\nSrta'
class TipoVehiculo(models.Model): class TipoVehiculo(models.Model):
id_tipo_vehiculo = models.IntegerField(primary_key=True) id_tipo_vehiculo = models.IntegerField(primary_key=True)
descripcion = models.CharField(max_length=100, blank=True, null=True) descripcion = models.CharField(max_length=100, blank=True, null=True)
@ -352,6 +371,7 @@ class TipoVehiculo(models.Model):
managed = False managed = False
db_table = 'tipo_vehiculo' db_table = 'tipo_vehiculo'
class Usuario(models.Model): class Usuario(models.Model):
login = models.CharField(primary_key=True, max_length=60) login = models.CharField(primary_key=True, max_length=60)
rut = models.ForeignKey(Persona, models.DO_NOTHING, db_column='rut', blank=True, null=True) rut = models.ForeignKey(Persona, models.DO_NOTHING, db_column='rut', blank=True, null=True)
@ -364,6 +384,7 @@ class Usuario(models.Model):
managed = False managed = False
db_table = 'usuario' db_table = 'usuario'
class Vehiculo(models.Model): class Vehiculo(models.Model):
ppu = models.CharField(primary_key=True, max_length=10) ppu = models.CharField(primary_key=True, max_length=10)
id_tipo_vehiculo = models.ForeignKey(TipoVehiculo, models.DO_NOTHING, db_column='id_tipo_vehiculo', blank=True, null=True) id_tipo_vehiculo = models.ForeignKey(TipoVehiculo, models.DO_NOTHING, db_column='id_tipo_vehiculo', blank=True, null=True)
@ -373,6 +394,7 @@ class Vehiculo(models.Model):
managed = False managed = False
db_table = 'vehiculo' db_table = 'vehiculo'
class VehiculoLinea(models.Model): class VehiculoLinea(models.Model):
patente = models.OneToOneField(Vehiculo, models.DO_NOTHING, db_column='patente', primary_key=True) # The composite primary key (patente, id_linea) found, that is not supported. The first column is selected. patente = models.OneToOneField(Vehiculo, models.DO_NOTHING, db_column='patente', primary_key=True) # The composite primary key (patente, id_linea) found, that is not supported. The first column is selected.
id_linea = models.ForeignKey(Linea, models.DO_NOTHING, db_column='id_linea') id_linea = models.ForeignKey(Linea, models.DO_NOTHING, db_column='id_linea')
@ -402,8 +424,7 @@ class GtfsArchivo(models.Model):
archivo = models.CharField(max_length=200, blank=True, null=True) archivo = models.CharField(max_length=200, blank=True, null=True)
ruta_archivo = models.CharField(max_length=200, blank=True, null=True) ruta_archivo = models.CharField(max_length=200, blank=True, null=True)
valid_from = models.DateField(blank=True, null=True) valid_from = models.DateField(blank=True, null=True)
#created = models.DateTimeField(blank=True, null=True) created = models.DateTimeField(blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
usuario = models.CharField(max_length=100, blank=True, null=True) usuario = models.CharField(max_length=100, blank=True, null=True)
vigente = models.BooleanField(blank=True, null=True) vigente = models.BooleanField(blank=True, null=True)
status = models.CharField(max_length=100, blank=True, null=True) status = models.CharField(max_length=100, blank=True, null=True)
@ -412,30 +433,3 @@ class GtfsArchivo(models.Model):
managed = False managed = False
db_table = 'gtfs_archivo' db_table = 'gtfs_archivo'
db_table_comment = 'Registro de los archivos GTFS que se cargan en el sistema' db_table_comment = 'Registro de los archivos GTFS que se cargan en el sistema'
class VistaFuncionario(models.Model):
rut = models.ForeignKey('Persona', models.DO_NOTHING, db_column='rut', blank=True, null=True)
id_operador = models.ForeignKey('Operador', models.DO_NOTHING, db_column='id_operador', blank=True, null=True)
#patente = models.OneToOneField('Vehiculo', models.DO_NOTHING, db_column='patente', primary_key=True)
class Meta:
managed = False
db_table = 'vw_funcionario'
class Contrato(models.Model):
rut = models.OneToOneField('Persona', models.DO_NOTHING, db_column='rut', primary_key=True)
id_operador = models.ForeignKey('Operador', models.DO_NOTHING, db_column='id_operador', blank=True, null=True)
desde = models.DateField(blank=True, null=True)
hasta = models.DateField(blank=True, null=True)
id_cargo = models.ForeignKey('TipoCargo', models.DO_NOTHING, db_column='id_cargo')
class Meta:
managed = False
db_table = 'contrato'
class PersonaDatosLaborales(models.Model):
rut = models.OneToOneField('Persona', models.DO_NOTHING, db_column='rut', primary_key=True)
vigencia_clase_licencia = models.DateField(blank=True, null=True)
clase_licencia_conducir = models.CharField(max_length=50, blank=True, null=True)
profesion = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'persona_datos_laborales'

View File

@ -149,23 +149,3 @@ class GtfsArchivoSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.GtfsArchivo model = models.GtfsArchivo
fields = '__all__' fields = '__all__'
class TipoCargoSerializer(serializers.ModelSerializer):
class Meta:
model = models.TipoCargo
fields = '__all__'
class VistaFuncionarioSerializer(serializers.ModelSerializer):
class Meta:
model = models.VistaFuncionario
fields = '__all__'
class ContratoSerializer(serializers.ModelSerializer):
class Meta:
model = models.Contrato
fields = '__all__'
class PersonaDatosLaboralesSerializer(serializers.ModelSerializer):
class Meta:
model = models.PersonaDatosLaborales
fields = '__all__'

View File

@ -3,7 +3,7 @@ from rest_framework import routers
# from api import views # from api import views
from api.views import usuario, auth, aplicacion, tipo, persona, comuna, region, rol, rolaplicacion from api.views import usuario, auth, aplicacion, tipo, persona, comuna, region, rol, rolaplicacion
from api.views import mapa, linea, letrero_lur, operador,red_transporte,gtfs_archivo from api.views import mapa, linea, letrero_lur, operador,red_transporte,gtfs_archivo
from api.views import paradero, paradero_imagen, linea_paradero, tipo_cargo from api.views import paradero, paradero_imagen, linea_paradero
from api.views import dispositivo from api.views import dispositivo
from api.views import rol_operador from api.views import rol_operador
from api.views import upload from api.views import upload
@ -31,7 +31,6 @@ router.register('gtfs-archivo', gtfs_archivo.GtfsArchivoViewSet)
router.register('roles', rol.RolViewSet) router.register('roles', rol.RolViewSet)
router.register('rolyaplicacion', rolaplicacion.RolAplicacionViewSet, basename='rol_aplicacion') router.register('rolyaplicacion', rolaplicacion.RolAplicacionViewSet, basename='rol_aplicacion')
router.register('roles-operadores', rol_operador.RolOperadorViewSet, basename='rol_operador') router.register('roles-operadores', rol_operador.RolOperadorViewSet, basename='rol_operador')
router.register('tipo-cargo', tipo_cargo.TipoCargoViewSet)
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),
@ -41,6 +40,5 @@ urlpatterns = [
path('auth/nueva-contrasena/', auth.nueva_contrasena, name='auth_contrasena'), path('auth/nueva-contrasena/', auth.nueva_contrasena, name='auth_contrasena'),
path('mapas/paraderos/', mapa.paraderos, name='mapa-paraderos'), path('mapas/paraderos/', mapa.paraderos, name='mapa-paraderos'),
path('mapas/rutas/', mapa.rutas, name='mapa-rutas'), path('mapas/rutas/', mapa.rutas, name='mapa-rutas'),
path('mapas/coordenadas/', mapa.coordenadas, name='mapa-coordenadas'),
path('upload/zip/', upload.upload_zip, name='upload_zip'), path('upload/zip/', upload.upload_zip, name='upload_zip'),
] ]

View File

@ -41,12 +41,12 @@ def jwt_login(request):
# solo se permite usuario 0 si no existen usuarios vigentes # solo se permite usuario 0 si no existen usuarios vigentes
count = models.Usuario.objects.filter(vigente = True).count() count = models.Usuario.objects.filter(vigente = True).count()
if count > 0: if count > 0:
return HttpResponse('Acceso no valido 1', status=400) return HttpResponse('Acceso no valido', status=400)
else: else:
usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first() usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first()
if not check_password(input['password'], usuario['clave']): if not check_password(input['password'], usuario['clave']):
return HttpResponse('Acceso no valido 2', status=400) return HttpResponse('Acceso no valido', status=400)
ahora = datetime.utcnow() ahora = datetime.utcnow()
manana = ahora + timedelta(days=1) manana = ahora + timedelta(days=1)
@ -79,10 +79,10 @@ def recuperar(request):
usuario = models.Usuario.objects.filter(rut=rut, vigente=True).first() usuario = models.Usuario.objects.filter(rut=rut, vigente=True).first()
if usuario == None or persona == None: if usuario == None or persona == None:
return HttpResponse('El usuario no existe', status=400) return HttpResponse('Acceso no valido', status=400)
if persona.email != input['email'].lower(): if persona.email != input['email'].lower():
return HttpResponse('El correo electrónico no es el registrado para el usuario', status=400) return HttpResponse('Acceso no valido', status=400)
codigo_aleatorio = random.randint(100000, 999999) codigo_aleatorio = random.randint(100000, 999999)
ahora = datetime.utcnow() ahora = datetime.utcnow()
@ -112,7 +112,6 @@ def recuperar(request):
def info_token(request): def info_token(request):
input = json.loads(request.body) input = json.loads(request.body)
token = input['token'] token = input['token']
logging.warning(input)
try: try:
decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
persona = models.Persona.objects.filter(rut=decoded['rut']).first() persona = models.Persona.objects.filter(rut=decoded['rut']).first()
@ -159,23 +158,27 @@ def nueva_contrasena(request):
return HttpResponse('error al cambiar contraseña', status = 500) return HttpResponse('error al cambiar contraseña', status = 500)
def enviar_correo(destinatario, asunto, contenido): def enviar_correo(destinatario, asunto, contenido):
try: try:
template = get_template('correo_recuperar.html') # Ruta al template del correo template = get_template('correo_recuperar.html') # Ruta al template del correo
contenido_renderizado = template.render(contenido) contenido_renderizado = template.render(contenido)
mensaje = EmailMultiAlternatives(asunto, '', settings.EMAIL_SENDER, [destinatario]) mensaje = EmailMultiAlternatives(asunto, '', settings.EMAIL_HOST_USER, [destinatario])
mensaje.attach_alternative(contenido_renderizado, 'text/html') mensaje.attach_alternative(contenido_renderizado, 'text/html')
mensaje.send() mensaje.send()
return True return True
except Exception as e: except Exception as e:
print(f'EMAIL_HOST: {settings.EMAIL_HOST}', flush=True) print(f'EMAIL_HOST: {EMAIL_HOST}', flush=True)
print(f'ERROR: {e}', flush=True) print(f'ERROR: {e}', flush=True)
return False return False
def http_referer(request, clean=False):
if 'HTTP_REFERER' in request.META and clean==False:
def http_referer(request):
if 'HTTP_REFERER' in request.META:
referer = request.META['HTTP_REFERER'] referer = request.META['HTTP_REFERER']
else: else:
protocol = request.scheme protocol = request.scheme

View File

@ -1,162 +0,0 @@
from django.db import transaction
from django.http import HttpResponse, JsonResponse
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
from api import models, schemas, serializers
import json
import logging
class ContratoViewSet(viewsets.ModelViewSet):
queryset = models.Contrato.objects.all()
serializer_class = serializers.ContratoSerializer
schema = schemas.ContratoSchema()
def retrieve(self, request, pk=None):
data = super().retrieve(request, pk)
return data
def create(self, request):
try:
with transaction.atomic():
input = json.loads(request.body)
persona = models.Persona.objects.filter(rut = input['rut']).first()
id_tipo_tratamiento = input.get('id_tipo_tratamiento',None)
if not id_tipo_tratamiento:
id_tipo_tratamiento = None
if not persona:
persona = models.Persona(
rut = input['rut'],
dv = input['dv'],
nombres = input['nombres'],
apellido_a = input.get('apellido_a',None),
apellido_b = input.get('apellido_b',None),
email = input.get('email',None),
id_tipo_tratamiento = id_tipo_tratamiento
)
persona.save()
else:
persona.nombres = input['nombres']
persona.apellido_a = input.get('apellido_a',None)
persona.apellido_b = input.get('apellido_b',None)
persona.email = input.get('email',None)
persona.id_tipo_tratamiento = id_tipo_tratamiento
persona.save()
cargo = models.TipoCargo.objects.filter(id_cargo=input.get('id_cargo',None)).first()
operador=models.Operador.objects.filter(id_operador=input.get('id_operador',None)).first()
if cargo == None:
raise ValueError('Cargo no encontrado')
Contrato = models.Contrato(
rut = persona,
id_operador = operador,
desde = input['desde'],
hasta = input['hasta']
)
Contrato.save()
if input['clave']:
logging.error('Modificar clave de Contrato')
Contrato.clave = make_password(input['clave'])
Contrato.save()
return Response({
'rut': persona.rut,
'dv': persona.dv,
'nombres': persona.nombres,
'apellido_a': persona.apellido_a,
'apellido_b': persona.apellido_b,
'email': persona.email,
'login': Contrato.login,
'vigente': Contrato.vigente,
})
except ValueError as e:
transaction.rollback()
return HttpResponse(str(e), status = 400)
except Exception as e:
transaction.rollback()
print(e)
return HttpResponse(str(e), status = 500)
def update(self, request, *args, **kwargs):
input = json.loads(request.body)
try:
pk = input['rut']
with transaction.atomic():
# validaciones se realiza a nivel del model
persona = models.Persona.objects.filter(rut = pk).first()
rol = models.Rol.objects.filter(id_rol = input.get('id_rol')).first()
Contrato = models.Contrato.objects.filter(rut = pk).first()
Contrato.vigente = input.get('vigente', False)
Contrato.superuser = input.get('superuser', False)
Contrato.id_rol = rol
Contrato.save()
if 'clave' in input:
logging.error('Modificar clave de Contrato')
Contrato.clave = make_password(input['clave'])
Contrato.save()
return Response({
'rut': persona.rut,
'dv': persona.dv,
'nombres': persona.nombres,
'apellido_a': persona.apellido_a,
'apellido_b': persona.apellido_b,
'email': persona.email,
'login': Contrato.login,
'vigente': Contrato.vigente,
})
except ValueError as e:
transaction.rollback()
return HttpResponse(str(e), status = 400)
except Exception as e:
transaction.rollback()
logging.error(e)
return HttpResponse(str(e), status = 500)
@action(detail=False, methods=['post'])
def permisos(self, request):
input = {}
if request.body > b'':
input = json.loads(request.body)
login = request.jwt_info['login']
Contrato = models.Contrato.objects.filter(login=login).first()
escritura = Contrato.superuser == True
if 'path' in input:
path = input.get('path')
aplicacion = models.Aplicacion.objects.filter(path_app=path).first()
if escritura == False:
rol_aplicacion = models.RolAplicacion.objects.filter(id_rol=Contrato.id_rol, id_aplicacion=aplicacion.id_aplicacion).first()
escritura = rol_aplicacion.solo_visualizar == False
return JsonResponse({
'path_app': path,
'nombre_app': aplicacion.nombre_app,
'escritura': escritura
})
else:
registros = models.RolAplicacion.objects.filter(id_rol=Contrato.id_rol)
aplicaciones = []
for registro in registros:
if registro.id_aplicacion.vigente:
rol_app = models.RolAplicacion.objects.filter(id_rol=registro.id_rol, id_aplicacion=registro.id_aplicacion).first()
aplicaciones.append({
'path_app': registro.id_aplicacion.path_app,
'nombre_app': registro.id_aplicacion.nombre_app,
})
return JsonResponse({ "aplicaciones": aplicaciones })

View File

@ -1,10 +1,10 @@
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.decorators import action
from django.http import JsonResponse from django.http import JsonResponse
from django.db.models import F from django.db.models import F
from django.db import connection from django.db import connection
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.decorators import action
from api import models, serializers from api import models, serializers
from os import getenv from os import getenv
import redis import redis
@ -18,7 +18,7 @@ class DispositivoViewSet(viewsets.ModelViewSet):
queryset = models.Dispositivo.objects.all() queryset = models.Dispositivo.objects.all()
serializer_class = serializers.DispositivoSerializer serializer_class = serializers.DispositivoSerializer
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ['id_dispositivo', 'id_paradero', 'id_tipo_dispositivo'] filterset_fields = ['id_paradero', 'id_tipo_dispositivo']
@action(detail=False, methods=['post']) @action(detail=False, methods=['post'])
@ -51,13 +51,12 @@ class DispositivoViewSet(viewsets.ModelViewSet):
}) })
@action(detail=False, methods=['post','get']) @action(detail=False, methods=['post'])
def getInfoDevice(self, request, pk=None): def getInfoDevice(self, request, pk=None):
input = json.loads(request.body) input = json.loads(request.body)
getInfoDevice = input['GetInfoDevice'] getInfoDevice = input['GetInfoDevice']
cursor = connection.cursor() record = models.Paradero.objects \
paradero = models.Paradero.objects \
.filter(dispositivo__id_dispositivo=getInfoDevice['idDispositivo']) \ .filter(dispositivo__id_dispositivo=getInfoDevice['idDispositivo']) \
.annotate(nro_paradero=F('id_paradero'), nombre_paradero=F('stop_name')) \ .annotate(nro_paradero=F('id_paradero'), nombre_paradero=F('stop_name')) \
.first() .first()
@ -66,171 +65,58 @@ class DispositivoViewSet(viewsets.ModelViewSet):
db_port = getenv('DB_REDIS_PORT') db_port = getenv('DB_REDIS_PORT')
r = redis.Redis(host=db_host, port=db_port, decode_responses=True) r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
key = f'stop_id:{paradero.nro_paradero}' key = f'stop_id:{record.nro_paradero}'
json_trayectos = r.get(key) json_trayectos = r.get(key)
trayectos = []
if json_trayectos != None: if json_trayectos != None:
trayectos = json.loads(json_trayectos) trayectos = json.loads(json_trayectos)
else:
key = f'stop_id:none' trayectos = []
json_trayectos = r.get(key)
trayectos_none = []
if json_trayectos != None:
trayectos_none = json.loads(json_trayectos)
# agregar al listado los trayecto en donde no se registro el paradero
"""
json_trayectos = r.get('stop_id:none')
trayectos_none = []
if json_trayectos != None:
trayectos_none = json.loads(json_trayectos)
for trayecto in trayectos_none:
trayecto['stop_id'] = 'none'
trayecto['hora_llegada'] = None
trayectos.append(trayecto)
"""
lineas = models.Linea.objects.filter(lineaparadero__id_paradero = paradero.id_paradero).order_by('route_short_name')
detalle_lineas = []
for linea in lineas:
llegadas = []
for trayecto in trayectos:
id_linea = f"{trayecto['route_id']}-{trayecto['direction_id']}"
stop_id = trayecto['stop_id']
patente = trayecto['vehicle_license_plate']
trayecto['stop_id_alterno'] = None
if id_linea == linea.id_linea:
hora_llegada = trayecto['hora_llegada']
distancia_km = None
texto_llegada= None
# si no trae latitud ni longitud: buscar en trayectos_none por patente
# y sobreescribir latitud y longitud
if trayecto['latitude'] == 0 and trayecto['longitude'] == 0:
for trayecto_none in trayectos_none:
if patente == trayecto_none['vehicle_license_plate']:
trayecto['longitude'] = trayecto_none['longitude']
trayecto['latitude'] = trayecto_none['latitude']
trayecto['stop_id_alterno'] = 'none'
break
if trayecto['latitude'] != 0 and trayecto['longitude'] != 0:
trip_id = trayecto['trip_id']
velocidad_promedio = 80
p_lon = trayecto['longitude']
p_lat = trayecto['latitude']
sql = "select hora_llegada, distancia_km, texto_llegada from fn_gtfs_calcula_distancia_tiempo_llegada(%s,%s,%s,%s,%s)"
cursor.execute(sql, [trip_id, stop_id, velocidad_promedio, p_lon, p_lat])
row = cursor.fetchone()
""" if patente == 'FDCB32':
print(f'SQL: {sql}', flush=True)
print(f'params: {[trip_id, stop_id, velocidad_promedio, p_lon, p_lat]}', flush=True)
print(f'row: {row}', flush=True) """
if row != None:
hora_llegada = row[0].strftime('%H:%M:%S')
distancia_km = row[1]
texto_llegada= row[2]
if distancia_km == None:
distancia_km == 999
llegadas.append({ lineas = {}
'patente': trayecto['vehicle_license_plate'], lineas_agrupadas = {}
'Planificada': trayecto['hora_llegada'], for t in trayectos:
'Latitud': trayecto['latitude'],
'Longitud': trayecto['longitude'],
'stop_id_alterno': trayecto['stop_id_alterno'],
'EstimadaGPS': hora_llegada,
'DistanciaGPS': distancia_km,
'textoLlegada' : texto_llegada,
'Mensajelinea': None,
})
try: pk_linea = f'{t["route_id"]}-{t["direction_id"]}'
llegadas_ordendas = sorted(llegadas, key=lambda x: x['DistanciaGPS']) if pk_linea not in lineas:
except: lineas[pk_linea] = models.Linea.objects.filter(id_linea=pk_linea).first()
logging.debug("No se pueden ordenar: {}".format(llegadas))
llegadas_ordendas = llegadas
linea = lineas[pk_linea]
item = { if linea == None:
logging.error(pk_linea)
if linea != None:
if pk_linea not in lineas_agrupadas:
lineas_agrupadas[pk_linea] = {
'Linea': linea.route_long_name, 'Linea': linea.route_long_name,
'Descripcion': linea.route_short_name, 'Descripcion': linea.route_short_name,
'TipoLocomocion': linea.route_type.descripcion, 'TipoLocomocion': linea.route_type.descripcion,
'colorFondo': linea.route_color, 'colorFondo': linea.route_color,
'colorTexto': linea.route_text_color, 'colorTexto': linea.route_text_color,
'Llegadas': llegadas_ordendas 'Llegadas': []
} }
detalle_lineas.append(item)
# lineas = {} lineas_agrupadas[pk_linea]['Llegadas'].append({
# lineas_agrupadas = {} 'patente': t['vehicle_license_plate'],
# for t in trayectos: 'Planificada': None,
'EstimadaGPS': t['hora_llegada'],
# pk_linea = f'{t["route_id"]}-{t["direction_id"]}' 'DistanciaGPS': None,
# if pk_linea not in lineas: 'Mensajelinea': None,
# lineas[pk_linea] = models.Linea.objects.filter(id_linea=pk_linea).first() })
# linea = lineas[pk_linea]
# if linea == None:
# print(pk_linea, flush=True)
# if linea != None:
# if pk_linea not in lineas_agrupadas:
# lineas_agrupadas[pk_linea] = {
# 'Linea': linea.route_long_name,
# 'Descripcion': linea.route_short_name,
# 'TipoLocomocion': linea.route_type.descripcion,
# 'colorFondo': linea.route_color,
# 'colorTexto': linea.route_text_color,
# 'Llegadas': []
# }
# sql = "select hora_llegada, distancia_km from fn_gtfs_calcula_distancia_tiempo_llegada(%s,%s,%s,%s,%s)"
# trip_id = t['trip_id']
# paradero_id = t['stop_id']
# velocidad_promedio = 30
# p_lon = t['longitude']
# p_lat = t['latitude']
# cursor.execute(sql, [trip_id, paradero_id, velocidad_promedio, p_lon, p_lat])
# row = cursor.fetchone()
# hora_llegada = None
# distancia_km = None
# if row != None:
# hora_llegada = row[0].strftime('%H:%M:%S')
# distancia_km = row[1]
# lineas_agrupadas[pk_linea]['Llegadas'].append({
# 'patente': t['vehicle_license_plate'],
# 'Planificada': t['hora_llegada'],
# 'EstimadaGPS': hora_llegada,
# 'DistanciaGPS': distancia_km,
# 'Mensajelinea': None,
# })
# detalle_lineas = [] detalle_lineas = []
# for pk_linea in lineas_agrupadas: for pk_linea in lineas_agrupadas:
# detalle_lineas.append(lineas_agrupadas[pk_linea]) detalle_lineas.append(lineas_agrupadas[pk_linea])
save_log_dispositivo(id_dispositivo=getInfoDevice['idDispositivo'], accion_url='getInfoDevice') save_log_dispositivo(id_dispositivo=getInfoDevice['idDispositivo'], accion_url='getInfoDevice')
cursor.close()
return JsonResponse({ return JsonResponse({
"GetInfoDeviceResponse": { "GetInfoDeviceResponse": {
"DetalleLineas": detalle_lineas, "DetalleLineas": detalle_lineas,
"MensajeParadero": "No considerar, uso futuro", "MensajeParadero": "No considerar, uso futuro",
"NroParadero": paradero.nro_paradero, "NroParadero": record.nro_paradero,
"NombreParadero": paradero.nombre_paradero, "NombreParadero": record.nombre_paradero
"proto": trayectos,
} }
}) })

View File

@ -2,24 +2,19 @@
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.http import FileResponse, HttpResponse from django.http import FileResponse, HttpResponse
from api import models , serializers from api import models , serializers
from decouple import config from decouple import config
import os import os
import logging import logging
class GtfsArchivoViewSet(viewsets.ModelViewSet): class GtfsArchivoViewSet(viewsets.ModelViewSet):
queryset = models.GtfsArchivo.objects.all() queryset = models.GtfsArchivo.objects.all()
serializer_class = serializers.GtfsArchivoSerializer serializer_class = serializers.GtfsArchivoSerializer
filter_backends = [DjangoFilterBackend, OrderingFilter] filter_backends = [DjangoFilterBackend]
filterset_fields = ['id_gtfs', 'id_red', 'archivo','valid_from','created','usuario','vigente','status'] filterset_fields = ['id_gtfs', 'id_red', 'archivo','valid_from','created','usuario','vigente','status']
ordering_fields = ['id_gtfs', 'id_red', 'archivo', 'valid_from', 'created', 'usuario', 'vigente', 'status']
ordering = ['id_gtfs']
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
fs = FileSystemStorage(location = config('GTFS_UPLOADS','/tmp')) fs = FileSystemStorage(location = config('GTFS_UPLOADS','/tmp'))

View File

@ -1,6 +1,6 @@
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.response import Response # from rest_framework.response import Response
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
@ -46,57 +46,6 @@ class LineaViewSet(viewsets.ModelViewSet):
return JsonResponse(list(paraderos), safe=False) return JsonResponse(list(paraderos), safe=False)
# @action(detail=False, methods=['get'])
def ___buses(self, request, pk=None):
pk = request.GET['id_linea']
# 1. obtener todas los paraderos de redis
# 2. consultar en cada paradero si hay una linea que corresponda a la consultada
# 3. si existe se agrega el vehiculo
db_host = getenv('DB_REDIS_HOST')
db_port = getenv('DB_REDIS_PORT')
r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
fileproto = r.get('fileproto')
paraderos_redis = r.keys('stop_id:*')
object_buses = {}
for key_paradero in paraderos_redis:
string_trayectos = r.get(key_paradero)
array_trayectos = json.loads(string_trayectos)
for trayecto in array_trayectos:
patente = trayecto['vehicle_license_plate']
id_linea = f"{trayecto['route_id']}-{trayecto['direction_id']}"
if id_linea == pk and key_paradero == 'stop_id:none':
print(trayecto, flush=True)
object_buses[patente] = {
'Patente_vehiculo': trayecto["vehicle_license_plate"],
'latitude': trayecto["latitude"],
'longitude': trayecto["longitude"],
'speed': trayecto["speed"]
}
if id_linea == pk and patente not in object_buses:
object_buses[patente] = {
'Patente_vehiculo': trayecto["vehicle_license_plate"],
'latitude': trayecto["latitude"],
'longitude': trayecto["longitude"],
'speed': trayecto["speed"]
}
array_buses = []
for patente in object_buses:
array_buses.append(object_buses[patente])
return Response({
'fileproto': fileproto,
'buses': array_buses
})
@action(detail=False, methods=['get']) @action(detail=False, methods=['get'])
def buses(self, request, pk=None): def buses(self, request, pk=None):
pk = request.GET['id_linea'] pk = request.GET['id_linea']
@ -131,23 +80,6 @@ class LineaViewSet(viewsets.ModelViewSet):
'speed': trayecto["speed"] 'speed': trayecto["speed"]
} }
key = f'stop_id:none'
data = r.get(key)
if data != None:
array_trayectos = json.loads(data)
for trayecto in array_trayectos:
key_route = f'{trayecto["route_id"]}-{trayecto["direction_id"]}'
if key_route == pk:
patente = trayecto["vehicle_license_plate"]
if (patente not in obj_buses) or (patente in obj_buses and obj_buses[patente]['longitude'] == 0 and obj_buses[patente]['latitude'] == 0):
obj_buses[patente] = {
'Patente_vehiculo': trayecto["vehicle_license_plate"],
'latitude': trayecto["latitude"],
'longitude': trayecto["longitude"],
'speed': trayecto["speed"]
}
for patente in obj_buses: for patente in obj_buses:
array_buses.append(obj_buses[patente]) array_buses.append(obj_buses[patente])
@ -165,6 +97,8 @@ class LineaViewSet(viewsets.ModelViewSet):
.filter(id_linea=pk) \ .filter(id_linea=pk) \
.first() .first()
logging.error(linea)
detalle_buses = [] detalle_buses = []
paraderos = models.Paradero.objects \ paraderos = models.Paradero.objects \
.filter(vigente=True, lineaparadero__id_linea=pk) \ .filter(vigente=True, lineaparadero__id_linea=pk) \
@ -238,11 +172,8 @@ class LineaViewSet(viewsets.ModelViewSet):
return JsonResponse(data, safe=False) return JsonResponse(data, safe=False)
@action(detail=False, methods=['get']) @action(detail=False, methods=['get'])
def count_buses_recorridos_old(self, request, pk=None): def count_buses_recorridos(self, request, pk=None):
query = "select count(distinct vehicle_license_plate) from gtfs_posiciones" query = "select count(distinct vehicle_license_plate) from gtfs_posiciones"
with connection.cursor() as cursor: with connection.cursor() as cursor:
@ -251,80 +182,3 @@ class LineaViewSet(viewsets.ModelViewSet):
return JsonResponse({ 'count': result[0] }) return JsonResponse({ 'count': result[0] })
@action(detail=False, methods=['get'])
def count_lineas_correctas(self, request, pk=None):
query = """
SELECT 'Total Rutas correctas' AS titulo, COUNT(*) - (
SELECT COUNT(*) AS cantidad
FROM gtfs_validaciones gv
WHERE id_gtfs IN (
SELECT id_gtfs
FROM gtfs_archivo
WHERE NOT vigente
)
) AS cantidad
FROM linea
WHERE vigente
UNION
SELECT 'Total Rutas con Inconsistencias' AS titulo, COUNT(*) AS cantidad
FROM gtfs_validaciones gv
WHERE id_gtfs IN (
SELECT id_gtfs
FROM gtfs_archivo
WHERE vigente
)
"""
try:
with connection.cursor() as cursor:
cursor.execute(query)
result = cursor.fetchall()
data = []
for row in result:
# Cada 'row' es una tupla con dos elementos: titulo y cantidad
data.append({
'titulo': row[0],
'cantidad': row[1]
})
return JsonResponse(data, safe=False) # Usar safe=False para permitir objetos no diccionario en la raíz
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
@action(detail=False, methods=['get'])
def count_buses_recorridos(self, request, pk=None):
db_host = getenv('DB_REDIS_HOST')
db_port = getenv('DB_REDIS_PORT')
r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
key = f'stop_id:none'
data = r.get(key)
data = json.loads(data)
unique_vehicle_plates = set(item["vehicle_license_plate"] for item in data)
count_unique_vehicle_plates = len(unique_vehicle_plates)
return JsonResponse({ 'count': count_unique_vehicle_plates })
@action(detail=False, methods=['get'])
def count_rutas_buses(self, request, pk=None):
db_host = getenv('DB_REDIS_HOST')
db_port = getenv('DB_REDIS_PORT')
r = redis.Redis(host=db_host, port=db_port, decode_responses=True)
key = f'stop_id:none'
data = r.get(key)
data = json.loads(data)
unique_route_direction = set(
(item["route_id"], item["direction_id"]) for item in data
)
count_unique_route_direction = len(unique_route_direction)
return JsonResponse({ 'count': count_unique_route_direction })

View File

@ -6,12 +6,10 @@ from django.views.decorators.csrf import csrf_exempt
from api.models import Paradero from api.models import Paradero
from api.models import GtfsShape, GtfsTrips from api.models import GtfsShape, GtfsTrips
from logging import error from logging import error
from decouple import config
google_api_key = 'AIzaSyDnFO9w_SsodjBuY5tOK8-kQJns_l5klQ4' google_api_key = 'AIzaSyDnFO9w_SsodjBuY5tOK8-kQJns_l5klQ4'
center = {'lat': -36.8077884, 'lng': -73.0775401} center = {'lat': -36.8077884, 'lng': -73.0775401}
@csrf_exempt @csrf_exempt
@action(detail=False, methods=['get']) @action(detail=False, methods=['get'])
@api_view(['GET']) @api_view(['GET'])
@ -89,18 +87,3 @@ def rutas(request):
'google_api_key': google_api_key, 'google_api_key': google_api_key,
'positions': list(resultados) 'positions': list(resultados)
}) })
@action(detail=False, methods=['get'])
@api_view(['GET'])
def coordenadas(request):
# Obtener las coordenadas iniciales desde las variables de entorno
initial_lat = config('COORDINI_LAT', default=-36.8270)
initial_lng = config('COORDINI_LNG', default=-73.0503)
# Enviar las coordenadas iniciales como parte de la respuesta
return JsonResponse({
'initialLat': initial_lat,
'initialLng': initial_lng,
})

View File

@ -8,7 +8,6 @@ from django.db.models import Max
from django.db import transaction from django.db import transaction
from api import models, serializers from api import models, serializers
import logging import logging
from decouple import config
class OperadorViewSet(viewsets.ModelViewSet): class OperadorViewSet(viewsets.ModelViewSet):
# queryset = models.Operador.objects.all() # queryset = models.Operador.objects.all()
@ -36,52 +35,30 @@ class OperadorViewSet(viewsets.ModelViewSet):
"No se puede crear el operador: 'id_operador' no proporcionado.", "No se puede crear el operador: 'id_operador' no proporcionado.",
status=HTTP_400_BAD_REQUEST status=HTTP_400_BAD_REQUEST
) )
newRecord= False;
if not models.Operador.objects.filter(id_operador=id_operador).exists():
newRecord = True
try: try:
with transaction.atomic(): with transaction.atomic():
#Se Define Operador, pero no se graba
operador = models.Operador( operador = models.Operador(
id_operador = id_operador, id_operador = id_operador,
nombre_operador = request.data.get('nombre_operador'), nombre_operador = request.data.get('nombre_operador'),
vigente = request.data.get('vigente'), vigente = request.data.get('vigente'),
) )
operador.save()
if newRecord:
# se crea el rol para el operador # se crea el rol para el operador
max_id = models.Rol.objects.aggregate(Max('id_rol'))['id_rol__max'] max_id = models.Rol.objects.aggregate(Max('id_rol'))['id_rol__max']
rol = models.Rol( rol = models.Rol(
id_rol = max_id + 1, id_rol = max_id + 1,
nombre_rol = f'Rol {operador.nombre_operador}' nombre_rol = f'Rol {operador.nombre_operador}'
) )
rol.save() rol.save()
operador.id_rol = rol
#Grabamos Operador, ya que si corresponde se le asigno el id del nuevo Rol
operador.save()
if newRecord :
app_default_operador_str = config('APP_DEFAULT_OPERADOR')
app_default_operador = [int(x) for x in app_default_operador_str.split(',')]
for id_aplicacion in app_default_operador:
aplicacion = models.Aplicacion.objects.get(id_aplicacion=id_aplicacion)
rolApp = models.RolAplicacion(
id_rol=rol,
id_aplicacion=aplicacion
)
rolApp.save()
rol_operador = models.RolOperador( rol_operador = models.RolOperador(
id_rol = rol, id_rol = rol,
id_operador = operador id_operador = operador
) )
rol_operador.save() rol_operador.save()
newRecord =False
return Response({ return Response({
'id_operador': operador.id_operador, 'id_operador': operador.id_operador,

View File

@ -3,9 +3,7 @@ from rest_framework import viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
from api.serializers import ParaderoSerializer from api.serializers import ParaderoSerializer
from api.models import Paradero, Dispositivo from api.models import Paradero, Dispositivo
from decouple import config
import logging import logging
from django.db.models import Count
class ParaderoViewSet(viewsets.ModelViewSet): class ParaderoViewSet(viewsets.ModelViewSet):
queryset = Paradero.objects.all() queryset = Paradero.objects.all()
@ -27,16 +25,6 @@ class ParaderoViewSet(viewsets.ModelViewSet):
return JsonResponse({ 'count': queryset.count() }) return JsonResponse({ 'count': queryset.count() })
@action(detail=False, methods=['get'], url_path='count_by_comuna')
def count_by_comuna(self, request, pk=None):
# Solo paraderos vigentes
queryset = Paradero.objects.filter(vigente=True)
# Conteo agrupado por comuna
count_by_comuna = queryset.values('id_comuna__nombre_comuna').annotate(total=Count('id_paradero')).order_by('id_comuna')
return JsonResponse({'count_by_comuna': list(count_by_comuna)})
@action(detail=False, methods=['get'], url_path='info-public/(?P<pk>\S+)') @action(detail=False, methods=['get'], url_path='info-public/(?P<pk>\S+)')
def info_public(self, request, pk=None): def info_public(self, request, pk=None):
if 'HTTP_REFERER' in request.META: if 'HTTP_REFERER' in request.META:
@ -53,8 +41,7 @@ class ParaderoViewSet(viewsets.ModelViewSet):
url = None url = None
if record != None: if record != None:
base_url = config('URL_PARADERO', 'http://localhost/') url = f'https://transporte-paradero.hz.kursor.cl/rutaParadero/?id={record.id_dispositivo}'
url = f'{base_url}{record.id_dispositivo}'
# url = f'{referer}/public/infoStop?codigoParadero={pk}' # url = f'{referer}/public/infoStop?codigoParadero={pk}'

View File

@ -1,16 +0,0 @@
from rest_framework import viewsets
from api import models , serializers
from django.db.models import Max
class TipoCargoViewSet(viewsets.ModelViewSet):
queryset = models.TipoCargo.objects.all()
serializer_class = serializers.TipoCargoSerializer
def create(self, request, *args, **kwargs):
# se indica que si no se indico el id, entonces sea el maximo + 1
if not request.data.get('id_cargo', None):
max_id = models.TipoCargo.objects.aggregate(Max('id_cargo'))['id_cargo__max']
new_id = max_id + 1 if max_id is not None else 1
request.data['id_cargo'] = new_id
return super().create(request, *args, **kwargs)

View File

@ -24,7 +24,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY') SECRET_KEY = 'django-insecure-ozq@8*t6cy&$lmu@qsvz+l6omsfncj6r1w)s**rtl3vd&j8_#b'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
@ -46,7 +46,6 @@ INSTALLED_APPS = [
'corsheaders', 'corsheaders',
'django_filters', 'django_filters',
'api', 'api',
'public',
'logger', 'logger',
] ]
@ -181,10 +180,7 @@ LOGGING = {
EMAIL_HOST = config('SMTP_HOST') EMAIL_HOST = config('SMTP_HOST')
EMAIL_PORT = config('SMTP_PORT') EMAIL_PORT = config('SMTP_PORT', 587)
EMAIL_SENDER = config('SMTP_FROM') EMAIL_HOST_USER = config('SMTP_USER', 'tu_correo@gmail.com') # Tu dirección de correo
EMAIL_HOST_PASSWORD = config('SMTP_PASS', 'tu_contraseña') # Tu contraseña de correo
#EMAIL_HOST_USER = config('SMTP_USER', 'tu_correo@gmail.com') # Tu dirección de correo
#EMAIL_HOST_PASSWORD = config('SMTP_PASS', 'tu_contraseña') # Tu contraseña de correo
EMAIL_USE_TLS = config('SMTP_PROTOCOL') == 'tls' EMAIL_USE_TLS = config('SMTP_PROTOCOL') == 'tls'

View File

@ -29,7 +29,6 @@ urlpatterns = [
# BACKEND # BACKEND
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('api/', include('api.urls')), path('api/', include('api.urls')),
path('api-public/', include('public.urls')),
path('docs/', include_docs_urls(title = 'API Documentation')), path('docs/', include_docs_urls(title = 'API Documentation')),
]#+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ]#+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,6 +0,0 @@
from django.apps import AppConfig
class PublicConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'public'

View File

@ -1,3 +0,0 @@
from django.db import models
# Create your models here.

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,10 +0,0 @@
from django.urls import path, include
from rest_framework import routers
from api.views.dispositivo import DispositivoViewSet
router = routers.DefaultRouter()
router.register('paradero_info', DispositivoViewSet)
urlpatterns = [
path('', include(router.urls)),
]

View File

@ -1,6 +0,0 @@
from django.shortcuts import render
from api.views.dispositivo import DispositivoViewSet
# Create your views here.
class DispositivoPublicViewSet(DispositivoViewSet):
pass

260
readme.md
View File

@ -68,50 +68,6 @@ gunzip -c "$LASTFILEDUMP" | psql -U postgres "$POSTGRES_DB"
~~~ ~~~
# archivo para compilar imagen: Dockerfile
~~~docker
# seccion frontend
FROM node:20-alpine as frontend
ARG gitusername
ARG gitpassword
# soluciona error en descarga de repositorio
RUN sed -i 's/https\:\/\//http\:\/\//g' /etc/apk/repositories
# descargar proyecto
RUN apk update && apk add git
RUN git clone "https://${gitusername}:${gitpassword}@gitlab.com/m3f_usm/admin_transporte/frontend" /frontend
RUN git clone "https://${gitusername}:${gitpassword}@gitlab.com/m3f_usm/admin_transporte/backend" /backend
RUN rm -rf /backend/project/dist
# compilar
WORKDIR /frontend
RUN npm install && npm run build
# seccion final -- se omite git y archivos innecerarios para reducir imagen
FROM python:3.11-alpine
COPY --from=frontend /backend/project/ /app/project
COPY --from=frontend /backend/readme.md /app
COPY --from=frontend /backend/requirements.txt /app
COPY --from=frontend /frontend/dist/ /app/project/dist
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python3"]
CMD [ "/app/project/manage.py", "runserver", "0.0.0.0:4000" ]
~~~
# instrucciones para compilar archivo Dockerfile
~~~bash
docker build -t <tagname:version> -f Dockerfile --no-cache --build-arg gitusername=<usuario gitlab> --build-arg gitpassword=<password gitlab> .
# ejemplo
# docker build -t transporte:v1.2 -f Dockerfile --no-cache --build-arg gitusername=johndoe --build-arg gitpassword=mypassword .
~~~
# archivo produccion: docker-compose.yml # archivo produccion: docker-compose.yml
~~~yml ~~~yml
@ -120,126 +76,25 @@ name: transporte
services: services:
transporte:
image: transporte:v1.2
depends_on:
- db
environment:
- PORT=4000
ports:
- 4000:4000
volumes:
- ./uploads:/uploads
#- .env.prod:/app/.env # (opcional: indicar conexiones a base datos en otro servidor)
db:
image: postgis/postgis:14-3.4-alpine
volumes:
- db:/var/lib/postgresql/data
- ./dumps:/dumps
- ./restore_db.sh:/docker-entrypoint-initdb.d/02_restore_db.sh
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: transporte
PGDATA: /var/lib/postgresql/data/pgdata
proto:
image: python:3.11-alpine
environment:
- DB_REDIS_HOST=dbproto
- DB_REDIS_PORT=6379
- TZ=America/Santiago
volumes:
- ./proto:/app
- venv_proto:/root/venv
working_dir: /app
command: sh -c "
[ -d /root/venv/bin ] || ( \
python -m venv /root/venv/ \
&& . /root/venv/bin/activate \
&& pip install -r requirements.txt \
) ;
. /root/venv/bin/activate ;
cd /app ;
[ -f .env ] || ( [ -f .env.develop ] && cp .env.develop .env ) ;
watch -n 30 -t python main.py
"
dbproto:
image: redis:7.2-alpine
volumes:
- dbredis:/data
dbmongo:
image: mongo:jammy
volumes:
- dbmongo:/data/db
- dbmongoconfig:/data/configdb
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
db:
dbredis:
dbmongo:
dbmongoconfig:
venv_proto:
~~~
<br>
<br>
<br>
# tunnel para desarrollo
Ver información en:
https://gitlab.com/m3f_usm/admin_transporte/backend/-/wikis/home
# archivo desarrollo: docker-compose.yml
~~~yml
version: '3'
name: transporte
services:
frontend:
image: node:18-alpine
volumes:
- ./frontend:/app
ports:
- 3000:3000
environment:
- VITE_PORT=3000
- VITE_BACKEND=http://localhost:4000/api
working_dir: /app
command: sh -c "
[ ! -d node_modules ] && npm install ;
chmod -R o+w . ;
npm run dev
"
backend: backend:
image: python:3.11-alpine image: python:3.11-alpine
depends_on: depends_on:
- db - db
environment: environment:
- PORT=4000 - PORT=4000
- DBHOST=db
- DBPORT=5432
- DBNAME=transporte
- DBSCHEMA=public
- DBUSER=postgres
- DBPASS=password
- DB_REDIS_HOST=dbproto
- DB_REDIS_PORT=6379
- SECRET_JWT="kf6Jc!f30Z!1k1N0#!%#"
ports: ports:
- 4000:4000 - 4000:4000
volumes: volumes:
- ./backend:/app - ./transporte:/app
- ./uploads:/uploads
- venv:/root/venv - venv:/root/venv
working_dir: /app working_dir: /app
command: sh -c " command: sh -c "
@ -297,30 +152,93 @@ services:
dbproto: dbproto:
image: redis:7.2-alpine image: redis:7.2-alpine
volumes:
- dbredis:/data
dbmongo:
image: mongo:jammy
volumes:
- dbmongo:/data/db
- dbmongoconfig:/data/configdb
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
volumes: volumes:
db: db:
dbredis:
dbmongo:
dbmongoconfig:
venv: venv:
venv_proto: venv_proto:
~~~ ~~~
<br>
<br>
<br>
# tunnel para desarrollo
Ver información en:
https://gitlab.com/m3f_usm/admin_transporte/backend/-/wikis/home
# archivo desarrollo: docker-compose.yml
~~~yml
version: '3'
name: transporte
services:
frontend:
image: node:18-alpine
volumes:
- ./frontend:/app
ports:
- 3000:3000
environment:
- VITE_PORT=3000
- VITE_BACKEND=http://localhost:4000/api
working_dir: /app
command: sh -c "
[ ! -d node_modules ] && npm install ;
chmod -R o+w . ;
npm run dev
"
backend:
image: python:3.11-alpine
depends_on:
- db
environment:
- PORT=4000
- DBHOST=db
- DBPORT=5432
- DBNAME=transporte
- DBSCHEMA=public
- DBUSER=postgres
- DBPASS=password
- DB_REDIS_HOST=dbproto
- DB_REDIS_PORT=6379
- SECRET_JWT="kf6Jc!f30Z!1k1N0#!%#"
ports:
- 4000:4000
volumes:
- ./transporte:/app
- venv:/root/venv
working_dir: /app
command: sh -c "
[ -d /root/venv/bin ] || ( \
python -m venv /root/venv/ \
&& . /root/venv/bin/activate \
&& pip install -r requirements.txt \
) ;
. /root/venv/bin/activate ;
cd /app ;
[ -d project ] || django-admin startproject project ;
[ -f .env ] || ( [ -f .env.develop ] && cp .env.develop .env ) ;
chmod -R o+w project/ ;
python project/manage.py runserver 0.0.0.0:$$PORT
"
extra_hosts:
- db:<direccion ip de tu computador>
volumes:
venv:
~~~
# Script para levantar aplicacion python sin docker # Script para levantar aplicacion python sin docker