diff --git a/backend/controller/PurchaseController.js b/backend/controller/PurchaseController.js index 1f6e322..f4a6654 100644 --- a/backend/controller/PurchaseController.js +++ b/backend/controller/PurchaseController.js @@ -31,9 +31,35 @@ const PurchaseService = require("../service/PurchaseService"); * /api/purchases/: * get: * summary: Get list of purchases - * description: Retrieve a list of all purchases with details such as email, birth date, purchase date, meet date, and price. - * tags: - * - Purchases + * description: Retrieve a list of all purchases with optional filters by date. + * tags: [Purchases] + * parameters: + * - in: query + * name: page + * schema: + * type: int32 + * required: false + * description: Page number + * - in: query + * name: limit + * schema: + * type: int32 + * required: false + * description: Limit + * - in: query + * name: startDate + * schema: + * type: string + * format: date + * required: false + * description: Filter purchases from this start date (inclusive). + * - in: query + * name: endDate + * schema: + * type: string + * format: date + * required: false + * description: Filter purchases up to this end date (inclusive). * responses: * '200': * description: A list of purchases @@ -114,101 +140,34 @@ router.post('/', async (req, res) => { const savedPurchase = await PurchaseService.save(purchase); res.json(savedPurchase); } catch (error) { - res.status(500).json({error: error.message}); + res.status(500).json({ error: error.message }); } }); router.get('/', async (req, res) => { try { - const purchases = [ - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'test@test.com', - birthDate: '01/01/2000', - purchaseDate: '01/01/2021', - meetDate: '01/01/2021', - price: 15 - }, - { - email: 'jane@test.com', - birthDate: '05/05/1998', - purchaseDate: '02/02/2022', - meetDate: '01/01/2021', - price: 15 - } - ] - res.json(purchases); + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const startDate = req.query.startDate ? new Date(req.query.startDate) : null; + const endDate = req.query.endDate ? new Date(req.query.endDate) : null; + + const { totalItems, totalPages, currentPage, itemsPerPage, purchases } = await PurchaseService.getPaginatedPurchases(page, limit, startDate, endDate); + + const paginationInfo = { + currentPage, + itemsPerPage, + totalItems, + totalPages, + hasNextPage: currentPage < totalPages, + hasPreviousPage: currentPage > 1 + }; + + res.json({ + paginationInfo, + data: purchases + }); } catch (error) { - res.status(500).json({error: error.message}); + res.status(500).json({ error: error.message }); } }); diff --git a/backend/service/PurchaseService.js b/backend/service/PurchaseService.js index 1423c6f..1f2bdaa 100644 --- a/backend/service/PurchaseService.js +++ b/backend/service/PurchaseService.js @@ -1,39 +1,67 @@ -const format = require('date-fns/format'); -const purchaseRepository = require('../persistance/PurchaseRepository') -const meetRepository = require('../persistance/MeetRepository') +const purchaseRepository = require('../persistance/PurchaseRepository'); +const meetRepository = require('../persistance/MeetRepository'); const userRepository = require("../persistance/UserRepository"); -const mailerService = require('./MailerService') -const invoiceMakerService = require('./InvoiceMakerService') -const PurchaseService = {} +const {Op, Sequelize} = require('sequelize'); +const PurchaseService = {}; PurchaseService.save = async function (purchase) { - const meet = await meetRepository.findByPk(purchase.meetId) - const user = await userRepository.findByPk(purchase.userId) - const newPurchase = await purchaseRepository.create({ + const meet = await meetRepository.findByPk(purchase.meetId); + const user = await userRepository.findByPk(purchase.userId); + return await purchaseRepository.create({ userId: user.id, meetId: meet.id, price: meet.price, - purchaseDate: new Date() - }) + purchaseDate: new Date(), + }); +}; - const dataForPdf = { - id: newPurchase.id, - purchaseDate: format(newPurchase.purchaseDate, 'dd/MM/yyyy HH:mm'), - price: meet.price, - items: [ - {product: "Clase de Karate", quantity: 1, cost: meet.price} - ] +PurchaseService.getPaginatedPurchases = async function (page = 1, limit = 10, startDate = null, endDate = null) { + const offset = (page - 1) * limit; + + // Crear el objeto de filtrado por fecha si se proporcionan fechas válidas + const whereConditions = {}; + + if (startDate) { + const startOfDay = new Date(startDate); + startOfDay.setHours(0, 0, 0, 0); // 00:00:00.000 + + // Aplicar el filtro sobre la tabla Meet + whereConditions['$Meet.meetDate$'] = {[Op.gte]: startOfDay}; } - const invoicePdf = await invoiceMakerService.generateInvoicePdf(dataForPdf) - await mailerService.sendMail( - user.email, - 'Purchase confirmation', - 'Your purchase has been processed', - 'Your purchase has been processed', - invoicePdf) + if (endDate) { + const endOfDay = new Date(endDate); + endOfDay.setHours(23, 59, 59, 999); // 23:59:59.999 + + // Aplicar el filtro sobre la tabla Meet + whereConditions['$Meet.meetDate$'] = { + ...whereConditions['$Meet.meetDate$'], + [Op.lte]: endOfDay + }; + } + + // Consultar las compras con los filtros de fecha sobre Meet.meetDate, paginación y contar el total de registros + const {count, rows: purchases} = await purchaseRepository.findAndCountAll({ + where: whereConditions, // Filtrar por las fechas en la tabla Meet + include: [ + {model: userRepository, attributes: ['id', 'email']}, + {model: meetRepository, attributes: ['id', 'meetDate']} + ], + offset: offset, + limit: limit, + order: [['purchaseDate', 'DESC']], // Ordenar por fecha de compra descendente + }); + + // Calcular la información de paginación + const totalPages = Math.ceil(count / limit); - return newPurchase -} + return { + totalItems: count, + totalPages: totalPages, + currentPage: page, + itemsPerPage: limit, + purchases: purchases, + }; +}; -module.exports = PurchaseService \ No newline at end of file +module.exports = PurchaseService; diff --git a/frontend/src/components/table/PurchasesTable.jsx b/frontend/src/components/table/PurchasesTable.jsx index e9a7509..b17db04 100644 --- a/frontend/src/components/table/PurchasesTable.jsx +++ b/frontend/src/components/table/PurchasesTable.jsx @@ -2,27 +2,48 @@ import {useState} from "react"; import {DataTable} from 'primereact/datatable'; import {Column} from 'primereact/column'; import {Calendar} from "primereact/calendar"; -import 'primereact/resources/themes/saga-blue/theme.css'; // Elige el tema que prefieras +import 'primereact/resources/themes/saga-blue/theme.css'; import 'primereact/resources/primereact.min.css'; import 'primeicons/primeicons.css'; -import {Button} from "primereact/button"; import useGetPurchases from "../../hooks/useGetPurchases"; import {hasSession, isUser} from "../../utils/session"; +import {format} from 'date-fns'; export default function PurchasesTable() { const userSession = hasSession(); const isUserValue = isUser(); - const {purchases, error} = useGetPurchases(isUserValue, userSession); - const [selectedStartDate, setSelectedStartDate] = useState(new Date()); - const [selectedEndDate, setSelectedEndDate] = useState(new Date()); - function searchMeet() { - console.log('Meet saved'); - } + const [page, setPage] = useState(1); + const [rowsPerPage, setRowsPerPage] = useState(4); + + const [selectedStartDate, setSelectedStartDate] = useState(null); // Se inicia como null para no filtrar inicialmente + const [selectedEndDate, setSelectedEndDate] = useState(null); + + const {purchases, totalRecords, error} = useGetPurchases(isUserValue, userSession, page, rowsPerPage, selectedStartDate, selectedEndDate); + + const onPageChange = (event) => { + setPage(event.page + 1); // PrimeReact usa índices basados en 0 + setRowsPerPage(event.rows); // Actualizar el número de filas por página + }; + + const formatDate = (dateString) => { + return format(new Date(dateString), 'dd/MM/yyyy'); + }; + + const purchaseDateTemplate = (rowData) => { + return formatDate(rowData.purchaseDate); + }; + + const meetDateTemplate = (rowData) => { + return formatDate(rowData.Meet.meetDate); + }; return (