奶产量分析

This commit is contained in:
ll 2025-08-13 18:55:55 +08:00
parent 8eedf3b3ff
commit c9f05d722f
6 changed files with 380 additions and 209 deletions

View File

@ -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, "羊奶产量分析数据");
}
}

View File

@ -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; }
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

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