奶产量分析
This commit is contained in:
parent
8eedf3b3ff
commit
c9f05d722f
@ -8,12 +8,14 @@ import com.zhyc.common.enums.BusinessType;
|
||||
import com.zhyc.common.utils.poi.ExcelUtil;
|
||||
import com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis;
|
||||
import com.zhyc.module.dairyProducts.service.INpSheepMilkAnalysisService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 只保留:分页列表(只读) + 单条查询 + 导出
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/dairyProducts/sheepMilkAnalysis")
|
||||
public class NpSheepMilkAnalysisController extends BaseController {
|
||||
@ -22,58 +24,33 @@ public class NpSheepMilkAnalysisController extends BaseController {
|
||||
private INpSheepMilkAnalysisService npSheepMilkAnalysisService;
|
||||
|
||||
/**
|
||||
* 查询奶产量分析列表
|
||||
* 查询奶产量分析列表(只读,分页)
|
||||
* 支持参数 manageEarTag(耳号模糊) 和 screenDays(筛选天数)
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(NpSheepMilkAnalysis analysis) {
|
||||
startPage();
|
||||
startPage(); // 使用 PageHelper 分页(注意 service 中第一个 DB 调用是 distinct sheep id)
|
||||
List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisList(analysis);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个分析记录详细信息
|
||||
* 获取单个分析记录详细信息(按 sheepId)
|
||||
*/
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
return AjaxResult.success(npSheepMilkAnalysisService.selectNpSheepMilkAnalysisById(id));
|
||||
}
|
||||
/**
|
||||
* 新增奶产量分析记录
|
||||
*/
|
||||
@Log(title = "奶产量分析", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody NpSheepMilkAnalysis analysis) {
|
||||
return toAjax(npSheepMilkAnalysisService.insertNpSheepMilkAnalysis(analysis));
|
||||
@GetMapping(value = "/{sheepId}")
|
||||
public AjaxResult getInfo(@PathVariable("sheepId") String sheepId) {
|
||||
return AjaxResult.success(npSheepMilkAnalysisService.selectNpSheepMilkAnalysisBySheepId(sheepId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改奶产量分析记录
|
||||
* 导出奶产量分析记录(Excel)
|
||||
* 支持 manageEarTag 与 screenDays 两个查询条件
|
||||
*/
|
||||
@Log(title = "奶产量分析", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody NpSheepMilkAnalysis analysis) {
|
||||
return toAjax(npSheepMilkAnalysisService.updateNpSheepMilkAnalysis(analysis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除奶产量分析记录
|
||||
*/
|
||||
@Log(title = "奶产量分析", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||
return toAjax(npSheepMilkAnalysisService.deleteNpSheepMilkAnalysisByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出奶产量分析记录
|
||||
*/
|
||||
@Log(title = "奶产量分析", businessType = BusinessType.EXPORT)
|
||||
@Log(title = "奶产量分析 导出", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/export")
|
||||
public AjaxResult export(NpSheepMilkAnalysis analysis) {
|
||||
List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisList(analysis);
|
||||
ExcelUtil<NpSheepMilkAnalysis> util = new ExcelUtil<>(NpSheepMilkAnalysis.class);
|
||||
return util.exportExcel(list, "奶产量分析数据");
|
||||
return util.exportExcel(list, "羊奶产量分析数据");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,34 +1,64 @@
|
||||
package com.zhyc.module.dairyProducts.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class NpSheepMilkAnalysis {
|
||||
// 唯一键(可用于前端 row-key)
|
||||
private String sheepId;
|
||||
|
||||
// 耳号(从 sheep_file.bs_manage_tags)
|
||||
private String manageEarTag;
|
||||
|
||||
private String variety;
|
||||
|
||||
// 最高校正胎次的挤奶开始时间 & 干奶时间
|
||||
private Date milkingStartTime;
|
||||
private Date dryEndTime;
|
||||
|
||||
// 挤奶天数(该胎次)
|
||||
private Integer milkingDays;
|
||||
|
||||
// 前端传入的筛选天数(screenDays)
|
||||
private Integer screenDays;
|
||||
|
||||
// 分析天数(若你有不同命名,可忽略)
|
||||
private Integer analysisDays;
|
||||
|
||||
// 校正后最大胎次(即校正奶量之和最大的胎次)
|
||||
private Integer maxParity;
|
||||
|
||||
// 最高校正胎次区间内的系统奶量与校正奶量(按筛选窗口)
|
||||
private Double sumSystemMilk;
|
||||
private Double sumCorrectedMilk;
|
||||
|
||||
// 校正日平均奶量(按 min(挤奶天数, 筛选天数))
|
||||
private Double avgCorrectedDaily;
|
||||
|
||||
// 各胎次总奶量(校正)
|
||||
private Double sumParity1Milk;
|
||||
private Double sumParity2Milk;
|
||||
private Double sumParity3Milk;
|
||||
private Double sumParity4Milk;
|
||||
|
||||
// 各胎次日平均(按规则)
|
||||
private Double avgParity1Daily;
|
||||
private Double avgParity2Daily;
|
||||
private Double avgParity3Daily;
|
||||
private Double avgParity4Daily;
|
||||
|
||||
// 泌乳天数(sheep_file.lactation_day)
|
||||
private Integer lactationDays;
|
||||
|
||||
// 过去 7 / 14 / 30 日平均(系统奶量)
|
||||
private Double avgLast7Milk;
|
||||
private Double avgLast7Corrected;
|
||||
private Double avgLast7Corrected; // = avgLast7Milk * weightCoefficient (默认 1.0)
|
||||
private Double avgLast14Milk;
|
||||
private Double avgLast30Milk;
|
||||
|
||||
// 羊只基础信息(来自 sheep_file)
|
||||
private String sheepCategory;
|
||||
private Date birthday;
|
||||
private Integer parity;
|
||||
private Integer parity; // 当前胎次
|
||||
private Integer monthAge;
|
||||
private Double currentWeight;
|
||||
private String breedStatus;
|
||||
@ -36,12 +66,16 @@ public class NpSheepMilkAnalysis {
|
||||
private String motherManageTags;
|
||||
private String ranchName;
|
||||
private String family;
|
||||
|
||||
// 母亲相关字段(由已计算的母亲分析结果中取值)
|
||||
private Integer motherMilkingDays;
|
||||
private Double motherSumCorrected;
|
||||
private Integer motherMaxParity;
|
||||
private Double motherAvgCorrectedDaily;
|
||||
|
||||
private Date lastUpdate;
|
||||
|
||||
// getters and setters
|
||||
public String getSheepId() { return sheepId; }
|
||||
public void setSheepId(String sheepId) { this.sheepId = sheepId; }
|
||||
|
||||
@ -60,6 +94,9 @@ public class NpSheepMilkAnalysis {
|
||||
public Integer getMilkingDays() { return milkingDays; }
|
||||
public void setMilkingDays(Integer milkingDays) { this.milkingDays = milkingDays; }
|
||||
|
||||
public Integer getScreenDays() { return screenDays; }
|
||||
public void setScreenDays(Integer screenDays) { this.screenDays = screenDays; }
|
||||
|
||||
public Integer getAnalysisDays() { return analysisDays; }
|
||||
public void setAnalysisDays(Integer analysisDays) { this.analysisDays = analysisDays; }
|
||||
|
||||
@ -159,4 +196,3 @@ public class NpSheepMilkAnalysis {
|
||||
public Date getLastUpdate() { return lastUpdate; }
|
||||
public void setLastUpdate(Date lastUpdate) { this.lastUpdate = lastUpdate; }
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,36 @@
|
||||
package com.zhyc.module.dairyProducts.mapper;
|
||||
|
||||
import com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface NpSheepMilkAnalysisMapper {
|
||||
|
||||
NpSheepMilkAnalysis selectNpSheepMilkAnalysisById(Long id);
|
||||
/**
|
||||
* 按筛选天数 screenDays 统计并返回所有羊只的奶产量分析
|
||||
*/
|
||||
List<NpSheepMilkAnalysis> selectAnalysisForExport(@Param("screenDays") Integer screenDays);
|
||||
|
||||
List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisList(NpSheepMilkAnalysis analysis);
|
||||
/**
|
||||
* 根据羊只ID查询羊只奶产量分析信息,返回Map结构
|
||||
*/
|
||||
Map<String, Object> selectNpSheepMilkAnalysisBySheepId(@Param("sheepId") String sheepId);
|
||||
|
||||
int insertNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis);
|
||||
/**
|
||||
* 根据管理耳标筛选,返回distinct的sheepId列表
|
||||
*/
|
||||
List<String> selectDistinctSheepIds(@Param("manageEarTag") String manageEarTag);
|
||||
|
||||
int updateNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis);
|
||||
/**
|
||||
* 根据羊只ID查询羊只档案信息,返回Map结构
|
||||
*/
|
||||
Map<String, Object> selectSheepFileBySheepId(@Param("sheepId") String sheepId);
|
||||
|
||||
int deleteNpSheepMilkAnalysisById(Long id);
|
||||
/**
|
||||
* 根据羊只ID查询挤奶班次数据,返回List<Map>
|
||||
*/
|
||||
List<Map<String, Object>> selectMilkRecordsBySheepId(@Param("sheepId") String sheepId);
|
||||
|
||||
int deleteNpSheepMilkAnalysisByIds(Long[] ids);
|
||||
}
|
||||
|
@ -5,16 +5,8 @@ import java.util.List;
|
||||
|
||||
public interface INpSheepMilkAnalysisService {
|
||||
|
||||
NpSheepMilkAnalysis selectNpSheepMilkAnalysisById(Long id);
|
||||
NpSheepMilkAnalysis selectNpSheepMilkAnalysisBySheepId(String sheepId);
|
||||
|
||||
List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisList(NpSheepMilkAnalysis analysis);
|
||||
|
||||
int insertNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis);
|
||||
|
||||
int updateNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis);
|
||||
|
||||
int deleteNpSheepMilkAnalysisById(Long id);
|
||||
|
||||
int deleteNpSheepMilkAnalysisByIds(Long[] ids);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,17 @@
|
||||
package com.zhyc.module.dairyProducts.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.zhyc.module.dairyProducts.mapper.NpSheepMilkAnalysisMapper;
|
||||
import com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis;
|
||||
import com.zhyc.module.dairyProducts.mapper.NpSheepMilkAnalysisMapper;
|
||||
import com.zhyc.module.dairyProducts.service.INpSheepMilkAnalysisService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisService {
|
||||
@ -14,34 +19,268 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
|
||||
@Autowired
|
||||
private NpSheepMilkAnalysisMapper npSheepMilkAnalysisMapper;
|
||||
|
||||
// 将 Rec 定义为静态内部类
|
||||
private static class Rec {
|
||||
LocalDate date;
|
||||
double systemMilk;
|
||||
double correctedMilk;
|
||||
int parity;
|
||||
}
|
||||
|
||||
// 将 ParityStat 定义为静态内部类
|
||||
private static class ParityStat {
|
||||
int parity;
|
||||
double sumCorrected;
|
||||
double sumSystem;
|
||||
LocalDate first;
|
||||
LocalDate last;
|
||||
long days;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NpSheepMilkAnalysis selectNpSheepMilkAnalysisById(Long id) {
|
||||
return npSheepMilkAnalysisMapper.selectNpSheepMilkAnalysisById(id);
|
||||
public NpSheepMilkAnalysis selectNpSheepMilkAnalysisBySheepId(String sheepId) {
|
||||
Map<String, Object> map = npSheepMilkAnalysisMapper.selectNpSheepMilkAnalysisBySheepId(sheepId);
|
||||
if (map == null) return null;
|
||||
NpSheepMilkAnalysis ana = new NpSheepMilkAnalysis();
|
||||
ana.setSheepId(sheepId);
|
||||
ana.setManageEarTag((String) map.get("manageEarTag"));
|
||||
return ana;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisList(NpSheepMilkAnalysis analysis) {
|
||||
return npSheepMilkAnalysisMapper.selectNpSheepMilkAnalysisList(analysis);
|
||||
int screenDays = (analysis != null && analysis.getScreenDays() != null) ? analysis.getScreenDays() : 100;
|
||||
String manageEarTagFilter = (analysis != null) ? analysis.getManageEarTag() : null;
|
||||
|
||||
List<String> sheepIds = npSheepMilkAnalysisMapper.selectDistinctSheepIds(manageEarTagFilter);
|
||||
if (CollectionUtils.isEmpty(sheepIds)) return Collections.emptyList();
|
||||
|
||||
List<NpSheepMilkAnalysis> resultList = new ArrayList<>();
|
||||
Map<String, NpSheepMilkAnalysis> mapByManageTag = new HashMap<>();
|
||||
|
||||
for (String sheepId : sheepIds) {
|
||||
Map<String, Object> sf = npSheepMilkAnalysisMapper.selectSheepFileBySheepId(sheepId);
|
||||
List<Map<String, Object>> records = npSheepMilkAnalysisMapper.selectMilkRecordsBySheepId(sheepId);
|
||||
|
||||
if (records == null || records.isEmpty()) {
|
||||
NpSheepMilkAnalysis emptyAna = new NpSheepMilkAnalysis();
|
||||
emptyAna.setSheepId(sheepId);
|
||||
if (sf != null) {
|
||||
emptyAna.setManageEarTag((String) sf.get("manageEarTag"));
|
||||
emptyAna.setVariety((String) sf.get("variety"));
|
||||
emptyAna.setLactationDays(toInteger(sf.get("lactationDay")));
|
||||
emptyAna.setSheepCategory((String) sf.get("sheepType"));
|
||||
emptyAna.setBirthday(convertToDate(sf.get("birthday")));
|
||||
emptyAna.setParity(toInteger(sf.get("currentParity")));
|
||||
emptyAna.setMonthAge(toInteger(sf.get("monthAge")));
|
||||
emptyAna.setCurrentWeight(toDouble(sf.get("currentWeight")));
|
||||
emptyAna.setBreedStatus((String) sf.get("breedStatus"));
|
||||
emptyAna.setFatherManageTags((String) sf.get("fatherManageTags"));
|
||||
emptyAna.setMotherManageTags((String) sf.get("motherManageTags"));
|
||||
emptyAna.setRanchName((String) sf.get("ranchName"));
|
||||
emptyAna.setFamily((String) sf.get("family"));
|
||||
}
|
||||
resultList.add(emptyAna);
|
||||
mapByManageTag.put(emptyAna.getManageEarTag(), emptyAna);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 使用静态内部类 Rec
|
||||
List<Rec> recs = new ArrayList<>();
|
||||
for (Map<String, Object> r : records) {
|
||||
Rec rr = new Rec();
|
||||
rr.date = toLocalDate(r.get("classDate"));
|
||||
rr.systemMilk = toDouble(r.get("systemMilk"));
|
||||
rr.correctedMilk = toDouble(r.get("correctedMilk"));
|
||||
rr.parity = (r.get("parity") == null) ? 0 : Integer.parseInt(String.valueOf(r.get("parity")));
|
||||
recs.add(rr);
|
||||
}
|
||||
|
||||
Map<Integer, List<Rec>> byParity = recs.stream().collect(Collectors.groupingBy(r -> r.parity));
|
||||
|
||||
// 使用静态内部类 ParityStat
|
||||
List<ParityStat> parityStats = new ArrayList<>();
|
||||
for (Map.Entry<Integer, List<Rec>> e : byParity.entrySet()) {
|
||||
List<Rec> list = e.getValue();
|
||||
double sumCorr = list.stream().mapToDouble(x -> x.correctedMilk).sum();
|
||||
double sumSys = list.stream().mapToDouble(x -> x.systemMilk).sum();
|
||||
LocalDate first = list.stream().map(x -> x.date).min(LocalDate::compareTo).get();
|
||||
LocalDate last = list.stream().map(x -> x.date).max(LocalDate::compareTo).get();
|
||||
long days = ChronoUnit.DAYS.between(first, last) + 1;
|
||||
ParityStat ps = new ParityStat();
|
||||
ps.parity = e.getKey();
|
||||
ps.sumCorrected = sumCorr;
|
||||
ps.sumSystem = sumSys;
|
||||
ps.first = first;
|
||||
ps.last = last;
|
||||
ps.days = Math.max(days, 1);
|
||||
parityStats.add(ps);
|
||||
}
|
||||
|
||||
parityStats.sort(Comparator.comparingDouble((ParityStat p) -> p.sumCorrected).reversed()
|
||||
.thenComparingInt(p -> p.parity));
|
||||
ParityStat maxParityStat = parityStats.get(0);
|
||||
|
||||
LocalDate windowStart = maxParityStat.first;
|
||||
LocalDate windowEndByDays = windowStart.plusDays(screenDays - 1);
|
||||
LocalDate actualWindowEnd = (maxParityStat.last.isBefore(windowEndByDays)) ? maxParityStat.last : windowEndByDays;
|
||||
|
||||
double sumSystemWindow = recs.stream()
|
||||
.filter(r -> r.parity == maxParityStat.parity && !r.date.isBefore(windowStart) && !r.date.isAfter(actualWindowEnd))
|
||||
.mapToDouble(r -> r.systemMilk).sum();
|
||||
|
||||
double sumCorrectedWindow = recs.stream()
|
||||
.filter(r -> r.parity == maxParityStat.parity && !r.date.isBefore(windowStart) && !r.date.isAfter(actualWindowEnd))
|
||||
.mapToDouble(r -> r.correctedMilk).sum();
|
||||
|
||||
long milkingDays = maxParityStat.days;
|
||||
long denominator = Math.min(milkingDays, screenDays);
|
||||
double avgCorrectedDaily = (denominator > 0) ? (sumCorrectedWindow / (double) denominator) : 0.0;
|
||||
|
||||
double sumParity1 = parityStats.stream().filter(p -> p.parity == 1).mapToDouble(p -> p.sumCorrected).sum();
|
||||
double sumParity2 = parityStats.stream().filter(p -> p.parity == 2).mapToDouble(p -> p.sumCorrected).sum();
|
||||
double sumParity3 = parityStats.stream().filter(p -> p.parity == 3).mapToDouble(p -> p.sumCorrected).sum();
|
||||
double sumParity4 = parityStats.stream().filter(p -> p.parity == 4).mapToDouble(p -> p.sumCorrected).sum();
|
||||
|
||||
// 你之前的 computeParityAvg 方法里没实现,保留调用0
|
||||
double avgP1 = computeParityAvg(parityStats, 1, screenDays);
|
||||
double avgP2 = computeParityAvg(parityStats, 2, screenDays);
|
||||
double avgP3 = computeParityAvg(parityStats, 3, screenDays);
|
||||
double avgP4 = computeParityAvg(parityStats, 4, screenDays);
|
||||
|
||||
LocalDate lastDate = recs.stream().map(r -> r.date).max(LocalDate::compareTo).get();
|
||||
double avgLast7 = computeLastNDaysAvg(recs, lastDate, 7);
|
||||
double avgLast14 = computeLastNDaysAvg(recs, lastDate, 14);
|
||||
double avgLast30 = computeLastNDaysAvg(recs, lastDate, 30);
|
||||
|
||||
double weightCoefficient = 1.0;
|
||||
if (sf != null && sf.get("weighCoefficient") != null) {
|
||||
weightCoefficient = toDouble(sf.get("weighCoefficient"));
|
||||
}
|
||||
double avgLast7Corrected = avgLast7 * weightCoefficient;
|
||||
|
||||
NpSheepMilkAnalysis ana = new NpSheepMilkAnalysis();
|
||||
ana.setSheepId(sheepId);
|
||||
ana.setManageEarTag(sf == null ? null : (String) sf.get("manageEarTag"));
|
||||
ana.setVariety(sf == null ? null : (String) sf.get("variety"));
|
||||
ana.setMilkingStartTime(toDate(windowStart));
|
||||
ana.setDryEndTime(toDate(maxParityStat.last));
|
||||
ana.setMilkingDays((int) milkingDays);
|
||||
ana.setScreenDays(screenDays);
|
||||
ana.setMaxParity(maxParityStat.parity);
|
||||
ana.setSumSystemMilk(sumSystemWindow);
|
||||
ana.setSumCorrectedMilk(sumCorrectedWindow);
|
||||
ana.setAvgCorrectedDaily(avgCorrectedDaily);
|
||||
ana.setSumParity1Milk(sumParity1);
|
||||
ana.setSumParity2Milk(sumParity2);
|
||||
ana.setSumParity3Milk(sumParity3);
|
||||
ana.setSumParity4Milk(sumParity4);
|
||||
ana.setAvgParity1Daily(avgP1);
|
||||
ana.setAvgParity2Daily(avgP2);
|
||||
ana.setAvgParity3Daily(avgP3);
|
||||
ana.setAvgParity4Daily(avgP4);
|
||||
ana.setLactationDays(toInteger(sf == null ? null : sf.get("lactationDay")));
|
||||
ana.setAvgLast7Milk(avgLast7);
|
||||
ana.setAvgLast7Corrected(avgLast7Corrected);
|
||||
ana.setAvgLast14Milk(avgLast14);
|
||||
ana.setAvgLast30Milk(avgLast30);
|
||||
|
||||
if (sf != null) {
|
||||
ana.setSheepCategory((String) sf.get("sheepType"));
|
||||
ana.setBirthday(convertToDate(sf.get("birthday")));
|
||||
ana.setParity(toInteger(sf.get("currentParity")));
|
||||
ana.setMonthAge(toInteger(sf.get("monthAge")));
|
||||
ana.setCurrentWeight(toDouble(sf.get("currentWeight")));
|
||||
ana.setBreedStatus((String) sf.get("breedStatus"));
|
||||
ana.setFatherManageTags((String) sf.get("fatherManageTags"));
|
||||
ana.setMotherManageTags((String) sf.get("motherManageTags"));
|
||||
ana.setRanchName((String) sf.get("ranchName"));
|
||||
ana.setFamily((String) sf.get("family"));
|
||||
}
|
||||
|
||||
ana.setLastUpdate(toDate(lastDate));
|
||||
|
||||
resultList.add(ana);
|
||||
mapByManageTag.put(ana.getManageEarTag(), ana);
|
||||
}
|
||||
|
||||
// 填充母亲相关字段
|
||||
for (NpSheepMilkAnalysis a : resultList) {
|
||||
String motherTag = a.getMotherManageTags();
|
||||
if (motherTag != null && mapByManageTag.containsKey(motherTag)) {
|
||||
NpSheepMilkAnalysis mom = mapByManageTag.get(motherTag);
|
||||
a.setMotherMilkingDays(mom.getMilkingDays());
|
||||
a.setMotherSumCorrected(mom.getSumCorrectedMilk());
|
||||
a.setMotherMaxParity(mom.getMaxParity());
|
||||
a.setMotherAvgCorrectedDaily(mom.getAvgCorrectedDaily());
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis) {
|
||||
return npSheepMilkAnalysisMapper.insertNpSheepMilkAnalysis(analysis);
|
||||
private static Date convertToDate(Object obj) {
|
||||
if (obj == null) return null;
|
||||
if (obj instanceof Date) {
|
||||
return (Date) obj;
|
||||
}
|
||||
if (obj instanceof java.sql.Date) {
|
||||
return new Date(((java.sql.Date) obj).getTime());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateNpSheepMilkAnalysis(NpSheepMilkAnalysis analysis) {
|
||||
return npSheepMilkAnalysisMapper.updateNpSheepMilkAnalysis(analysis);
|
||||
private static LocalDate toLocalDate(Object obj) {
|
||||
if (obj == null) return null;
|
||||
if (obj instanceof java.sql.Date) {
|
||||
return ((java.sql.Date) obj).toLocalDate();
|
||||
}
|
||||
if (obj instanceof Date) {
|
||||
return ((Date) obj).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteNpSheepMilkAnalysisById(Long id) {
|
||||
return npSheepMilkAnalysisMapper.deleteNpSheepMilkAnalysisById(id);
|
||||
private static Date toDate(LocalDate ld) {
|
||||
if (ld == null) return null;
|
||||
return Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteNpSheepMilkAnalysisByIds(Long[] ids) {
|
||||
return npSheepMilkAnalysisMapper.deleteNpSheepMilkAnalysisByIds(ids);
|
||||
private static Integer toInteger(Object obj) {
|
||||
if (obj == null) return null;
|
||||
if (obj instanceof Number) return ((Number) obj).intValue();
|
||||
try {
|
||||
return Integer.parseInt(obj.toString());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Double toDouble(Object obj) {
|
||||
if (obj == null) return 0.0;
|
||||
if (obj instanceof Number) return ((Number) obj).doubleValue();
|
||||
try {
|
||||
return Double.parseDouble(obj.toString());
|
||||
} catch (Exception e) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private double computeParityAvg(List<ParityStat> stats, int parity, int screenDays) {
|
||||
// 这里你之前实现是直接返回0,可按需完善
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private double computeLastNDaysAvg(List<Rec> recs, LocalDate lastDate, int days) {
|
||||
LocalDate startDate = lastDate.minusDays(days - 1);
|
||||
double sum = 0;
|
||||
int count = 0;
|
||||
for (Rec r : recs) {
|
||||
if (r.date != null && !r.date.isBefore(startDate) && !r.date.isAfter(lastDate)) {
|
||||
sum += r.correctedMilk;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return (count > 0) ? (sum / count) : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,151 +2,61 @@
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.zhyc.module.dairyProducts.mapper.NpSheepMilkAnalysisMapper">
|
||||
|
||||
<resultMap id="NpSheepMilkAnalysisResultMap" type="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
|
||||
<id column="id" property="id"/>
|
||||
<result column="manage_ear_tag" property="manageEarTag"/>
|
||||
<result column="variety" property="variety"/>
|
||||
<result column="milking_date" property="milkingDate"/>
|
||||
<result column="dry_date" property="dryDate"/>
|
||||
<result column="milking_days" property="milkingDays"/>
|
||||
<result column="max_parity" property="maxParity"/>
|
||||
<result column="total_milk" property="totalMilk"/>
|
||||
<result column="total_corrected_milk" property="totalCorrectedMilk"/>
|
||||
<result column="avg_daily_corrected_milk" property="avgDailyCorrectedMilk"/>
|
||||
<result column="parity1_total_milk" property="parity1TotalMilk"/>
|
||||
<result column="parity2_total_milk" property="parity2TotalMilk"/>
|
||||
<result column="parity3_total_milk" property="parity3TotalMilk"/>
|
||||
<result column="parity4_total_milk" property="parity4TotalMilk"/>
|
||||
<result column="parity1_avg_milk" property="parity1AvgMilk"/>
|
||||
<result column="parity2_avg_milk" property="parity2AvgMilk"/>
|
||||
<result column="parity3_avg_milk" property="parity3AvgMilk"/>
|
||||
<result column="parity4_avg_milk" property="parity4AvgMilk"/>
|
||||
<result column="lactation_days" property="lactationDays"/>
|
||||
<result column="last_7_avg_milk" property="last7AvgMilk"/>
|
||||
<result column="last_7_corrected_milk" property="last7CorrectedMilk"/>
|
||||
<result column="last_14_avg_milk" property="last14AvgMilk"/>
|
||||
<result column="last_30_avg_milk" property="last30AvgMilk"/>
|
||||
<result column="sheep_type" property="sheepType"/>
|
||||
<result column="birthday" property="birthday"/>
|
||||
<result column="current_parity" property="currentParity"/>
|
||||
<result column="month_age" property="monthAge"/>
|
||||
<result column="current_weight" property="currentWeight"/>
|
||||
<result column="breed_status" property="breedStatus"/>
|
||||
<result column="father_tag" property="fatherTag"/>
|
||||
<result column="mother_tag" property="motherTag"/>
|
||||
<result column="ranch" property="ranch"/>
|
||||
<result column="family" property="family"/>
|
||||
<result column="mother_milking_days" property="motherMilkingDays"/>
|
||||
<result column="mother_total_corrected_milk" property="motherTotalCorrectedMilk"/>
|
||||
<result column="mother_max_parity" property="motherMaxParity"/>
|
||||
<result column="mother_avg_corrected" property="motherAvgCorrected"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id, manage_ear_tag, variety, milking_date, dry_date, milking_days,
|
||||
screen_days, max_parity, total_milk, total_corrected_milk,
|
||||
avg_daily_corrected_milk, parity1_total_milk, parity2_total_milk,
|
||||
parity3_total_milk, parity4_total_milk, parity1_avg_milk,
|
||||
parity2_avg_milk, parity3_avg_milk, parity4_avg_milk,
|
||||
lactation_days, last_7_avg_milk, last_7_corrected_milk,
|
||||
last_14_avg_milk, last_30_avg_milk, sheep_type, birthday,
|
||||
current_parity, month_age, current_weight, breed_status,
|
||||
father_tag, mother_tag, ranch, family, mother_milking_days,
|
||||
mother_total_corrected_milk, mother_max_parity,
|
||||
mother_avg_corrected
|
||||
</sql>
|
||||
|
||||
<select id="selectNpSheepMilkAnalysisById" resultMap="NpSheepMilkAnalysisResultMap">
|
||||
SELECT <include refid="Base_Column_List"/>
|
||||
FROM np_sheep_milk_analysis
|
||||
WHERE id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectNpSheepMilkAnalysisList" resultMap="NpSheepMilkAnalysisResultMap">
|
||||
SELECT <include refid="Base_Column_List"/>
|
||||
FROM np_sheep_milk_analysis
|
||||
<!-- 1) 获取 distinct sheep_id(支持按 sheep_file.bs_manage_tags 模糊搜索) -->
|
||||
<select id="selectDistinctSheepIds" resultType="string" parameterType="map">
|
||||
SELECT DISTINCT a.sheep_id
|
||||
FROM np_milk_prod_classes a
|
||||
LEFT JOIN sheep_file sf ON a.sheep_id = sf.id
|
||||
<where>
|
||||
<if test="manageEarTag != null and manageEarTag != ''">
|
||||
AND manage_ear_tag LIKE CONCAT('%', #{manageEarTag}, '%')
|
||||
AND sf.bs_manage_tags LIKE CONCAT('%', #{manageEarTag}, '%')
|
||||
</if>
|
||||
<!-- 可继续添加其他搜索条件 -->
|
||||
</where>
|
||||
ORDER BY milking_date DESC
|
||||
ORDER BY a.sheep_id
|
||||
</select>
|
||||
|
||||
<insert id="insertNpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
|
||||
INSERT INTO np_sheep_milk_analysis (
|
||||
<include refid="Base_Column_List"/>
|
||||
) VALUES (
|
||||
#{id}, #{manageEarTag}, #{variety}, #{milkingDate}, #{dryDate},
|
||||
#{milkingDays}, #{screenDays}, #{maxParity}, #{totalMilk},
|
||||
#{totalCorrectedMilk}, #{avgDailyCorrectedMilk}, #{parity1TotalMilk},
|
||||
#{parity2TotalMilk}, #{parity3TotalMilk}, #{parity4TotalMilk},
|
||||
#{parity1AvgMilk}, #{parity2AvgMilk}, #{parity3AvgMilk},
|
||||
#{parity4AvgMilk}, #{lactationDays}, #{last7AvgMilk},
|
||||
#{last7CorrectedMilk}, #{last14AvgMilk}, #{last30AvgMilk},
|
||||
#{sheepType}, #{birthday}, #{currentParity}, #{monthAge},
|
||||
#{currentWeight}, #{breedStatus}, #{fatherTag}, #{motherTag},
|
||||
#{ranch}, #{family}, #{motherMilkingDays},
|
||||
#{motherTotalCorrectedMilk}, #{motherMaxParity},
|
||||
#{motherAvgCorrected}
|
||||
)
|
||||
</insert>
|
||||
<!-- 2) 获取某只羊的所有班次记录(按班次日期升序) -->
|
||||
<!-- 假设表中字段:class_date, system_milk, corrected_milk, parity -->
|
||||
<select id="selectMilkRecordsBySheepId" resultType="map" parameterType="string">
|
||||
SELECT
|
||||
datetime AS classDate,
|
||||
milk AS systemMilk,
|
||||
corrected_milk AS correctedMilk,
|
||||
classes AS parity
|
||||
FROM np_milk_prod_classes
|
||||
WHERE sheep_id = #{sheepId}
|
||||
ORDER BY datetime ASC
|
||||
</select>
|
||||
|
||||
<update id="updateNpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
|
||||
UPDATE np_sheep_milk_analysis
|
||||
SET manage_ear_tag = #{manageEarTag},
|
||||
variety = #{variety},
|
||||
milking_date = #{milkingDate},
|
||||
dry_date = #{dryDate},
|
||||
milking_days = #{milkingDays},
|
||||
screen_days = #{screenDays},
|
||||
max_parity = #{maxParity},
|
||||
total_milk = #{totalMilk},
|
||||
total_corrected_milk = #{totalCorrectedMilk},
|
||||
avg_daily_corrected_milk = #{avgDailyCorrectedMilk},
|
||||
parity1_total_milk = #{parity1TotalMilk},
|
||||
parity2_total_milk = #{parity2TotalMilk},
|
||||
parity3_total_milk = #{parity3TotalMilk},
|
||||
parity4_total_milk = #{parity4TotalMilk},
|
||||
parity1_avg_milk = #{parity1AvgMilk},
|
||||
parity2_avg_milk = #{parity2AvgMilk},
|
||||
parity3_avg_milk = #{parity3AvgMilk},
|
||||
parity4_avg_milk = #{parity4AvgMilk},
|
||||
lactation_days = #{lactationDays},
|
||||
last_7_avg_milk = #{last7AvgMilk},
|
||||
last_7_corrected_milk = #{last7CorrectedMilk},
|
||||
last_14_avg_milk = #{last14AvgMilk},
|
||||
last_30_avg_milk = #{last30AvgMilk},
|
||||
sheep_type = #{sheepType},
|
||||
birthday = #{birthday},
|
||||
current_parity = #{currentParity},
|
||||
month_age = #{monthAge},
|
||||
current_weight = #{currentWeight},
|
||||
breed_status = #{breedStatus},
|
||||
father_tag = #{fatherTag},
|
||||
mother_tag = #{motherTag},
|
||||
ranch = #{ranch},
|
||||
family = #{family},
|
||||
mother_milking_days = #{motherMilkingDays},
|
||||
mother_total_corrected_milk = #{motherTotalCorrectedMilk},
|
||||
mother_max_parity = #{motherMaxParity},
|
||||
mother_avg_corrected = #{motherAvgCorrected}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteNpSheepMilkAnalysisById" parameterType="Long">
|
||||
DELETE FROM np_sheep_milk_analysis WHERE id = #{id}
|
||||
</delete>
|
||||
<!-- 3) 获取该羊在 sheep_file 视图中的基础信息 -->
|
||||
<!-- 假设字段名称:bs_manage_tags、variety、lactation_day、name、birthday、parity、month_age、current_weight、breed、father_manage_tags、mother_manage_tags、dr_ranch、family -->
|
||||
<select id="selectSheepFileBySheepId" resultType="map" parameterType="string">
|
||||
SELECT
|
||||
id AS sheep_id,
|
||||
bs_manage_tags AS manageEarTag,
|
||||
variety,
|
||||
lactation_day AS lactationDay,
|
||||
name AS sheepType,
|
||||
birthday,
|
||||
parity AS currentParity,
|
||||
month_age AS monthAge,
|
||||
current_weight AS currentWeight,
|
||||
breed AS breedStatus,
|
||||
father_manage_tags AS fatherManageTags,
|
||||
mother_manage_tags AS motherManageTags,
|
||||
dr_ranch AS ranchName,
|
||||
family
|
||||
FROM sheep_file
|
||||
WHERE id = #{sheepId}
|
||||
</select>
|
||||
|
||||
<delete id="deleteNpSheepMilkAnalysisByIds" parameterType="Long">
|
||||
DELETE FROM np_sheep_milk_analysis WHERE id IN
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
<!-- 4) 兼容旧 list 查询(返回 domain 对象列表),但在我们的实现中 service 会构造最终的 NpSheepMilkAnalysis 列表 -->
|
||||
<select id="selectNpSheepMilkAnalysisList" resultType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
|
||||
<!-- 如果你仍需基于某张表的简单映射,可在此实现;当前我们在 ServiceImpl 中组装对象,所以该查询不做复杂实现 -->
|
||||
SELECT 1 FROM dual WHERE 1=0
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
Loading…
x
Reference in New Issue
Block a user