From 02d95fc51fc98de8a25b4884a47f04b1daa4f8c5 Mon Sep 17 00:00:00 2001 From: HashMap Date: Sun, 24 Aug 2025 23:40:21 +0800 Subject: [PATCH] =?UTF-8?q?feat(module):=20=E9=A5=B2=E5=96=82=E9=87=8F?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + 添加量饲喂量统计功能 + 解决了其他两个页面的若干逻辑错误 + 优化了配料清单的缓存结构: + 将缓存和同步过程移动到Service层, 以便其他模块调用 --- .../feed/controller/SgFeedListController.java | 110 +---------- .../controller/SgFeedStatisticController.java | 129 +++++++++++++ .../module/feed/domain/SgFeedStatistic.java | 98 ++++++++++ .../module/feed/domain/SgFormulaList.java | 15 +- .../feed/mapper/SgFeedStatisticMapper.java | 63 +++++++ .../TypeHandler/DaSheepfoldHandler.java | 38 ++++ .../mapper/TypeHandler/JsonTypeHandler.java | 42 +++++ .../TypeHandler/SgFormulaListHandler.java | 37 ++++ .../feed/service/ISgFeedListService.java | 6 +- .../feed/service/ISgFeedStatisticService.java | 65 +++++++ .../service/impl/SgFeedListServiceImpl.java | 126 +++++++++++-- .../impl/SgFeedStatisticServiceImpl.java | 176 ++++++++++++++++++ .../mapper/feed/SgFeedListMapper.xml | 1 + .../mapper/feed/SgFeedStatisticMapper.xml | 100 ++++++++++ 14 files changed, 881 insertions(+), 125 deletions(-) create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedStatisticController.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFeedStatistic.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/mapper/SgFeedStatisticMapper.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/DaSheepfoldHandler.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/JsonTypeHandler.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/SgFormulaListHandler.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedStatisticService.java create mode 100644 zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedStatisticServiceImpl.java create mode 100644 zhyc-module/src/main/resources/mapper/feed/SgFeedStatisticMapper.xml diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedListController.java b/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedListController.java index 446327d..895f061 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedListController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedListController.java @@ -1,15 +1,10 @@ package com.zhyc.module.feed.controller; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.servlet.http.HttpServletResponse; -import com.zhyc.module.feed.domain.SgFeedPlan; -import com.zhyc.module.feed.domain.SgFormulaManagement; -import com.zhyc.module.feed.service.ISgFeedPlanService; -import com.zhyc.module.feed.service.ISgFormulaManagementService; +import com.zhyc.module.feed.service.impl.SgFeedListServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; @@ -41,19 +36,12 @@ import com.zhyc.common.core.page.TableDataInfo; public class SgFeedListController extends BaseController { private final ISgFeedListService sgFeedListService; - private final ISgFormulaManagementService sgFormulaManagementService; - - private final ISgFeedPlanService sgFeedPlanService; - - private final Map sgFeedListMap = new HashMap<>(); public static boolean refresh = true; @Autowired - public SgFeedListController(ISgFeedListService sgFeedListService, ISgFormulaManagementService sgFormulaManagementService, ISgFeedPlanService sgFeedPlanService) { + public SgFeedListController(ISgFeedListService sgFeedListService) { this.sgFeedListService = sgFeedListService; - this.sgFormulaManagementService = sgFormulaManagementService; - this.sgFeedPlanService = sgFeedPlanService; } /** @@ -68,7 +56,7 @@ public class SgFeedListController extends BaseController { 当配方管理表出现更新 或 饲喂计划表出现增删改时会将refresh置为true 通知此处进行刷新 */ if (refresh) { - SyncFeedList(); + sgFeedListService.SyncFeedList(); refresh = false; } startPage(); @@ -78,7 +66,7 @@ public class SgFeedListController extends BaseController { for (SgFeedList item : list) { String key = item.getFormulaId() + "_" + item.getFormulaBatchId(); // 从缓存中取出完整对象 - SgFeedList itemInCache = sgFeedListMap.getOrDefault(key, item); + SgFeedList itemInCache = SgFeedListServiceImpl.getSgFeedListMap().getOrDefault(key, item); // 将数据库查询的基本信息替换掉缓存中去除的内容 - 前端展示与修改需要 itemInCache.setId(item.getId()); itemInCache.setFormulaBatchId(item.getFormulaBatchId()); @@ -143,94 +131,4 @@ public class SgFeedListController extends BaseController { return toAjax(sgFeedListService.deleteSgFeedListByIds(ids)); } - - public void SyncFeedList() { - // 清空旧缓存 - sgFeedListMap.clear(); - // 获取配方管理和现有配料清单内容 - List formulaManagementList = sgFormulaManagementService.selectSgFormulaManagementList(new SgFormulaManagement()); - List feedLists = sgFeedListService.selectSgFeedListList(new SgFeedList()); - // 将最新查询的配料清单加入缓存 - for (SgFeedList sgFeedList : feedLists) { - sgFeedListMap.put(sgFeedList.getFormulaId() + "_" + sgFeedList.getFormulaBatchId(), sgFeedList); - } - // 与新的配方管理列表同步 - 如果配料清单没有对应数据则加入 - for (SgFormulaManagement sgFormulaManagement : formulaManagementList) { - // 匹配 但忽略模板配方 - if (sgFormulaManagement.getFormulaId() != null && sgFormulaManagement.getBatchId() != null && !sgFormulaManagement.getBatchId().equals("0")) { - // 查询当前配方管理项是否存在现有配料计划中 (不论是否存在都要设置,因为缓存被清空,存在则更新,不存在则插入) - boolean isExist = sgFeedListMap.containsKey(sgFormulaManagement.getFormulaId() + "_" + sgFormulaManagement.getBatchId()); - // 标志位 : 如果当前配方不在饲喂计划中则不生成配量清单 - boolean isPlan = true; - // 设置缓存对象具体值 - SgFeedList sgFeedList = new SgFeedList(); - sgFeedList.setFormulaId(sgFormulaManagement.getFormulaId()); - sgFeedList.setFormulaBatchId(sgFormulaManagement.getBatchId()); - sgFeedList.setFormulaList(sgFormulaManagement.getSgFormulaList()); - sgFeedList.setRootFormula(sgFormulaManagement); - - - // 从饲喂计划列表中查出对应值(饲喂量需要计划中的比例计算) - SgFeedPlan rootPlanQuery = new SgFeedPlan(); - rootPlanQuery.setFormulaId(sgFormulaManagement.getFormulaId()); - rootPlanQuery.setBatchId(sgFormulaManagement.getBatchId()); - List sgFeedPlans = sgFeedPlanService.selectSgFeedPlanList(rootPlanQuery); - // 为空则标识当前配方不在饲喂计划中 && 不在缓存中设置 - if (sgFeedPlans.isEmpty()) { - isPlan = false; - } else { - // rootPlan中存储的是该配方批号的总量 - SgFeedPlan rootPlan = computePlanTotal(sgFeedPlans); - - // 将计划实体对象设置到配料清单中 - sgFeedList.setRootPlan(rootPlan); - - // 完整的配料清单对象加入缓存 - sgFeedListMap.put(sgFormulaManagement.getFormulaId() + "_" + sgFormulaManagement.getBatchId(), sgFeedList); - } - - // 不存在则插入 - if (!isExist && isPlan) { - sgFeedListService.insertSgFeedList(sgFeedList); - } - } - } - } - - /** - * 计算某个配方某个批次的总和值 - * - * @param sgFeedPlans 配方计划列表 - * @return 各个值总和 - */ - private static SgFeedPlan computePlanTotal(List sgFeedPlans) { - SgFeedPlan rootPlan = new SgFeedPlan(); - if (!sgFeedPlans.isEmpty()) { - int sheepCountTotal = 0; - double sheepDailySize = 0.0; - double planFeedMorningSize = 0.0; - double planFeedNoonSize = 0.0; - double planFeedAfternoonSize = 0.0; - double planFeedTotalSize = 0.0; - for (SgFeedPlan sgFeedPlan : sgFeedPlans) { - sheepCountTotal += sgFeedPlan.getSheepCount(); - sheepDailySize += sgFeedPlan.getPlanDailySize(); - planFeedMorningSize += sgFeedPlan.getPlanMorningSize(); - planFeedNoonSize += sgFeedPlan.getPlanNoonSize(); - planFeedAfternoonSize += sgFeedPlan.getPlanAfternoonSize(); - planFeedTotalSize += sgFeedPlan.getPlanFeedTotal(); - } - - rootPlan.setSheepCount(sheepCountTotal); - rootPlan.setPlanDailySize(sheepDailySize); - rootPlan.setPlanMorningSize(planFeedMorningSize); - rootPlan.setPlanNoonSize(planFeedNoonSize); - rootPlan.setPlanAfternoonSize(planFeedAfternoonSize); - rootPlan.setPlanFeedTotal(planFeedTotalSize); - - // 设置计划日期 - rootPlan.setPlanDate(sgFeedPlans.get(0).getPlanDate()); - } - return rootPlan; - } } diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedStatisticController.java b/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedStatisticController.java new file mode 100644 index 0000000..de0334f --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/controller/SgFeedStatisticController.java @@ -0,0 +1,129 @@ +package com.zhyc.module.feed.controller; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.zhyc.common.utils.uuid.UUID; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.zhyc.common.annotation.Log; +import com.zhyc.common.core.controller.BaseController; +import com.zhyc.common.core.domain.AjaxResult; +import com.zhyc.common.enums.BusinessType; +import com.zhyc.module.feed.domain.SgFeedStatistic; +import com.zhyc.module.feed.service.ISgFeedStatisticService; +import com.zhyc.common.utils.poi.ExcelUtil; +import com.zhyc.common.core.page.TableDataInfo; + +/** + * 饲喂量统计Controller + * + * @author HashMap + * @date 2025-08-23 + */ +@RestController +@RequestMapping("/feed/FeedStatistic") +@Transactional(rollbackFor = Exception.class) +public class SgFeedStatisticController extends BaseController { + private final ISgFeedStatisticService sgFeedStatisticService; + + + + public SgFeedStatisticController(ISgFeedStatisticService sgFeedStatisticService) { + this.sgFeedStatisticService = sgFeedStatisticService; + } + + /** + * 查询饲喂量统计列表 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:list')") + @GetMapping("/list") + public TableDataInfo list(SgFeedStatistic sgFeedStatistic) { + startPage(); + List list = sgFeedStatisticService.selectSgFeedStatisticList(sgFeedStatistic); + return getDataTable(list); + } + + /** + * 导出饲喂量统计列表 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:export')") + @Log(title = "饲喂量统计", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SgFeedStatistic sgFeedStatistic) { + List list = sgFeedStatisticService.selectSgFeedStatisticList(sgFeedStatistic); + ExcelUtil util = new ExcelUtil<>(SgFeedStatistic.class); + util.exportExcel(response, list, "饲喂量统计数据"); + } + + /** + * 获取饲喂量统计详细信息 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") String id) { + return success(sgFeedStatisticService.selectSgFeedStatisticById(id)); + } + + /** + * 新增饲喂量统计 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:add')") + @Log(title = "饲喂量统计", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SgFeedStatistic sgFeedStatistic) { + if (null == sgFeedStatistic.getFormulaId() && null == sgFeedStatistic.getFormulaBatchId()) { + throw new RuntimeException("ERROR: 数据为空"); + } + List isExist = sgFeedStatisticService.selectSgFeedStatisticList(sgFeedStatistic); + if (null != isExist && !isExist.isEmpty()) { + throw new RuntimeException("WARNING: 数据重复"); + } + // 设定唯一标识符主键 + sgFeedStatistic.setId(UUID.randomUUID().toString()); + /* + * 初始化数据 + * 弃用: 此处不再需要初始化,前端选定批号后会触发预载, 此处再初始化会覆盖前端后续的自定义数据 + */ + // sgFeedStatisticService.getInitSgFeedStatistic(sgFeedStatistic); + return toAjax(sgFeedStatisticService.insertSgFeedStatistic(sgFeedStatistic)); + } + + /** + * 修改饲喂量统计 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:edit')") + @Log(title = "饲喂量统计", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SgFeedStatistic sgFeedStatistic) { + return toAjax(sgFeedStatisticService.updateSgFeedStatistic(sgFeedStatistic)); + } + + /** + * 删除饲喂量统计 + */ + @PreAuthorize("@ss.hasPermi('feed:FeedStatistic:remove')") + @Log(title = "饲喂量统计", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable String[] ids) { + return toAjax(sgFeedStatisticService.deleteSgFeedStatisticByIds(ids)); + } + + @GetMapping("/init") + public TableDataInfo getInitData(SgFeedStatistic sgFeedStatistic){ + sgFeedStatisticService.getInitSgFeedStatistic(sgFeedStatistic); + // 兼容写法 - 实际只是为了返回一个 sgFeedStatistic + List list = new ArrayList<>(); + list.add(sgFeedStatistic); + return getDataTable(list); + } +} diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFeedStatistic.java b/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFeedStatistic.java new file mode 100644 index 0000000..2cdc21e --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFeedStatistic.java @@ -0,0 +1,98 @@ +package com.zhyc.module.feed.domain; + +import com.alibaba.fastjson2.JSON; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.zhyc.module.base.domain.DaSheepfold; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.zhyc.common.annotation.Excel; +import com.zhyc.common.core.domain.BaseEntity; + +import java.util.Date; +import java.util.List; + +/** + * 饲喂量统计对象 sg_feed_statistic + * + * @author HashMap + * @date 2025-08-23 + */ +@Setter +@Getter +public class SgFeedStatistic extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * UUID + */ + private String id; + + /** + * 配方编号 + */ + @Excel(name = "配方编号") + private String formulaId; + + /** + * 配方批号 + */ + @Excel(name = "配方批号") + private String formulaBatchId; + + /** + * 羊只数量 + */ + @Excel(name = "羊只数量") + private Long sheepFoldCount; + + /** + * 青贮损耗比例 + */ + @Excel(name = "青贮损耗比例") + private String silageLossRate; + + /** + * 总饲喂量 + */ + @Excel(name = "总饲喂量") + private Double feedTotalSize; + + /** + * 日均饲喂量 + */ + @Excel(name = "日均饲喂量") + private Double feedDailySize; + + /** + * 配方列表 + */ + @Excel(name = "配方列表") + private List materialList; + + /** + * 羊舍列表 + */ + @Excel(name = "羊舍列表") + private List sheepFoldList; + + @Excel(name = "日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date feedDate; + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("formulaId", getFormulaId()) + .append("formulaBatchId", getFormulaBatchId()) + .append("sheepFoldCount", getSheepFoldCount()) + .append("silageLossRate", getSilageLossRate()) + .append("feedTotalSize", getFeedTotalSize()) + .append("feedDailySize", getFeedDailySize()) + .append("materialList", getMaterialList()) + .append("sheepFoldList", getSheepFoldList()) + .toString(); + } +} diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFormulaList.java b/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFormulaList.java index 03ab542..aac1fc9 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFormulaList.java +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/domain/SgFormulaList.java @@ -39,14 +39,25 @@ public class SgFormulaList extends BaseEntity @Excel(name = "比例") private Long ratio; - /** 颗粒原料 */ + /** + * 颗粒原料 + * 当前不局限于 "是否颗粒原料" 而且多种类型的标识符 + */ @Excel(name = "颗粒原料") private String isGranular; - /** 补饲 */ + /** + * 补饲 + * 当前用作饲喂类型标识 + */ @Excel(name = "补饲") private String isSupplement; + /** + * 添加量 - 供其他一些统计模块使用 + */ + private Double feedSize; + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/SgFeedStatisticMapper.java b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/SgFeedStatisticMapper.java new file mode 100644 index 0000000..abee631 --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/SgFeedStatisticMapper.java @@ -0,0 +1,63 @@ +package com.zhyc.module.feed.mapper; + +import java.util.List; +import com.zhyc.module.feed.domain.SgFeedStatistic; +import org.apache.ibatis.annotations.Mapper; + +/** + * 饲喂量统计Mapper接口 + * + * @author HashMap + * @date 2025-08-23 + */ +@Mapper +public interface SgFeedStatisticMapper +{ + /** + * 查询饲喂量统计 + * + * @param id 饲喂量统计主键 + * @return 饲喂量统计 + */ + SgFeedStatistic selectSgFeedStatisticById(String id); + + /** + * 查询饲喂量统计列表 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 饲喂量统计集合 + */ + List selectSgFeedStatisticList(SgFeedStatistic sgFeedStatistic); + + /** + * 新增饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + int insertSgFeedStatistic(SgFeedStatistic sgFeedStatistic); + + /** + * 修改饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + int updateSgFeedStatistic(SgFeedStatistic sgFeedStatistic); + + /** + * 删除饲喂量统计 + * + * @param id 饲喂量统计主键 + * @return 结果 + */ + int deleteSgFeedStatisticById(String id); + + /** + * 批量删除饲喂量统计 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + int deleteSgFeedStatisticByIds(String[] ids); +} diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/DaSheepfoldHandler.java b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/DaSheepfoldHandler.java new file mode 100644 index 0000000..af89abc --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/DaSheepfoldHandler.java @@ -0,0 +1,38 @@ +package com.zhyc.module.feed.mapper.TypeHandler; + +import com.alibaba.fastjson2.JSON; +import com.zhyc.module.base.domain.DaSheepfold; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@MappedTypes(List.class) +public class DaSheepfoldHandler extends BaseTypeHandler> { + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + List parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSON.toJSONString(parameter)); + } + + @Override + public List getNullableResult(ResultSet rs, String columnName) throws SQLException { + return JSON.parseArray(rs.getString(columnName), DaSheepfold.class); + } + + @Override + public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return JSON.parseArray(rs.getString(columnIndex), DaSheepfold.class); + } + + @Override + public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return JSON.parseArray(cs.getString(columnIndex), DaSheepfold.class); + } +} + diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/JsonTypeHandler.java b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/JsonTypeHandler.java new file mode 100644 index 0000000..dd0d22f --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/JsonTypeHandler.java @@ -0,0 +1,42 @@ +package com.zhyc.module.feed.mapper.TypeHandler; + +import com.alibaba.fastjson2.JSON; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class JsonTypeHandler extends BaseTypeHandler { + private final Class type; + + public JsonTypeHandler(Class type) { + this.type = type; + } + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSON.toJSONString(parameter)); + } + + @Override + public T getNullableResult(ResultSet rs, String columnName) throws SQLException { + String json = rs.getString(columnName); + return JSON.parseObject(json, type); + } + + @Override + public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + String json = rs.getString(columnIndex); + return JSON.parseObject(json, type); + } + + @Override + public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + String json = cs.getString(columnIndex); + return JSON.parseObject(json, type); + } +} + diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/SgFormulaListHandler.java b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/SgFormulaListHandler.java new file mode 100644 index 0000000..10d857b --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/mapper/TypeHandler/SgFormulaListHandler.java @@ -0,0 +1,37 @@ +package com.zhyc.module.feed.mapper.TypeHandler; + +import com.alibaba.fastjson2.JSON; +import com.zhyc.module.feed.domain.SgFormulaList; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@MappedTypes(List.class) +public class SgFormulaListHandler extends BaseTypeHandler> { + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + List parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSON.toJSONString(parameter)); + } + + @Override + public List getNullableResult(ResultSet rs, String columnName) throws SQLException { + return JSON.parseArray(rs.getString(columnName), SgFormulaList.class); + } + + @Override + public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return JSON.parseArray(rs.getString(columnIndex), SgFormulaList.class); + } + + @Override + public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return JSON.parseArray(cs.getString(columnIndex), SgFormulaList.class); + } +} diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedListService.java b/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedListService.java index b293d84..b3c5a5f 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedListService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedListService.java @@ -1,6 +1,7 @@ package com.zhyc.module.feed.service; import java.util.List; + import com.zhyc.module.feed.domain.SgFeedList; /** @@ -9,8 +10,7 @@ import com.zhyc.module.feed.domain.SgFeedList; * @author HashMap * @date 2025-08-19 */ -public interface ISgFeedListService -{ +public interface ISgFeedListService { /** * 查询配料清单 * @@ -58,4 +58,6 @@ public interface ISgFeedListService * @return 结果 */ int deleteSgFeedListById(Long id); + + void SyncFeedList(); } diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedStatisticService.java b/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedStatisticService.java new file mode 100644 index 0000000..9bdad7a --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/service/ISgFeedStatisticService.java @@ -0,0 +1,65 @@ +package com.zhyc.module.feed.service; + +import java.util.List; +import com.zhyc.module.feed.domain.SgFeedStatistic; + +/** + * 饲喂量统计Service接口 + * + * @author HashMap + * @date 2025-08-23 + */ +public interface ISgFeedStatisticService +{ + /** + * 查询饲喂量统计 + * + * @param id 饲喂量统计主键 + * @return 饲喂量统计 + */ + SgFeedStatistic selectSgFeedStatisticById(String id); + + /** + * 查询饲喂量统计列表 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 饲喂量统计集合 + */ + List selectSgFeedStatisticList(SgFeedStatistic sgFeedStatistic); + + /** + * 新增饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + int insertSgFeedStatistic(SgFeedStatistic sgFeedStatistic); + + /** + * 修改饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + int updateSgFeedStatistic(SgFeedStatistic sgFeedStatistic); + + /** + * 批量删除饲喂量统计 + * + * @param ids 需要删除的饲喂量统计主键集合 + * @return 结果 + */ + int deleteSgFeedStatisticByIds(String[] ids); + + /** + * 删除饲喂量统计信息 + * + * @param id 饲喂量统计主键 + * @return 结果 + */ + int deleteSgFeedStatisticById(String id); + + void getInitSgFeedStatistic(SgFeedStatistic sgFeedStatistic); + + +} diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedListServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedListServiceImpl.java index 704d45d..225d851 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedListServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedListServiceImpl.java @@ -1,7 +1,14 @@ package com.zhyc.module.feed.service.impl; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.zhyc.module.feed.domain.SgFeedPlan; +import com.zhyc.module.feed.domain.SgFormulaManagement; +import com.zhyc.module.feed.service.ISgFeedPlanService; +import com.zhyc.module.feed.service.ISgFormulaManagementService; +import lombok.Getter; import org.springframework.stereotype.Service; import com.zhyc.module.feed.mapper.SgFeedListMapper; import com.zhyc.module.feed.domain.SgFeedList; @@ -14,12 +21,17 @@ import com.zhyc.module.feed.service.ISgFeedListService; * @date 2025-08-19 */ @Service -public class SgFeedListServiceImpl implements ISgFeedListService -{ +public class SgFeedListServiceImpl implements ISgFeedListService { private final SgFeedListMapper sgFeedListMapper; + private final ISgFormulaManagementService sgFormulaManagementService; + private final ISgFeedPlanService sgFeedPlanService; + @Getter + private final static Map sgFeedListMap = new HashMap<>(); - public SgFeedListServiceImpl(SgFeedListMapper sgFeedListMapper) { + public SgFeedListServiceImpl(SgFeedListMapper sgFeedListMapper, ISgFormulaManagementService sgFormulaManagementService, ISgFeedPlanService sgFeedPlanService) { this.sgFeedListMapper = sgFeedListMapper; + this.sgFormulaManagementService = sgFormulaManagementService; + this.sgFeedPlanService = sgFeedPlanService; } /** @@ -29,8 +41,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 配料清单 */ @Override - public SgFeedList selectSgFeedListById(Long id) - { + public SgFeedList selectSgFeedListById(Long id) { return sgFeedListMapper.selectSgFeedListById(id); } @@ -41,8 +52,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 配料清单 */ @Override - public List selectSgFeedListList(SgFeedList sgFeedList) - { + public List selectSgFeedListList(SgFeedList sgFeedList) { return sgFeedListMapper.selectSgFeedListList(sgFeedList); } @@ -53,8 +63,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 结果 */ @Override - public int insertSgFeedList(SgFeedList sgFeedList) - { + public int insertSgFeedList(SgFeedList sgFeedList) { return sgFeedListMapper.insertSgFeedList(sgFeedList); } @@ -65,8 +74,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 结果 */ @Override - public int updateSgFeedList(SgFeedList sgFeedList) - { + public int updateSgFeedList(SgFeedList sgFeedList) { return sgFeedListMapper.updateSgFeedList(sgFeedList); } @@ -77,8 +85,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 结果 */ @Override - public int deleteSgFeedListByIds(Long[] ids) - { + public int deleteSgFeedListByIds(Long[] ids) { return sgFeedListMapper.deleteSgFeedListByIds(ids); } @@ -89,8 +96,97 @@ public class SgFeedListServiceImpl implements ISgFeedListService * @return 结果 */ @Override - public int deleteSgFeedListById(Long id) - { + public int deleteSgFeedListById(Long id) { return sgFeedListMapper.deleteSgFeedListById(id); } + + public void SyncFeedList() { + // 清空旧缓存 + sgFeedListMap.clear(); + // 获取配方管理和现有配料清单内容 + List formulaManagementList = sgFormulaManagementService.selectSgFormulaManagementList(new SgFormulaManagement()); + List feedLists = this.selectSgFeedListList(new SgFeedList()); + // 将最新查询的配料清单加入缓存 + for (SgFeedList sgFeedList : feedLists) { + sgFeedListMap.put(sgFeedList.getFormulaId() + "_" + sgFeedList.getFormulaBatchId(), sgFeedList); + } + // 与新的配方管理列表同步 - 如果配料清单没有对应数据则加入 + for (SgFormulaManagement sgFormulaManagement : formulaManagementList) { + // 匹配 但忽略模板配方 + if (sgFormulaManagement.getFormulaId() != null && sgFormulaManagement.getBatchId() != null && !sgFormulaManagement.getBatchId().equals("0")) { + // 查询当前配方管理项是否存在现有配料计划中 (不论是否存在都要设置,因为缓存被清空,存在则更新,不存在则插入) + boolean isExist = sgFeedListMap.containsKey(sgFormulaManagement.getFormulaId() + "_" + sgFormulaManagement.getBatchId()); + // 标志位 : 如果当前配方不在饲喂计划中则不生成配量清单 + boolean isPlan = true; + // 设置缓存对象具体值 + SgFeedList sgFeedList = new SgFeedList(); + sgFeedList.setFormulaId(sgFormulaManagement.getFormulaId()); + sgFeedList.setFormulaBatchId(sgFormulaManagement.getBatchId()); + sgFeedList.setFormulaList(sgFormulaManagement.getSgFormulaList()); + sgFeedList.setRootFormula(sgFormulaManagement); + + + // 从饲喂计划列表中查出对应值(饲喂量需要计划中的比例计算) + SgFeedPlan rootPlanQuery = new SgFeedPlan(); + rootPlanQuery.setFormulaId(sgFormulaManagement.getFormulaId()); + rootPlanQuery.setBatchId(sgFormulaManagement.getBatchId()); + List sgFeedPlans = sgFeedPlanService.selectSgFeedPlanList(rootPlanQuery); + // 为空则标识当前配方不在饲喂计划中 && 不在缓存中设置 + if (sgFeedPlans.isEmpty()) { + isPlan = false; + } else { + // rootPlan中存储的是该配方批号的总量 + SgFeedPlan rootPlan = computePlanTotal(sgFeedPlans); + + // 将计划实体对象设置到配料清单中 + sgFeedList.setRootPlan(rootPlan); + + // 完整的配料清单对象加入缓存 + sgFeedListMap.put(sgFormulaManagement.getFormulaId() + "_" + sgFormulaManagement.getBatchId(), sgFeedList); + } + + // 不存在则插入 + if (!isExist && isPlan) { + this.insertSgFeedList(sgFeedList); + } + } + } + } + + /** + * 计算某个配方某个批次的总和值 + * + * @param sgFeedPlans 配方计划列表 + * @return 各个值总和 + */ + private static SgFeedPlan computePlanTotal(List sgFeedPlans) { + SgFeedPlan rootPlan = new SgFeedPlan(); + if (!sgFeedPlans.isEmpty()) { + int sheepCountTotal = 0; + double sheepDailySize = 0.0; + double planFeedMorningSize = 0.0; + double planFeedNoonSize = 0.0; + double planFeedAfternoonSize = 0.0; + double planFeedTotalSize = 0.0; + for (SgFeedPlan sgFeedPlan : sgFeedPlans) { + sheepCountTotal += sgFeedPlan.getSheepCount(); + sheepDailySize += sgFeedPlan.getPlanDailySize(); + planFeedMorningSize += sgFeedPlan.getPlanMorningSize(); + planFeedNoonSize += sgFeedPlan.getPlanNoonSize(); + planFeedAfternoonSize += sgFeedPlan.getPlanAfternoonSize(); + planFeedTotalSize += sgFeedPlan.getPlanFeedTotal(); + } + + rootPlan.setSheepCount(sheepCountTotal); + rootPlan.setPlanDailySize(sheepDailySize); + rootPlan.setPlanMorningSize(planFeedMorningSize); + rootPlan.setPlanNoonSize(planFeedNoonSize); + rootPlan.setPlanAfternoonSize(planFeedAfternoonSize); + rootPlan.setPlanFeedTotal(planFeedTotalSize); + + // 设置计划日期 + rootPlan.setPlanDate(sgFeedPlans.get(0).getPlanDate()); + } + return rootPlan; + } } diff --git a/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedStatisticServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedStatisticServiceImpl.java new file mode 100644 index 0000000..b1766bd --- /dev/null +++ b/zhyc-module/src/main/java/com/zhyc/module/feed/service/impl/SgFeedStatisticServiceImpl.java @@ -0,0 +1,176 @@ +package com.zhyc.module.feed.service.impl; + +import java.util.List; +import java.util.stream.Collectors; + +import com.zhyc.module.base.domain.DaSheepfold; +import com.zhyc.module.feed.domain.SgFeedList; +import com.zhyc.module.feed.domain.SgFeedPlan; +import com.zhyc.module.feed.domain.SgFormulaList; +import com.zhyc.module.feed.service.ISgFeedListService; +import com.zhyc.module.feed.service.ISgFeedPlanService; +import org.springframework.stereotype.Service; +import com.zhyc.module.feed.mapper.SgFeedStatisticMapper; +import com.zhyc.module.feed.domain.SgFeedStatistic; +import com.zhyc.module.feed.service.ISgFeedStatisticService; + +/** + * 饲喂量统计Service业务层处理 + * + * @author HashMap + * @date 2025-08-23 + */ +@Service +public class SgFeedStatisticServiceImpl implements ISgFeedStatisticService { + private final SgFeedStatisticMapper sgFeedStatisticMapper; + + private final ISgFeedListService sgFeedListService; + private final ISgFeedPlanService sgFeedPlanService; + + public SgFeedStatisticServiceImpl(SgFeedStatisticMapper sgFeedStatisticMapper, ISgFeedListService sgFeedListService, ISgFeedPlanService sgFeedPlanService) { + this.sgFeedStatisticMapper = sgFeedStatisticMapper; + this.sgFeedListService = sgFeedListService; + this.sgFeedPlanService = sgFeedPlanService; + } + + /** + * 查询饲喂量统计 + * + * @param id 饲喂量统计主键 + * @return 饲喂量统计 + */ + @Override + public SgFeedStatistic selectSgFeedStatisticById(String id) { + return sgFeedStatisticMapper.selectSgFeedStatisticById(id); + } + + /** + * 查询饲喂量统计列表 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 饲喂量统计 + */ + @Override + public List selectSgFeedStatisticList(SgFeedStatistic sgFeedStatistic) { + return sgFeedStatisticMapper.selectSgFeedStatisticList(sgFeedStatistic); + } + + /** + * 新增饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + @Override + public int insertSgFeedStatistic(SgFeedStatistic sgFeedStatistic) { + return sgFeedStatisticMapper.insertSgFeedStatistic(sgFeedStatistic); + } + + /** + * 修改饲喂量统计 + * + * @param sgFeedStatistic 饲喂量统计 + * @return 结果 + */ + @Override + public int updateSgFeedStatistic(SgFeedStatistic sgFeedStatistic) { + return sgFeedStatisticMapper.updateSgFeedStatistic(sgFeedStatistic); + } + + /** + * 批量删除饲喂量统计 + * + * @param ids 需要删除的饲喂量统计主键 + * @return 结果 + */ + @Override + public int deleteSgFeedStatisticByIds(String[] ids) { + return sgFeedStatisticMapper.deleteSgFeedStatisticByIds(ids); + } + + /** + * 删除饲喂量统计信息 + * + * @param id 饲喂量统计主键 + * @return 结果 + */ + @Override + public int deleteSgFeedStatisticById(String id) { + return sgFeedStatisticMapper.deleteSgFeedStatisticById(id); + } + + /** + * 向待插入数据表单提供数据预载服务 + * + * @param sgFeedStatistic 待填充的初始化数据 + * @author ShiHan Wang + */ + @Override + public void getInitSgFeedStatistic(SgFeedStatistic sgFeedStatistic) { + // 1. 查找饲料清单 + SgFeedList sgFeedListQuery = new SgFeedList(); + sgFeedListQuery.setFormulaId(sgFeedStatistic.getFormulaId()); + sgFeedListQuery.setFormulaBatchId(sgFeedStatistic.getFormulaBatchId()); + + List feedLists = sgFeedListService.selectSgFeedListList(sgFeedListQuery); + + if (!feedLists.isEmpty()) { + // 刷新缓存 + sgFeedListService.SyncFeedList(); + + // 从缓存获取完整配方清单 + String cacheKey = sgFeedStatistic.getFormulaId() + "_" + sgFeedStatistic.getFormulaBatchId(); + SgFeedList sgFeedList = SgFeedListServiceImpl.getSgFeedListMap().get(cacheKey); + + if (sgFeedList != null && sgFeedList.getFormulaList() != null) { + // 并行流式计算 提高性能 + sgFeedList.getFormulaList().parallelStream().forEach(item -> { + double ratio = item.getRatio() / 100.0; + double feedSize = sgFeedList.getRootPlan().getPlanMorningSize() * ratio + + sgFeedList.getRootPlan().getPlanNoonSize() * ratio + + sgFeedList.getRootPlan().getPlanAfternoonSize() * ratio; + item.setFeedSize(feedSize); + }); + + // 统计总和 + double totalFeedSize = sgFeedList.getFormulaList() + .parallelStream() + .mapToDouble(SgFormulaList::getFeedSize) + .sum(); + sgFeedStatistic.setMaterialList(sgFeedList.getFormulaList()); + sgFeedStatistic.setFeedTotalSize(totalFeedSize); + } else { + throw new RuntimeException("WARNING: 原料数据为空"); + } + } + + // 2. 查找饲喂计划并填充羊舍信息 + SgFeedPlan sgFeedPlanQuery = new SgFeedPlan(); + sgFeedPlanQuery.setFormulaId(sgFeedStatistic.getFormulaId()); + sgFeedPlanQuery.setBatchId(sgFeedStatistic.getFormulaBatchId()); + + List sgFeedPlans = sgFeedPlanService.selectSgFeedPlanList(sgFeedPlanQuery); + + if (!sgFeedPlans.isEmpty()) { + // 并行计算提高查询性能 + List sheepfolds = sgFeedPlans.parallelStream() + .map(plan -> { + DaSheepfold sheepfold = new DaSheepfold(); + sheepfold.setId((long) plan.getSheepHouseId()); + return sheepfold; + }) + .collect(Collectors.toList()); + + long sheepCount = sgFeedPlans.parallelStream() + .mapToLong(SgFeedPlan::getSheepCount) + .sum(); + sgFeedStatistic.setSheepFoldList(sheepfolds); + sgFeedStatistic.setSheepFoldCount(sheepCount); + // 计算日均饲喂量 + sgFeedStatistic.setFeedDailySize(sgFeedStatistic.getFeedTotalSize() / sgFeedStatistic.getSheepFoldCount()); + } else { + throw new RuntimeException("WARNING: 不存在该计划"); + } + } + +} diff --git a/zhyc-module/src/main/resources/mapper/feed/SgFeedListMapper.xml b/zhyc-module/src/main/resources/mapper/feed/SgFeedListMapper.xml index 25e0143..0c10e17 100644 --- a/zhyc-module/src/main/resources/mapper/feed/SgFeedListMapper.xml +++ b/zhyc-module/src/main/resources/mapper/feed/SgFeedListMapper.xml @@ -20,6 +20,7 @@ and formula_id = #{formulaId} + and formula_batch_id = #{formulaBatchId} and zookeeper = #{zookeeper} and deploy_date = #{deployDate} diff --git a/zhyc-module/src/main/resources/mapper/feed/SgFeedStatisticMapper.xml b/zhyc-module/src/main/resources/mapper/feed/SgFeedStatisticMapper.xml new file mode 100644 index 0000000..0bd9657 --- /dev/null +++ b/zhyc-module/src/main/resources/mapper/feed/SgFeedStatisticMapper.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + select id, formula_id, formula_batch_id, sheep_fold_count, silage_loss_rate, feed_total_size, feed_daily_size, material_list, sheep_fold_list,feed_date from sg_feed_statistic + + + + + + + + insert into sg_feed_statistic + + id, + formula_id, + formula_batch_id, + sheep_fold_count, + silage_loss_rate, + feed_total_size, + feed_daily_size, + material_list, + sheep_fold_list, + feed_date, + + + #{id}, + #{formulaId}, + #{formulaBatchId}, + #{sheepFoldCount}, + #{silageLossRate}, + #{feedTotalSize}, + #{feedDailySize}, +# 写入操作需要手动指定 TypeHandler 参数 + #{materialList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.SgFormulaListHandler}, + #{sheepFoldList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.DaSheepfoldHandler}, + #{feedDate}, + + + + + update sg_feed_statistic + + formula_id = #{formulaId}, + formula_batch_id = #{formulaBatchId}, + sheep_fold_count = #{sheepFoldCount}, + silage_loss_rate = #{silageLossRate}, + feed_total_size = #{feedTotalSize}, + feed_daily_size = #{feedDailySize}, + material_list = #{materialList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.SgFormulaListHandler}, + sheep_fold_list = #{sheepFoldList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.DaSheepfoldHandler}, + feed_date = #{feedDate}, + + where id = #{id} + + + + delete from sg_feed_statistic where id = #{id} + + + + delete from sg_feed_statistic where id in + + #{id} + + + \ No newline at end of file