Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

DATABASE_URL="postgresql://postgres:admin@localhost:5432/postgres"

1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text eol=lf
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## <1.0.0> - <2023-09-2023>

### Sprint Learnings

+ 1. Fundamentos de Desarrollo de API Node.js y PostgreSQL

- Conexión a la base de datos PostgreSQL
- Modelado de datos en PostgreSQL
- Operaciones CRUD básicas con PostgreSQL
- Uso de pgAdmin4 para administrar la base de datos PostgreSQL
- Uso de Postman para pruebas de API y solicitudes HTTP
- Módulos de CommonJS y ECMAScript (ES Modules)
- Uso de identificadores descriptivos en JavaScript

+ 2. Gestión de Versiones

- Git: Integración de cambios entre ramas
- Git: Control de versiones con git
- Git: Instalación y configuración
- Colaboración en GitHub (branches, forks, pull requests, code review, tags)
- Organización en GitHub (projects, issues, labels, milestones, releases)
- Creación de cuenta y repositorios en GitHub, configuración de llaves SSH

### Added

Integracion con Prisma

### Changed

Schema model users, model orders, model orders_products, model Products


5 changes: 2 additions & 3 deletions config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
exports.port = process.argv[2] || process.env.PORT || 8080;
exports.dbUrl = process.env.MONGO_URL || process.env.DB_URL || 'mongodb://127.0.0.1:27017/test';
exports.dbUrl = process.env.MONGO_URL || process.env.DB_URL || 'postgresql://postgres:admin@localhost:5432/postgres';
exports.secret = process.env.JWT_SECRET || 'esta-es-la-api-burger-queen';
exports.adminEmail = process.env.ADMIN_EMAIL || 'admin@localhost';
exports.adminPassword = process.env.ADMIN_PASSWORD || 'changeme';
exports.adminPassword = process.env.ADMIN_PASSWORD || 'admin';
13 changes: 8 additions & 5 deletions connect.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const config = require('./config');

// eslint-disable-next-line no-unused-vars
const { dbUrl } = config;
const { dbUrl } = require('./config');

async function connect() {
// TODO: Conexión a la Base de Datos
try {
await dbUrl.$connect();
console.info('Conexión con la base de datos exitosa.');
} catch (error) {
console.error('Error no se establecido conexión con la base de datos', error);
throw error;
}
}

module.exports = { connect };
58 changes: 58 additions & 0 deletions controller/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* eslint-disable max-len */
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const { secret } = require('../config');
const { setGlobalToken } = require('../middleware/tokenStorage');

module.exports = {
postAuth: async (req, resp) => {
console.info('Solicitud de inicio de sesion recibida');
const { email, password } = req.body;

if (!email || !password) {
resp.status(400).json({ error: 'Tu Email y Password son requeridos' });
}

const user = await prisma.users.findUnique({
where: {
email,
},
});

if (!user) {
resp.status(404).json({ message: 'User Not found' });
}

// -----
// const passwordnew = '$2b$12$kWnYNePujvMYgGG7FjANg.0jqf1BqTNa7ii/FauLcPNWMgQjp.BIC';
// const isPasswordMatch = bcrypt.compareSync('admin', passwordnew);

// if (isPasswordMatch) {
// resp.json('ok');
// } else {
// resp.json('no son iguales');
// }

// --------

// Comprobar si la contraseña proporcionada coincide con la contraseña almacenada en la base de datos
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
resp.status(404).json({ message: 'Not found' });
}

// Generar un token JWT con la información del usuario
const token = jwt.sing({ email: user.email, role: user.Role }, secret, {
expiresIn: '1h',
});

console.info('Token generado:', token);
// Almacenar el token en un lugar adecuado
setGlobalToken(token);

resp.status(200).json({ token });
},
};
260 changes: 260 additions & 0 deletions controller/orders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
/* eslint-disable max-len */
/* eslint-disable radix */
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

module.exports = {
getOrders: async (req, resp, next) => {
try {
const orders = await prisma.orders.findMany({
where: {
isActive: true,
},
include: {
Products: {
select: {
quantity: true,
id: true,
Products: {
select: {
name: true,
price: true,
image: true,
type: true,
updateAt: true,
},
},
},
},
},
});

const ordersWtihStatus = orders.map((order) => ({
id: order.id,
UserId: order.id,
client: order.client,
status: order.status,
updateAt: order.updateAt,
...(order.status === 'delivered' && {
dateProcessed: order.dateProcessed,
}),
Products: order.Products.map((product) => ({
id: product.id,
quantity: product.quantity,
product: product.Products,
})),
}));

resp.status(200).json(ordersWtihStatus);
} catch (error) {
next(error);
}
},

getOrderById: async (req, resp, next) => {
try {
const { id: orderId } = req.params;

const orders = await prisma.orders.findUnique({
where: {
id: parseInt(orderId),
},
include: {
Products: {
select: {
quantity: true,
id: true,
Products: {
select: {
name: true,
price: true,
image: true,
type: true,
updateAt: true,
},
},
},
},
},
});

resp.status(200).json(orders);
} catch (error) {
next(error);
}
},

createOrder: async (req, resp, next) => {
try {
const { UserId, client, Products } = req.body;

// console.info('UserId:', UserId);
// console.info('client:', client);
// console.info('products:', Products);

if (!UserId || !client || !Products /* || !Products.length */) {
resp.status(400).json({ message: 'Datos incompletos en la solicitud' });
}

const existingUser = await prisma.users.findUnique({
where: {
id: UserId,
},
});

console.info('existing:', existingUser);

if (!existingUser) {
resp.status(404).json({ message: `User con ID ${UserId} no encontrado` });
}

// Crear order
const order = await prisma.orders.create({
data: {
UserId,
client,
status: 'pending',
updateAt: new Date(),
},
});

console.info('order:', order);

// Agregar productos a la order
await Promise.all(
Products.map(async (productData) => {
const { quantity, product } = productData;
const existingProduct = await prisma.products.findUnique({
where: { id: product.id },
});

if (!existingProduct) {
resp.status(404).json({ message: `Producto con ID ${product.id} no encontrado` });
}

await prisma.ordersProducts.create({
data: {
OrderId: order.id,
ProductId: existingProduct.id,
quantity,
},
});
}),
);

// Obtener la order con detalles de productos
const orderWithProducts = await prisma.orders.findUnique({
where: { id: order.id },
include: {
Products: {
select: {
id: true,
name: true,
image: true,
price: true,
},
througth: { // Relaciona la tabla asociada OrdersProducts y permite usar esos datos en comun
select: {
quantity: true,
},
},
},
},
select: {
id: true,
UserId: true,
client: true,
status: true,
updateAt: true,
dateProcessed: true,
},
});

// Preparar la respuesta
const responseOrder = {
id: orderWithProducts.id,
UserId: orderWithProducts.id,
client: orderWithProducts.id,
status: orderWithProducts.status,
updateAt: orderWithProducts.updateAt,
Products: orderWithProducts.Products,
};

if (orderWithProducts.dateProcessed !== null) {
responseOrder.dateProcessed = orderWithProducts.dateProcessed;
}

// Enviar respuesta exitosa
resp.status(200).json(responseOrder);
} catch (error) {
next(error);
} finally {
await prisma.$disconnect();
}
},

updateOrder: async (req, resp, next) => {
try {
const { id: orderId } = req.params;
const { status } = req.body;

const statusValues = ['pending', 'canceled', 'delivering', 'delivered'];
if (!statusValues.includes(status)) {
resp.status(400).json({
message: `Ingresar status: ${statusValues.join(', ')}`,
});
}

const order = await prisma.order.update({
where: { id: parseInt(orderId) },
data: {
status,
dateProcessed: status === 'delivered' ? new Date() : null,
},
});

const responseOrder = {
id: order.id,
UserId: order.UserId,
client: order.client,
status: order.status,
updateAt: order.updateAt,
dateProcessed: order.dateProcessed,
};

resp.status(200).json(responseOrder);
} catch (error) {
next(error);
}
},

deleteOrder: async (req, resp, next) => {
const { id: orderId } = req.params;
try {
const inactiveOrder = await prisma.orders.update({
where: { id: parseInt(orderId) },
data: { isActive: false },
});

if (!inactiveOrder) {
resp.status(404).json({ message: 'Order Not Found' });
} else {
resp.status(200).json({
Product: {
id: inactiveOrder.id,
isActive: false,
name: inactiveOrder.name,
price: inactiveOrder.price,
image: inactiveOrder.image,
type: inactiveOrder.type,
updateAt: inactiveOrder.updateAt,
},
message: 'Eliminación exitosa',
});
}
} catch (error) {
next(error);
}
},
};
Loading