数据统计(Excel报表)
工作台
需求分析和设计
工作台是系统运营的数据看板,并提供快捷操作入口,可以有效提高商家的工作效率。
产品原型
工作台展示的数据
- 今日数据
- 订单管理
- 菜品总览
- 套餐总览
- 订单信息
名词解释
- 营业额:已完成订单的总金额。
- 有效订单:已完成订单的数量。
- 订单完成率:有效订单数 / 总订单数 * 100%。
- 平均客单价:营业额 / 有效订单数。
- 新增用户:新增用户的数量。
接口设计
- 今日数据接口
- 订单管理接口
- 菜品总览接口
- 套餐总览接口
-
订单搜索(已完成)
-
各个状态的订单数量统计(已完成)
代码导入
- 导入WorkSpaceController.java:
@RestController
@RequestMapping("/admin/workspace")
@Slf4j
@Api(tags = "工作台相关接口")
public class WorkSpaceController {
@Autowired
private WorkspaceService workspaceService;
/**
* 工作台今日数据查询
*
* @return
*/
@GetMapping("/businessData")
@ApiOperation("工作台今日数据查询")
public Result<BusinessDataVO> businessData() {
//获得当天的开始时间
LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN);
//获得当天的结束时间
LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX);
BusinessDataVO businessDataVO = workspaceService.getBusinessData(begin, end);
return Result.success(businessDataVO);
}
/**
* 查询订单管理数据
*
* @return
*/
@GetMapping("/overviewOrders")
@ApiOperation("查询订单管理数据")
public Result<OrderOverViewVO> orderOverView() {
return Result.success(workspaceService.getOrderOverView());
}
/**
* 查询菜品总览
*
* @return
*/
@GetMapping("/overviewDishes")
@ApiOperation("查询菜品总览")
public Result<DishOverViewVO> dishOverView() {
return Result.success(workspaceService.getDishOverView());
}
/**
* 查询套餐总览
*
* @return
*/
@GetMapping("/overviewSetmeals")
@ApiOperation("查询套餐总览")
public Result<SetmealOverViewVO> setmealOverView() {
return Result.success(workspaceService.getSetmealOverView());
}
}
- 导入WorkSpaceService.java:
public interface WorkspaceService {
/**
* 根据时间段统计营业数据
*
* @param begin
* @param end
* @return
*/
BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end);
/**
* 查询订单管理数据
*
* @return
*/
OrderOverViewVO getOrderOverView();
/**
* 查询菜品总览
*
* @return
*/
DishOverViewVO getDishOverView();
/**
* 查询套餐总览
*
* @return
*/
SetmealOverViewVO getSetmealOverView();
}
- 导入WorkSpaceServiceImpl.java:
@Service
@Slf4j
public class WorkspaceServiceImpl implements WorkspaceService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private DishMapper dishMapper;
@Autowired
private SetmealMapper setmealMapper;
/**
* 根据时间段统计营业数据
*
* @param begin
* @param end
* @return
*/
public BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end) {
/**
* 营业额:当日已完成订单的总金额
* 有效订单:当日已完成订单的数量
* 订单完成率:有效订单数 / 总订单数
* 平均客单价:营业额 / 有效订单数
* 新增用户:当日新增用户的数量
*/
Map map = new HashMap();
map.put("begin", begin);
map.put("end", end);
//查询总订单数
Integer totalOrderCount = orderMapper.countByMap(map);
map.put("status", Orders.COMPLETED);
//营业额
Double turnover = orderMapper.sumByMap(map);
turnover = turnover == null ? 0.0 : turnover;
//有效订单数
Integer validOrderCount = orderMapper.countByMap(map);
Double unitPrice = 0.0;
Double orderCompletionRate = 0.0;
if (totalOrderCount != 0 && validOrderCount != 0) {
//订单完成率
orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
//平均客单价
unitPrice = turnover / validOrderCount;
}
//新增用户数
Integer newUsers = userMapper.countByMap(map);
return BusinessDataVO.builder()
.turnover(turnover)
.validOrderCount(validOrderCount)
.orderCompletionRate(orderCompletionRate)
.unitPrice(unitPrice)
.newUsers(newUsers)
.build();
}
/**
* 查询订单管理数据
*
* @return
*/
public OrderOverViewVO getOrderOverView() {
Map map = new HashMap();
map.put("begin", LocalDateTime.now().with(LocalTime.MIN));
map.put("status", Orders.TO_BE_CONFIRMED);
//待接单
Integer waitingOrders = orderMapper.countByMap(map);
//待派送
map.put("status", Orders.CONFIRMED);
Integer deliveredOrders = orderMapper.countByMap(map);
//已完成
map.put("status", Orders.COMPLETED);
Integer completedOrders = orderMapper.countByMap(map);
//已取消
map.put("status", Orders.CANCELLED);
Integer cancelledOrders = orderMapper.countByMap(map);
//全部订单
map.put("status", null);
Integer allOrders = orderMapper.countByMap(map);
return OrderOverViewVO.builder()
.waitingOrders(waitingOrders)
.deliveredOrders(deliveredOrders)
.completedOrders(completedOrders)
.cancelledOrders(cancelledOrders)
.allOrders(allOrders)
.build();
}
/**
* 查询菜品总览
*
* @return
*/
public DishOverViewVO getDishOverView() {
Map map = new HashMap();
map.put("status", StatusConstant.ENABLE);
Integer sold = dishMapper.countByMap(map);
map.put("status", StatusConstant.DISABLE);
Integer discontinued = dishMapper.countByMap(map);
return DishOverViewVO.builder()
.sold(sold)
.discontinued(discontinued)
.build();
}
/**
* 查询套餐总览
*
* @return
*/
public SetmealOverViewVO getSetmealOverView() {
Map map = new HashMap();
map.put("status", StatusConstant.ENABLE);
Integer sold = setmealMapper.countByMap(map);
map.put("status", StatusConstant.DISABLE);
Integer discontinued = setmealMapper.countByMap(map);
return SetmealOverViewVO.builder()
.sold(sold)
.discontinued(discontinued)
.build();
}
}
- 导入DishMapper.java中的countByMap方法声明:
Integer countByMap(Map map);
- 导入DishMapper.xml中的countByMap方法的动态SQL语句:
<select id="countByMap" resultType="java.lang.Integer">
select count(id) from dish
<where>
<if test="status != null">
and status = #{status}
</if>
<if test="categoryId != null">
and category_id = #{categoryId}
</if>
</where>
</select>
- 导入SetmealMapper.java中的countByMap方法声明:
Integer countByMap(Map map);
- 导入SetmealMapper.xml中的countByMap方法的动态SQL语句:
<select id="countByMap" resultType="java.lang.Integer">
select count(id) from setmeal
<where>
<if test="status != null">
and status = #{status}
</if>
<if test="categoryId != null">
and category_id = #{categoryId}
</if>
</where>
</select>
功能测试
可以通过如下方式进行测试:通过接口文档测试,前后端联调测试。
Apache POI
介绍
- Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。
- 一般情况下,POI 都是用于操作 Excel 文件。
Apache POI 的应用场景
- 银行网银系统导出交易明细。
- 各种业务系统导出Excel报表。
- 批量导入业务数据。
Apache POI的maven坐标
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
导出运营数据Excel报表
需求分析和设计
产品原型
导出的Excel报表格式
业务功能
- 导出Excel形式的报表文件。
- 导出最近30天的运营数据。
接口设计
注意:当前接口没有返回数据,因为报表导出功能本质上是文件下载,服务端会通过输出流将Excel文件下载到客户端浏览器。
实现步骤
- 设计Excel模板文件。
- 查询近30天的运营数据。
- 将查询到的运营数据写入模板文件。
- 通过输出流将Excel文件下载到客户端浏览器。
代码开发
- 根据接口定义,在ReportController中创建export方法:
@GetMapping("/export")
@ApiOperation("导出运营数据报表")
public void export(HttpServletResponse response) {
log.info("导出运营数据报表,员工id为:{}", BaseContext.getCurrentId());
reportService.exportBusinessData(response);
}
- 在ReportService接口中声明导出运营数据报表的方法:
void exportBusinessData(HttpServletResponse response);
- 在ReportServiceImpl实现类中实现导出运营数据报表的方法:
@Override
public void exportBusinessData(HttpServletResponse response) {
//1.查询数据库,获取营业资源
LocalDate dateBegin = LocalDate.now().minusDays(30);
LocalDate dateEnd = LocalDate.now().minusDays(1);
//查询概览数据
BusinessDataVO businessDataVO = workspaceService.getBusinessData(
LocalDateTime.of(dateBegin, LocalTime.MIN), LocalDateTime.of(dateEnd, LocalTime.MAX));
//2.通过POI将数据写入到Excel文件中
try (
//基于模板文件创建一个新的excel文件
InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/OperationalDataReportFormTemplate.xlsx");
XSSFWorkbook excel = new XSSFWorkbook(in);
ServletOutputStream out = response.getOutputStream()
) {
//填充时间和概览数据
XSSFSheet sheet = excel.getSheetAt(0);
sheet.getRow(1).getCell(1).setCellValue("时间:" + dateBegin + "至" + dateEnd);
XSSFRow row = sheet.getRow(3); //获取第四行数据
row.getCell(2).setCellValue(businessDataVO.getTurnover());
row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
row.getCell(6).setCellValue(businessDataVO.getNewUsers());
row = sheet.getRow(4); //获取第5行数据
row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
row.getCell(4).setCellValue(businessDataVO.getUnitPrice());
//填充明细数据
for (int i = 0; i < 30; i++) {
LocalDate date = dateBegin.plusDays(i); //获得当天日期
//查询当天的数据
BusinessDataVO businessData = workspaceService.getBusinessData(
LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));
row = sheet.getRow(i + 7); //获取第i+1行数据,即第i天数据所在的行
row.getCell(1).setCellValue(date.toString());
row.getCell(2).setCellValue(businessData.getTurnover());
row.getCell(3).setCellValue(businessData.getValidOrderCount());
row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
row.getCell(5).setCellValue(businessData.getUnitPrice());
row.getCell(6).setCellValue(businessData.getNewUsers());
}
//3.通过输出流将Excel文件上传到客户端浏览器
excel.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
功能测试
可以通过前后端联调进行测试。
标签:status,map,return,外卖,countByMap,Integer,第十二天,苍穹,row From: https://www.cnblogs.com/zgg1h/p/18313712