- 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:
- 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. - La página envía una solicitud AJAX para obtener las categorías de platos y mostrarlas en una ventana para añadir platos.
- 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.
- La página envía una solicitud para subir una imagen, y el backend la guarda en el servidor.
- La página envía una solicitud para descargar la imagen, mostrando la imagen cargada previamente.
- 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>
- 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:
- 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. - 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>
- 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:
- Al eliminar un combo individual, la página envía una solicitud AJAX para eliminar el combo correspondiente según su ID.
- 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>
- 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>
- 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:
- 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.
- 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>