pagina para ver precios historicos

fixes #59
This commit is contained in:
Cat /dev/Nulo 2024-09-22 16:39:04 -03:00
parent 6fb0cdb963
commit e96bf8dc74
13 changed files with 1346 additions and 17 deletions

Binary file not shown.

View file

@ -91,6 +91,9 @@ export const precios = pgTable(
idx_precios_id_producto_id_dataset: index( idx_precios_id_producto_id_dataset: index(
"idx_precios_id_producto_id_dataset" "idx_precios_id_producto_id_dataset"
).using("btree", table.id_producto, table.id_dataset), ).using("btree", table.id_producto, table.id_dataset),
idx_precios_id_producto_id_comercio_id_sucursal: index(
"idx_precios_id_producto_id_comercio_id_sucursal"
).on(table.id_producto, table.id_comercio, table.id_sucursal),
}; };
} }
); );
@ -186,6 +189,10 @@ export const sucursalesRelations = relations(sucursales, ({ one }) => ({
fields: [sucursales.id_dataset], fields: [sucursales.id_dataset],
references: [datasets.id], references: [datasets.id],
}), }),
bandera: one(banderas, {
fields: [sucursales.id_comercio, sucursales.id_bandera],
references: [banderas.id_comercio, banderas.id_bandera],
}),
})); }));
// para actualizar la tabla: // para actualizar la tabla:

View file

@ -0,0 +1 @@
CREATE INDEX IF NOT EXISTS "idx_precios_id_dataset_id_comercio_id_sucursal" ON "precios" USING btree ("id_dataset","id_comercio","id_sucursal");

View file

@ -0,0 +1,2 @@
DROP INDEX IF EXISTS "idx_precios_id_dataset_id_comercio_id_sucursal";--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "idx_precios_id_producto_id_comercio_id_sucursal" ON "precios" USING btree ("id_producto","id_comercio","id_sucursal");

View file

@ -0,0 +1,559 @@
{
"id": "c63ebee0-9e80-431e-9caf-195ee5b4d222",
"prevId": "069e6444-9867-4037-adfa-9ae798c70b7c",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.banderas": {
"name": "banderas",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"comercio_cuit": {
"name": "comercio_cuit",
"type": "text",
"primaryKey": false,
"notNull": true
},
"comercio_razon_social": {
"name": "comercio_razon_social",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_bandera_nombre": {
"name": "comercio_bandera_nombre",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_bandera_url": {
"name": "comercio_bandera_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_ultima_actualizacion": {
"name": "comercio_ultima_actualizacion",
"type": "date",
"primaryKey": false,
"notNull": false
},
"comercio_version_sepa": {
"name": "comercio_version_sepa",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"banderas_id_dataset_datasets_id_fk": {
"name": "banderas_id_dataset_datasets_id_fk",
"tableFrom": "banderas",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"banderas_id_dataset": {
"name": "banderas_id_dataset",
"nullsNotDistinct": false,
"columns": [
"id_dataset"
]
}
}
},
"public.datasets": {
"name": "datasets",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"datasets_name_key": {
"name": "datasets_name_key",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
}
},
"public.precios": {
"name": "precios",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_sucursal": {
"name": "id_sucursal",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_producto": {
"name": "id_producto",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"productos_ean": {
"name": "productos_ean",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"productos_descripcion": {
"name": "productos_descripcion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_cantidad_presentacion": {
"name": "productos_cantidad_presentacion",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_unidad_medida_presentacion": {
"name": "productos_unidad_medida_presentacion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_marca": {
"name": "productos_marca",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_lista": {
"name": "productos_precio_lista",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_precio_referencia": {
"name": "productos_precio_referencia",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_cantidad_referencia": {
"name": "productos_cantidad_referencia",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_unidad_medida_referencia": {
"name": "productos_unidad_medida_referencia",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_unitario_promo1": {
"name": "productos_precio_unitario_promo1",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_leyenda_promo1": {
"name": "productos_leyenda_promo1",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_unitario_promo2": {
"name": "productos_precio_unitario_promo2",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_leyenda_promo2": {
"name": "productos_leyenda_promo2",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"idx_precios_id_producto": {
"name": "idx_precios_id_producto",
"columns": [
{
"expression": "id_producto",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"idx_precios_id_producto_id_dataset": {
"name": "idx_precios_id_producto_id_dataset",
"columns": [
{
"expression": "id_producto",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"idx_precios_id_dataset_id_comercio_id_sucursal": {
"name": "idx_precios_id_dataset_id_comercio_id_sucursal",
"columns": [
{
"expression": "id_dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_comercio",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_sucursal",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"precios_id_dataset_datasets_id_fk": {
"name": "precios_id_dataset_datasets_id_fk",
"tableFrom": "precios",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.productos_descripcion_index": {
"name": "productos_descripcion_index",
"schema": "",
"columns": {
"id_producto": {
"name": "id_producto",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"productos_descripcion": {
"name": "productos_descripcion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_marca": {
"name": "productos_marca",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"productos_descripcion_index_search_descripcion": {
"name": "productos_descripcion_index_search_descripcion",
"columns": [
{
"expression": "to_tsvector('spanish', \"productos_descripcion\")",
"asc": true,
"isExpression": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"productos_descripcion_index_productos_descripcion_unique": {
"name": "productos_descripcion_index_productos_descripcion_unique",
"nullsNotDistinct": false,
"columns": [
"productos_descripcion"
]
}
}
},
"public.sucursales": {
"name": "sucursales",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_sucursal": {
"name": "id_sucursal",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"sucursales_nombre": {
"name": "sucursales_nombre",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_tipo": {
"name": "sucursales_tipo",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_calle": {
"name": "sucursales_calle",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_numero": {
"name": "sucursales_numero",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_latitud": {
"name": "sucursales_latitud",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"sucursales_longitud": {
"name": "sucursales_longitud",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"sucursales_observaciones": {
"name": "sucursales_observaciones",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_barrio": {
"name": "sucursales_barrio",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_codigo_postal": {
"name": "sucursales_codigo_postal",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_localidad": {
"name": "sucursales_localidad",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_provincia": {
"name": "sucursales_provincia",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_lunes_horario_atencion": {
"name": "sucursales_lunes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_martes_horario_atencion": {
"name": "sucursales_martes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_miercoles_horario_atencion": {
"name": "sucursales_miercoles_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_jueves_horario_atencion": {
"name": "sucursales_jueves_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_viernes_horario_atencion": {
"name": "sucursales_viernes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_sabado_horario_atencion": {
"name": "sucursales_sabado_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_domingo_horario_atencion": {
"name": "sucursales_domingo_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sucursales_id_dataset_datasets_id_fk": {
"name": "sucursales_id_dataset_datasets_id_fk",
"tableFrom": "sucursales",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"sucursales_id_dataset_id_comercio_id_bandera_id_sucursal_key": {
"name": "sucursales_id_dataset_id_comercio_id_bandera_id_sucursal_key",
"nullsNotDistinct": false,
"columns": [
"id_dataset",
"id_comercio",
"id_bandera",
"id_sucursal"
]
}
}
}
},
"enums": {},
"schemas": {},
"sequences": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View file

@ -0,0 +1,559 @@
{
"id": "fc65894f-ded2-444d-b634-2c66780ec6c5",
"prevId": "c63ebee0-9e80-431e-9caf-195ee5b4d222",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.banderas": {
"name": "banderas",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"comercio_cuit": {
"name": "comercio_cuit",
"type": "text",
"primaryKey": false,
"notNull": true
},
"comercio_razon_social": {
"name": "comercio_razon_social",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_bandera_nombre": {
"name": "comercio_bandera_nombre",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_bandera_url": {
"name": "comercio_bandera_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"comercio_ultima_actualizacion": {
"name": "comercio_ultima_actualizacion",
"type": "date",
"primaryKey": false,
"notNull": false
},
"comercio_version_sepa": {
"name": "comercio_version_sepa",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"banderas_id_dataset_datasets_id_fk": {
"name": "banderas_id_dataset_datasets_id_fk",
"tableFrom": "banderas",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"banderas_id_dataset": {
"name": "banderas_id_dataset",
"nullsNotDistinct": false,
"columns": [
"id_dataset"
]
}
}
},
"public.datasets": {
"name": "datasets",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"datasets_name_key": {
"name": "datasets_name_key",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
}
},
"public.precios": {
"name": "precios",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_sucursal": {
"name": "id_sucursal",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_producto": {
"name": "id_producto",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"productos_ean": {
"name": "productos_ean",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"productos_descripcion": {
"name": "productos_descripcion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_cantidad_presentacion": {
"name": "productos_cantidad_presentacion",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_unidad_medida_presentacion": {
"name": "productos_unidad_medida_presentacion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_marca": {
"name": "productos_marca",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_lista": {
"name": "productos_precio_lista",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_precio_referencia": {
"name": "productos_precio_referencia",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_cantidad_referencia": {
"name": "productos_cantidad_referencia",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_unidad_medida_referencia": {
"name": "productos_unidad_medida_referencia",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_unitario_promo1": {
"name": "productos_precio_unitario_promo1",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_leyenda_promo1": {
"name": "productos_leyenda_promo1",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_precio_unitario_promo2": {
"name": "productos_precio_unitario_promo2",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"productos_leyenda_promo2": {
"name": "productos_leyenda_promo2",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"idx_precios_id_producto": {
"name": "idx_precios_id_producto",
"columns": [
{
"expression": "id_producto",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"idx_precios_id_producto_id_dataset": {
"name": "idx_precios_id_producto_id_dataset",
"columns": [
{
"expression": "id_producto",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"idx_precios_id_producto_id_comercio_id_sucursal": {
"name": "idx_precios_id_producto_id_comercio_id_sucursal",
"columns": [
{
"expression": "id_producto",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_comercio",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id_sucursal",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"precios_id_dataset_datasets_id_fk": {
"name": "precios_id_dataset_datasets_id_fk",
"tableFrom": "precios",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.productos_descripcion_index": {
"name": "productos_descripcion_index",
"schema": "",
"columns": {
"id_producto": {
"name": "id_producto",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"productos_descripcion": {
"name": "productos_descripcion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"productos_marca": {
"name": "productos_marca",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"productos_descripcion_index_search_descripcion": {
"name": "productos_descripcion_index_search_descripcion",
"columns": [
{
"expression": "to_tsvector('spanish', \"productos_descripcion\")",
"asc": true,
"isExpression": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"productos_descripcion_index_productos_descripcion_unique": {
"name": "productos_descripcion_index_productos_descripcion_unique",
"nullsNotDistinct": false,
"columns": [
"productos_descripcion"
]
}
}
},
"public.sucursales": {
"name": "sucursales",
"schema": "",
"columns": {
"id_dataset": {
"name": "id_dataset",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_comercio": {
"name": "id_comercio",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_bandera": {
"name": "id_bandera",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"id_sucursal": {
"name": "id_sucursal",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"sucursales_nombre": {
"name": "sucursales_nombre",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_tipo": {
"name": "sucursales_tipo",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_calle": {
"name": "sucursales_calle",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_numero": {
"name": "sucursales_numero",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_latitud": {
"name": "sucursales_latitud",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"sucursales_longitud": {
"name": "sucursales_longitud",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"sucursales_observaciones": {
"name": "sucursales_observaciones",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_barrio": {
"name": "sucursales_barrio",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_codigo_postal": {
"name": "sucursales_codigo_postal",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_localidad": {
"name": "sucursales_localidad",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_provincia": {
"name": "sucursales_provincia",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_lunes_horario_atencion": {
"name": "sucursales_lunes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_martes_horario_atencion": {
"name": "sucursales_martes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_miercoles_horario_atencion": {
"name": "sucursales_miercoles_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_jueves_horario_atencion": {
"name": "sucursales_jueves_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_viernes_horario_atencion": {
"name": "sucursales_viernes_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_sabado_horario_atencion": {
"name": "sucursales_sabado_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sucursales_domingo_horario_atencion": {
"name": "sucursales_domingo_horario_atencion",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"sucursales_id_dataset_datasets_id_fk": {
"name": "sucursales_id_dataset_datasets_id_fk",
"tableFrom": "sucursales",
"tableTo": "datasets",
"columnsFrom": [
"id_dataset"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"sucursales_id_dataset_id_comercio_id_bandera_id_sucursal_key": {
"name": "sucursales_id_dataset_id_comercio_id_bandera_id_sucursal_key",
"nullsNotDistinct": false,
"columns": [
"id_dataset",
"id_comercio",
"id_bandera",
"id_sucursal"
]
}
}
}
},
"enums": {},
"schemas": {},
"sequences": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View file

@ -50,6 +50,20 @@
"when": 1727016580605, "when": 1727016580605,
"tag": "0006_short_ravenous", "tag": "0006_short_ravenous",
"breakpoints": true "breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1727018495637,
"tag": "0007_wandering_marvel_boy",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1727019109117,
"tag": "0008_mixed_sentinels",
"breakpoints": true
} }
] ]
} }

View file

@ -19,6 +19,7 @@
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6",
"@tailwindcss/typography": "^0.5.15", "@tailwindcss/typography": "^0.5.15",
"@types/d3-scale": "^4.0.8",
"@types/eslint": "^9.6.0", "@types/eslint": "^9.6.0",
"@types/leaflet": "^1.9.12", "@types/leaflet": "^1.9.12",
"@types/leaflet.markercluster": "^1.5.4", "@types/leaflet.markercluster": "^1.5.4",
@ -46,8 +47,11 @@
"@types/node": "^22.5.0", "@types/node": "^22.5.0",
"bits-ui": "^0.21.13", "bits-ui": "^0.21.13",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"d3-array": "^3.2.4",
"d3-scale": "^4.0.2",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"drizzle-orm": "^0.33.0", "drizzle-orm": "^0.33.0",
"layerchart": "^0.44.0",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"lucide-svelte": "^0.441.0", "lucide-svelte": "^0.441.0",

View file

@ -0,0 +1,30 @@
export function processBanderaNombre(comercio: {
comercio_cuit?: string | null;
comercio_bandera_nombre?: string | null;
}) {
if (
comercio.comercio_cuit === '30687310434' &&
!comercio.comercio_bandera_nombre?.includes('Carrefour')
) {
return `Carrefour ${comercio.comercio_bandera_nombre}`;
}
if (comercio.comercio_cuit === '30678774495') {
return `YPF ${comercio.comercio_bandera_nombre}`;
}
return comercio.comercio_bandera_nombre;
}
export function generateGoogleMapsLink(sucursal: {
sucursales_calle: string;
sucursales_numero?: string | null;
}) {
const params = new URLSearchParams({
query: `${sucursal.sucursales_calle} ${sucursal.sucursales_numero}`
});
return `https://www.google.com/maps/search/?api=1&${params.toString()}`;
}
export const pesosFormatter = new Intl.NumberFormat('es-AR', {
style: 'currency',
currency: 'ARS'
});

View file

@ -4,13 +4,9 @@
import Map from '$lib/components/Map.svelte'; import Map from '$lib/components/Map.svelte';
import Badge from '$lib/components/ui/badge/badge.svelte'; import Badge from '$lib/components/ui/badge/badge.svelte';
import {} from '$app/navigation'; import {} from '$app/navigation';
import { generateGoogleMapsLink, pesosFormatter, processBanderaNombre } from '$lib/sepa-utils';
export let data: PageData; export let data: PageData;
const pesosFormatter = new Intl.NumberFormat('es-AR', {
style: 'currency',
currency: 'ARS'
});
</script> </script>
<svelte:head> <svelte:head>
@ -57,28 +53,31 @@
const createElement = () => { const createElement = () => {
const div = document.createElement('div'); const div = document.createElement('div');
let banderaNombre = precio.comercio_bandera_nombre;
if (precio.comercio_cuit === '30687310434' && !banderaNombre?.includes('Carrefour')) {
banderaNombre = `Carrefour ${banderaNombre}`;
}
[ [
`fecha del precio: ${precio.dataset_date}`, `fecha del precio: ${precio.dataset_date}`,
`precio: ${pesosFormatter.format(precio.productos_precio_lista)}`, `precio: ${pesosFormatter.format(precio.productos_precio_lista)}`,
`comercio: ${banderaNombre} (${precio.comercio_razon_social} CUIT ${precio.comercio_cuit})`, `comercio: ${processBanderaNombre(precio)} (${precio.comercio_razon_social} CUIT ${precio.comercio_cuit})`,
`sucursal: ${precio.sucursales_nombre}`, `sucursal: ${precio.sucursales_nombre}`,
`dirección: ${precio.sucursales_calle} ${precio.sucursales_numero}`, `dirección: ${precio.sucursales_calle} ${precio.sucursales_numero}`,
() => { () => {
const a = document.createElement('a'); const a = document.createElement('a');
const params = new URLSearchParams({ if (precio.sucursales_calle) {
query: `${precio.sucursales_calle} ${precio.sucursales_numero}` a.href = generateGoogleMapsLink({
}); sucursales_calle: precio.sucursales_calle,
a.href = `https://www.google.com/maps/search/?api=1&${params.toString()}`; sucursales_numero: precio.sucursales_numero
});
}
a.target = '_blank'; a.target = '_blank';
a.append('ver en Google Maps'); a.append('ver en Google Maps');
return a; return a;
}, },
`descripcion del producto segun el comercio: ${precio.productos_descripcion}` `descripcion del producto segun el comercio: ${precio.productos_descripcion}`,
() => {
const a = document.createElement('a');
a.href = `/id_producto/${data.id_producto}/sucursal/${precio.id_comercio}/${precio.id_sucursal}`;
a.append('ver precios historicos');
return a;
}
].forEach((el) => { ].forEach((el) => {
div.append(typeof el === 'function' ? el() : el); div.append(typeof el === 'function' ? el() : el);
div.append(document.createElement('br')); div.append(document.createElement('br'));

View file

@ -0,0 +1,59 @@
import { precios, sucursales } from '$lib/server/db/schema';
import { and, eq } from 'drizzle-orm';
import type { PageServerLoad } from './$types';
import * as Sentry from '@sentry/sveltekit';
import { db } from '$lib/server/db';
export const load: PageServerLoad = async ({ params, setHeaders }) => {
const id = BigInt(params.id);
const id_comercio = parseInt(params.id_comercio);
const id_sucursal = parseInt(params.id_sucursal);
const sucursalQuery = db.query.sucursales.findFirst({
where: and(eq(sucursales.id_comercio, id_comercio), eq(sucursales.id_sucursal, id_sucursal)),
with: {
bandera: true
},
orderBy: (sucursales, { desc }) => [desc(sucursales.id_dataset)]
});
const sucursal = await Sentry.startSpan(
{
op: 'db.query',
name: sucursalQuery.toSQL().sql,
data: { 'db.system': 'postgresql' }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
() => sucursalQuery
);
const preciosHistoricosQuery = db.query.precios.findMany({
where: and(
eq(precios.id_producto, id),
eq(precios.id_comercio, id_comercio),
eq(precios.id_sucursal, id_sucursal)
),
with: {
dataset: true
}
});
const preciosHistoricosUncasted = await Sentry.startSpan(
{
op: 'db.query',
name: preciosHistoricosQuery.toSQL().sql,
data: { 'db.system': 'postgresql' }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
() => preciosHistoricosQuery
);
const preciosHistoricos = preciosHistoricosUncasted.map((precio) => ({
...precio,
productos_precio_lista:
precio.productos_precio_lista && parseFloat(precio.productos_precio_lista)
}));
setHeaders({
'Cache-Control': 'public, max-age=600'
});
return { preciosHistoricos, sucursal };
};

View file

@ -0,0 +1,88 @@
<script lang="ts">
import { format } from 'date-fns';
import type { PageData } from './$types';
import { Chart, Svg, Axis, Spline, Highlight, Tooltip, TooltipItem } from 'layerchart';
import { scaleTime } from 'd3-scale';
import { ArrowLeft } from 'lucide-svelte';
import { generateGoogleMapsLink, pesosFormatter, processBanderaNombre } from '$lib/sepa-utils';
import { MapPin } from 'lucide-svelte';
import Button from '$lib/components/ui/button/button.svelte';
import { es } from 'date-fns/locale';
export let data: PageData;
$: dateSeriesData = data.preciosHistoricos
.map((precio) => ({
date: precio.dataset?.date ? new Date(precio.dataset?.date) : null,
value: precio.productos_precio_lista
}))
.filter((precio): precio is { date: Date; value: number } => !!precio.date)
.sort((a, b) => a.date.getTime() - b.date.getTime());
$: latestPrice = dateSeriesData[dateSeriesData.length - 1].value;
</script>
<div>
<div class="max-w-screen flex items-stretch gap-3 overflow-hidden px-2">
<button on:click={() => window.history.back()}>
<ArrowLeft class="size-8 flex-shrink-0" />
</button>
<div class="flex flex-wrap items-center gap-x-2 overflow-hidden p-1">
<h1 class="overflow-hidden text-ellipsis whitespace-nowrap pb-1 text-2xl font-bold">
{data.preciosHistoricos[0].productos_descripcion}
</h1>
</div>
</div>
<p class="px-4 py-2">
Viendo precios del <strong
>{data.sucursal?.bandera && processBanderaNombre(data.sucursal?.bandera)}</strong
>
en la sucursal <strong>"{data.sucursal?.sucursales_nombre}"</strong>
{#if data.sucursal?.sucursales_calle}
en {data.sucursal?.sucursales_calle}
{data.sucursal?.sucursales_numero}
{/if}
</p>
<div class="flex flex-col px-4 py-2">
<span class="text-sm">Precio actual:</span>
<span class="text-2xl font-bold">{pesosFormatter.format(latestPrice)}</span>
</div>
<div class="flex gap-2 px-4 py-2">
{#if data.sucursal?.sucursales_calle}
<Button
href={generateGoogleMapsLink({
sucursales_calle: data.sucursal?.sucursales_calle,
sucursales_numero: data.sucursal?.sucursales_numero
})}
target="_blank"
variant="outline"
size="sm"
class="inline-flex items-center gap-1"
>
<MapPin class="size-4" />
Google Maps
</Button>
{/if}
</div>
<div class="h-[300px] border-y p-4">
<Chart
data={dateSeriesData}
x="date"
xScale={scaleTime()}
y="value"
yDomain={[0, null]}
yNice
padding={{ left: 16, bottom: 24 }}
tooltip={{ mode: 'bisect-x' }}
>
<Svg>
<Axis placement="left" grid rule />
<Axis placement="bottom" format={(d) => format(d, 'dd/MM', { locale: es })} rule />
<Spline class="stroke-primary stroke-2" />
<Highlight points lines />
</Svg>
<Tooltip header={(data) => format(data.date, 'eee, MMMM do', { locale: es })} let:data>
<TooltipItem label="value" value={data.value} />
</Tooltip>
</Chart>
</div>
</div>

View file

@ -4,7 +4,7 @@ import typography from '@tailwindcss/typography';
const config: Config = { const config: Config = {
darkMode: ['class'], darkMode: ['class'],
content: ['./src/**/*.{html,js,svelte,ts}'], content: ['./src/**/*.{html,js,svelte,ts}', '../node_modules/layerchart/**/*.{svelte,js}'],
safelist: ['dark'], safelist: ['dark'],
theme: { theme: {
container: { container: {
@ -48,6 +48,13 @@ const config: Config = {
card: { card: {
DEFAULT: 'hsl(var(--card) / <alpha-value>)', DEFAULT: 'hsl(var(--card) / <alpha-value>)',
foreground: 'hsl(var(--card-foreground) / <alpha-value>)' foreground: 'hsl(var(--card-foreground) / <alpha-value>)'
},
surface: {
content: 'hsl(var(--card-foreground) / <alpha-value>)',
100: 'hsl(var(--background) / <alpha-value>)',
200: 'hsl(var(---muted) / <alpha-value>)',
// not sure what color maps here (should be darker than 200). Could add a new color to `app.css`
300: 'hsl(var(--background) / <alpha-value>)'
} }
}, },
borderRadius: { borderRadius: {