Merge remote-tracking branch 'origin/main'

This commit is contained in:
漂泊 2025-09-04 10:51:15 +08:00
commit b47e1d115a
55 changed files with 2673 additions and 306 deletions

View File

@ -33,6 +33,11 @@ public @interface Excel
*/ */
public String dateFormat() default ""; public String dateFormat() default "";
/**
* 数字格式, : 0.00
*/
public String numFormat() default ""; // 新增数字格式属性
/** /**
* 如果是字典类型请设置字典的type值 (: sys_user_sex) * 如果是字典类型请设置字典的type值 (: sys_user_sex)
*/ */

View File

@ -1142,7 +1142,6 @@ public class ExcelUtil<T>
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column)); sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
} }
} }
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
@ -1150,14 +1149,33 @@ public class ExcelUtil<T>
String readConverterExp = attr.readConverterExp(); String readConverterExp = attr.readConverterExp();
String separator = attr.separator(); String separator = attr.separator();
String dictType = attr.dictType(); String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) String numFormat = attr.numFormat(); // 获取数字格式
// 创建单元格样式
CellStyle cellStyle = wb.createCellStyle();
cellStyle.cloneStyleFrom(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}",
attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
// 处理日期格式
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value) && value instanceof Date)
{ {
cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat)); DataFormat format = wb.createDataFormat();
cell.setCellValue(parseDateToStr(dateFormat, value)); cellStyle.setDataFormat(format.getFormat(dateFormat));
cell.setCellValue((Date) value);
cell.setCellStyle(cellStyle);
}
// 处理数字格式
else if (StringUtils.isNotEmpty(numFormat) && StringUtils.isNotNull(value) && value instanceof Number)
{
DataFormat format = wb.createDataFormat();
cellStyle.setDataFormat(format.getFormat(numFormat));
cell.setCellValue(((Number) value).doubleValue());
cell.setCellStyle(cellStyle);
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{ {
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
cell.setCellStyle(cellStyle);
} }
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{ {
@ -1167,20 +1185,32 @@ public class ExcelUtil<T>
sysDictMap.put(dictType + value, lable); sysDictMap.put(dictType + value, lable);
} }
cell.setCellValue(sysDictMap.get(dictType + value)); cell.setCellValue(sysDictMap.get(dictType + value));
cell.setCellStyle(cellStyle);
} }
else if (value instanceof BigDecimal && -1 != attr.scale()) else if (value instanceof BigDecimal && -1 != attr.scale())
{ {
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
cell.setCellStyle(cellStyle);
} }
else if (!attr.handler().equals(ExcelHandlerAdapter.class)) else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{ {
cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell)); cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
cell.setCellStyle(cellStyle);
} }
else else
{ {
// 设置列类型 // 设置列类型
setCellVo(value, attr, cell); setCellVo(value, attr, cell);
// 对于日期类型确保应用日期格式
if (value instanceof Date && StringUtils.isNotEmpty(dateFormat)) {
DataFormat format = wb.createDataFormat();
CellStyle dateStyle = wb.createCellStyle();
dateStyle.cloneStyleFrom(cell.getCellStyle());
dateStyle.setDataFormat(format.getFormat(dateFormat));
cell.setCellStyle(dateStyle);
} }
}
addStatisticsData(column, Convert.toStr(value), attr); addStatisticsData(column, Convert.toStr(value), attr);
} }
} }
@ -1254,7 +1284,7 @@ public class ExcelUtil<T>
DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容 // 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
// 设置数据有效性加载在哪个单元格上,四个参数分别是起始行终止行起始列终止列 // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行终止行起始列终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象 // 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, regions); DataValidation dataValidation = helper.createValidation(constraint, regions);
@ -1754,7 +1784,7 @@ public class ExcelUtil<T>
* @param workbook 工作簿对象 * @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData * @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/ */
public static Map<String, List<PictureData>> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) public static Map<String, List<PictureData> > getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
{ {
Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>(); Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>();
List<HSSFPictureData> pictures = workbook.getAllPictures(); List<HSSFPictureData> pictures = workbook.getAllPictures();

View File

@ -2,6 +2,7 @@ package com.zhyc.module.base.mapper;
import com.zhyc.module.base.domain.BasSheepGroup; import com.zhyc.module.base.domain.BasSheepGroup;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -64,4 +65,8 @@ public interface BasSheepGroupMapper
List<BasSheepGroup> selectLeafNodes(); List<BasSheepGroup> selectLeafNodes();
// 新增方法根据父节点和分组名称查询是否存在
BasSheepGroup selectByParentIdAndGroupName(@Param("parentId") Long parentId, @Param("groupName") String groupName);
} }

View File

@ -1,5 +1,6 @@
package com.zhyc.module.base.service.impl; package com.zhyc.module.base.service.impl;
import com.zhyc.common.exception.ServiceException;
import com.zhyc.common.utils.DateUtils; import com.zhyc.common.utils.DateUtils;
import com.zhyc.module.base.domain.BasSheepGroup; import com.zhyc.module.base.domain.BasSheepGroup;
import com.zhyc.module.base.mapper.BasSheepGroupMapper; import com.zhyc.module.base.mapper.BasSheepGroupMapper;
@ -68,6 +69,12 @@ public class BasSheepGroupServiceImpl implements IBasSheepGroupService
@Override @Override
public int insertBasSheepGroup(BasSheepGroup basSheepGroup) public int insertBasSheepGroup(BasSheepGroup basSheepGroup)
{ {
// 新增唯一性校验
BasSheepGroup existing = basSheepGroupMapper.selectByParentIdAndGroupName(
basSheepGroup.getParentId(), basSheepGroup.getGroupName());
if (existing != null) {
throw new ServiceException("同一分支下已存在该分组名称");
}
basSheepGroup.setCreateTime(DateUtils.getNowDate()); basSheepGroup.setCreateTime(DateUtils.getNowDate());
return basSheepGroupMapper.insertBasSheepGroup(basSheepGroup); return basSheepGroupMapper.insertBasSheepGroup(basSheepGroup);
} }
@ -81,6 +88,12 @@ public class BasSheepGroupServiceImpl implements IBasSheepGroupService
@Override @Override
public int updateBasSheepGroup(BasSheepGroup basSheepGroup) public int updateBasSheepGroup(BasSheepGroup basSheepGroup)
{ {
// 新增唯一性校验排除当前记录
BasSheepGroup existing = basSheepGroupMapper.selectByParentIdAndGroupName(
basSheepGroup.getParentId(), basSheepGroup.getGroupName());
if (existing != null && !existing.getGroupId().equals(basSheepGroup.getGroupId())) {
throw new ServiceException("同一分支下已存在该分组名称");
}
basSheepGroup.setUpdateTime(DateUtils.getNowDate()); basSheepGroup.setUpdateTime(DateUtils.getNowDate());
return basSheepGroupMapper.updateBasSheepGroup(basSheepGroup); return basSheepGroupMapper.updateBasSheepGroup(basSheepGroup);
} }

View File

@ -58,10 +58,12 @@ public class NpMilkProdClassesController extends BaseController {
public void export(HttpServletResponse response, public void export(HttpServletResponse response,
@RequestParam(required = false) Date datetimeStart, @RequestParam(required = false) Date datetimeStart,
@RequestParam(required = false) Date datetimeEnd, @RequestParam(required = false) Date datetimeEnd,
@RequestParam(required = false) String manageEarNos, @RequestParam(required = false) String manageEarNo,
@RequestParam(required = false) String factory, @RequestParam(required = false) String factory,
@RequestParam(required = false) Integer classes) { @RequestParam(required = false) Integer classes) {
List<NpMilkProdClasses> list = npMilkProdClassesService.selectNpMilkProdClassesList(datetimeStart, datetimeEnd, manageEarNos, factory, classes); List<NpMilkProdClasses> list = npMilkProdClassesService.selectNpMilkProdClassesList(
datetimeStart, datetimeEnd, manageEarNo, factory, classes);
ExcelUtil<NpMilkProdClasses> util = new ExcelUtil<>(NpMilkProdClasses.class); ExcelUtil<NpMilkProdClasses> util = new ExcelUtil<>(NpMilkProdClasses.class);
util.exportExcel(response, list, "班次产奶数据"); util.exportExcel(response, list, "班次产奶数据");
} }

View File

@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
/** /**
* 奶产量分析控制器
* 只保留分页列表只读 + 单条查询 + 导出 * 只保留分页列表只读 + 单条查询 + 导出
*/ */
@RestController @RestController
@ -29,13 +30,13 @@ public class NpSheepMilkAnalysisController extends BaseController {
*/ */
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(NpSheepMilkAnalysis analysis) { public TableDataInfo list(NpSheepMilkAnalysis analysis) {
startPage(); // 使用 PageHelper 分页注意 service 中第一个 DB 调用是 distinct sheep id startPage(); // 使用PageHelper分页注意service中第一个DB调用是distinct sheep id
List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisList(analysis); List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisList(analysis);
return getDataTable(list); return getDataTable(list);
} }
/** /**
* 获取单个分析记录详细信息 sheepId * 获取单个分析记录详细信息sheepId
*/ */
@GetMapping(value = "/{sheepId}") @GetMapping(value = "/{sheepId}")
public AjaxResult getInfo(@PathVariable("sheepId") String sheepId) { public AjaxResult getInfo(@PathVariable("sheepId") String sheepId) {
@ -44,12 +45,12 @@ public class NpSheepMilkAnalysisController extends BaseController {
/** /**
* 导出奶产量分析记录Excel * 导出奶产量分析记录Excel
* 支持 manageEarTag screenDays 两个查询条件 * 支持manageEarTag与screenDays两个查询条件
*/ */
@Log(title = "奶产量分析 导出", businessType = BusinessType.EXPORT) @Log(title = "奶产量分析 导出", businessType = BusinessType.EXPORT)
@GetMapping("/export") @GetMapping("/export")
public AjaxResult export(NpSheepMilkAnalysis analysis) { public AjaxResult export(NpSheepMilkAnalysis analysis) {
List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisList(analysis); List<NpSheepMilkAnalysis> list = npSheepMilkAnalysisService.selectNpSheepMilkAnalysisForExport(analysis);
ExcelUtil<NpSheepMilkAnalysis> util = new ExcelUtil<>(NpSheepMilkAnalysis.class); ExcelUtil<NpSheepMilkAnalysis> util = new ExcelUtil<>(NpSheepMilkAnalysis.class);
return util.exportExcel(list, "羊奶产量分析数据"); return util.exportExcel(list, "羊奶产量分析数据");
} }

View File

@ -19,12 +19,13 @@ import com.zhyc.common.enums.BusinessType;
import com.zhyc.module.dairyProducts.domain.XzParityCorrection; import com.zhyc.module.dairyProducts.domain.XzParityCorrection;
import com.zhyc.module.dairyProducts.service.IXzParityCorrectionService; import com.zhyc.module.dairyProducts.service.IXzParityCorrectionService;
import com.zhyc.common.utils.poi.ExcelUtil; import com.zhyc.common.utils.poi.ExcelUtil;
import com.zhyc.common.core.page.TableDataInfo;
/** /**
* 胎次校正Controller * 胎次校正Controller
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-14 * @date 2025-08-24
*/ */
@RestController @RestController
@RequestMapping("/parityCorrection/parityCorrection") @RequestMapping("/parityCorrection/parityCorrection")
@ -37,20 +38,12 @@ public class XzParityCorrectionController extends BaseController
* 查询胎次校正列表 * 查询胎次校正列表
*/ */
@PreAuthorize("@ss.hasPermi('parityCorrection:parityCorrection:list')") @PreAuthorize("@ss.hasPermi('parityCorrection:parityCorrection:list')")
// @GetMapping("/list") @GetMapping("/list")
// public TableDataInfo list(XzParityCorrection xzParityCorrection) public TableDataInfo list(XzParityCorrection xzParityCorrection)
// { {
// startPage(); startPage();
// List<XzParityCorrection> list = xzParityCorrectionService.selectXzParityCorrectionList(xzParityCorrection);
// return getDataTable(list);
// }
/**
* 获取全部胎次校正无需分页供下拉/列表直接显示
*/
@GetMapping("/listAll")
public AjaxResult listAll(XzParityCorrection xzParityCorrection){
List<XzParityCorrection> list = xzParityCorrectionService.selectXzParityCorrectionList(xzParityCorrection); List<XzParityCorrection> list = xzParityCorrectionService.selectXzParityCorrectionList(xzParityCorrection);
return success(list); // 直接返回数组 return getDataTable(list);
} }
/** /**

View File

@ -15,7 +15,7 @@ public class NpMilkProdClasses implements Serializable {
private Date updateTime; // 更新时间 private Date updateTime; // 更新时间
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "日期") @Excel(name = "日期", dateFormat = "yyyy-MM-dd") // 添加日期格式
private Date datetime; private Date datetime;
@Excel(name = "管理耳号") @Excel(name = "管理耳号")
@ -33,10 +33,10 @@ public class NpMilkProdClasses implements Serializable {
@Excel(name = "班次") @Excel(name = "班次")
private Integer classes; private Integer classes;
@Excel(name = "班次产奶量") @Excel(name = "班次产奶量", numFormat = "0.00")
private Double milk; private Double milk;
@Excel(name = "班次校正奶量") @Excel(name = "班次校正奶量", numFormat = "0.00")
private Double correctedMilk; private Double correctedMilk;
private String sheepId; private String sheepId;

View File

@ -1,78 +1,141 @@
package com.zhyc.module.dairyProducts.domain; package com.zhyc.module.dairyProducts.domain;
import com.zhyc.common.annotation.Excel;
import java.util.Date; import java.util.Date;
public class NpSheepMilkAnalysis { public class NpSheepMilkAnalysis {
// 唯一键可用于前端 row-key // 唯一键可用于前端 row-key
@Excel(name = "羊只ID")
private String sheepId; private String sheepId;
// 耳号 sheep_file.bs_manage_tags // 耳号 sheep_file.bs_manage_tags
@Excel(name = "耳号")
private String manageEarTag; private String manageEarTag;
@Excel(name = "品种")
private String variety; private String variety;
// 最高校正胎次的挤奶开始时间 & 干奶时间 // 最高校正胎次的挤奶开始时间 & 干奶时间
@Excel(name = "挤奶开始时间", dateFormat = "yyyy-MM-dd")
private Date milkingStartTime; private Date milkingStartTime;
@Excel(name = "干奶时间", dateFormat = "yyyy-MM-dd")
private Date dryEndTime; private Date dryEndTime;
// 挤奶天数该胎次 // 挤奶天数该胎次
@Excel(name = "挤奶天数")
private Integer milkingDays; private Integer milkingDays;
// 前端传入的筛选天数screenDays // 前端传入的筛选天数screenDays
@Excel(name = "筛选天数")
private Integer screenDays; private Integer screenDays;
// 分析天数若你有不同命名可忽略 // 分析天数若你有不同命名可忽略
private Integer analysisDays; private Integer analysisDays;
// 校正后最大胎次即校正奶量之和最大的胎次 // 校正后最大胎次即校正奶量之和最大的胎次
@Excel(name = "校正后最大胎次")
private Integer maxParity; private Integer maxParity;
// 最高校正胎次区间内的系统奶量与校正奶量按筛选窗口 // 最高校正胎次区间内的系统奶量与校正奶量按筛选窗口
@Excel(name = "系统奶量合计")
private Double sumSystemMilk; private Double sumSystemMilk;
@Excel(name = "校正奶量合计")
private Double sumCorrectedMilk; private Double sumCorrectedMilk;
// 校正日平均奶量 min(挤奶天数, 筛选天数) // 校正日平均奶量按min(挤奶天数,筛选天数)
@Excel(name = "校正日平均奶量")
private Double avgCorrectedDaily; private Double avgCorrectedDaily;
// 各胎次总奶量校正 // 各胎次总奶量校正
@Excel(name = "胎次1总奶量")
private Double sumParity1Milk; private Double sumParity1Milk;
@Excel(name = "胎次2总奶量")
private Double sumParity2Milk; private Double sumParity2Milk;
@Excel(name = "胎次3总奶量")
private Double sumParity3Milk; private Double sumParity3Milk;
@Excel(name = "胎次4总奶量")
private Double sumParity4Milk; private Double sumParity4Milk;
// 各胎次日平均按规则 // 各胎次日平均按规则
@Excel(name = "胎次1日平均")
private Double avgParity1Daily; private Double avgParity1Daily;
@Excel(name = "胎次2日平均")
private Double avgParity2Daily; private Double avgParity2Daily;
@Excel(name = "胎次3日平均")
private Double avgParity3Daily; private Double avgParity3Daily;
@Excel(name = "胎次4日平均")
private Double avgParity4Daily; private Double avgParity4Daily;
// 泌乳天数sheep_file.lactation_day // 泌乳天数sheep_file.lactation_day
@Excel(name = "泌乳天数")
private Integer lactationDays; private Integer lactationDays;
// 过去 7 / 14 / 30 日平均系统奶量 // 过去7/14/30日平均系统奶量
@Excel(name = "过去7日均奶量")
private Double avgLast7Milk; private Double avgLast7Milk;
private Double avgLast7Corrected; // = avgLast7Milk * weightCoefficient 默认 1.0
@Excel(name = "校正过去7日均")
private Double avgLast7Corrected;
@Excel(name = "过去14日均奶量")
private Double avgLast14Milk; private Double avgLast14Milk;
@Excel(name = "过去30日均奶量")
private Double avgLast30Milk; private Double avgLast30Milk;
// 羊只基础信息来自 sheep_file // 羊只基础信息来自sheep_file
@Excel(name = "羊只类别")
private String sheepCategory; private String sheepCategory;
@Excel(name = "生日", dateFormat = "yyyy-MM-dd")
private Date birthday; private Date birthday;
private Integer parity; // 当前胎次
@Excel(name = "当前胎次")
private Integer parity;
@Excel(name = "月龄")
private Integer monthAge; private Integer monthAge;
@Excel(name = "当前体重")
private Double currentWeight; private Double currentWeight;
@Excel(name = "繁育状态")
private String breedStatus; private String breedStatus;
@Excel(name = "父号")
private String fatherManageTags; private String fatherManageTags;
@Excel(name = "母号")
private String motherManageTags; private String motherManageTags;
@Excel(name = "牧场")
private String ranchName; private String ranchName;
@Excel(name = "家系")
private String family; private String family;
// 母亲相关字段由已计算的母亲分析结果中取值 // 母亲相关字段由已计算的母亲分析结果中取值
@Excel(name = "母亲挤奶天数")
private Integer motherMilkingDays; private Integer motherMilkingDays;
@Excel(name = "母亲校正奶量合计")
private Double motherSumCorrected; private Double motherSumCorrected;
@Excel(name = "母亲校正后最大胎次")
private Integer motherMaxParity; private Integer motherMaxParity;
@Excel(name = "母亲校正日平均奶量")
private Double motherAvgCorrectedDaily; private Double motherAvgCorrectedDaily;
@Excel(name = "最后更新时间", dateFormat = "yyyy-MM-dd")
private Date lastUpdate; private Date lastUpdate;
// getters and setters // getters and setters

View File

@ -1,8 +1,7 @@
package com.zhyc.module.dairyProducts.domain; package com.zhyc.module.dairyProducts.domain;
import lombok.AllArgsConstructor; import org.apache.commons.lang3.builder.ToStringBuilder;
import lombok.Data; import org.apache.commons.lang3.builder.ToStringStyle;
import lombok.NoArgsConstructor;
import com.zhyc.common.annotation.Excel; import com.zhyc.common.annotation.Excel;
import com.zhyc.common.core.domain.BaseEntity; import com.zhyc.common.core.domain.BaseEntity;
@ -10,11 +9,8 @@ import com.zhyc.common.core.domain.BaseEntity;
* 胎次校正对象 xz_parity_correction * 胎次校正对象 xz_parity_correction
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-14 * @date 2025-08-24
*/ */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class XzParityCorrection extends BaseEntity public class XzParityCorrection extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -30,4 +26,42 @@ public class XzParityCorrection extends BaseEntity
@Excel(name = "系数") @Excel(name = "系数")
private Double coef; private Double coef;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setParity(Integer parity)
{
this.parity = parity;
}
public Integer getParity()
{
return parity;
}
public void setCoef(Double coef)
{
this.coef = coef;
}
public Double getCoef()
{
return coef;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("parity", getParity())
.append("coef", getCoef())
.toString();
}
} }

View File

@ -9,7 +9,7 @@ import java.util.Map;
public interface NpSheepMilkAnalysisMapper { public interface NpSheepMilkAnalysisMapper {
/** /**
* 按筛选天数 screenDays 统计并返回所有羊只的奶产量分析 * 按筛选天数screenDays统计并返回所有羊只的奶产量分析
*/ */
List<NpSheepMilkAnalysis> selectAnalysisForExport(@Param("screenDays") Integer screenDays); List<NpSheepMilkAnalysis> selectAnalysisForExport(@Param("screenDays") Integer screenDays);
@ -33,4 +33,9 @@ public interface NpSheepMilkAnalysisMapper {
*/ */
List<Map<String, Object>> selectMilkRecordsBySheepId(@Param("sheepId") String sheepId); List<Map<String, Object>> selectMilkRecordsBySheepId(@Param("sheepId") String sheepId);
/**
* 导出奶产量分析记录
*/
List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisForExport(NpSheepMilkAnalysis analysis);
} }

View File

@ -2,15 +2,13 @@ package com.zhyc.module.dairyProducts.mapper;
import java.util.List; import java.util.List;
import com.zhyc.module.dairyProducts.domain.XzParityCorrection; import com.zhyc.module.dairyProducts.domain.XzParityCorrection;
import org.apache.ibatis.annotations.Mapper;
/** /**
* 胎次校正Mapper接口 * 胎次校正Mapper接口
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-14 * @date 2025-08-24
*/ */
@Mapper
public interface XzParityCorrectionMapper public interface XzParityCorrectionMapper
{ {
/** /**

View File

@ -9,4 +9,9 @@ public interface INpSheepMilkAnalysisService {
List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisList(NpSheepMilkAnalysis analysis); List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisList(NpSheepMilkAnalysis analysis);
/**
* 导出奶产量分析记录
*/
List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisForExport(NpSheepMilkAnalysis analysis);
} }

View File

@ -1,14 +1,13 @@
package com.zhyc.module.dairyProducts.service; package com.zhyc.module.dairyProducts.service;
import java.util.List; import java.util.List;
import com.zhyc.module.dairyProducts.domain.XzParityCorrection; import com.zhyc.module.dairyProducts.domain.XzParityCorrection;
/** /**
* 胎次校正Service接口 * 胎次校正Service接口
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-14 * @date 2025-08-24
*/ */
public interface IXzParityCorrectionService public interface IXzParityCorrectionService
{ {

View File

@ -19,7 +19,7 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
@Autowired @Autowired
private NpSheepMilkAnalysisMapper npSheepMilkAnalysisMapper; private NpSheepMilkAnalysisMapper npSheepMilkAnalysisMapper;
// Rec 定义为静态内部类 // Rec定义为静态内部类
private static class Rec { private static class Rec {
LocalDate date; LocalDate date;
double systemMilk; double systemMilk;
@ -27,7 +27,7 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
int parity; int parity;
} }
// ParityStat 定义为静态内部类 // ParityStat定义为静态内部类
private static class ParityStat { private static class ParityStat {
int parity; int parity;
double sumCorrected; double sumCorrected;
@ -85,7 +85,7 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
continue; continue;
} }
// 使用静态内部类 Rec // 使用静态内部类Rec
List<Rec> recs = new ArrayList<>(); List<Rec> recs = new ArrayList<>();
for (Map<String, Object> r : records) { for (Map<String, Object> r : records) {
Rec rr = new Rec(); Rec rr = new Rec();
@ -98,7 +98,7 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
Map<Integer, List<Rec>> byParity = recs.stream().collect(Collectors.groupingBy(r -> r.parity)); Map<Integer, List<Rec>> byParity = recs.stream().collect(Collectors.groupingBy(r -> r.parity));
// 使用静态内部类 ParityStat // 使用静态内部类ParityStat
List<ParityStat> parityStats = new ArrayList<>(); List<ParityStat> parityStats = new ArrayList<>();
for (Map.Entry<Integer, List<Rec>> e : byParity.entrySet()) { for (Map.Entry<Integer, List<Rec>> e : byParity.entrySet()) {
List<Rec> list = e.getValue(); List<Rec> list = e.getValue();
@ -142,7 +142,7 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
double sumParity3 = parityStats.stream().filter(p -> p.parity == 3).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(); double sumParity4 = parityStats.stream().filter(p -> p.parity == 4).mapToDouble(p -> p.sumCorrected).sum();
// 你之前的 computeParityAvg 方法里没实现保留调用0 // 你之前的computeParityAvg方法里没实现保留调用0
double avgP1 = computeParityAvg(parityStats, 1, screenDays); double avgP1 = computeParityAvg(parityStats, 1, screenDays);
double avgP2 = computeParityAvg(parityStats, 2, screenDays); double avgP2 = computeParityAvg(parityStats, 2, screenDays);
double avgP3 = computeParityAvg(parityStats, 3, screenDays); double avgP3 = computeParityAvg(parityStats, 3, screenDays);
@ -219,6 +219,12 @@ public class NpSheepMilkAnalysisServiceImpl implements INpSheepMilkAnalysisServi
return resultList; return resultList;
} }
@Override
public List<NpSheepMilkAnalysis> selectNpSheepMilkAnalysisForExport(NpSheepMilkAnalysis analysis) {
// 直接调用Mapper的导出方法避免复杂的业务逻辑
return npSheepMilkAnalysisMapper.selectNpSheepMilkAnalysisForExport(analysis);
}
private static Date convertToDate(Object obj) { private static Date convertToDate(Object obj) {
if (obj == null) return null; if (obj == null) return null;
if (obj instanceof Date) { if (obj instanceof Date) {

View File

@ -44,29 +44,62 @@ public class XzDryMatterCorrectionServiceImpl implements IXzDryMatterCorrectionS
} }
/** /**
* 新增干物质校正 * 新增干物质校正 - 添加默认值和重复校验
*
* @param xzDryMatterCorrection 干物质校正
* @return 结果
*/ */
@Override @Override
public int insertXzDryMatterCorrection(XzDryMatterCorrection xzDryMatterCorrection) public int insertXzDryMatterCorrection(XzDryMatterCorrection xzDryMatterCorrection)
{ {
// 设置干物质标准默认值为18如果未提供
if (xzDryMatterCorrection.getStandard() == null) {
xzDryMatterCorrection.setStandard(18.0);
}
// 检查同年月同厂区是否已存在
if (isDuplicateRecord(xzDryMatterCorrection)) {
throw new RuntimeException("该厂区在同一年月已存在记录,不能重复添加");
}
return xzDryMatterCorrectionMapper.insertXzDryMatterCorrection(xzDryMatterCorrection); return xzDryMatterCorrectionMapper.insertXzDryMatterCorrection(xzDryMatterCorrection);
} }
/** /**
* 修改干物质校正 * 修改干物质校正 - 添加重复校验
*
* @param xzDryMatterCorrection 干物质校正
* @return 结果
*/ */
@Override @Override
public int updateXzDryMatterCorrection(XzDryMatterCorrection xzDryMatterCorrection) public int updateXzDryMatterCorrection(XzDryMatterCorrection xzDryMatterCorrection)
{ {
// 检查同年月同厂区是否已存在排除当前记录
if (isDuplicateRecord(xzDryMatterCorrection)) {
throw new RuntimeException("该厂区在同一年月已存在记录,不能重复添加");
}
return xzDryMatterCorrectionMapper.updateXzDryMatterCorrection(xzDryMatterCorrection); return xzDryMatterCorrectionMapper.updateXzDryMatterCorrection(xzDryMatterCorrection);
} }
/**
* 检查是否存在重复记录同年月同厂区
*/
private boolean isDuplicateRecord(XzDryMatterCorrection xzDryMatterCorrection) {
// 查询相同年月和厂区的记录
XzDryMatterCorrection query = new XzDryMatterCorrection();
query.setDatetime(xzDryMatterCorrection.getDatetime());
query.setFactory(xzDryMatterCorrection.getFactory());
List<XzDryMatterCorrection> existingRecords = xzDryMatterCorrectionMapper.selectXzDryMatterCorrectionList(query);
// 如果是更新操作需要排除当前记录
if (xzDryMatterCorrection.getId() != null) {
return existingRecords.stream()
.anyMatch(record ->
!record.getId().equals(xzDryMatterCorrection.getId())
);
}
// 如果是新增操作只要存在记录就返回true
return !existingRecords.isEmpty();
}
/** /**
* 批量删除干物质校正 * 批量删除干物质校正
* *

View File

@ -1,10 +1,9 @@
package com.zhyc.module.dairyProducts.service.impl; package com.zhyc.module.dairyProducts.service.impl;
import java.util.List; import java.util.List;
import com.zhyc.module.dairyProducts.mapper.XzParityCorrectionMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.zhyc.module.dairyProducts.mapper.XzParityCorrectionMapper;
import com.zhyc.module.dairyProducts.domain.XzParityCorrection; import com.zhyc.module.dairyProducts.domain.XzParityCorrection;
import com.zhyc.module.dairyProducts.service.IXzParityCorrectionService; import com.zhyc.module.dairyProducts.service.IXzParityCorrectionService;
@ -12,7 +11,7 @@ import com.zhyc.module.dairyProducts.service.IXzParityCorrectionService;
* 胎次校正Service业务层处理 * 胎次校正Service业务层处理
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-14 * @date 2025-08-24
*/ */
@Service @Service
public class XzParityCorrectionServiceImpl implements IXzParityCorrectionService public class XzParityCorrectionServiceImpl implements IXzParityCorrectionService

View File

@ -1,7 +1,10 @@
package com.zhyc.module.dairyProducts.service.impl; package com.zhyc.module.dairyProducts.service.impl;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import com.zhyc.common.exception.ServiceException;
import com.zhyc.module.dairyProducts.domain.XzWegihCorrection; import com.zhyc.module.dairyProducts.domain.XzWegihCorrection;
import com.zhyc.module.dairyProducts.mapper.XzWegihCorrectionMapper; import com.zhyc.module.dairyProducts.mapper.XzWegihCorrectionMapper;
import com.zhyc.module.dairyProducts.service.IXzWegihCorrectionService; import com.zhyc.module.dairyProducts.service.IXzWegihCorrectionService;
@ -44,27 +47,60 @@ public class XzWegihCorrectionServiceImpl implements IXzWegihCorrectionService
return xzWegihCorrectionMapper.selectXzWegihCorrectionList(xzWegihCorrection); return xzWegihCorrectionMapper.selectXzWegihCorrectionList(xzWegihCorrection);
} }
/**
* 检查是否已存在相同日期和厂区的记录
* @param datetime 日期
* @param factory 厂区
* @param excludeId 需要排除的ID用于更新操作时排除自身
* @return 如果存在返回true否则返回false
*/
private boolean existsSameDateAndFactory(Date datetime, String factory, Long excludeId) {
// 创建一个查询条件对象
XzWegihCorrection query = new XzWegihCorrection();
query.setDatetime(datetime);
query.setFactory(factory);
// 查询符合条件的记录
List<XzWegihCorrection> existingRecords = xzWegihCorrectionMapper.selectXzWegihCorrectionList(query);
// 如果有需要排除的ID更新操作则过滤掉自身
if (excludeId != null) {
existingRecords = existingRecords.stream()
.filter(record -> !record.getId().equals(excludeId))
.collect(Collectors.toList());
}
// 如果找到记录返回true
return !existingRecords.isEmpty();
}
/** /**
* 新增称重校正 * 新增称重校正
*
* @param xzWegihCorrection 称重校正
* @return 结果
*/ */
@Override @Override
public int insertXzWegihCorrection(XzWegihCorrection xzWegihCorrection) public int insertXzWegihCorrection(XzWegihCorrection xzWegihCorrection)
{ {
// 新增前检查是否已存在相同日期和厂区的记录
if (existsSameDateAndFactory(xzWegihCorrection.getDatetime(), xzWegihCorrection.getFactory(), null)) {
// 抛出异常提示用户已存在相同记录
throw new ServiceException("已存在相同日期和厂区的记录,请勿重复添加");
}
return xzWegihCorrectionMapper.insertXzWegihCorrection(xzWegihCorrection); return xzWegihCorrectionMapper.insertXzWegihCorrection(xzWegihCorrection);
} }
/** /**
* 修改称重校正 * 修改称重校正
*
* @param xzWegihCorrection 称重校正
* @return 结果
*/ */
@Override @Override
public int updateXzWegihCorrection(XzWegihCorrection xzWegihCorrection) public int updateXzWegihCorrection(XzWegihCorrection xzWegihCorrection)
{ {
// 更新前检查是否已存在相同日期和厂区的记录排除自身
if (existsSameDateAndFactory(xzWegihCorrection.getDatetime(), xzWegihCorrection.getFactory(), xzWegihCorrection.getId())) {
// 抛出异常提示用户已存在相同记录
throw new ServiceException("已存在相同日期和厂区的记录,无法修改");
}
return xzWegihCorrectionMapper.updateXzWegihCorrection(xzWegihCorrection); return xzWegihCorrectionMapper.updateXzWegihCorrection(xzWegihCorrection);
} }

View File

@ -1,15 +1,12 @@
package com.zhyc.module.feed.controller; package com.zhyc.module.feed.controller;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.Arrays;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.zhyc.module.feed.domain.SgFeedPlan; import com.zhyc.module.feed.service.impl.SgFeedListServiceImpl;
import com.zhyc.module.feed.domain.SgFormulaManagement;
import com.zhyc.module.feed.service.ISgFeedPlanService;
import com.zhyc.module.feed.service.ISgFormulaManagementService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -41,19 +38,12 @@ import com.zhyc.common.core.page.TableDataInfo;
public class SgFeedListController extends BaseController { public class SgFeedListController extends BaseController {
private final ISgFeedListService sgFeedListService; private final ISgFeedListService sgFeedListService;
private final ISgFormulaManagementService sgFormulaManagementService;
private final ISgFeedPlanService sgFeedPlanService;
private final Map<String, SgFeedList> sgFeedListMap = new HashMap<>();
public static boolean refresh = true; public static boolean refresh = true;
@Autowired @Autowired
public SgFeedListController(ISgFeedListService sgFeedListService, ISgFormulaManagementService sgFormulaManagementService, ISgFeedPlanService sgFeedPlanService) { public SgFeedListController(ISgFeedListService sgFeedListService) {
this.sgFeedListService = sgFeedListService; this.sgFeedListService = sgFeedListService;
this.sgFormulaManagementService = sgFormulaManagementService;
this.sgFeedPlanService = sgFeedPlanService;
} }
/** /**
@ -68,7 +58,7 @@ public class SgFeedListController extends BaseController {
当配方管理表出现更新 饲喂计划表出现增删改时会将refresh置为true 通知此处进行刷新 当配方管理表出现更新 饲喂计划表出现增删改时会将refresh置为true 通知此处进行刷新
*/ */
if (refresh) { if (refresh) {
SyncFeedList(); sgFeedListService.SyncFeedList();
refresh = false; refresh = false;
} }
startPage(); startPage();
@ -76,9 +66,9 @@ public class SgFeedListController extends BaseController {
// map 中已有的数据替换 list 中的元素 // map 中已有的数据替换 list 中的元素
List<SgFeedList> replacedList = new ArrayList<>(); List<SgFeedList> replacedList = new ArrayList<>();
for (SgFeedList item : list) { for (SgFeedList item : list) {
String key = item.getFormulaId() + "_" + item.getFormulaBatchId(); String key = item.getFormulaId() + "_" + item.getFormulaBatchId() + "_" + item.getDeployDate();
// 从缓存中取出完整对象 // 从缓存中取出完整对象
SgFeedList itemInCache = sgFeedListMap.getOrDefault(key, item); SgFeedList itemInCache = SgFeedListServiceImpl.getSgFeedListMap().getOrDefault(key, item);
// 将数据库查询的基本信息替换掉缓存中去除的内容 - 前端展示与修改需要 // 将数据库查询的基本信息替换掉缓存中去除的内容 - 前端展示与修改需要
itemInCache.setId(item.getId()); itemInCache.setId(item.getId());
itemInCache.setFormulaBatchId(item.getFormulaBatchId()); itemInCache.setFormulaBatchId(item.getFormulaBatchId());
@ -129,6 +119,7 @@ public class SgFeedListController extends BaseController {
@Log(title = "配料清单", businessType = BusinessType.UPDATE) @Log(title = "配料清单", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody SgFeedList sgFeedList) { public AjaxResult edit(@RequestBody SgFeedList sgFeedList) {
return toAjax(sgFeedListService.updateSgFeedList(sgFeedList)); return toAjax(sgFeedListService.updateSgFeedList(sgFeedList));
} }
@ -143,94 +134,4 @@ public class SgFeedListController extends BaseController {
return toAjax(sgFeedListService.deleteSgFeedListByIds(ids)); return toAjax(sgFeedListService.deleteSgFeedListByIds(ids));
} }
public void SyncFeedList() {
// 清空旧缓存
sgFeedListMap.clear();
// 获取配方管理和现有配料清单内容
List<SgFormulaManagement> formulaManagementList = sgFormulaManagementService.selectSgFormulaManagementList(new SgFormulaManagement());
List<SgFeedList> 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<SgFeedPlan> 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<SgFeedPlan> 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;
}
} }

View File

@ -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<SgFeedStatistic> 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<SgFeedStatistic> list = sgFeedStatisticService.selectSgFeedStatisticList(sgFeedStatistic);
ExcelUtil<SgFeedStatistic> 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<SgFeedStatistic> 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<SgFeedStatistic> list = new ArrayList<>();
list.add(sgFeedStatistic);
return getDataTable(list);
}
}

View File

@ -53,6 +53,8 @@ public class SgFeedList extends BaseEntity
private List<SgFormulaList> formulaList; private List<SgFormulaList> formulaList;
private List<SgFeedPlan> planList;
@Override @Override
public String toString() { public String toString() {

View File

@ -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<SgFormulaList> materialList;
/**
* 羊舍列表
*/
@Excel(name = "羊舍列表")
private List<DaSheepfold> 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();
}
}

View File

@ -39,14 +39,25 @@ public class SgFormulaList extends BaseEntity
@Excel(name = "比例") @Excel(name = "比例")
private Long ratio; private Long ratio;
/** 颗粒原料 */ /**
* 颗粒原料
* 当前不局限于 "是否颗粒原料" 而且多种类型的标识符
*/
@Excel(name = "颗粒原料") @Excel(name = "颗粒原料")
private String isGranular; private String isGranular;
/** 补饲 */ /**
* 补饲
* 当前用作饲喂类型标识
*/
@Excel(name = "补饲") @Excel(name = "补饲")
private String isSupplement; private String isSupplement;
/**
* 添加量 - 供其他一些统计模块使用
*/
private Double feedSize;
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -60,4 +60,7 @@ public interface SgFeedListMapper
* @return 结果 * @return 结果
*/ */
int deleteSgFeedListByIds(Long[] ids); int deleteSgFeedListByIds(Long[] ids);
// 清空所有
int deleteAll();
} }

View File

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

View File

@ -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<List<DaSheepfold>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
List<DaSheepfold> parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, JSON.toJSONString(parameter));
}
@Override
public List<DaSheepfold> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return JSON.parseArray(rs.getString(columnName), DaSheepfold.class);
}
@Override
public List<DaSheepfold> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return JSON.parseArray(rs.getString(columnIndex), DaSheepfold.class);
}
@Override
public List<DaSheepfold> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return JSON.parseArray(cs.getString(columnIndex), DaSheepfold.class);
}
}

View File

@ -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<T> extends BaseTypeHandler<T> {
private final Class<T> type;
public JsonTypeHandler(Class<T> 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);
}
}

View File

@ -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<List<SgFormulaList>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
List<SgFormulaList> parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, JSON.toJSONString(parameter));
}
@Override
public List<SgFormulaList> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return JSON.parseArray(rs.getString(columnName), SgFormulaList.class);
}
@Override
public List<SgFormulaList> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return JSON.parseArray(rs.getString(columnIndex), SgFormulaList.class);
}
@Override
public List<SgFormulaList> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return JSON.parseArray(cs.getString(columnIndex), SgFormulaList.class);
}
}

View File

@ -1,6 +1,7 @@
package com.zhyc.module.feed.service; package com.zhyc.module.feed.service;
import java.util.List; import java.util.List;
import com.zhyc.module.feed.domain.SgFeedList; import com.zhyc.module.feed.domain.SgFeedList;
/** /**
@ -9,8 +10,7 @@ import com.zhyc.module.feed.domain.SgFeedList;
* @author HashMap * @author HashMap
* @date 2025-08-19 * @date 2025-08-19
*/ */
public interface ISgFeedListService public interface ISgFeedListService {
{
/** /**
* 查询配料清单 * 查询配料清单
* *
@ -58,4 +58,6 @@ public interface ISgFeedListService
* @return 结果 * @return 结果
*/ */
int deleteSgFeedListById(Long id); int deleteSgFeedListById(Long id);
void SyncFeedList();
} }

View File

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

View File

@ -1,7 +1,12 @@
package com.zhyc.module.feed.service.impl; package com.zhyc.module.feed.service.impl;
import java.util.List; import java.util.*;
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 org.springframework.stereotype.Service;
import com.zhyc.module.feed.mapper.SgFeedListMapper; import com.zhyc.module.feed.mapper.SgFeedListMapper;
import com.zhyc.module.feed.domain.SgFeedList; import com.zhyc.module.feed.domain.SgFeedList;
@ -14,12 +19,23 @@ import com.zhyc.module.feed.service.ISgFeedListService;
* @date 2025-08-19 * @date 2025-08-19
*/ */
@Service @Service
public class SgFeedListServiceImpl implements ISgFeedListService public class SgFeedListServiceImpl implements ISgFeedListService {
{
private final SgFeedListMapper sgFeedListMapper; private final SgFeedListMapper sgFeedListMapper;
private final ISgFormulaManagementService sgFormulaManagementService;
private final ISgFeedPlanService sgFeedPlanService;
@Getter
private final static Map<String, SgFeedList> sgFeedListMap = new HashMap<>();
public SgFeedListServiceImpl(SgFeedListMapper sgFeedListMapper) { public SgFeedListServiceImpl(SgFeedListMapper sgFeedListMapper, ISgFormulaManagementService sgFormulaManagementService, ISgFeedPlanService sgFeedPlanService) {
this.sgFeedListMapper = sgFeedListMapper; this.sgFeedListMapper = sgFeedListMapper;
this.sgFormulaManagementService = sgFormulaManagementService;
this.sgFeedPlanService = sgFeedPlanService;
// 构造时将数据库初始数据写入缓存
List<SgFeedList> feedListsFromDataBase = this.selectSgFeedListList(new SgFeedList());
for (SgFeedList sgFeedListItem : feedListsFromDataBase) {
String key = sgFeedListItem.getFormulaId() + "_" + sgFeedListItem.getFormulaBatchId() + "_" + sgFeedListItem.getDeployDate();
sgFeedListMap.put(key, sgFeedListItem);
}
} }
/** /**
@ -29,8 +45,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 配料清单 * @return 配料清单
*/ */
@Override @Override
public SgFeedList selectSgFeedListById(Long id) public SgFeedList selectSgFeedListById(Long id) {
{
return sgFeedListMapper.selectSgFeedListById(id); return sgFeedListMapper.selectSgFeedListById(id);
} }
@ -41,8 +56,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 配料清单 * @return 配料清单
*/ */
@Override @Override
public List<SgFeedList> selectSgFeedListList(SgFeedList sgFeedList) public List<SgFeedList> selectSgFeedListList(SgFeedList sgFeedList) {
{
return sgFeedListMapper.selectSgFeedListList(sgFeedList); return sgFeedListMapper.selectSgFeedListList(sgFeedList);
} }
@ -53,8 +67,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int insertSgFeedList(SgFeedList sgFeedList) public int insertSgFeedList(SgFeedList sgFeedList) {
{
return sgFeedListMapper.insertSgFeedList(sgFeedList); return sgFeedListMapper.insertSgFeedList(sgFeedList);
} }
@ -65,8 +78,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateSgFeedList(SgFeedList sgFeedList) public int updateSgFeedList(SgFeedList sgFeedList) {
{
return sgFeedListMapper.updateSgFeedList(sgFeedList); return sgFeedListMapper.updateSgFeedList(sgFeedList);
} }
@ -77,8 +89,7 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteSgFeedListByIds(Long[] ids) public int deleteSgFeedListByIds(Long[] ids) {
{
return sgFeedListMapper.deleteSgFeedListByIds(ids); return sgFeedListMapper.deleteSgFeedListByIds(ids);
} }
@ -89,8 +100,166 @@ public class SgFeedListServiceImpl implements ISgFeedListService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteSgFeedListById(Long id) public int deleteSgFeedListById(Long id) {
{
return sgFeedListMapper.deleteSgFeedListById(id); return sgFeedListMapper.deleteSgFeedListById(id);
} }
public void SyncFeedList_old() {
// 清空旧缓存
sgFeedListMap.clear();
// 获取配方管理和现有配料清单内容
List<SgFormulaManagement> formulaManagementList = sgFormulaManagementService.selectSgFormulaManagementList(new SgFormulaManagement());
List<SgFeedList> 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<SgFeedPlan> 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);
}
}
}
}
public void SyncFeedList() {
HashMap<String, SgFeedList> cacheTemp = new HashMap<>(sgFeedListMap);
// 清空旧缓存
sgFeedListMap.clear();
List<SgFeedPlan> sgFeedPlans = sgFeedPlanService.selectSgFeedPlanList(new SgFeedPlan());
List<List<SgFeedPlan>> planGroups = new ArrayList<>();
List<SgFeedPlan> currentFeedPlan = new ArrayList<>();
if (!sgFeedPlans.isEmpty()) {
String currentFormulaId = sgFeedPlans.get(0).getFormulaId();
String currentBatchId = sgFeedPlans.get(0).getBatchId();
Date currentDate = sgFeedPlans.get(0).getPlanDate();
// 对饲喂计划进行分组
for (SgFeedPlan sgFeedPlan : sgFeedPlans) {
if (sgFeedPlan.getBatchId() != null && !sgFeedPlan.getBatchId().equals("0")) {
if (sgFeedPlan.getFormulaId().equals(currentFormulaId) && sgFeedPlan.getBatchId().equals(currentBatchId) && sgFeedPlan.getPlanDate().equals(currentDate)) {
currentFeedPlan.add(sgFeedPlan);
} else {
currentDate = sgFeedPlan.getPlanDate();
currentBatchId = sgFeedPlan.getBatchId();
currentFormulaId = sgFeedPlan.getFormulaId();
planGroups.add(currentFeedPlan);
currentFeedPlan = new ArrayList<>();
// 立即插入否则会丢失该元素
currentFeedPlan.add(sgFeedPlan);
}
}
}
// 插入最后一个列表 - 否则该列表会丢失
planGroups.add(currentFeedPlan);
// 注册数据 - 每一个List为一个清单
for (List<SgFeedPlan> sgFeedPlanList : planGroups) {
SgFeedList sgFeedList = new SgFeedList();
// 计算饲喂总和
SgFeedPlan rootPlan = computePlanTotal(sgFeedPlanList);
sgFeedList.setRootPlan(rootPlan);
sgFeedList.setPlanList(sgFeedPlanList);
// 写入信息
sgFeedList.setFormulaId(sgFeedPlanList.get(0).getFormulaId());
sgFeedList.setFormulaBatchId(sgFeedPlanList.get(0).getBatchId());
sgFeedList.setDeployDate(sgFeedPlanList.get(0).getPlanDate());
// 写入配方管理信息
SgFormulaManagement formulaManagementQuery = new SgFormulaManagement();
formulaManagementQuery.setFormulaId(sgFeedList.getFormulaId());
formulaManagementQuery.setBatchId(sgFeedList.getFormulaBatchId());
List<SgFormulaManagement> formulaManagements = sgFormulaManagementService.selectSgFormulaManagementList(formulaManagementQuery);
if (!formulaManagements.isEmpty()) {
sgFeedList.setRootFormula(formulaManagements.get(0));
sgFeedList.setFormulaList(formulaManagements.get(0).getSgFormulaList());
}
String cacheKey = sgFeedList.getFormulaId() + "_" + sgFeedList.getFormulaBatchId() + "_" + sgFeedList.getDeployDate();
// 从就缓存中查找如果存在则更新可修改的值
if (cacheTemp.containsKey(cacheKey)) {
SgFeedList cacheItem = cacheTemp.get(cacheKey);
sgFeedList.setZookeeper(cacheItem.getZookeeper());
}
sgFeedListMap.put(cacheKey, sgFeedList);
}
List<SgFeedList> toDataBase = new ArrayList<>(sgFeedListMap.values());
// 清空再写入
this.sgFeedListMapper.deleteAll();
// 处理结果写入数据库
for (SgFeedList recordItem : toDataBase) {
this.insertSgFeedList(recordItem);
}
}
}
/**
* 计算某个配方某个批次的总和值
*
* @param sgFeedPlans 配方计划列表
* @return 各个值总和
*/
private static SgFeedPlan computePlanTotal(List<SgFeedPlan> 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.setFormulaId(sgFeedPlans.get(0).getFormulaId());
rootPlan.setBatchId(sgFeedPlans.get(0).getBatchId());
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;
}
} }

View File

@ -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<SgFeedStatistic> 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<SgFeedList> feedLists = sgFeedListService.selectSgFeedListList(sgFeedListQuery);
if (!feedLists.isEmpty()) {
// 刷新缓存
sgFeedListService.SyncFeedList();
// 从缓存获取完整配方清单
String cacheKey = sgFeedStatistic.getFormulaId() + "_" + sgFeedStatistic.getFormulaBatchId() + "_" + sgFeedStatistic.getFeedDate();
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());
sgFeedPlanQuery.setPlanDate(sgFeedStatistic.getFeedDate());
List<SgFeedPlan> sgFeedPlans = sgFeedPlanService.selectSgFeedPlanList(sgFeedPlanQuery);
if (!sgFeedPlans.isEmpty()) {
// 并行计算提高查询性能
List<DaSheepfold> 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: 不存在该计划");
}
}
}

View File

@ -31,7 +31,7 @@ public class ScBreastRating extends BaseEntity {
*/ */
private String sheepId; private String sheepId;
@Excel(name = "羊只id") @Excel(name = "管理耳号")
private String manageTags; private String manageTags;
/** /**

View File

@ -27,7 +27,7 @@ public class ScChangeComment extends BaseEntity {
* 羊只id * 羊只id
*/ */
private String sheepId; private String sheepId;
@Excel(name = "管理耳号")
private String manageTags; private String manageTags;
/** 羊舍 */ /** 羊舍 */

View File

@ -0,0 +1,117 @@
package com.zhyc.module.sale.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestParam;
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.sale.domain.SxSheepSale;
import com.zhyc.module.sale.service.ISxSheepSaleService;
import com.zhyc.common.utils.poi.ExcelUtil;
import com.zhyc.common.core.page.TableDataInfo;
/**
* 羊只销售记录Controller
*
* @author ruoyi
* @date 2025-08-19
*/
@RestController
@RequestMapping("/saleRecord/saleRecord")
public class SxSheepSaleController extends BaseController {
@Autowired
private ISxSheepSaleService sxSheepSaleService;
/**
* 查询羊只销售记录列表
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:list')")
@GetMapping("/list")
public TableDataInfo list(SxSheepSale sxSheepSale) {
startPage();
List<SxSheepSale> list = sxSheepSaleService.selectSxSheepSaleList(sxSheepSale);
return getDataTable(list);
}
/**
* 导出羊只销售记录列表
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:export')")
@Log(title = "羊只销售记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SxSheepSale sxSheepSale) {
List<SxSheepSale> list = sxSheepSaleService.selectSxSheepSaleList(sxSheepSale);
ExcelUtil<SxSheepSale> util = new ExcelUtil<SxSheepSale>(SxSheepSale.class);
util.exportExcel(response, list, "羊只销售记录数据");
}
/**
* 获取羊只销售记录详细信息
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
SxSheepSale sxSheepSale = sxSheepSaleService.selectSxSheepSaleById(id);
// 将数据库中的逗号分隔的耳号字符串转换为列表
if (sxSheepSale.getBsManageTags() != null && !sxSheepSale.getBsManageTags().isEmpty()) {
sxSheepSale.setBsManageTagsList(java.util.Arrays.asList(sxSheepSale.getBsManageTags().split(",")));
}
return success(sxSheepSale);
}
/**
* 新增羊只销售记录
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:add')")
@Log(title = "羊只销售记录", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SxSheepSale sxSheepSale) {
return toAjax(sxSheepSaleService.insertSxSheepSale(sxSheepSale));
}
/**
* 修改羊只销售记录
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:edit')")
@Log(title = "羊只销售记录", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SxSheepSale sxSheepSale) {
return toAjax(sxSheepSaleService.updateSxSheepSale(sxSheepSale));
}
/**
* 删除羊只销售记录
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:remove')")
@Log(title = "羊只销售记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(sxSheepSaleService.deleteSxSheepSaleByIds(ids));
}
/**
* 新增根据耳号查询羊只信息
*/
@PreAuthorize("@ss.hasPermi('saleRecord:saleRecord:add')" + "|| @ss.hasPermi('saleRecord:saleRecord:edit')")
@GetMapping("/getSheepInfo")
public AjaxResult getSheepInfo(@RequestParam String bsManageTags) {
// 调用Service方法查询信息
SxSheepSale sheepInfo = sxSheepSaleService.selectSheepInfoByTag(bsManageTags);
if (sheepInfo == null) {
return AjaxResult.error("未找到耳号为 [" + bsManageTags + "] 的羊只信息");
}
return AjaxResult.success(sheepInfo);
}
}

View File

@ -0,0 +1,49 @@
package com.zhyc.module.sale.domain;
import com.zhyc.common.annotation.Excel;
public class SxCustomerExport {
@Excel(name = "客户名称")
private String name;
@Excel(name = "客户电话")
private String phone;
@Excel(name = "客户地址")
private String fullAddress;
@Excel(name = "备注")
private String remark;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getFullAddress() {
return fullAddress;
}
public void setFullAddress(String fullAddress) {
this.fullAddress = fullAddress;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

View File

@ -0,0 +1,545 @@
package com.zhyc.module.sale.domain;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
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;
/**
* 羊只销售记录对象 sx_sheep_sale
*
* @author ruoyi
* @date 2025-08-19
*/
public class SxSheepSale extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 耳号 */
@Excel(name = "耳号")
private String bsManageTags;
/** 羊舍ID当时销售的羊舍 */
@Excel(name = "羊舍ID", readConverterExp = "当=时销售的羊舍")
private Long sheepfoldId;
/** 品种快照 */
@Excel(name = "品种快照")
private String variety;
/** 羊只类别快照 */
@Excel(name = "羊只类别快照")
private String sheepName;
/** 性别快照 */
@Excel(name = "性别快照")
private String gender;
/** 月龄快照 */
@Excel(name = "月龄快照")
private Long monthAge;
/** 胎次快照 */
@Excel(name = "胎次快照")
private Long parity;
/** 繁育状态快照 */
@Excel(name = "繁育状态快照")
private String breed;
/** 产后天数快照 */
@Excel(name = "产后天数快照")
private Long postLambingDay;
/** 泌乳天数快照 */
@Excel(name = "泌乳天数快照")
private Long lactationDay;
/** 怀孕天数快照 */
@Excel(name = "怀孕天数快照")
private Long lambingDay;
/** 事件类型 */
@Excel(name = "事件类型")
private String eventType;
/** 销售日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "销售日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date saleDate;
/** 计价方式 */
@Excel(name = "计价方式")
private String pricingMethod;
/** 单价 */
@Excel(name = "单价")
private BigDecimal unitPrice;
/** 总价(自动计算) */
@Excel(name = "总价", readConverterExp = "自=动计算")
private BigDecimal totalPrice;
/** 总体重(按体重时输入) */
@Excel(name = "总体重", readConverterExp = "按=体重时输入")
private BigDecimal totalWeight;
/** 平均体重(自动) */
@Excel(name = "平均体重", readConverterExp = "自=动")
private BigDecimal avgWeight;
/** 平均单只价格(自动) */
@Excel(name = "平均单只价格", readConverterExp = "自=动")
private BigDecimal avgPricePerSheep;
/** 销售类别dict_type = sale_type */
@Excel(name = "销售类别", readConverterExp = "d=ict_type,==,s=ale_type")
private String saleType;
/** 疾病类型dict_type = disea_type */
@Excel(name = "疾病类型", readConverterExp = "d=ict_type,==,d=isea_type")
private String diseaseType;
/** 次要原因 */
@Excel(name = "次要原因")
private String secondaryReason;
/** 班组dict_type = group */
@Excel(name = "班组", readConverterExp = "d=ict_type,==,g=roup")
private String groupCode;
/** 客户IDsx_customer.id */
@Excel(name = "客户ID", readConverterExp = "s=x_customer.id")
private Long customerId;
/** 销售人员IDsys_user.id */
@Excel(name = "销售人员ID", readConverterExp = "s=ys_user.id")
private Long salesPersonId;
/** 检疫证号 */
@Excel(name = "检疫证号")
private String quarantineNo;
/** 审批编号 */
@Excel(name = "审批编号")
private String approvalNo;
/** 技术员IDsys_user.id */
@Excel(name = "技术员ID", readConverterExp = "s=ys_user.id")
private Long technicianId;
/** 处理人IDsys_user.id */
@Excel(name = "处理人ID", readConverterExp = "s=ys_user.id")
private Long handlerId;
/** 创建人IDsys_user.id */
@Excel(name = "创建人ID", readConverterExp = "s=ys_user.id")
private Long createdBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date createdAt;
// 新增非数据库字段用于前端展示和选择羊舍后传递多个耳号
private List<String> bsManageTagsList;
// 新增非数据库字段客户名称从客户表查询
private String customerName;
// 新增非数据库字段客户电话
private String customerPhone;
// 新增非数据库字段客户地址
private String customerAddress;
// 新增非数据库字段销售人员姓名
private String salesPersonName;
// 新增非数据库字段技术员姓名
private String technicianName;
// 新增非数据库字段处理人姓名
private String handlerName;
// 新增非数据库字段创建人姓名
private String createdByName;
// 新增非数据库字段羊舍名称
private String sheepfoldName;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setBsManageTags(String bsManageTags) {
this.bsManageTags = bsManageTags;
}
public String getBsManageTags() {
return bsManageTags;
}
public void setSheepfoldId(Long sheepfoldId) {
this.sheepfoldId = sheepfoldId;
}
public Long getSheepfoldId() {
return sheepfoldId;
}
public void setVariety(String variety) {
this.variety = variety;
}
public String getVariety() {
return variety;
}
public void setSheepName(String sheepName) {
this.sheepName = sheepName;
}
public String getSheepName() {
return sheepName;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getGender() {
return gender;
}
public void setMonthAge(Long monthAge) {
this.monthAge = monthAge;
}
public Long getMonthAge() {
return monthAge;
}
public void setParity(Long parity) {
this.parity = parity;
}
public Long getParity() {
return parity;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getBreed() {
return breed;
}
public void setPostLambingDay(Long postLambingDay) {
this.postLambingDay = postLambingDay;
}
public Long getPostLambingDay() {
return postLambingDay;
}
public void setLactationDay(Long lactationDay) {
this.lactationDay = lactationDay;
}
public Long getLactationDay() {
return lactationDay;
}
public void setLambingDay(Long lambingDay) {
this.lambingDay = lambingDay;
}
public Long getLambingDay() {
return lambingDay;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String getEventType() {
return eventType;
}
public void setSaleDate(Date saleDate) {
this.saleDate = saleDate;
}
public Date getSaleDate() {
return saleDate;
}
public void setPricingMethod(String pricingMethod) {
this.pricingMethod = pricingMethod;
}
public String getPricingMethod() {
return pricingMethod;
}
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}
public BigDecimal getUnitPrice() {
return unitPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalWeight(BigDecimal totalWeight) {
this.totalWeight = totalWeight;
}
public BigDecimal getTotalWeight() {
return totalWeight;
}
public void setAvgWeight(BigDecimal avgWeight) {
this.avgWeight = avgWeight;
}
public BigDecimal getAvgWeight() {
return avgWeight;
}
public void setAvgPricePerSheep(BigDecimal avgPricePerSheep) {
this.avgPricePerSheep = avgPricePerSheep;
}
public BigDecimal getAvgPricePerSheep() {
return avgPricePerSheep;
}
public void setSaleType(String saleType) {
this.saleType = saleType;
}
public String getSaleType() {
return saleType;
}
public void setDiseaseType(String diseaseType) {
this.diseaseType = diseaseType;
}
public String getDiseaseType() {
return diseaseType;
}
public void setSecondaryReason(String secondaryReason) {
this.secondaryReason = secondaryReason;
}
public String getSecondaryReason() {
return secondaryReason;
}
public void setGroupCode(String groupCode) {
this.groupCode = groupCode;
}
public String getGroupCode() {
return groupCode;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public Long getCustomerId() {
return customerId;
}
public void setSalesPersonId(Long salesPersonId) {
this.salesPersonId = salesPersonId;
}
public Long getSalesPersonId() {
return salesPersonId;
}
public void setQuarantineNo(String quarantineNo) {
this.quarantineNo = quarantineNo;
}
public String getQuarantineNo() {
return quarantineNo;
}
public void setApprovalNo(String approvalNo) {
this.approvalNo = approvalNo;
}
public String getApprovalNo() {
return approvalNo;
}
public void setTechnicianId(Long technicianId) {
this.technicianId = technicianId;
}
public Long getTechnicianId() {
return technicianId;
}
public void setHandlerId(Long handlerId) {
this.handlerId = handlerId;
}
public Long getHandlerId() {
return handlerId;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getCreatedAt() {
return createdAt;
}
// 新增getter setter 方法
public List<String> getBsManageTagsList() {
return bsManageTagsList;
}
public void setBsManageTagsList(List<String> bsManageTagsList) {
this.bsManageTagsList = bsManageTagsList;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerPhone() {
return customerPhone;
}
public void setCustomerPhone(String customerPhone) {
this.customerPhone = customerPhone;
}
public String getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}
public String getSalesPersonName() {
return salesPersonName;
}
public void setSalesPersonName(String salesPersonName) {
this.salesPersonName = salesPersonName;
}
public String getTechnicianName() {
return technicianName;
}
public void setTechnicianName(String technicianName) {
this.technicianName = technicianName;
}
public String getHandlerName() {
return handlerName;
}
public void setHandlerName(String handlerName) {
this.handlerName = handlerName;
}
public String getCreatedByName() {
return createdByName;
}
public void setCreatedByName(String createdByName) {
this.createdByName = createdByName;
}
public String getSheepfoldName() {
return sheepfoldName;
}
public void setSheepfoldName(String sheepfoldName) {
this.sheepfoldName = sheepfoldName;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("bsManageTags", getBsManageTags())
.append("sheepfoldId", getSheepfoldId())
.append("variety", getVariety())
.append("sheepName", getSheepName())
.append("gender", getGender())
.append("monthAge", getMonthAge())
.append("parity", getParity())
.append("breed", getBreed())
.append("postLambingDay", getPostLambingDay())
.append("lactationDay", getLactationDay())
.append("lambingDay", getLambingDay())
.append("eventType", getEventType())
.append("saleDate", getSaleDate())
.append("pricingMethod", getPricingMethod())
.append("unitPrice", getUnitPrice())
.append("totalPrice", getTotalPrice())
.append("totalWeight", getTotalWeight())
.append("avgWeight", getAvgWeight())
.append("avgPricePerSheep", getAvgPricePerSheep())
.append("saleType", getSaleType())
.append("diseaseType", getDiseaseType())
.append("secondaryReason", getSecondaryReason())
.append("groupCode", getGroupCode())
.append("customerId", getCustomerId())
.append("salesPersonId", getSalesPersonId())
.append("quarantineNo", getQuarantineNo())
.append("approvalNo", getApprovalNo())
.append("technicianId", getTechnicianId())
.append("handlerId", getHandlerId())
.append("createdBy", getCreatedBy())
.append("createdAt", getCreatedAt())
.append("remark", getRemark())
.append("customerName", getCustomerName())
.append("customerPhone", getCustomerPhone())
.append("customerAddress", getCustomerAddress())
.append("salesPersonName", getSalesPersonName())
.append("technicianName", getTechnicianName())
.append("handlerName", getHandlerName())
.append("createdByName", getCreatedByName())
.append("sheepfoldName", getSheepfoldName())
.toString();
}
}

View File

@ -0,0 +1,68 @@
package com.zhyc.module.sale.mapper;
import java.util.List;
import com.zhyc.module.sale.domain.SxSheepSale;
import org.apache.ibatis.annotations.Param;
/**
* 羊只销售记录Mapper接口
*
* @author ruoyi
* @date 2025-08-19
*/
public interface SxSheepSaleMapper {
/**
* 查询羊只销售记录
*
* @param id 羊只销售记录主键
* @return 羊只销售记录
*/
public SxSheepSale selectSxSheepSaleById(Long id);
/**
* 查询羊只销售记录列表
*
* @param sxSheepSale 羊只销售记录
* @return 羊只销售记录集合
*/
public List<SxSheepSale> selectSxSheepSaleList(SxSheepSale sxSheepSale);
/**
* 新增羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
public int insertSxSheepSale(SxSheepSale sxSheepSale);
/**
* 修改羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
public int updateSxSheepSale(SxSheepSale sxSheepSale);
/**
* 删除羊只销售记录
*
* @param id 羊只销售记录主键
* @return 结果
*/
public int deleteSxSheepSaleById(Long id);
/**
* 批量删除羊只销售记录
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteSxSheepSaleByIds(Long[] ids);
/**
* 新增从sheep_file视图查询羊只信息
* @param bsManageTags 耳号
* @return 羊只信息 (只包含视图中的字段)
*/
public SxSheepSale selectSheepInfoByTag(@Param("bsManageTags") String bsManageTags);
}

View File

@ -0,0 +1,67 @@
package com.zhyc.module.sale.service;
import java.util.List;
import com.zhyc.module.sale.domain.SxSheepSale;
/**
* 羊只销售记录Service接口
*
* @author ruoyi
* @date 2025-08-19
*/
public interface ISxSheepSaleService {
/**
* 查询羊只销售记录
*
* @param id 羊只销售记录主键
* @return 羊只销售记录
*/
public SxSheepSale selectSxSheepSaleById(Long id);
/**
* 查询羊只销售记录列表
*
* @param sxSheepSale 羊只销售记录
* @return 羊只销售记录集合
*/
public List<SxSheepSale> selectSxSheepSaleList(SxSheepSale sxSheepSale);
/**
* 新增羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
public int insertSxSheepSale(SxSheepSale sxSheepSale);
/**
* 修改羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
public int updateSxSheepSale(SxSheepSale sxSheepSale);
/**
* 批量删除羊只销售记录
*
* @param ids 需要删除的羊只销售记录主键集合
* @return 结果
*/
public int deleteSxSheepSaleByIds(Long[] ids);
/**
* 删除羊只销售记录信息
*
* @param id 羊只销售记录主键
* @return 结果
*/
public int deleteSxSheepSaleById(Long id);
/**
* 新增根据耳号查询羊只信息
* @param bsManageTags 耳号
* @return 羊只信息
*/
public SxSheepSale selectSheepInfoByTag(String bsManageTags);
}

View File

@ -0,0 +1,194 @@
package com.zhyc.module.sale.service.impl;
import java.util.List;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zhyc.module.sale.mapper.SxSheepSaleMapper;
import com.zhyc.module.sale.domain.SxSheepSale;
import com.zhyc.module.sale.service.ISxSheepSaleService;
/**
* 羊只销售记录Service业务层处理
*
* @author ruoyi
* @date 2025-08-19
*/
@Service
public class SxSheepSaleServiceImpl implements ISxSheepSaleService {
@Autowired
private SxSheepSaleMapper sxSheepSaleMapper;
/**
* 查询羊只销售记录
*
* @param id 羊只销售记录主键
* @return 羊只销售记录
*/
@Override
public SxSheepSale selectSxSheepSaleById(Long id) {
return sxSheepSaleMapper.selectSxSheepSaleById(id);
}
/**
* 查询羊只销售记录列表
*
* @param sxSheepSale 羊只销售记录
* @return 羊只销售记录
*/
@Override
public List<SxSheepSale> selectSxSheepSaleList(SxSheepSale sxSheepSale) {
return sxSheepSaleMapper.selectSxSheepSaleList(sxSheepSale);
}
/**
* 新增羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
@Override
public int insertSxSheepSale(SxSheepSale sxSheepSale) {
// 1. 业务验证 (例如销售日期不能为空淘汰销售必须填写疾病类型等)
validateSalesFields(sxSheepSale);
// 2. 自动计算逻辑
calculateSalesFields(sxSheepSale);
// 3. 设置默认事件类型
if (sxSheepSale.getEventType() == null) {
sxSheepSale.setEventType("销售");
}
// 4. 处理耳号列表多个耳号用逗号分隔
if (sxSheepSale.getBsManageTagsList() != null && !sxSheepSale.getBsManageTagsList().isEmpty()) {
sxSheepSale.setBsManageTags(String.join(",", sxSheepSale.getBsManageTagsList()));
}
// 5. 调用Mapper插入数据
return sxSheepSaleMapper.insertSxSheepSale(sxSheepSale);
}
/**
* 修改羊只销售记录
*
* @param sxSheepSale 羊只销售记录
* @return 结果
*/
@Override
public int updateSxSheepSale(SxSheepSale sxSheepSale) {
// 1. 业务验证
validateSalesFields(sxSheepSale);
// 2. 自动计算逻辑
calculateSalesFields(sxSheepSale);
// 3. 处理耳号列表多个耳号用逗号分隔
if (sxSheepSale.getBsManageTagsList() != null && !sxSheepSale.getBsManageTagsList().isEmpty()) {
sxSheepSale.setBsManageTags(String.join(",", sxSheepSale.getBsManageTagsList()));
}
// 4. 调用Mapper更新数据
return sxSheepSaleMapper.updateSxSheepSale(sxSheepSale);
}
/**
* 批量删除羊只销售记录
*
* @param ids 需要删除的羊只销售记录主键
* @return 结果
*/
@Override
public int deleteSxSheepSaleByIds(Long[] ids) {
return sxSheepSaleMapper.deleteSxSheepSaleByIds(ids);
}
/**
* 删除羊只销售记录信息
*
* @param id 羊只销售记录主键
* @return 结果
*/
@Override
public int deleteSxSheepSaleById(Long id) {
return sxSheepSaleMapper.deleteSxSheepSaleById(id);
}
/**
* 新增根据耳号查询羊只信息
*/
@Override
public SxSheepSale selectSheepInfoByTag(String bsManageTags) {
return sxSheepSaleMapper.selectSheepInfoByTag(bsManageTags);
}
/**
* 新增自动计算总价平均体重平均单只价格
*/
private void calculateSalesFields(SxSheepSale sxSheepSale) {
String pricingMethod = sxSheepSale.getPricingMethod();
BigDecimal unitPrice = sxSheepSale.getUnitPrice();
// 获取羊只数量
int sheepCount = 1;
if (sxSheepSale.getBsManageTagsList() != null && !sxSheepSale.getBsManageTagsList().isEmpty()) {
sheepCount = sxSheepSale.getBsManageTagsList().size();
} else if (sxSheepSale.getBsManageTags() != null && !sxSheepSale.getBsManageTags().isEmpty()) {
// 如果前端没有传递列表但有逗号分隔的字符串也计算数量
sheepCount = sxSheepSale.getBsManageTags().split(",").length;
}
if ("按个体".equals(pricingMethod)) {
// 总价 = 单价 * 数量
if (unitPrice != null) {
sxSheepSale.setTotalPrice(unitPrice.multiply(new BigDecimal(sheepCount)));
}
// 平均单只价格就是单价
sxSheepSale.setAvgPricePerSheep(unitPrice);
} else if ("按体重".equals(pricingMethod)) {
BigDecimal totalWeight = sxSheepSale.getTotalWeight();
// 总价 = 单价 * 总重量
if (unitPrice != null && totalWeight != null) {
sxSheepSale.setTotalPrice(unitPrice.multiply(totalWeight));
}
// 平均体重 = 总重量 / 数量
if (totalWeight != null && sheepCount > 0) {
sxSheepSale.setAvgWeight(totalWeight.divide(new BigDecimal(sheepCount), 2, RoundingMode.HALF_UP));
}
// 平均单只价格 = 总价 / 数量
if (sxSheepSale.getTotalPrice() != null && sheepCount > 0) {
sxSheepSale.setAvgPricePerSheep(sxSheepSale.getTotalPrice().divide(new BigDecimal(sheepCount), 2, RoundingMode.HALF_UP));
}
}
// 可以添加其他计价方式的逻辑
}
/**
* 新增业务字段验证
*/
private void validateSalesFields(SxSheepSale sxSheepSale) {
// 验证销售日期不能为空
if (sxSheepSale.getSaleDate() == null) {
throw new RuntimeException("销售日期不能为空!");
}
String saleType = sxSheepSale.getSaleType();
// 如果销售类别是"淘汰销售""淘汰屠宰"则疾病类型和班组不能为空
if ("淘汰销售".equals(saleType) || "淘汰屠宰".equals(saleType)) {
if (sxSheepSale.getDiseaseType() == null) {
throw new RuntimeException("淘汰销售或淘汰屠宰必须选择疾病类型!");
}
if (sxSheepSale.getGroupCode() == null) {
throw new RuntimeException("淘汰销售或淘汰屠宰必须选择班组!");
}
}
// 如果疾病类型是"病残羊"则次要原因不能为空
if ("病残羊".equals(sxSheepSale.getDiseaseType())) {
if (sxSheepSale.getSecondaryReason() == null || sxSheepSale.getSecondaryReason().trim().isEmpty()) {
throw new RuntimeException("疾病类型为病残羊时,必须填写次要原因!");
}
}
}
}

View File

@ -47,6 +47,7 @@ public class WzStockInController extends BaseController
{ {
startPage(); startPage();
List<WzStockIn> list = wzStockInService.selectWzStockInList(wzStockIn); List<WzStockIn> list = wzStockInService.selectWzStockInList(wzStockIn);
logger.debug(wzStockIn.toString());
return getDataTable(list); return getDataTable(list);
} }

View File

@ -126,5 +126,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</delete> </delete>
<select id="selectByParentIdAndGroupName" resultMap="BasSheepGroupResult">
SELECT * FROM bas_sheep_group
WHERE parent_id = #{parentId} AND group_name = #{groupName}
LIMIT 1
</select>
</mapper> </mapper>

View File

@ -35,6 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectDewormVo"/> <include refid="selectDewormVo"/>
<where> <where>
<if test="sheepId != null "> and sheep_id = #{sheepId}</if> <if test="sheepId != null "> and sheep_id = #{sheepId}</if>
<if test="sheepNo != null and sheepNo != ''">and bs.manage_tags like concat('%',#{sheepNo},'%')</if>
<if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if> <if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if>
<if test="technical != null and technical != ''"> and technical = #{technical}</if> <if test="technical != null and technical != ''"> and technical = #{technical}</if>
</where> </where>

View File

@ -34,9 +34,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<select id="selectHealthList" parameterType="Health" resultMap="HealthResult"> <select id="selectHealthList" parameterType="Health" resultMap="HealthResult">
<include refid="selectHealthVo"/> select s.id, datetime, sheep_id, usage_id, variety, sheep_type, s.gender, month_age, s.parity, breed, technical,
s.comment, s.update_by, s.update_time, s.create_by, s.create_time,
bs.manage_tags sheep_no
from sw_health s
left join bas_sheep bs on s.sheep_id = bs.id
<where> <where>
<if test="datetime != null "> and datetime = #{datetime}</if> <if test="datetime != null "> and datetime = #{datetime}</if>
<if test="sheepNo != null and sheepNo != ''">and bs.manage_tags like concat('%',#{sheepNo},'%')</if>
<if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if>
<if test="technical != null and technical != ''"> and technical = #{technical}</if> <if test="technical != null and technical != ''"> and technical = #{technical}</if>
</where> </where>
ORDER BY datetime DESC ORDER BY datetime DESC

View File

@ -32,10 +32,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<select id="selectImmunityList" parameterType="Immunity" resultMap="ImmunityResult"> <select id="selectImmunityList" parameterType="Immunity" resultMap="ImmunityResult">
<include refid="selectImmunityVo"/> select s.id, datetime, sheep_id, usage_id, variety, sheep_type, s.gender, month_age, s.parity, breed, technical,
s.comment, s.update_by, s.update_time, s.create_by, s.create_time,
bs.manage_tags sheep_no
from sw_immunity s
left join bas_sheep bs on s.sheep_id = bs.id
<where> <where>
<if test="sheepId != null "> and sheep_id = #{sheepId}</if> <if test="sheepId != null "> and sheep_id = #{sheepId}</if>
<if test="sheepType != null "> and sheep_type = #{sheepType}</if> <if test="sheepType != null "> and sheep_type = #{sheepType}</if>
<if test="sheepNo != null and sheepNo != ''">and bs.manage_tags like concat('%',#{sheepNo},'%')</if>
<if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if> <if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if>
<if test="technical != null and technical != ''"> and technical = #{technical}</if> <if test="technical != null and technical != ''"> and technical = #{technical}</if>
</where> </where>

View File

@ -44,9 +44,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<select id="selectTreatmentList" parameterType="Treatment" resultMap="TreatmentResult"> <select id="selectTreatmentList" parameterType="Treatment" resultMap="TreatmentResult">
<include refid="selectTreatmentVo"/> select t.id, diag_id, sheep_id, variety, sheep_type, month_age, t.gender, t.parity, breed, lact_day, gest_day, datetime, disease_id, disease_pid, veterinary, usage_id,status, t.comment, t.update_by, t.update_time, t.create_by, t.create_time,
bs.manage_tags,
sd.name disease_name,
sd2.name disease_pname
from sw_treatment t
left join bas_sheep bs on t.sheep_id = bs.id
left join sw_disease sd on t.disease_id = sd.id
left join sw_disease sd2 on t.disease_pid = sd2.id
<where> <where>
<if test="sheepId != null "> and sheep_id = #{sheepId}</if> <if test="sheepId != null "> and sheep_id = #{sheepId}</if>
<if test="sheepNo != null and sheepNo != ''">and bs.manage_tags like concat('%',#{sheepNo},'%')</if>
<if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if> <if test="params.beginDatetime != null and params.beginDatetime != '' and params.endDatetime != null and params.endDatetime != ''"> and datetime between #{params.beginDatetime} and #{params.endDatetime}</if>
<if test="diseaseId != null "> and disease_id = #{diseaseId}</if> <if test="diseaseId != null "> and disease_id = #{diseaseId}</if>
<if test="status != null and status !=''"> and status = #{status}</if> <if test="status != null and status !=''"> and status = #{status}</if>

View File

@ -4,7 +4,7 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhyc.module.dairyProducts.mapper.NpSheepMilkAnalysisMapper"> <mapper namespace="com.zhyc.module.dairyProducts.mapper.NpSheepMilkAnalysisMapper">
<!-- 1) 获取 distinct sheep_id支持按 sheep_file.bs_manage_tags 模糊搜索) --> <!-- 1) 获取distinct sheep_id支持按sheep_file.bs_manage_tags模糊搜索 -->
<select id="selectDistinctSheepIds" resultType="string" parameterType="map"> <select id="selectDistinctSheepIds" resultType="string" parameterType="map">
SELECT DISTINCT a.sheep_id SELECT DISTINCT a.sheep_id
FROM np_milk_prod_classes a FROM np_milk_prod_classes a
@ -30,8 +30,7 @@
ORDER BY datetime ASC ORDER BY datetime ASC
</select> </select>
<!-- 3) 获取该羊在sheep_file视图中的基础信息 -->
<!-- 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 --> <!-- 假设字段名称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="selectSheepFileBySheepId" resultType="map" parameterType="string">
SELECT SELECT
@ -53,10 +52,29 @@
WHERE id = #{sheepId} WHERE id = #{sheepId}
</select> </select>
<!-- 4) 兼容旧 list 查询(返回 domain 对象列表),但在我们的实现中 service 会构造最终的 NpSheepMilkAnalysis 列表 --> <!-- 4) 兼容旧list查询返回domain对象列表但在我们的实现中service会构造最终的NpSheepMilkAnalysis列表 -->
<select id="selectNpSheepMilkAnalysisList" resultType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis"> <select id="selectNpSheepMilkAnalysisList" resultType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
<!-- 如果你仍需基于某张表的简单映射,可在此实现;当前我们在 ServiceImpl 中组装对象,所以该查询不做复杂实现 --> <!-- 如果你仍需基于某张表的简单映射,可在此实现;当前我们在ServiceImpl中组装对象所以该查询不做复杂实现 -->
SELECT 1 FROM dual WHERE 1=0 SELECT 1 FROM dual WHERE 1=0
</select> </select>
<!-- 5) 导出奶产量分析记录 -->
<select id="selectNpSheepMilkAnalysisForExport" resultType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis" parameterType="com.zhyc.module.dairyProducts.domain.NpSheepMilkAnalysis">
<!-- 这里需要根据实际表结构编写SQL查询 -->
<!-- 示例SQL需要根据实际表结构调整 -->
SELECT
sf.id as sheepId,
sf.bs_manage_tags as manageEarTag,
sf.variety,
<!-- 其他字段 -->
FROM sheep_file sf
LEFT JOIN np_milk_prod_classes m ON sf.id = m.sheep_id
<where>
<if test="manageEarTag != null and manageEarTag != ''">
AND sf.bs_manage_tags LIKE CONCAT('%', #{manageEarTag}, '%')
</if>
</where>
GROUP BY sf.id
</select>
</mapper> </mapper>

View File

@ -13,16 +13,17 @@
<result property="coefficient" column="coefficient"/> <result property="coefficient" column="coefficient"/>
</resultMap> </resultMap>
<!-- 修改SQL片段系数保留两位小数 -->
<sql id="selectXzDryMatterCorrectionVo"> <sql id="selectXzDryMatterCorrectionVo">
SELECT SELECT
id, id,
datetime, datetime,
factory, factory,
content, content,
standard, COALESCE(standard, 18) as standard, <!-- 设置默认值为18 -->
CASE CASE
WHEN standard = 0 OR standard IS NULL THEN NULL WHEN standard = 0 OR standard IS NULL THEN NULL
ELSE content / standard ELSE ROUND(content / standard, 2) <!-- 系数保留两位小数 -->
END AS coefficient END AS coefficient
FROM xz_dry_matter_correction FROM xz_dry_matter_correction
</sql> </sql>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhyc.module.dairyProducts.mapper.XzParityCorrectionMapper"> <mapper namespace="com.zhyc.module.dairyProducts.mapper.XzParityCorrectionMapper">
<resultMap type="XzParityCorrection" id="XzParityCorrectionResult"> <resultMap type="XzParityCorrection" id="XzParityCorrectionResult">

View File

@ -20,9 +20,11 @@
<include refid="selectSgFeedListVo"/> <include refid="selectSgFeedListVo"/>
<where> <where>
<if test="formulaId != null and formulaId != ''"> and formula_id = #{formulaId}</if> <if test="formulaId != null and formulaId != ''"> and formula_id = #{formulaId}</if>
<if test="formulaBatchId != null and formulaBatchId != ''"> and formula_batch_id = #{formulaBatchId}</if>
<if test="zookeeper != null and zookeeper != ''"> and zookeeper = #{zookeeper}</if> <if test="zookeeper != null and zookeeper != ''"> and zookeeper = #{zookeeper}</if>
<if test="deployDate != null "> and deploy_date = #{deployDate}</if> <if test="deployDate != null "> and deploy_date = #{deployDate}</if>
</where> </where>
ORDER BY deploy_date ASC, formula_id ASC, formula_batch_id ASC
</select> </select>
<select id="selectSgFeedListById" parameterType="Long" resultMap="SgFeedListResult"> <select id="selectSgFeedListById" parameterType="Long" resultMap="SgFeedListResult">
@ -67,4 +69,8 @@
#{id} #{id}
</foreach> </foreach>
</delete> </delete>
<delete id="deleteAll">
DELETE FROM sg_feed_list;
</delete>
</mapper> </mapper>

View File

@ -37,9 +37,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectSgFeedPlanVo"/> <include refid="selectSgFeedPlanVo"/>
<where> <where>
<if test="formulaId != null and formulaId != ''"> and formula_id = #{formulaId}</if> <if test="formulaId != null and formulaId != ''"> and formula_id = #{formulaId}</if>
<if test="batchId != null and batchId != ''"> and batch_id = #{batchId}</if>
<if test="sheepHouseId != null "> and sheep_house_id = #{sheepHouseId}</if> <if test="sheepHouseId != null "> and sheep_house_id = #{sheepHouseId}</if>
<if test="planDate != null "> and plan_date = #{planDate}</if>
</where> </where>
ORDER BY formula_id ASC, plan_date ASC ORDER BY plan_date ASC, formula_id ASC , batch_id ASC
</select> </select>
<select id="selectSgFeedPlanByCreateDate" parameterType="Date" resultMap="SgFeedPlanResult"> <select id="selectSgFeedPlanByCreateDate" parameterType="Date" resultMap="SgFeedPlanResult">

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhyc.module.feed.mapper.SgFeedStatisticMapper">
<resultMap type="SgFeedStatistic" id="SgFeedStatisticResult">
<result property="id" column="id" />
<result property="formulaId" column="formula_id" />
<result property="formulaBatchId" column="formula_batch_id" />
<result property="sheepFoldCount" column="sheep_fold_count" />
<result property="silageLossRate" column="silage_loss_rate" />
<result property="feedTotalSize" column="feed_total_size" />
<result property="feedDailySize" column="feed_daily_size" />
<!--
适配泛型TypeHandler
弃用: XML中无法使用"<>"
-->
<!-- <result property="materialList" column="material_list"-->
<!-- typeHandler="com.zhyc.module.feed.mapper.TypeHandler.JsonTypeHandler<java.util.List<com.zhyc.module.feed.domain.SgFormulaList>>" />-->
<!-- 分别使用两个TypeHandler完成实体类List<T> 到 数据库 JSON串的映射转换 -->
<result property="materialList" column="material_list" typeHandler="com.zhyc.module.feed.mapper.TypeHandler.SgFormulaListHandler"/>
<result property="sheepFoldList" column="sheep_fold_list" typeHandler="com.zhyc.module.feed.mapper.TypeHandler.DaSheepfoldHandler"/>
<result property="feedDate" column="feed_date" />
</resultMap>
<sql id="selectSgFeedStatisticVo">
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
</sql>
<select id="selectSgFeedStatisticList" parameterType="SgFeedStatistic" resultMap="SgFeedStatisticResult">
<include refid="selectSgFeedStatisticVo"/>
<where>
<if test="formulaId != null and formulaId != ''"> and formula_id = #{formulaId}</if>
<if test="formulaBatchId != null and formulaBatchId != ''"> and formula_batch_id = #{formulaBatchId}</if>
<if test="silageLossRate != null and silageLossRate != ''"> and silage_loss_rate = #{silageLossRate}</if>
</where>
</select>
<select id="selectSgFeedStatisticById" parameterType="String" resultMap="SgFeedStatisticResult">
<include refid="selectSgFeedStatisticVo"/>
where id = #{id}
</select>
<insert id="insertSgFeedStatistic" parameterType="SgFeedStatistic">
insert into sg_feed_statistic
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="formulaId != null and formulaId != ''">formula_id,</if>
<if test="formulaBatchId != null and formulaBatchId != ''">formula_batch_id,</if>
<if test="sheepFoldCount != null">sheep_fold_count,</if>
<if test="silageLossRate != null">silage_loss_rate,</if>
<if test="feedTotalSize != null">feed_total_size,</if>
<if test="feedDailySize != null">feed_daily_size,</if>
<if test="materialList != null">material_list,</if>
<if test="sheepFoldList != null">sheep_fold_list,</if>
<if test="feedDate != null">feed_date,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="formulaId != null and formulaId != ''">#{formulaId},</if>
<if test="formulaBatchId != null and formulaBatchId != ''">#{formulaBatchId},</if>
<if test="sheepFoldCount != null">#{sheepFoldCount},</if>
<if test="silageLossRate != null">#{silageLossRate},</if>
<if test="feedTotalSize != null">#{feedTotalSize},</if>
<if test="feedDailySize != null">#{feedDailySize},</if>
# 写入操作需要手动指定 TypeHandler 参数
<if test="materialList != null">#{materialList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.SgFormulaListHandler},</if>
<if test="sheepFoldList != null">#{sheepFoldList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.DaSheepfoldHandler},</if>
<if test="feedDate != null">#{feedDate},</if>
</trim>
</insert>
<update id="updateSgFeedStatistic" parameterType="SgFeedStatistic">
update sg_feed_statistic
<trim prefix="SET" suffixOverrides=",">
<if test="formulaId != null and formulaId != ''">formula_id = #{formulaId},</if>
<if test="formulaBatchId != null and formulaBatchId != ''">formula_batch_id = #{formulaBatchId},</if>
<if test="sheepFoldCount != null">sheep_fold_count = #{sheepFoldCount},</if>
<if test="silageLossRate != null">silage_loss_rate = #{silageLossRate},</if>
<if test="feedTotalSize != null">feed_total_size = #{feedTotalSize},</if>
<if test="feedDailySize != null">feed_daily_size = #{feedDailySize},</if>
<if test="materialList != null">material_list = #{materialList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.SgFormulaListHandler},</if>
<if test="sheepFoldList != null">sheep_fold_list = #{sheepFoldList, typeHandler=com.zhyc.module.feed.mapper.TypeHandler.DaSheepfoldHandler},</if>
<if test="feedDate != null">feed_date = #{feedDate},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteSgFeedStatisticById" parameterType="String">
delete from sg_feed_statistic where id = #{id}
</delete>
<delete id="deleteSgFeedStatisticByIds" parameterType="String">
delete from sg_feed_statistic where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhyc.module.sale.mapper.SxSheepSaleMapper">
<resultMap type="SxSheepSale" id="SxSheepSaleResult">
<result property="id" column="id" />
<result property="bsManageTags" column="bs_manage_tags" />
<result property="sheepfoldId" column="sheepfold_id" />
<result property="variety" column="variety" />
<result property="sheepName" column="sheep_name" />
<result property="gender" column="gender" />
<result property="monthAge" column="month_age" />
<result property="parity" column="parity" />
<result property="breed" column="breed" />
<result property="postLambingDay" column="post_lambing_day" />
<result property="lactationDay" column="lactation_day" />
<result property="lambingDay" column="lambing_day" />
<result property="eventType" column="event_type" />
<result property="saleDate" column="sale_date" />
<result property="pricingMethod" column="pricing_method" />
<result property="unitPrice" column="unit_price" />
<result property="totalPrice" column="total_price" />
<result property="totalWeight" column="total_weight" />
<result property="avgWeight" column="avg_weight" />
<result property="avgPricePerSheep" column="avg_price_per_sheep" />
<result property="saleType" column="sale_type" />
<result property="diseaseType" column="disease_type" />
<result property="secondaryReason" column="secondary_reason" />
<result property="groupCode" column="group_code" />
<result property="customerId" column="customer_id" />
<result property="salesPersonId" column="sales_person_id" />
<result property="quarantineNo" column="quarantine_no" />
<result property="approvalNo" column="approval_no" />
<result property="technicianId" column="technician_id" />
<result property="handlerId" column="handler_id" />
<result property="createdBy" column="created_by" />
<result property="createdAt" column="created_at" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectSxSheepSaleVo">
select id, bs_manage_tags, sheepfold_id, variety, sheep_name, gender, month_age, parity, breed, post_lambing_day, lactation_day, lambing_day, event_type, sale_date, pricing_method, unit_price, total_price, total_weight, avg_weight, avg_price_per_sheep, sale_type, disease_type, secondary_reason, group_code, customer_id, sales_person_id, quarantine_no, approval_no, technician_id, handler_id, created_by, created_at, remark from sx_sheep_sale
</sql>
<!-- 【新增】根据耳号查询羊只信息的SQL片段 -->
<sql id="selectSheepFileVo">
select
bs_manage_tags,
variety,
name as sheep_name,
gender,
month_age,
parity,
breed,
post_lambing_day,
lactation_day,
lambing_day,
sheepfold_id
from sheep_file
</sql>
<!-- 【新增】根据耳号查询羊只信息 -->
<select id="selectSheepInfoByTag" parameterType="String" resultMap="SxSheepSaleResult">
<include refid="selectSheepFileVo"/>
where bs_manage_tags = #{bsManageTags}
</select>
<select id="selectSxSheepSaleList" parameterType="SxSheepSale" resultMap="SxSheepSaleResult">
<include refid="selectSxSheepSaleVo"/>
<where>
<if test="bsManageTags != null and bsManageTags != ''"> and bs_manage_tags = #{bsManageTags}</if>
<if test="sheepfoldId != null "> and sheepfold_id = #{sheepfoldId}</if>
<if test="variety != null and variety != ''"> and variety = #{variety}</if>
<if test="sheepName != null and sheepName != ''"> and sheep_name = #{sheepName}</if>
<if test="saleDate != null"> and sale_date = #{saleDate}</if>
<if test="saleType != null and saleType != ''"> and sale_type = #{saleType}</if>
</where>
</select>
<select id="selectSxSheepSaleById" parameterType="Long" resultMap="SxSheepSaleResult">
<include refid="selectSxSheepSaleVo"/>
where id = #{id}
</select>
<insert id="insertSxSheepSale" parameterType="SxSheepSale" useGeneratedKeys="true" keyProperty="id">
insert into sx_sheep_sale
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bsManageTags != null and bsManageTags != ''">bs_manage_tags,</if>
<if test="sheepfoldId != null">sheepfold_id,</if>
<if test="variety != null and variety != ''">variety,</if>
<if test="sheepName != null and sheepName != ''">sheep_name,</if>
<if test="gender != null and gender != ''">gender,</if>
<if test="monthAge != null">month_age,</if>
<if test="parity != null">parity,</if>
<if test="breed != null and breed != ''">breed,</if>
<if test="postLambingDay != null">post_lambing_day,</if>
<if test="lactationDay != null">lactation_day,</if>
<if test="lambingDay != null">lambing_day,</if>
<if test="eventType != null and eventType != ''">event_type,</if>
<if test="saleDate != null">sale_date,</if>
<if test="pricingMethod != null and pricingMethod != ''">pricing_method,</if>
<if test="unitPrice != null">unit_price,</if>
<if test="totalPrice != null">total_price,</if>
<if test="totalWeight != null">total_weight,</if>
<if test="avgWeight != null">avg_weight,</if>
<if test="avgPricePerSheep != null">avg_price_per_sheep,</if>
<if test="saleType != null and saleType != ''">sale_type,</if>
<if test="diseaseType != null and diseaseType != ''">disease_type,</if>
<if test="secondaryReason != null and secondaryReason != ''">secondary_reason,</if>
<if test="groupCode != null and groupCode != ''">group_code,</if>
<if test="customerId != null">customer_id,</if>
<if test="salesPersonId != null">sales_person_id,</if>
<if test="quarantineNo != null and quarantineNo != ''">quarantine_no,</if>
<if test="approvalNo != null and approvalNo != ''">approval_no,</if>
<if test="technicianId != null">technician_id,</if>
<if test="handlerId != null">handler_id,</if>
<if test="createdBy != null">created_by,</if>
<if test="createdAt != null">created_at,</if>
<if test="remark != null">remark,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bsManageTags != null and bsManageTags != ''">#{bsManageTags},</if>
<if test="sheepfoldId != null">#{sheepfoldId},</if>
<if test="variety != null and variety != ''">#{variety},</if>
<if test="sheepName != null and sheepName != ''">#{sheepName},</if>
<if test="gender != null and gender != ''">#{gender},</if>
<if test="monthAge != null">#{monthAge},</if>
<if test="parity != null">#{parity},</if>
<if test="breed != null and breed != ''">#{breed},</if>
<if test="postLambingDay != null">#{postLambingDay},</if>
<if test="lactationDay != null">#{lactationDay},</if>
<if test="lambingDay != null">#{lambingDay},</if>
<if test="eventType != null and eventType != ''">#{eventType},</if>
<if test="saleDate != null">#{saleDate},</if>
<if test="pricingMethod != null and pricingMethod != ''">#{pricingMethod},</if>
<if test="unitPrice != null">#{unitPrice},</if>
<if test="totalPrice != null">#{totalPrice},</if>
<if test="totalWeight != null">#{totalWeight},</if>
<if test="avgWeight != null">#{avgWeight},</if>
<if test="avgPricePerSheep != null">#{avgPricePerSheep},</if>
<if test="saleType != null and saleType != ''">#{saleType},</if>
<if test="diseaseType != null and diseaseType != ''">#{diseaseType},</if>
<if test="secondaryReason != null and secondaryReason != ''">#{secondaryReason},</if>
<if test="groupCode != null and groupCode != ''">#{groupCode},</if>
<if test="customerId != null">#{customerId},</if>
<if test="salesPersonId != null">#{salesPersonId},</if>
<if test="quarantineNo != null and quarantineNo != ''">#{quarantineNo},</if>
<if test="approvalNo != null and approvalNo != ''">#{approvalNo},</if>
<if test="technicianId != null">#{technicianId},</if>
<if test="handlerId != null">#{handlerId},</if>
<if test="createdBy != null">#{createdBy},</if>
<if test="createdAt != null">#{createdAt},</if>
<if test="remark != null">#{remark},</if>
</trim>
</insert>
<update id="updateSxSheepSale" parameterType="SxSheepSale">
update sx_sheep_sale
<trim prefix="SET" suffixOverrides=",">
<if test="bsManageTags != null and bsManageTags != ''">bs_manage_tags = #{bsManageTags},</if>
<if test="sheepfoldId != null">sheepfold_id = #{sheepfoldId},</if>
<if test="variety != null and variety != ''">variety = #{variety},</if>
<if test="sheepName != null and sheepName != ''">sheep_name = #{sheepName},</if>
<if test="gender != null and gender != ''">gender = #{gender},</if>
<if test="monthAge != null">month_age = #{monthAge},</if>
<if test="parity != null">parity = #{parity},</if>
<if test="breed != null and breed != ''">breed = #{breed},</if>
<if test="postLambingDay != null">post_lambing_day = #{postLambingDay},</if>
<if test="lactationDay != null">lactation_day = #{lactationDay},</if>
<if test="lambingDay != null">lambing_day = #{lambingDay},</if>
<if test="eventType != null and eventType != ''">event_type = #{eventType},</if>
<if test="saleDate != null">sale_date = #{saleDate},</if>
<if test="pricingMethod != null and pricingMethod != ''">pricing_method = #{pricingMethod},</if>
<if test="unitPrice != null">unit_price = #{unitPrice},</if>
<if test="totalPrice != null">total_price = #{totalPrice},</if>
<if test="totalWeight != null">total_weight = #{totalWeight},</if>
<if test="avgWeight != null">avg_weight = #{avgWeight},</if>
<if test="avgPricePerSheep != null">avg_price_per_sheep = #{avgPricePerSheep},</if>
<if test="saleType != null and saleType != ''">sale_type = #{saleType},</if>
<if test="diseaseType != null and diseaseType != ''">disease_type = #{diseaseType},</if>
<if test="secondaryReason != null and secondaryReason != ''">secondary_reason = #{secondaryReason},</if>
<if test="groupCode != null and groupCode != ''">group_code = #{groupCode},</if>
<if test="customerId != null">customer_id = #{customerId},</if>
<if test="salesPersonId != null">sales_person_id = #{salesPersonId},</if>
<if test="quarantineNo != null and quarantineNo != ''">quarantine_no = #{quarantineNo},</if>
<if test="approvalNo != null and approvalNo != ''">approval_no = #{approvalNo},</if>
<if test="technicianId != null">technician_id = #{technicianId},</if>
<if test="handlerId != null">handler_id = #{handlerId},</if>
<if test="createdBy != null">created_by = #{createdBy},</if>
<if test="createdAt != null">created_at = #{createdAt},</if>
<if test="remark != null">remark = #{remark},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteSxSheepSaleById" parameterType="Long">
delete from sx_sheep_sale where id = #{id}
</delete>
<delete id="deleteSxSheepSaleByIds" parameterType="String">
delete from sx_sheep_sale where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -26,7 +26,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectWzMaterialsManagementVo"/> <include refid="selectWzMaterialsManagementVo"/>
<where> <where>
<if test="materialName != null and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if> <if test="materialName != null and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if>
<if test="params.beginProductionDate != null and params.beginProductionDate != '' and params.endProductionDate != null and params.endProductionDate != ''"> and production_date between #{params.beginProductionDate} and #{params.endProductionDate}</if> <if test="params.beginProductionDate != null and params.endProductionDate != null"> and production_date between #{params.beginProductionDate} and #{params.endProductionDate}</if>
<if test="productionDate != null"> and production_date = #{productionDate}</if>
</where> </where>
</select> </select>

View File

@ -41,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="businessType != null and businessType != ''"> and business_type = #{businessType}</if> <if test="businessType != null and businessType != ''"> and business_type = #{businessType}</if>
<if test="repositoryName != null and repositoryName != ''"> and repository_name like concat('%', #{repositoryName}, '%')</if> <if test="repositoryName != null and repositoryName != ''"> and repository_name like concat('%', #{repositoryName}, '%')</if>
<if test="materialName != null and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if> <if test="materialName != null and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if>
<if test="docDate != null"> and doc_date = #{docDate}</if>
</where> </where>
</select> </select>