Gestión de Combos en la Aplicación de Comida Rápida Reiji

  1. Creación de Nuevos Combos

1.1 Análisis de Requisitos

Un combo es esencialmente una colección de platos. El sistema de administración backend permite gestionar la información de los combos. La función de añadir un nuevo combo permite registrar uno nuevo. Al crear un combo, es necesario seleccionar la categoría a la que pertenece y los platos que lo componen. Además, se debe cargar una imagen representativa. La aplicación móvil mostrará los combos agrupados por categoría.

1.2 Modelo de Datos

  • setmeal: Tabla de combos.
  • setmeal_dish: Tabla de relación entre combos y platos.

1.3 Desarrollo de Código

Se deben crear las clases, interfaces y controladores básicos.

  • Entidad SetmealDish (importada de los recursos del curso).
  • Entidad Setmeal (previamente importada en lecciones anteriores).
  • DTO SetmealDto (importado de los recursos del curso).
  • Interfaz Mapper SetmealDishMapper.
  • Interfaz de Servicio SetmealDishService.
  • Clase de Implementación de Servicio SetmealDishServiceImpl.
  • Controlador SetmealController.

Proceso de interacción entre la interfaz de usuario y el backend:

  1. La página (backend/page/combo/add.html) envía una solicitud AJAX para obtener las categorías de combos y mostrarlas en un menú desplegable.
  2. La página envía una solicitud AJAX para obtener las categorías de platos y mostrarlas en una ventana para añadir platos.
  3. La página envía una solicitud AJAX para consultar los datos de los platos correspondientes según la categoría seleccionada y mostrarlos en la ventana de adición de platos.
  4. La página envía una solicitud para subir una imagen, y el backend la guarda en el servidor.
  5. La página envía una solicitud para descargar la imagen, mostrando la imagen cargada previamente.
  6. Al hacer clic en el botón de guardar, se envía una solicitud AJAX con los datos del combo en formato JSON al backend.

Solicitud al backend para obtener datos de categorías de platos y mostrarlos en la ventana de adición de platos:


   /**
    * Consulta de datos de platos según criterios.
    * @param dish Objeto Dish con criterios de búsqueda.
    * @return Respuesta genérica con lista de platos.
    */
   @GetMapping("list")
   public R<list>> list(Dish dish) {
       // Construcción de la consulta
       LambdaQueryWrapper<dish> queryWrapper = new LambdaQueryWrapper<>();
       // Condición: si categoryId no es nulo, igualar categoryId
       queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
       // Condición: consultar platos con estado 1 (disponibles)
       queryWrapper.eq(Dish::getStatus, 1);
       // Condición de ordenación: ascendente por sort, descendente por updateTime
       queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

       List<dish> dishList = dishService.list(queryWrapper);

       return R.success(dishList);
   }
   </dish></dish></list>

Envío de datos del combo en formato JSON al backend:


   @RestController
   @RequestMapping("setmeal")
   @Slf4j
   public class SetmealController {

       @Autowired
       private SetmealService setmealService;

       @Autowired
       private SetmealDishService setmealDishService;

       /**
        * Crea un nuevo combo.
        * @param setmealDto DTO que contiene la información del combo y sus platos asociados.
        * @return Respuesta genérica indicando el resultado de la operación.
        */
       @PostMapping
       public R<string> save(@RequestBody SetmealDto setmealDto) {
           log.info("Información del combo: {}", setmealDto);
           setmealService.saveWithDish(setmealDto);
           return R.success("Combo creado exitosamente!");
       }
   }
   </string>

   @Service
   public class SetmealServiceImpl extends ServiceImpl<setmealmapper setmeal="">
           implements SetmealService {

       @Autowired
       private SetmealDishService setmealDishService;

       /**
        * Guarda la información básica del combo y las relaciones con los platos.
        * @param setmealDto DTO con la información del combo y sus platos.
        */
       @Override
       @Transactional
       public void saveWithDish(SetmealDto setmealDto) {
           // Guarda la información básica del combo
           this.save(setmealDto);

           // Obtiene la lista de platos asociados al combo
           List<setmealdish> setmealDishes = setmealDto.getSetmealDishes();
           // Asigna el ID del combo a cada plato asociado
           setmealDishes.stream().map((dish) -> {
               dish.setSetmealId(setmealDto.getId());
               return dish;
           }).collect(Collectors.toList());
           // Guarda las relaciones entre el combo y los platos
           setmealDishService.saveBatch(setmealDishes);
       }
   }
   </setmealdish></setmealmapper>
  1. Consulta de Combos con Paginación

2.1 Análisis de Requisitos

Cuando la cantidad de combos en el sistema es grande, mostrarlos todos en una sola página puede ser confuso y dificultar la visualización. Por lo tanto, los sistemas suelen implementar paginación para mostrar listas de datos.

2.2 Desarrollo de Código

Proceso de interacción entre la interfaz de usuario y el backend:

  1. La página (backend/page/combo/list.html) envía una solicitud AJAX con parámetros de paginación (page, pageSize, name) al backend para obtener los datos paginados.
  2. La página envía una solicitud para descargar la imagen, utilizada para la visualización en la página.

Consulta paginada:


   /**
    * Consulta paginada de combos.
    * @param page Número de página.
    * @param pageSize Número de elementos por página.
    * @param name Nombre del combo para filtrar (búsqueda difusa).
    * @return Respuesta genérica con la página de combos y sus detalles.
    */
   @GetMapping("page")
   public R<page> page(int page, int pageSize, String name) {
       // Constructor de paginación
       Page<setmeal> setmealPage = new Page<>(page, pageSize);
       // DTO para la paginación de combos
       Page<setmealdto> setmealDtoPage = new Page<>();

       // Constructor de consulta Lambda
       LambdaQueryWrapper<setmeal> queryWrapper = new LambdaQueryWrapper<>();
       // Condición de filtro: búsqueda difusa por nombre
       queryWrapper.like(name != null, Setmeal::getName, name);
       // Condición de ordenación: descendente por fecha de actualización
       queryWrapper.orderByDesc(Setmeal::getUpdateTime);

       // Realiza la consulta paginada
       setmealService.page(setmealPage, queryWrapper);

       // Copia las propiedades generales de la paginación
       BeanUtils.copyProperties(setmealPage, setmealDtoPage, "records");
       // Obtiene la lista de combos de la página actual
       List<setmeal> records = setmealPage.getRecords();

       // Mapea los combos a DTOs, incluyendo el nombre de la categoría
       List<setmealdto> dtoList = records.stream().map((item) -> {
           SetmealDto setmealDto = new SetmealDto();
           // Copia las propiedades del combo al DTO
           BeanUtils.copyProperties(item, setmealDto);
           // Obtiene el ID de la categoría
           Long categoryId = item.getCategoryId();
           // Consulta el objeto de categoría por su ID
           Category category = categoryService.getById(categoryId);
           if (category != null) {
               // Asigna el nombre de la categoría al DTO
               String categoryName = category.getName();
               setmealDto.setCategoryName(categoryName);
           }
           return setmealDto;
       }).collect(Collectors.toList());

       // Establece los registros mapeados en el DTO de paginación
       setmealDtoPage.setRecords(dtoList);

       return R.success(setmealDtoPage);
   }
   </setmealdto></setmeal></setmeal></setmealdto></setmeal></page>
  1. Eliminación de Combos

3.1 Análisis de Requisitos

Desde la página de gestión de combos, se puede eliminar un combo específico haciendo clic en el botón de eliminar. También es posible eliminar múltiples combos seleccionándolos mediante casillas de verificación y haciendo clic en el botón de eliminación masiva. Es importante destacar que los combos que están actualmente en venta no se pueden eliminar; primero deben ser puestos fuera de venta.

3.2 Desarrollo de Código

Proceso de interacción entre la interfaz de usuario y el backend:

  1. Al eliminar un combo individual, la página envía una solicitud AJAX para eliminar el combo correspondiente según su ID.
  2. Al eliminar múltiples combos, la página envía una solicitud AJAX para eliminar los combos correspondientes según sus IDs.

Las solicitudes para eliminar un combo individual y eliminar múltiples combos utilizan la misma dirección y método HTTP. La diferencia radica en la cantidad de IDs transmitidos. Por lo tanto, el backend puede proporcionar un único método para manejar ambas operaciones.

Capa del controlador:


   /**
    * Elimina uno o varios combos.
    * @param ids Lista de IDs de los combos a eliminar.
    * @return Respuesta genérica indicando el resultado de la operación.
    */
   @DeleteMapping
   public R<string> delete(@RequestParam List<long> ids) {
       log.info("Eliminando combos con IDs: {}", ids);
       setmealService.removeWithDish(ids);
       return R.success("Combos eliminados exitosamente!");
   }
   </long></string>

Método removeWithDish en SetmealServiceImpl:


   /**
    * Elimina combos y sus relaciones con los platos.
    * Verifica si los combos están en venta antes de la eliminación.
    * @param ids Lista de IDs de los combos a eliminar.
    */
   @Override
   @Transactional
   public void removeWithDish(List<long> ids) {
       // Consulta el estado de los combos para determinar si se pueden eliminar
       LambdaQueryWrapper<setmeal> queryWrapper = new LambdaQueryWrapper<>();
       queryWrapper.in(Setmeal::getId, ids);
       queryWrapper.eq(Setmeal::getStatus, 1); // Estado 1: en venta

       // Cuenta cuántos combos están en venta
       int count = this.count(queryWrapper);
       if (count > 0) {
           // Lanza una excepción si hay combos en venta
           throw new CustomerException("No se pueden eliminar combos que están en venta.");
       }

       // Si se pueden eliminar, primero elimina los datos de la tabla de combos
       this.removeByIds(ids);

       // Luego, elimina los datos de la tabla de relaciones
       LambdaQueryWrapper<setmealdish> relationQueryWrapper = new LambdaQueryWrapper<>();
       relationQueryWrapper.in(SetmealDish::getSetmealId, ids);
       setmealDishService.remove(relationQueryWrapper);
   }
   </setmealdish></setmeal></long>
  1. Modificación del Estado de Venta de Combos

4.1 Análisis de Requisitos

Se puede modificar el estado de venta (en venta/fuera de venta) de los combos según sea necesario.

4.2 Desarrollo de Código


   /**
    * Modifica el estado de venta de uno o varios combos.
    * @param status Nuevo estado de venta (1 para en venta, 0 para fuera de venta).
    * @param ids Lista de IDs de los combos a actualizar.
    * @return Respuesta genérica indicando el resultado de la operación.
    */
   @PostMapping("status/{status}")
   public R<string> updateStatus(@PathVariable int status, @RequestParam List<long> ids) {
       log.info("Actualizando estado de venta para combos con IDs: {}", ids);

       for (Long id : ids) {
           // Obtiene el combo actual
           Setmeal currentSetmeal = setmealService.getById(id);
           // Actualiza el estado de venta
           currentSetmeal.setStatus(status);
           // Guarda los cambios
           setmealService.updateById(currentSetmeal);
       }

       return R.success("Estado de venta de los combos actualizado exitosamente!");
   }
   </long></string>
  1. Modificación de Combos

5.1 Análisis de Requisitos

Se pueden modificar la información de un combo específico, como el precio, el nombre del combo, etc.

5.2 Desarrollo de Código

Proceso de interacción entre la interfaz de usuario y el backend:

  1. Al hacer clic en la operación de modificar, se navega a la página de modificación de combos (la misma que la de añadir combos). Primero, se muestran los datos del combo.
  2. Se modifican los datos del combo.

Operación de visualización de información del combo:

Capa del controlador:


   /**
    * Obtiene la información detallada de un combo por su ID para precargarla en la página de modificación.
    * @param id El ID del combo a consultar.
    * @return Respuesta genérica con el DTO del combo y sus platos asociados.
    */
   @GetMapping("/{id}")
   public R<setmealdto> get(@PathVariable Long id) {
       log.info("Consultando información detallada del combo con ID: {}", id);
       SetmealDto setmealDto = setmealService.getByIdWithDish(id);
       return R.success(setmealDto);
   }
   </setmealdto>

Método getByIdWithDish en SetmealServiceImpl:


   /**
    * Obtiene la información detallada de un combo, incluyendo sus platos asociados.
    * @param id El ID del combo.
    * @return DTO con la información del combo y su lista de platos.
    */
   @Override
   public SetmealDto getByIdWithDish(Long id) {
       // Obtiene la información básica del combo
       Setmeal setmeal = this.getById(id);
       SetmealDto setmealDto = new SetmealDto();
       BeanUtils.copyProperties(setmeal, setmealDto);

       // Consulta la información de los platos asociados a este combo
       LambdaQueryWrapper<setmealdish> queryWrapper = new LambdaQueryWrapper<>();
       queryWrapper.eq(SetmealDish::getSetmealId, id);
       List<setmealdish> dishList = setmealDishService.list(queryWrapper);

       // Establece la lista de platos en el DTO
       setmealDto.setSetmealDishes(dishList);

       return setmealDto;
   }
   </setmealdish></setmealdish>

Operación de modificación de datos del combo:

Capa del controlador:


   /**
    * Modifica la información de un combo existente.
    * @param setmealDto DTO con la información actualizada del combo y sus platos.
    * @return Respuesta genérica indicando el resultado de la operación.
    */
   @PutMapping
   public R<string> update(@RequestBody SetmealDto setmealDto) {
       log.info("Modificando combo: {}", setmealDto);
       setmealService.updateWithDish(setmealDto);
       return R.success("Información del combo modificada exitosamente!");
   }
   </string>

Método updateWithDish en SetmealServiceImpl:


   /**
    * Actualiza la información de un combo y sus platos asociados.
    * @param setmealDto DTO con la información actualizada del combo.
    */
   @Override
   public void updateWithDish(SetmealDto setmealDto) {
       // Actualiza la información en la tabla 'setmeal'
       this.updateById(setmealDto);

       // Limpia los platos actualmente asociados a este combo
       LambdaQueryWrapper<setmealdish> queryWrapper = new LambdaQueryWrapper<>();
       queryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());
       setmealDishService.remove(queryWrapper);

       // Agrega los nuevos platos enviados en la solicitud
       List<setmealdish> setmealDishes = setmealDto.getSetmealDishes();
       setmealDishes.stream().map((dish) -> {
           dish.setSetmealId(setmealDto.getId());
           return dish;
       }).collect(Collectors.toList());

       setmealDishService.saveBatch(setmealDishes);
   }
   </setmealdish></setmealdish>

Etiquetas: java Spring Boot MyBatis Plus Gestión de Combos backend

Publicado el 7-25 13:41