苍穹外卖08——(涉及接收日期格式数据、ApachePOI导出报表、sql获取top10菜品数据)

营业额统计

service层 

  • 在需要处理空值、与数据库交互或使用集合时,Integer 、Double是更好的选择。
// 导入string工具类  
import org.apache.commons.lang.StringUtils;  


@Service // 标记该类为Spring的服务组件  
@Slf4j // 引入日志功能  
public class ReportServiceImpl implements ReportService {  
    
    @Override  
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {  
        // 该方法用于获取从begin到end之间的时间区间  
        List<LocalDate> datelist = new ArrayList<>(); // 创建一个列表以存储日期  
        datelist.add(begin); // 将开始日期添加到日期列表中  

        // 循环直到开始日期等于结束日期  
        while (!begin.equals(end)) {  // 注意,最后一天end也存到集合里了 
            // 自动增加一天直到符合的日期  
            begin = begin.plusDays(1); // 将开始日期增加一天  
            datelist.add(begin); // 将新的开始日期添加到日期列表中  
        }  

        // 存储每个日期的营业额  
        List<Double> turnoverList = new ArrayList<>(); // 创建一个列表以存储营业额  
        for (LocalDate date : datelist) { // 遍历每个日期,将LocalDate 转为LocalDateTime 
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN); // 获取当天的最小时间(00:00)   
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX); // 获取当天的最大时间(23:59:59.999999999)  

            // 创建一个Map以存储查询条件  
            Map<String, Object> map = new HashMap<>();  
            map.put("begin", beginTime); // 将开始时间放入Map中  
            map.put("end", endTime); // 将结束时间放入Map中  
            map.put("status", Orders.COMPLETED); // 将订单状态放入Map中  

            // 调用数据访问层的方法,获取指定时间段内的营业额  
            Double turnover = orderMapper.sumByMap(map); // 获取营业额  
            turnover = turnover == null ? 0.0 : turnover; // 处理null
            turnoverList.add(turnover); // 将营业额添加到营业额列表中  
        }  

        // 构建并返回TurnoverReportVO对象  
        return TurnoverReportVO  
                .builder() // 创建构建器  
                .dateList(StringUtils.join(datelist, ",")) // 将日期列表转换为以逗号分隔的字符串  
                .turnoverList(StringUtils.join(turnoverList, ",")) // 将营业额列表转换为以逗号分隔的字符串  
                .build(); // 构建对象并返回  
    }  
}

mapper层 

<select id="sumByMap" resultType="java.lang.Double">
        select sum(amount) from orders
        <where>
            <if test="begin != null">
                and order_time &gt; #{begin}
            </if>
            <if test="end != null">
                and order_time &lt; #{end}
            </if>
            <if test="status != null">
                and status = #{status}
            </if>
        </where>
    </select>

用户统计

controller层

@GetMapping("/userStatistics")
    @ApiOperation("用户统计")
    public Result<UserReportVO> userStatistics(
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        log.info("用户数据统计:{},{}", begin, end);
        return Result.success(reportService.getUserStatistics(begin, end));
    }

service层

@Override
public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
    // 收集begin和end之间的每天的日期
    // 创建一个列表来存储日期
    List<LocalDate> dateList = new ArrayList<>();
    // 将开始日期添加到列表中
    dateList.add(begin);

    // 使用循环将开始日期逐天增加,直到等于结束日期
    while (!begin.equals(end)) {
        // 将开始日期增加一天
        begin = begin.plusDays(1);
        // 将增加后的日期添加到列表中
        dateList.add(begin);
    }

    // 保存每天的新用户数
    // 创建一个列表来存储每天的新用户数
    List<Integer> newUserList = new ArrayList<>();

    // 保存每天的总用户数
    // 创建一个列表来存储每天的总用户数
    List<Integer> totalUserList = new ArrayList<>();

    // 遍历日期列表
    for (LocalDate date : dateList) {
        // 获取当前日期的开始时间(00:00:00)
        LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
        // 获取当前日期的结束时间(23:59:59)
        LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);

        // 创建一个Map来存储查询条件
        Map map = new HashMap();
        // 将结束时间作为查询条件添加到Map中
        map.put("end", endTime);

        // 查询当前日期的总用户数
        Integer totalUser = userMapper.countByMap(map);

        // 将开始时间也作为查询条件添加到Map中
        map.put("begin", beginTime);
        // 查询当前日期的新用户数
        Integer newUser = userMapper.countByMap(map);

        // 将查询到的总用户数添加到列表中
        totalUserList.add(totalUser);
        // 将查询到的新用户数添加到列表中
        newUserList.add(newUser);
    }

    // 返回结果  
    // 使用UserReportVO的构建器创建一个UserReportVO对象
    return UserReportVO.builder()
            // 将日期列表转换为逗号分隔的字符串,并设置到UserReportVO对象中
            .dateList(StringUtils.join(dateList,","))
            // 将总用户数列表转换为逗号分隔的字符串,并设置到UserReportVO对象中
            .totalUserList(StringUtils.join(totalUserList,","))
            // 将新用户数列表转换为逗号分隔的字符串,并设置到UserReportVO对象中
            .newUserList(StringUtils.join(newUserList,","))
            // 构建并返回UserReportVO对象
            .build();
}

Mapper层(动态sql实现,可以使得service层调用同一个方法)

<select id="countByMap" resultType="java.lang.Integer">
        select count(id) from user
        <where>
            <if test="begin != null">
                and create_time &gt; #{begin}
            </if>
            <if test="end != null">
                and create_time &lt; #{end}
            </if>
        </where>
    </select>

 销量排名统计top10

service层

@Override
    public SalesTop10ReportVO getSalesTop10Statistics(LocalDate begin, LocalDate end) {
        // 将LocalDate转换为LocalDateTime,分别设置为当天的开始和结束时间
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        // 调用orderMapper.getSalesTop10方法获取销量排名前10的商品信息
        List<GoodsSalesDTO> salesTop10 = orderMapper.getSalesTop10(beginTime, endTime);

        // 使用流操作获取所有商品的名称,并收集到列表中
        List<String> names = salesTop10.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        // 将商品名称列表转换为逗号分隔的字符串
        String nameList = StringUtils.join(names, ","); // 注意:separator参数应为",",而不是separator:","

        // 使用流操作获取所有商品的销量,并收集到列表中
        List<Integer> numbers = salesTop10.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
        // 将销量列表转换为逗号分隔的字符串
        String numberList = StringUtils.join(numbers, ","); // 同上,应为","

        // 使用构建器模式封装返回结果
        return SalesTop10ReportVO.builder()
                .nameList(nameList) // 设置商品名称列表
                .numberList(numberList) // 设置销量列表
                .build(); // 构建并返回SalesTop10ReportVO对象
    }

 mapper层(关于获取top10排名的sql)

<select id="getSalesTop10" resultType="com.sky.dto.GoodsSalesDTO">
        select od.name, sum(od.number) number
        from order_detail od, orders o
        where od.order_id = o.id and o.status = 5
        <if test="begin != null">
            and o.order_time &gt; #{begin}
        </if>
        <if test="end != null">
            and o.order_time &lt; #{end}
        </if>
        group by od.name
        order by number desc
        limit 0, 10
    </select>

ApachePOI 

介绍

Apache POI 是一个处理 Microsoft Office 各种文件格式的开源项目。简单来说,我们可以使用 POI 在 Java 程序中对 Microsoft Office 各种文件进行读写操作。

一般情况下,POI 都是用于操作 Excel 文件。

坐标导入

<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>

案例引入:读取文件和写入文件

实现步骤:

  1. 设计Excel模板文件(不要手动编程去实现)
  2. 查询近30天的运营数据
  3. 将查询到的运营数据写入模板文件
  4. 通过输出来将Excel文件下载到客户端浏览器

代码开发:

    @GetMapping("/export")
    @ApiOperation("导出运营数据结果")
 // 传入HttpServletResponse ,是负责设置响应携带的文件
    public void export(HttpServletResponse response){
        reportService.exportBusinessData(response);
    }
/**  
 * 导出运营数据报表  
 * @param response HTTP响应对象,用于输出Excel文件  
 */  
public void exportBusinessData(HttpServletResponse response) {  
    // 1. 查询数据库,获取营业数据---查询最近30天的运营数据  
    LocalDate dateBegin = LocalDate.now().minusDays(30); // 获取30天前的日期  
    LocalDate dateEnd = LocalDate.now().minusDays(1); // 获取昨天的日期  

    // 查询概览数据  
    BusinessDataVO businessDataVO = workspaceService.getBusinessData(  
        LocalDateTime.of(dateBegin, LocalTime.MIN),   
        LocalDateTime.of(dateEnd, LocalTime.MAX)  
    );  

    // 2. 通过POI将数据写入到Excel文件中  
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx"); // 加载Excel模板  
 // 加载资源文件,并以输入流的形式返回
    try {  
        // 基于模板文件创建一个新的Excel文件  
        XSSFWorkbook excel = new XSSFWorkbook(in);  

        // 获取表格文件的Sheet页  
        XSSFSheet sheet = excel.getSheet("Sheet1");  

        // 填充数据--时间  
        sheet.getRow(1).getCell(1).setCellValue("时间:" + dateBegin + "至" + dateEnd); // 设置时间范围  

        // 获得第4行  
        XSSFRow row = sheet.getRow(3);  
        row.getCell(2).setCellValue(businessDataVO.getTurnover()); // 填充营业额  
        row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate()); // 填充订单完成率  
        row.getCell(6).setCellValue(businessDataVO.getNewUsers()); // 填充新增用户数  

        // 获得第5行  
        row = sheet.getRow(4);  
        row.getCell(2).setCellValue(businessDataVO.getValidOrderCount()); // 填充有效订单数  
        row.getCell(4).setCellValue(businessDataVO.getUnitPrice()); // 填充单价  

        // 填充明细数据  
        for (int i = 0; i < 30; i++) { // 遍历最近30天  
            LocalDate date = dateBegin.plusDays(i); // 获取当前遍历的日期  
            // 查询某一天的营业数据  
            BusinessDataVO businessData = workspaceService.getBusinessData(  
                LocalDateTime.of(date, LocalTime.MIN),   
                LocalDateTime.of(date, LocalTime.MAX)  
            );  

            // 获得某一行  
            row = sheet.getRow(7 + i); // 从第8行开始填充数据  
            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文件通过响应发送给浏览器端
        ServletOutputStream out = response.getOutputStream(); // 获取输出流  
        excel.write(out); // 将Excel内容写入输出流  

        // 关闭资源  
        out.close(); // 关闭输出流  
        excel.close(); // 关闭Excel文件  
    } catch (IOException e) {  
        e.printStackTrace(); // 捕获并打印异常  
    }  
}

效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构9——二叉搜索树

&#x1f947;1.二叉搜索树的概念 二叉搜索树(Binary Search Tree,BST)又称二叉排序树或二叉查找树&#xff0c;其要么是一棵空树&#xff0c;要么具有以下性质&#xff1a; ①&#xff1a;左子树上所有节点的值都小于根节点&#xff1b; ②&#xff1a;右子树上所有节点的值都…

如何使用wireshark 解密TLS-SSL报文

目录 前言 原理 操作 前言 现在网站都是https 或者 很多站点都支持 http2。这些站点为了保证数据的安全都通过TLS/SSL 加密过&#xff0c;用wireshark 并不能很好的去解析报文&#xff0c;我们就需要用wireshark去解密这些报文。我主要讲解下mac 在 chrome 怎么配置的&…

c++ haru生成pdf输出文本实例

haru是一个开源的生成pdf的库&#xff0c;花时间终于编译成功&#xff0c;以下是一个特别简单的写文本的实例&#xff1a; #include "hpdf.h" void CDemoDlg::OnBnClickedOk() { HPDF_Error_Handler error_handler NULL; HPDF_Doc pdf; pdf HPDF_New(…

Redis与MySQL主从复制原理解析

目录 1. 介绍2. Mysql主从复制的工作原理3. Mysql复制的类型3.1 基于语句的复制&#xff08;Statement-based Replication, SBR&#xff09;3.2 基于行的复制&#xff08;Row-based Replication, RBR&#xff09;3.3 混合复制&#xff08;Mixed Replication&#xff09; 4. Red…

一步到位Python Django部署,浅谈Python Django框架

Django是一个使用Python开发的Web应用程序框架&#xff0c;它遵循MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;旨在帮助开发人员更快、更轻松地构建和维护高质量的Web应用程序。Django提供了强大的基础设施和工具&#xff0c;以便于处理复杂的业务逻…

迅为RK3568开发板篇OpenHarmony配置HDF驱动控制LED-新增 topeet子系统-编写 bundle.json文件

bundle.json 文件内容如下所示&#xff1a; 下面是对各个字段的解释&#xff1a; 1. name: "ohos/demos" - 这是组件或项目的名称&#xff0c;这里表示它属于 OHOS&#xff08;OpenHarmony OS&#xff09;生态系统下的一个名为"demos"的组件。 2. descri…

STM32 物联网智能家居 (三) 输入子系统

STM32 物联网智能家居 (三) 输入子系统 下面是物联网智能家居的输入子系统&#xff0c;见下图&#xff0c;在输入子系统中会实现按键输入、网络输入、标准输入Scanf&#xff0c;其中的网络输入放入到网络子系统中进行讲解。 一、输入子系统核心功能 STM32 物联网智能家居输入…

Windows 正确配置android adb调试的方法

下载适用于 Windows 的 SDK Platform-Tools https://developer.android.google.cn/tools/releases/platform-tools?hlzh-cn 设置系统变量&#xff0c;路径为platform-tools文件夹的绝对路径 点击Path添加环境变量 %adb%打开终端输入adb shell 这就成功了&#xff01;

【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理

【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理 项目背景项目实现推理过程训练过程 项目展望写在最后项目下载链接 本文为原创文章&#xff0c;若需要转载&#xff0c;请注明出处。 原文地址&#xff1a;https://blog.csdn.net/qq_30270773/article…

线性回归超详解

目录 一、回归问题 vs 分类问题 二、线性回归 1、一句话理解 2、数学推导 2.1 线性函数表示 2.2 损失函数 2.3 梯度下降 2.3.1 什么是梯度 2.3.2 梯度下降目标 2.3.3 过程 2.3.4 迭代公式 3、特征预处理 3.1 为什么要预处理 3.2 数据归一化方法 1&#xff09;最小…

docker 部署 Kafka 单机和集群

一、准备工作 安装 Docker 确保本机已安装 Docker。可以通过以下命令检查 Docker 是否已安装&#xff1a;docker --version如果未安装&#xff0c;可以访问 Docker 官网下载并安装 Docker Desktop&#xff08;Windows 和 Mac&#xff09;或使用包管理器安装&#xff08;Linux&…

Uniapp开发安卓App,配置第一次打开软件出现的弹窗-隐私政策提示框

这里是直接使用的uniapp官方所提供的“原生隐私政策提示框”&#xff0c;废话不多说&#xff0c;直接上教程&#xff01; 1.manifest.json—>安卓/IOS启动界面配置—>勾选“使用原生隐私政策提示框”2.勾选后&#xff0c;在你的项目下就会出现一个文件&#xff0c;andro…

微信小程序:播放音频

在小程序开发中&#xff0c;音频播放是一个重要的功能。本文将详细介绍小程序音频播放的相关知识点&#xff0c;帮助开发者更好地掌握小程序音频播放的实现方法。 一、小程序音频播放的基本流程 在小程序中&#xff0c;音频播放的基本流程如下&#xff1a; 获取音频数据&#…

Unity解决滑动条的value值的滑动条消失问题

在这里我们看到原本的value的滑动条消失了 解决办法 把编辑器的边框往外面拉一下就可以了&#xff08;之前遇到这个问题还重启了几次unity没想到居然是这个问题&#xff09;

Mac上安装Label Studio

在Mac上安装Anaconda并随后安装Label Studio&#xff0c;可以按照以下步骤进行&#xff1a; 1. 在Mac上安装Anaconda 首先&#xff0c;你需要从Anaconda的官方网站下载适用于Mac的安装程序。访问Anaconda官网&#xff0c;点击“Download Anaconda”按钮&#xff0c;选择适合M…

微软震撼发布:Phi-4语言模型登陆Hugging Face

近日&#xff0c;微软公司在Hugging Face平台上正式发布了其最新的语言模型Phi-4&#xff0c;这一发布标志着人工智能技术的又一重要进步。Phi-4模型以其140亿参数的高效配置&#xff0c;在复杂推理任务中表现出色&#xff0c;特别是在数学领域&#xff0c;更是展现出了卓越的能…

使用WebdriverIO和Appium测试App

1.新建项目 打开Webstorm新建项目 打开终端输入命令 npm init -y npm install wdio/cli allure-commandline --save-dev npx wdio config 然后在终端依次选择如下&#xff1a; 然后在终端输入命令&#xff1a; npm install wdio/local-runnerlatest wdio/mocha-frameworkla…

【opencv】第7章 图像变换

7.1 基 于OpenCV 的 边 缘 检 测 本节中&#xff0c;我们将一起学习OpenCV 中边缘检测的各种算子和滤波器——Canny 算子、Sobel 算 子 、Laplacian 算子以及Scharr 滤波器。 7.1.1 边缘检测的一般步骤 在具体介绍之前&#xff0c;先来一起看看边缘检测的一般步骤。 1.【第…

浙江安吉成新照明电器:Acrel-1000DP 分布式光伏监控系统应用探索

安科瑞吕梦怡 18706162527 摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活…

Linux检查磁盘占用情况

1.检查使用情况 df -h发现是/dev/vda1占用很高 2.查看/dev/vda1文件夹 cd /dev/vda1发现不是文件夹 3.继续查看使用情况 df -h *4.原因可能是文件已经删除但是进程还在&#xff0c;没有释放空间 5.查看删除操作的进程 lsof -n | grep deleted6.杀死进程 kill -9 PID