问题:
在项目上遇到一个之前没有碰到过的需求,根据月份分类账单,还需汇总总金额,原型图如下所示。在原型图中可以看出,不仅需要展示每个月的所有任务信息、金额以及这个月份中的总金额等,还需要计算出所有任务的总金额。下面还有按照类型进行按需查询。
解决思路:
1、首先得按照发布时间的年月来分组查询,查询出各个年月以及这个年月的金钱总和。
2、查找出这个年月的所有任务。
3、将每个年月的总金额累加在一起,就能得到这个账号所有任务的总金额。
具体实现:
由于任务的时间和账单不是在一张表中,此时需要连表查询。因为现在所需要的分组时间为xxxx年xx月,所以我们可以使用mysql中的DATE_FORMAT函数来处理时间,按类型分类的话根据type来判断即可。具体代码如下:
<select id="getHaveDate" resultType="com.BillDTO">
SELECT
DATE_FORMAT(a.finish_time,'%Y-%m') date,SUM(b.total_amount) totalMoney
FROM
announcement a JOIN execution_bill b ON a.id = b.id
WHERE
a.brand_owner_id = #{userId} AND a.`status` >=14
<if test="type!=null">
AND a.type = #{type}
</if>
GROUP BY DATE_FORMAT(a.finish_time,'%Y-%m')
</select>
经过此步骤我们就可以得到所有任务的年月以及这个年月的总金额。
接下来我们只需要再写一个根据时间年月来查询这个年月中所有的任务信息即可。
<select id="getCurrentDateData" resultType="com.AnnouncementBillDTO">
SELECT
a.id,a.title,a.type,eb.total_amount,DATE_FORMAT(a.finish_time,'%Y-%m') finish_time
FROM
announcement a JOIN execution_bill eb ON a.id = eb.id
WHERE
a.brand_owner_id = #{userId} AND a.`status` >= 14 AND DATE_FORMAT(a.finish_time,'%Y-%m') = #{date}
<if test="type!=null">
and a.type = #{type}
</if>
ORDER BY
DATE_FORMAT(a.finish_time,'%Y-%m')
</select>
在BillDTO中,date代表具体年月,totalMoney代表这个年月的总金额,announcementBillDTOList为这个年月完成的所有任务记录。
@Data
public class BillDTO {
private String date;
private BigDecimal totalMoney;
private List<AnnouncementBillDTO> announcementBillDTOList;
}
最后在service层处理好数据放入map中返回给前端即可。
public Map getBillDetails(Integer type) {
Map map = new HashMap();
Integer userId = SecurityUtil.getUserId();
List<BillDTO> billDTOS = baseMapper.getHaveDate(userId,type);
billDTOS.forEach(item -> {
//根据年月查出这个年月所有的任务
List<AnnouncementBillDTO> announcementBillDTOS = baseMapper.getCurrentDateData(userId, item.getDate(),type);
item.setAnnouncementBillDTOList(announcementBillDTOS);
});
BigDecimal totalMoney = BigDecimal.ZERO;
//所有年月的总金额
if (billDTOS.size() > 0) {
totalMoney = billDTOS.stream().map(BillDTO::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
}
map.put("data", billDTOS);
map.put("totalMoney", totalMoney);
return map;
}