This commit is contained in:
2025-11-21 10:53:04 +08:00
parent e24d6ef0b4
commit 24ca9148dd
61 changed files with 4918 additions and 582 deletions

View File

@@ -0,0 +1,15 @@
package com.delivery.framework.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/** 配送定位上报规则配置 */
@Data
@Component("locationReportProperties")
@ConfigurationProperties(prefix = "delivery.location")
public class LocationReportProperties {
private long minPersistIntervalMs;
private long stateTtlHours;
private long lockSeconds;
}

View File

@@ -32,6 +32,10 @@ public class ResourcesConfig implements WebMvcConfigurer
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
.addResourceLocations("file:" + DeliveryConfig.getProfile() + "/");
/** D:\delivery 的静态映射 */
registry.addResourceHandler("/delivery/**")
.addResourceLocations("file:D:/delivery/");
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")

View File

@@ -114,7 +114,14 @@ public class SecurityConfig
requests.antMatchers(
"/login",
"/register",
"/app/**",
"/delivery/**",
"/document/vehicle/**",
"/document/type/**",
"/document/location/**",
"/document/mtd/**",
"/document/info/**",
"/delivery/location/**",
"/document/attachment/**",
"/document/order/**",
// "/document/info/bill/groups",

View File

@@ -173,4 +173,28 @@ public class SysLoginService
{
userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate());
}
public LoginUser loginWithoutCaptcha(String username, String password) {
loginPreCheck(username, password);
Authentication authentication;
try {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(token);
authentication = authenticationManager.authenticate(token);
}catch (Exception e){
throw new ServiceException("登录失败");
}finally {
AuthenticationContextHolder.clearContext();
}
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
return loginUser;
}
}

View File

@@ -1,15 +1,15 @@
package com.delivery.project.document.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.delivery.common.exception.ServiceException;
import com.delivery.common.utils.MinioUtil;
import com.delivery.common.utils.uuid.IdUtils;
import com.delivery.project.document.domain.dto.DeliveryAttachUploadDTO;
import com.delivery.project.document.domain.dto.DeliveryExecuteBindDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile;
* @date 2025-10-15
*/
@RestController
@Slf4j
@RequestMapping("/document/attachment")
public class DeliveryAttachmentController extends BaseController
{
@@ -45,6 +46,7 @@ public class DeliveryAttachmentController extends BaseController
@Value("${minio.bucketName}")
private String bucketName;
/**
* 查询配送附件列表
*/
@@ -118,8 +120,8 @@ public class DeliveryAttachmentController extends BaseController
*/
// @PreAuthorize("@ss.hasPermi('document:attachment:add')")
// @Log(title = "配送附件-上传(仅MinIO)", businessType = BusinessType.OTHER)
@PostMapping(value = "/upload", consumes = {"multipart/form-data"})
public AjaxResult upload(@RequestPart("files") MultipartFile[] files,
@PostMapping(value = "/uploads", consumes = {"multipart/form-data"})
public AjaxResult uploads(@RequestPart("files") MultipartFile[] files,
@Validated @ModelAttribute DeliveryAttachUploadDTO dto) {
try {
// 用 scene + bizType 自动当作子目录(可空)
@@ -133,7 +135,7 @@ public class DeliveryAttachmentController extends BaseController
List<String> urls = minioUtil.uploadBatch(
files,
bucketName,
minioUtil.buildDateFolder("delivery", sub) // delivery/yyyy-MM-dd[/scene/bizType]
minioUtil.buildDateFolder("delivery", sub)
);
return AjaxResult.success("urls", urls);
} catch (ServiceException se) {
@@ -142,4 +144,36 @@ public class DeliveryAttachmentController extends BaseController
return AjaxResult.error("上传失败:" + e.getMessage());
}
}
/**
* 开始配送
* @param dto
* @return
*/
// @PreAuthorize("@ss.hasPermi('document:attachment:add')")
// @Log(title = "配送附件-执行绑定", businessType = BusinessType.INSERT)
@PostMapping("/executeBind")
public AjaxResult executeBind(@Validated @RequestBody DeliveryExecuteBindDTO dto) {
int saved = deliveryAttachmentService.executeBind(dto);
return AjaxResult.success()
.put("orderNo", dto.getOrderNo())
.put("scene", dto.getScene());
}
@Log(title = "配送附件上传", businessType = BusinessType.OTHER)
@PostMapping(value = "/upload", consumes = "multipart/form-data")
public AjaxResult upload(@RequestPart("files") MultipartFile[] files,
@Validated @ModelAttribute DeliveryAttachUploadDTO dto,
HttpServletRequest request) {
try {
List<String> urls = deliveryAttachmentService.upload(files, dto, request);
return AjaxResult.success("上传成功", urls);
} catch (Exception e) {
log.error("【附件上传失败】{}", e.getMessage(), e);
return AjaxResult.error("上传失败:" + e.getMessage());
}
}
}

View File

@@ -0,0 +1,118 @@
package com.delivery.project.document.controller;
import com.delivery.common.utils.poi.ExcelUtil;
import com.delivery.framework.aspectj.lang.annotation.Log;
import com.delivery.framework.aspectj.lang.enums.BusinessType;
import com.delivery.framework.web.controller.BaseController;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.framework.web.page.TableDataInfo;
import com.delivery.project.document.domain.DeliveryLocationRecord;
import com.delivery.project.document.domain.dto.DeliverySimpleLocationDTO;
import com.delivery.project.document.domain.dto.LocationReportDTO;
import com.delivery.project.document.service.ILocationReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 配送定位上报 Controller仅打印经纬度
*
* @author delivery
* @date 2025-10-20
*/
@Slf4j
@RestController
@RequestMapping("/delivery/location")
public class DeliveryLocationController extends BaseController {
@Autowired
private ILocationReportService deliveryLocationRecordService;
@PostMapping("/report")
public AjaxResult report(@Validated @RequestBody LocationReportDTO dto) {
String username = getUsername();
return AjaxResult.success(deliveryLocationRecordService.report(dto, username));
}
/**
* 查询配送定位记录(车牌+单号维度)列表
*/
@PreAuthorize("@ss.hasPermi('document:record:list')")
@GetMapping("/list")
public TableDataInfo list(DeliveryLocationRecord deliveryLocationRecord)
{
startPage();
List<DeliveryLocationRecord> list = deliveryLocationRecordService.selectDeliveryLocationRecordList(deliveryLocationRecord);
return getDataTable(list);
}
/**
* 导出配送定位记录(车牌+单号维度)列表
*/
@PreAuthorize("@ss.hasPermi('document:record:export')")
@Log(title = "配送定位记录(车牌+单号维度)", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DeliveryLocationRecord deliveryLocationRecord)
{
List<DeliveryLocationRecord> list = deliveryLocationRecordService.selectDeliveryLocationRecordList(deliveryLocationRecord);
ExcelUtil<DeliveryLocationRecord> util = new ExcelUtil<DeliveryLocationRecord>(DeliveryLocationRecord.class);
util.exportExcel(response, list, "配送定位记录(车牌+单号维度)数据");
}
/**
* 获取配送定位记录(车牌+单号维度)详细信息
*/
@PreAuthorize("@ss.hasPermi('document:record:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(deliveryLocationRecordService.selectDeliveryLocationRecordById(id));
}
/**
* 新增配送定位记录(车牌+单号维度)
*/
@PreAuthorize("@ss.hasPermi('document:record:add')")
@Log(title = "配送定位记录(车牌+单号维度)", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DeliveryLocationRecord deliveryLocationRecord)
{
return toAjax(deliveryLocationRecordService.insertDeliveryLocationRecord(deliveryLocationRecord));
}
/**
* 修改配送定位记录(车牌+单号维度)
*/
@PreAuthorize("@ss.hasPermi('document:record:edit')")
@Log(title = "配送定位记录(车牌+单号维度)", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DeliveryLocationRecord deliveryLocationRecord)
{
return toAjax(deliveryLocationRecordService.updateDeliveryLocationRecord(deliveryLocationRecord));
}
/**
* 删除配送定位记录(车牌+单号维度)
*/
@PreAuthorize("@ss.hasPermi('document:record:remove')")
@Log(title = "配送定位记录(车牌+单号维度)", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(deliveryLocationRecordService.deleteDeliveryLocationRecordByIds(ids));
}
// @PreAuthorize("@ss.hasPermi('document:record:track')")
@GetMapping("/track")
public AjaxResult track(@RequestParam("orderNo") String orderNo,
@RequestParam("plateNo") String plateNo) {
List<DeliverySimpleLocationDTO> points =
deliveryLocationRecordService.selectTrackPoints(orderNo, plateNo);
return AjaxResult.success(points);
}
}

View File

@@ -3,7 +3,10 @@ package com.delivery.project.document.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.delivery.project.document.domain.RkInfo;
import com.delivery.project.document.domain.dto.DeliveryOrderCreateDTO;
import com.delivery.project.document.domain.dto.DeliveryOrderSaveDTO;
import com.delivery.project.document.domain.vo.DeliveryOrderGroupVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -88,8 +91,7 @@ public class DeliveryOrderController extends BaseController
@PreAuthorize("@ss.hasPermi('document:order:edit')")
@Log(title = "配送单据主", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DeliveryOrder deliveryOrder)
{
public AjaxResult edit(@RequestBody DeliveryOrder deliveryOrder) {
return toAjax(deliveryOrderService.updateDeliveryOrder(deliveryOrder));
}
@@ -119,4 +121,41 @@ public class DeliveryOrderController extends BaseController
return toAjax(rows);
}
/** 新增配送单据:同一单号多行写入 */
// @PreAuthorize("@ss.hasPermi('document:order:add')")
// @Log(title = "配送单据", businessType = BusinessType.INSERT)
@PostMapping("/batch")
public AjaxResult createBatch(@RequestBody DeliveryOrderCreateDTO dto) {
String plateNo = deliveryOrderService.createOrder(dto);
return success("创建成功,单号:" + plateNo);
}
/** 列表:按单号分组(分页) */
// @PreAuthorize("@ss.hasPermi('document:order:list')")
@GetMapping("/group")
public TableDataInfo listGroup(DeliveryOrder query) {
startPage();
List<DeliveryOrderGroupVO> list = deliveryOrderService.listGroup(query);
return getDataTable(list);
}
/** 详情:按单号查询所有行 */
// @PreAuthorize("@ss.hasPermi('document:order:query')")
@GetMapping("/detail/{orderNo}")
public AjaxResult detail(@PathVariable String orderNo) {
return success(deliveryOrderService.listByOrderNo(orderNo));
}
/**
* 从智慧实物系统拉取待配送出库单据列表
*/
@GetMapping("/wisdom/rk/list")
public AjaxResult listRkFromWisdom() {
List<RkInfo> list = deliveryOrderService.listWisdomRkForDelivery();
return AjaxResult.success(list);
}
}

View File

@@ -0,0 +1,29 @@
package com.delivery.project.document.controller;
import com.delivery.framework.web.controller.BaseController;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.project.document.domain.dto.LocationReportDTO;
import com.delivery.project.document.service.ILocationReportService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
///** 配送定位上报 Controller车牌+单号维度) */
//@RestController
//@RequestMapping("/document/location")
//public class LocationController extends BaseController {
//
// @Resource
// private ILocationReportService locationReportService;
//
// /** APP 上报定位(车牌号 + 配送单号 + 经纬度) */
//// @PreAuthorize("@ss.hasPermi('document:location:report')")
// @PostMapping("/report")
// public AjaxResult report(@Validated @RequestBody LocationReportDTO dto) {
//// String username = getUsername();
// System.out.println("1`1111111111111111111111111111");
// String username = "大爷的!!!";
// return AjaxResult.success(locationReportService.report(dto, username));
// }
//}

View File

@@ -0,0 +1,128 @@
package com.delivery.project.document.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.delivery.project.document.domain.dto.CalcTotalWvDTO;
import com.delivery.project.document.domain.vo.TotalWvVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.delivery.framework.aspectj.lang.annotation.Log;
import com.delivery.framework.aspectj.lang.enums.BusinessType;
import com.delivery.project.document.domain.Mtd;
import com.delivery.project.document.service.IMtdService;
import com.delivery.framework.web.controller.BaseController;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.common.utils.poi.ExcelUtil;
import com.delivery.framework.web.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* 物料字典Controller
*
* @author delivery
* @date 2025-10-23
*/
@RestController
@RequestMapping("/document/mtd")
public class MtdController extends BaseController
{
@Autowired
private IMtdService mtdService;
/**
* 查询物料字典列表
*/
@PreAuthorize("@ss.hasPermi('document:mtd:list')")
@GetMapping("/list")
public TableDataInfo list(Mtd mtd)
{
startPage();
List<Mtd> list = mtdService.selectMtdList(mtd);
return getDataTable(list);
}
/**
* 导出物料字典列表
*/
@PreAuthorize("@ss.hasPermi('document:mtd:export')")
@Log(title = "物料字典", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Mtd mtd)
{
List<Mtd> list = mtdService.selectMtdList(mtd);
ExcelUtil<Mtd> util = new ExcelUtil<Mtd>(Mtd.class);
util.exportExcel(response, list, "物料字典数据");
}
/**
* Excel 导入物料字典(同 wlNo 则更新,不存在则新增)
*/
@PreAuthorize("@ss.hasPermi('document:mtd:import')")
@Log(title = "物料字典", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(@RequestParam("file") MultipartFile file) throws Exception
{
if (file == null || file.isEmpty()) {
return AjaxResult.error("导入文件不能为空");
}
ExcelUtil<Mtd> util = new ExcelUtil<>(Mtd.class);
List<Mtd> list = util.importExcel(file.getInputStream());
int handled = mtdService.importMtd(list, getUsername());
return success("导入成功,共处理 " + handled + "");
}
/**
* 获取物料字典详细信息
*/
@PreAuthorize("@ss.hasPermi('document:mtd:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mtdService.selectMtdById(id));
}
/**
* 新增物料字典
*/
@PreAuthorize("@ss.hasPermi('document:mtd:add')")
@Log(title = "物料字典", businessType = BusinessType.INSERT)
@PostMapping()
public AjaxResult add(@RequestBody Mtd mtd)
{
return toAjax(mtdService.insertMtd(mtd));
}
/**
* 修改物料字典
*/
@PreAuthorize("@ss.hasPermi('document:mtd:edit')")
@Log(title = "物料字典", businessType = BusinessType.UPDATE)
@PutMapping()
public AjaxResult edit(@RequestBody Mtd mtd)
{
return toAjax(mtdService.updateMtd(mtd));
}
/**
* 删除物料字典
*/
@PreAuthorize("@ss.hasPermi('document:mtd:remove')")
@Log(title = "物料字典", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mtdService.deleteMtdByIds(ids));
}
/**
* 计算货物的总体积和重量
*/
// @PreAuthorize("@ss.hasPermi('document:mtd:calc')")
@PostMapping("/calcTotalWv")
public AjaxResult calcTotalWv(@RequestBody CalcTotalWvDTO dto) {
TotalWvVO vo = mtdService.calcTotalWv(dto);
return AjaxResult.success(vo);
}
}

View File

@@ -3,9 +3,7 @@ package com.delivery.project.document.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.delivery.project.document.domain.dto.RkInfoQueryDTO;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.ApiOperation;
import com.delivery.project.document.service.IVehicleTypeService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -42,9 +40,13 @@ public class RkInfoController extends BaseController
* 查询库存单据明细列表
*/
@GetMapping("/list")
public TableDataInfo list(RkInfo rkInfo) {
public TableDataInfo list(RkInfo rkInfo)
{
List<RkInfo> list = rkInfoService.selectRkInfoList(rkInfo);
// 封装分页返回
return getDataTable(list);
}
/**
* 导出库存单据明细列表
@@ -62,7 +64,7 @@ public class RkInfoController extends BaseController
/**
* 获取库存单据明细详细信息
*/
@PreAuthorize("@ss.hasPermi('document:info:query')")
// @PreAuthorize("@ss.hasPermi('document:info:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
@@ -114,4 +116,15 @@ public class RkInfoController extends BaseController
return getDataTable(rows);
}
@GetMapping("/page")
public TableDataInfo page(RkInfo rkInfo)
{
// 开启分页
startPage();
List<RkInfo> list = rkInfoService.selectRkInfoList(rkInfo);
// 封装分页返回
return getDataTable(list);
}
}

View File

@@ -0,0 +1,104 @@
package com.delivery.project.document.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.RestController;
import com.delivery.framework.aspectj.lang.annotation.Log;
import com.delivery.framework.aspectj.lang.enums.BusinessType;
import com.delivery.project.document.domain.Vehicle;
import com.delivery.project.document.service.IVehicleService;
import com.delivery.framework.web.controller.BaseController;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.common.utils.poi.ExcelUtil;
import com.delivery.framework.web.page.TableDataInfo;
/**
* 车辆档案Controller
*
* @author delivery
* @date 2025-10-23
*/
@RestController
@RequestMapping("/document/vehicle")
public class VehicleController extends BaseController
{
@Autowired
private IVehicleService vehicleService;
/**
* 查询车辆档案列表
*/
// @PreAuthorize("@ss.hasPermi('document:vehicle:list')")
@GetMapping("/list")
public TableDataInfo list(Vehicle vehicle)
{
startPage();
List<Vehicle> list = vehicleService.selectVehicleList(vehicle);
return getDataTable(list);
}
/**
* 导出车辆档案列表
*/
@PreAuthorize("@ss.hasPermi('document:vehicle:export')")
@Log(title = "车辆档案", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Vehicle vehicle)
{
List<Vehicle> list = vehicleService.selectVehicleList(vehicle);
ExcelUtil<Vehicle> util = new ExcelUtil<Vehicle>(Vehicle.class);
util.exportExcel(response, list, "车辆档案数据");
}
/**
* 获取车辆档案详细信息
*/
@PreAuthorize("@ss.hasPermi('document:vehicle:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(vehicleService.selectVehicleById(id));
}
/**
* 新增车辆档案
*/
@PreAuthorize("@ss.hasPermi('document:vehicle:add')")
@Log(title = "车辆档案", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Vehicle vehicle)
{
return toAjax(vehicleService.insertVehicle(vehicle));
}
/**
* 修改车辆档案
*/
@PreAuthorize("@ss.hasPermi('document:vehicle:edit')")
@Log(title = "车辆档案", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Vehicle vehicle)
{
return toAjax(vehicleService.updateVehicle(vehicle));
}
/**
* 删除车辆档案
*/
@PreAuthorize("@ss.hasPermi('document:vehicle:remove')")
@Log(title = "车辆档案", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(vehicleService.deleteVehicleByIds(ids));
}
}

View File

@@ -0,0 +1,127 @@
package com.delivery.project.document.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.delivery.project.document.domain.dto.CalcSuggestFeeDTO;
import com.delivery.project.document.domain.vo.CalcSuggestFeeVO;
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.RestController;
import com.delivery.framework.aspectj.lang.annotation.Log;
import com.delivery.framework.aspectj.lang.enums.BusinessType;
import com.delivery.project.document.domain.VehicleType;
import com.delivery.project.document.service.IVehicleTypeService;
import com.delivery.framework.web.controller.BaseController;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.common.utils.poi.ExcelUtil;
import com.delivery.framework.web.page.TableDataInfo;
/**
* 车型定义Controller
*
* @author delivery
* @date 2025-10-23
*/
@RestController
@RequestMapping("/document/type")
public class VehicleTypeController extends BaseController
{
@Autowired
private IVehicleTypeService vehicleTypeService;
/**
* 查询车型定义列表
*/
// @PreAuthorize("@ss.hasPermi('document:type:list')")
@GetMapping("/list")
public TableDataInfo list(VehicleType vehicleType)
{
startPage();
List<VehicleType> list = vehicleTypeService.selectVehicleTypeList(vehicleType);
return getDataTable(list);
}
/**
* 导出车型定义列表
*/
@PreAuthorize("@ss.hasPermi('document:type:export')")
@Log(title = "车型定义", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, VehicleType vehicleType)
{
List<VehicleType> list = vehicleTypeService.selectVehicleTypeList(vehicleType);
ExcelUtil<VehicleType> util = new ExcelUtil<VehicleType>(VehicleType.class);
util.exportExcel(response, list, "车型定义数据");
}
/**
* 获取车型定义详细信息
*/
@PreAuthorize("@ss.hasPermi('document:type:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(vehicleTypeService.selectVehicleTypeById(id));
}
/**
* 新增车型定义
*/
@PreAuthorize("@ss.hasPermi('document:type:add')")
@Log(title = "车型定义", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody VehicleType vehicleType)
{
return toAjax(vehicleTypeService.insertVehicleType(vehicleType));
}
/**
* 修改车型定义
*/
@PreAuthorize("@ss.hasPermi('document:type:edit')")
@Log(title = "车型定义", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody VehicleType vehicleType)
{
return toAjax(vehicleTypeService.updateVehicleType(vehicleType));
}
/**
* 删除车型定义
*/
@PreAuthorize("@ss.hasPermi('document:type:remove')")
@Log(title = "车型定义", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(vehicleTypeService.deleteVehicleTypeByIds(ids));
}
/** 计算建议费用(支持前端指定车型重算) */
@PostMapping("/fee")
public AjaxResult calcSuggestFee(@RequestBody CalcSuggestFeeDTO dto) {
CalcSuggestFeeVO vo = vehicleTypeService.calcSuggestFee(dto);
return success(vo);
}
/**
* 查看全部车型
* @param vehicleType
* @return
*/
@GetMapping("/page")
public TableDataInfo page(VehicleType vehicleType)
{
List<VehicleType> list = vehicleTypeService.selectVehicleTypeList(vehicleType);
return getDataTable(list);
}
}

View File

@@ -0,0 +1,49 @@
package com.delivery.project.document.controller.app;
import com.delivery.framework.security.LoginBody;
import com.delivery.framework.security.LoginUser;
import com.delivery.framework.security.service.SysLoginService;
import com.delivery.framework.security.service.TokenService;
import com.delivery.framework.web.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/app")
public class LoginController {
@Autowired
private SysLoginService loginService;
@Autowired
private TokenService tokenService;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody) {
String username = loginBody.getUsername();
String password = loginBody.getPassword();
LoginUser loginUser = loginService.loginWithoutCaptcha(username, password);
String token = tokenService.createToken(loginUser);
Map<String, Object> data = new HashMap<>();
data.put("token", token);
data.put("user", loginUser.getUser());
return AjaxResult.success(data);
}
}

View File

@@ -20,7 +20,7 @@ public class DeliveryAttachment extends BaseEntity
/** 关联的配送单ID */
@Excel(name = "关联的配送单ID")
private Long orderId;
private String orderNo;
/** 场景ORIGIN起点、DEST终点 */
@@ -57,14 +57,14 @@ public class DeliveryAttachment extends BaseEntity
return id;
}
public void setOrderId(Long orderId)
public void setOrderNo(String orderNo)
{
this.orderId = orderId;
this.orderNo = orderNo;
}
public Long getOrderId()
public String getOrderNo()
{
return orderId;
return orderNo;
}
public void setScene(String scene)
@@ -131,7 +131,7 @@ public class DeliveryAttachment extends BaseEntity
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("orderId", getOrderId())
.append("orderNo", getOrderNo())
.append("scene", getScene())
.append("bizType", getBizType())
.append("url", getUrl())

View File

@@ -0,0 +1,39 @@
package com.delivery.project.document.domain;
import com.delivery.framework.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/** 配送定位落库记录实体(车牌+单号维度) */
@Data
public class DeliveryLocationRecord extends BaseEntity {
/** 主键ID */
private Long id;
/** 车牌号(上报维度之一) */
private String plateNo;
/** 配送单号(上报维度之一,必填) */
private String orderNo;
/** 经度保留6位小数 */
private BigDecimal lng;
/** 纬度保留6位小数 */
private BigDecimal lat;
/** 服务端接收并确认落库时间 */
private Date reportedAt;
/** 来源app等 */
private String source;
/** 触发原因3_same/15s_tick等 */
private String remark;
/** 是否删除0正常1删除 */
private String isDelete;
}

View File

@@ -12,17 +12,19 @@ import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 配送单据主对象 delivery_order
*
* @author delivery
* @date 2025-10-15
*/
public class DeliveryOrder extends BaseEntity
{
public class DeliveryOrder extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 配送单据号 */
@Excel(name = "配送单据号")
private String orderNo;
/** 项目描述 */
@Excel(name = "项目描述")
private String xmMs;
@@ -86,7 +88,15 @@ public class DeliveryOrder extends BaseEntity
/** 配送车牌 */
@Excel(name = "配送车牌")
private String vehiclePlate;
private String plateNo;
/** 司机姓名 */
@Excel(name = "司机姓名")
private String driverName;
/** 司机联系方式 */
@Excel(name = "司机联系方式")
private String driverPhone;
/** 发货人姓名 */
@Excel(name = "发货人姓名")
@@ -112,6 +122,21 @@ public class DeliveryOrder extends BaseEntity
@Excel(name = "配送吨位")
private BigDecimal deliveryTon;
/** 货物尺寸(㎡),占地面积 */
@Excel(name = "货物尺寸(㎡)")
private BigDecimal goodsSize;
/** 配送状态0待接单1已接单2配送中3已签收 */
@Excel(name = "配送状态", readConverterExp = "0=待接单,1=已接单,2=配送中,3=已签收")
private String orderStatus;
/** 车辆类型ID */
private Long vehicleTypeId;
/** 车辆类型名称 */
@Excel(name = "车辆类型名称")
private String vehicleTypeName;
/** 是否删除0正常 1已删除 */
@Excel(name = "是否删除", readConverterExp = "0=正常,1=已删除")
private String isDelete;
@@ -119,281 +144,175 @@ public class DeliveryOrder extends BaseEntity
/** 连表查询用:附件列表 */
private List<DeliveryAttachment> attachments;
// ===================== 费用与里程 =====================
/** 建议费用(按车型单价*里程的推荐值) */
@Excel(name = "建议费用")
private BigDecimal suggestFee;
/** 实际费用(最终确认费用) */
@Excel(name = "实际费用")
private BigDecimal actualFee;
/** 高速费用 */
@Excel(name = "高速费用")
private BigDecimal tollFee;
/** 总公里数(行驶里程) */
@Excel(name = "总公里数")
private BigDecimal totalKm;
// ===================== Getter & Setter =====================
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getOrderNo() { return orderNo; }
public void setOrderNo(String orderNo) { this.orderNo = orderNo; }
public String getXmMs() { return xmMs; }
public void setXmMs(String xmMs) { this.xmMs = xmMs; }
public String getXmNo() { return xmNo; }
public void setXmNo(String xmNo) { this.xmNo = xmNo; }
public String getWlNo() { return wlNo; }
public void setWlNo(String wlNo) { this.wlNo = wlNo; }
public String getWlMs() { return wlMs; }
public void setWlMs(String wlMs) { this.wlMs = wlMs; }
public BigDecimal getRealQty() { return realQty; }
public void setRealQty(BigDecimal realQty) { this.realQty = realQty; }
public String getDw() { return dw; }
public void setDw(String dw) { this.dw = dw; }
public String getSapNo() { return sapNo; }
public void setSapNo(String sapNo) { this.sapNo = sapNo; }
public String getGysMc() { return gysMc; }
public void setGysMc(String gysMc) { this.gysMc = gysMc; }
public String getOriginName() { return originName; }
public void setOriginName(String originName) { this.originName = originName; }
public BigDecimal getOriginLng() { return originLng; }
public void setOriginLng(BigDecimal originLng) { this.originLng = originLng; }
public BigDecimal getOriginLat() { return originLat; }
public void setOriginLat(BigDecimal originLat) { this.originLat = originLat; }
public String getDestName() { return destName; }
public void setDestName(String destName) { this.destName = destName; }
public BigDecimal getDestLng() { return destLng; }
public void setDestLng(BigDecimal destLng) { this.destLng = destLng; }
public BigDecimal getDestLat() { return destLat; }
public void setDestLat(BigDecimal destLat) { this.destLat = destLat; }
public Date getDeliveryDate() { return deliveryDate; }
public void setDeliveryDate(Date deliveryDate) { this.deliveryDate = deliveryDate; }
public String getplateNo() { return plateNo; }
public void setplateNo(String plateNo) { this.plateNo = plateNo; }
public String getDriverName() { return driverName; }
public void setDriverName(String driverName) { this.driverName = driverName; }
public String getDriverPhone() { return driverPhone; }
public void setDriverPhone(String driverPhone) { this.driverPhone = driverPhone; }
public String getShipperName() { return shipperName; }
public void setShipperName(String shipperName) { this.shipperName = shipperName; }
public String getShipperPhone() { return shipperPhone; }
public void setShipperPhone(String shipperPhone) { this.shipperPhone = shipperPhone; }
public String getReceiverName() { return receiverName; }
public void setReceiverName(String receiverName) { this.receiverName = receiverName; }
public String getReceiverPhone() { return receiverPhone; }
public void setReceiverPhone(String receiverPhone) { this.receiverPhone = receiverPhone; }
public String getReceiverOrgName() { return receiverOrgName; }
public void setReceiverOrgName(String receiverOrgName) { this.receiverOrgName = receiverOrgName; }
public BigDecimal getDeliveryTon() { return deliveryTon; }
public void setDeliveryTon(BigDecimal deliveryTon) { this.deliveryTon = deliveryTon; }
public BigDecimal getGoodsSize() { return goodsSize; }
public void setGoodsSize(BigDecimal goodsSize) { this.goodsSize = goodsSize; }
public String getOrderStatus() { return orderStatus; }
public void setOrderStatus(String orderStatus) { this.orderStatus = orderStatus; }
public Long getVehicleTypeId() { return vehicleTypeId; }
public void setVehicleTypeId(Long vehicleTypeId) { this.vehicleTypeId = vehicleTypeId; }
public String getVehicleTypeName() { return vehicleTypeName; }
public void setVehicleTypeName(String vehicleTypeName) { this.vehicleTypeName = vehicleTypeName; }
public String getIsDelete() { return isDelete; }
public void setIsDelete(String isDelete) { this.isDelete = isDelete; }
public List<DeliveryAttachment> getAttachments() { return attachments; }
public void setAttachments(List<DeliveryAttachment> attachments) { this.attachments = attachments; }
public void setId(Long id)
{
this.id = id;
}
public BigDecimal getSuggestFee() { return suggestFee; }
public void setSuggestFee(BigDecimal suggestFee) { this.suggestFee = suggestFee; }
public Long getId()
{
return id;
}
public BigDecimal getActualFee() { return actualFee; }
public void setActualFee(BigDecimal actualFee) { this.actualFee = actualFee; }
public void setXmMs(String xmMs)
{
this.xmMs = xmMs;
}
public BigDecimal getTollFee() { return tollFee; }
public void setTollFee(BigDecimal tollFee) { this.tollFee = tollFee; }
public String getXmMs()
{
return xmMs;
}
public void setXmNo(String xmNo)
{
this.xmNo = xmNo;
}
public String getXmNo()
{
return xmNo;
}
public void setWlNo(String wlNo)
{
this.wlNo = wlNo;
}
public String getWlNo()
{
return wlNo;
}
public void setWlMs(String wlMs)
{
this.wlMs = wlMs;
}
public String getWlMs()
{
return wlMs;
}
public void setRealQty(BigDecimal realQty)
{
this.realQty = realQty;
}
public BigDecimal getRealQty()
{
return realQty;
}
public void setDw(String dw)
{
this.dw = dw;
}
public String getDw()
{
return dw;
}
public void setSapNo(String sapNo)
{
this.sapNo = sapNo;
}
public String getSapNo()
{
return sapNo;
}
public void setGysMc(String gysMc)
{
this.gysMc = gysMc;
}
public String getGysMc()
{
return gysMc;
}
public void setOriginName(String originName)
{
this.originName = originName;
}
public String getOriginName()
{
return originName;
}
public void setOriginLng(BigDecimal originLng)
{
this.originLng = originLng;
}
public BigDecimal getOriginLng()
{
return originLng;
}
public void setOriginLat(BigDecimal originLat)
{
this.originLat = originLat;
}
public BigDecimal getOriginLat()
{
return originLat;
}
public void setDestName(String destName)
{
this.destName = destName;
}
public String getDestName()
{
return destName;
}
public void setDestLng(BigDecimal destLng)
{
this.destLng = destLng;
}
public BigDecimal getDestLng()
{
return destLng;
}
public void setDestLat(BigDecimal destLat)
{
this.destLat = destLat;
}
public BigDecimal getDestLat()
{
return destLat;
}
public void setDeliveryDate(Date deliveryDate)
{
this.deliveryDate = deliveryDate;
}
public Date getDeliveryDate()
{
return deliveryDate;
}
public void setVehiclePlate(String vehiclePlate)
{
this.vehiclePlate = vehiclePlate;
}
public String getVehiclePlate()
{
return vehiclePlate;
}
public void setShipperName(String shipperName)
{
this.shipperName = shipperName;
}
public String getShipperName()
{
return shipperName;
}
public void setShipperPhone(String shipperPhone)
{
this.shipperPhone = shipperPhone;
}
public String getShipperPhone()
{
return shipperPhone;
}
public void setReceiverName(String receiverName)
{
this.receiverName = receiverName;
}
public String getReceiverName()
{
return receiverName;
}
public void setReceiverPhone(String receiverPhone)
{
this.receiverPhone = receiverPhone;
}
public String getReceiverPhone()
{
return receiverPhone;
}
public void setReceiverOrgName(String receiverOrgName)
{
this.receiverOrgName = receiverOrgName;
}
public String getReceiverOrgName()
{
return receiverOrgName;
}
public void setDeliveryTon(BigDecimal deliveryTon)
{
this.deliveryTon = deliveryTon;
}
public BigDecimal getDeliveryTon()
{
return deliveryTon;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
public BigDecimal getTotalKm() { return totalKm; }
public void setTotalKm(BigDecimal totalKm) { this.totalKm = totalKm; }
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("xmMs", getXmMs())
.append("xmNo", getXmNo())
.append("wlNo", getWlNo())
.append("wlMs", getWlMs())
.append("realQty", getRealQty())
.append("dw", getDw())
.append("sapNo", getSapNo())
.append("gysMc", getGysMc())
.append("remark", getRemark())
.append("originName", getOriginName())
.append("originLng", getOriginLng())
.append("originLat", getOriginLat())
.append("destName", getDestName())
.append("destLng", getDestLng())
.append("destLat", getDestLat())
.append("deliveryDate", getDeliveryDate())
.append("vehiclePlate", getVehiclePlate())
.append("shipperName", getShipperName())
.append("shipperPhone", getShipperPhone())
.append("receiverName", getReceiverName())
.append("receiverPhone", getReceiverPhone())
.append("receiverOrgName", getReceiverOrgName())
.append("deliveryTon", getDeliveryTon())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
.append("id", getId())
.append("orderNo", getOrderNo())
.append("xmMs", getXmMs())
.append("xmNo", getXmNo())
.append("wlNo", getWlNo())
.append("wlMs", getWlMs())
.append("realQty", getRealQty())
.append("dw", getDw())
.append("sapNo", getSapNo())
.append("gysMc", getGysMc())
.append("originName", getOriginName())
.append("originLng", getOriginLng())
.append("originLat", getOriginLat())
.append("destName", getDestName())
.append("destLng", getDestLng())
.append("destLat", getDestLat())
.append("deliveryDate", getDeliveryDate())
.append("plateNo", getplateNo())
.append("driverName", getDriverName())
.append("driverPhone", getDriverPhone())
.append("shipperName", getShipperName())
.append("shipperPhone", getShipperPhone())
.append("receiverName", getReceiverName())
.append("receiverPhone", getReceiverPhone())
.append("receiverOrgName", getReceiverOrgName())
.append("deliveryTon", getDeliveryTon())
.append("goodsSize", getGoodsSize())
.append("orderStatus", getOrderStatus())
.append("suggestFee", getSuggestFee())
.append("actualFee", getActualFee())
.append("tollFee", getTollFee())
.append("totalKm", getTotalKm())
.append("vehicleTypeId", getVehicleTypeId())
.append("vehicleTypeName", getVehicleTypeName())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,25 @@
package com.delivery.project.document.domain;
import lombok.Data;
import java.math.BigDecimal;
/** 按单号部分字段更新动态UPDATE覆盖该单号下所有行 */
@Data
public class DeliveryOrderPatch {
private String plateNo;
// 地理位置
private BigDecimal originLng;
private BigDecimal originLat;
private BigDecimal destLng;
private BigDecimal destLat;
// 状态 & 费用
private String orderStatus; // "2" 配送中 / "3" 已签收
private BigDecimal actualFee;
private BigDecimal totalKm;
private BigDecimal tollFee;
// 元数据
private String updateBy;
}

View File

@@ -0,0 +1,132 @@
package com.delivery.project.document.domain;
import java.math.BigDecimal;
import com.delivery.framework.aspectj.lang.annotation.Excel;
import com.delivery.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 物料字典对象 mtd
*
* @author delivery
* @date 2025-10-23
*/
public class Mtd extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 物料编号 */
@Excel(name = "物料编号")
private String wlNo;
/** 物料描述 */
@Excel(name = "物料描述")
private String wlMs;
/** 计量单位 */
@Excel(name = "计量单位")
private String dw;
/** 单件重量(kg) */
@Excel(name = "单件重量(kg)")
private BigDecimal weightKg;
/** 单件体积(立方米) */
@Excel(name = "单件体积(立方米)")
private BigDecimal volumeM3;
/** 是否删除(0正常 1删除) */
@Excel(name = "是否删除(0正常 1删除)")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setWlNo(String wlNo)
{
this.wlNo = wlNo;
}
public String getWlNo()
{
return wlNo;
}
public void setWlMs(String wlMs)
{
this.wlMs = wlMs;
}
public String getWlMs()
{
return wlMs;
}
public void setDw(String dw)
{
this.dw = dw;
}
public String getDw()
{
return dw;
}
public void setWeightKg(BigDecimal weightKg)
{
this.weightKg = weightKg;
}
public BigDecimal getWeightKg()
{
return weightKg;
}
public void setVolumeM3(BigDecimal volumeM3)
{
this.volumeM3 = volumeM3;
}
public BigDecimal getVolumeM3()
{
return volumeM3;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("wlNo", getWlNo())
.append("wlMs", getWlMs())
.append("dw", getDw())
.append("weightKg", getWeightKg())
.append("volumeM3", getVolumeM3())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -145,6 +145,9 @@ public class RkInfo extends BaseEntity {
@Excel(name = "库位码")
private String pcode;
@Excel(name = "出库类型名称")
private String ckTypeName;
/** 库位16进制编码 */
@Excel(name = "库位16进制编码")
private String pcodeId;
@@ -204,6 +207,12 @@ public class RkInfo extends BaseEntity {
@Excel(name = "供应计划ID")
private Long gysJhId;
// ===================== MTD 侧重量/体积 =====================
/** 单件重量(kg) */
private BigDecimal weightKg;
/** 单件体积(m³) */
private BigDecimal volumeM3;
// ===================== Getter / Setter =====================
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@@ -310,6 +319,9 @@ public class RkInfo extends BaseEntity {
public String getCkLihuoY() { return ckLihuoY; }
public void setCkLihuoY(String ckLihuoY) { this.ckLihuoY = ckLihuoY; }
public String getCkTypeName() { return ckTypeName; }
public void setCkTypeName(String ckTypeName) { this.ckTypeName = ckTypeName; }
public String getTeamCode() { return teamCode; }
public void setTeamCode(String teamCode) { this.teamCode = teamCode; }
@@ -334,6 +346,11 @@ public class RkInfo extends BaseEntity {
public Long getGysJhId() { return gysJhId; }
public void setGysJhId(Long gysJhId) { this.gysJhId = gysJhId; }
public BigDecimal getWeightKg() { return weightKg; }
public void setWeightKg(BigDecimal weightKg) { this.weightKg = weightKg; }
public BigDecimal getVolumeM3() { return volumeM3; }
public void setVolumeM3(BigDecimal volumeM3) { this.volumeM3 = volumeM3; }
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
@@ -374,6 +391,7 @@ public class RkInfo extends BaseEntity {
.append("ckLihuoY", getCkLihuoY())
.append("teamCode", getTeamCode())
.append("ckType", getCkType())
.append("ckTypeName", getCkTypeName())
.append("ckRemark", getCkRemark())
.append("rkTime", getRkTime())
.append("lyTime", getLyTime())
@@ -385,6 +403,8 @@ public class RkInfo extends BaseEntity {
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("weightKg", getWeightKg())
.append("volumeM3", getVolumeM3())
.toString();
}
}

View File

@@ -0,0 +1,258 @@
package com.delivery.project.document.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.delivery.framework.web.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.delivery.framework.aspectj.lang.annotation.Excel;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 车辆档案对象 vehicle
*
* @author delivery
* @date 2025-10-23
*/
public class Vehicle extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 车牌号(唯一) */
@Excel(name = "车牌号", readConverterExp = "唯=一")
private String plateNo;
/** VIN/车架号 */
@Excel(name = "VIN/车架号")
private String vin;
/** 车型IDvehicle_type.id */
@Excel(name = "车型ID", readConverterExp = "v=ehicle_type.id")
private Long vehicleTypeId;
/** 申报承重(吨) */
@Excel(name = "申报承重(吨)")
private BigDecimal declaredWeightTon;
/** 申报载方(立方米) */
@Excel(name = "申报载方(立方米)")
private BigDecimal declaredVolumeM3;
/** 司机姓名 */
@Excel(name = "司机姓名")
private String driverName;
/** 司机手机号 */
@Excel(name = "司机手机号")
private String driverPhone;
/** 司机身份证号(可选) */
@Excel(name = "司机身份证号(可选)")
private String driverIdNo;
/** 驾驶证号(可选) */
@Excel(name = "驾驶证号(可选)")
private String driverLicenseNo;
/** 准驾车型(可选) */
@Excel(name = "准驾车型(可选)")
private String driverLicenseLevel;
/** 年检到期日 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "年检到期日", width = 30, dateFormat = "yyyy-MM-dd")
private Date inspectionExpireDate;
/** 保险到期日 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "保险到期日", width = 30, dateFormat = "yyyy-MM-dd")
private Date insuranceExpireDate;
/** 状态(0启用 1停用 2维修) */
@Excel(name = "状态(0启用 1停用 2维修)")
private String status;
/** 是否删除(0正常 1删除) */
@Excel(name = "是否删除(0正常 1删除)")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setPlateNo(String plateNo)
{
this.plateNo = plateNo;
}
public String getPlateNo()
{
return plateNo;
}
public void setVin(String vin)
{
this.vin = vin;
}
public String getVin()
{
return vin;
}
public void setVehicleTypeId(Long vehicleTypeId)
{
this.vehicleTypeId = vehicleTypeId;
}
public Long getVehicleTypeId()
{
return vehicleTypeId;
}
public void setDeclaredWeightTon(BigDecimal declaredWeightTon)
{
this.declaredWeightTon = declaredWeightTon;
}
public BigDecimal getDeclaredWeightTon()
{
return declaredWeightTon;
}
public void setDeclaredVolumeM3(BigDecimal declaredVolumeM3)
{
this.declaredVolumeM3 = declaredVolumeM3;
}
public BigDecimal getDeclaredVolumeM3()
{
return declaredVolumeM3;
}
public void setDriverName(String driverName)
{
this.driverName = driverName;
}
public String getDriverName()
{
return driverName;
}
public void setDriverPhone(String driverPhone)
{
this.driverPhone = driverPhone;
}
public String getDriverPhone()
{
return driverPhone;
}
public void setDriverIdNo(String driverIdNo)
{
this.driverIdNo = driverIdNo;
}
public String getDriverIdNo()
{
return driverIdNo;
}
public void setDriverLicenseNo(String driverLicenseNo)
{
this.driverLicenseNo = driverLicenseNo;
}
public String getDriverLicenseNo()
{
return driverLicenseNo;
}
public void setDriverLicenseLevel(String driverLicenseLevel)
{
this.driverLicenseLevel = driverLicenseLevel;
}
public String getDriverLicenseLevel()
{
return driverLicenseLevel;
}
public void setInspectionExpireDate(Date inspectionExpireDate)
{
this.inspectionExpireDate = inspectionExpireDate;
}
public Date getInspectionExpireDate()
{
return inspectionExpireDate;
}
public void setInsuranceExpireDate(Date insuranceExpireDate)
{
this.insuranceExpireDate = insuranceExpireDate;
}
public Date getInsuranceExpireDate()
{
return insuranceExpireDate;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("plateNo", getPlateNo())
.append("vin", getVin())
.append("vehicleTypeId", getVehicleTypeId())
.append("declaredWeightTon", getDeclaredWeightTon())
.append("declaredVolumeM3", getDeclaredVolumeM3())
.append("driverName", getDriverName())
.append("driverPhone", getDriverPhone())
.append("driverIdNo", getDriverIdNo())
.append("driverLicenseNo", getDriverLicenseNo())
.append("driverLicenseLevel", getDriverLicenseLevel())
.append("inspectionExpireDate", getInspectionExpireDate())
.append("insuranceExpireDate", getInsuranceExpireDate())
.append("status", getStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,178 @@
package com.delivery.project.document.domain;
import java.math.BigDecimal;
import com.delivery.framework.aspectj.lang.annotation.Excel;
import com.delivery.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 车型定义对象 vehicle_type
*
* @author delivery
* @date 2025-10-23
*/
public class VehicleType extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 车型编码(唯一) */
@Excel(name = "车型编码", readConverterExp = "唯=一")
private String typeCode;
/** 车型名称(如:微面/小面/3米8/5米2/6米8/7米6/9米6/13米/17米5 */
@Excel(name = "车型名称", readConverterExp = "如=:微面/小面/3米8/5米2/6米8/7米6/9米6/13米/17米5")
private String typeName;
/** 承重下限(吨, 含) */
@Excel(name = "承重下限(吨, 含)")
private BigDecimal weightMinTon;
/** 承重上限(吨, 含) */
@Excel(name = "承重上限(吨, 含)")
private BigDecimal weightMaxTon;
/** 载方下限(立方米, 含) */
@Excel(name = "载方下限(立方米, 含)")
private BigDecimal volumeMinM3;
/** 载方上限(立方米, 含) */
@Excel(name = "载方上限(立方米, 含)")
private BigDecimal volumeMaxM3;
/** 每公里单价(元/km) */
@Excel(name = "每公里单价(元/km)")
private BigDecimal unitPricePerKm;
/** 状态(0启用 1停用) */
@Excel(name = "状态(0启用 1停用)")
private String status;
/** 是否删除(0正常 1删除) */
@Excel(name = "是否删除(0正常 1删除)")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setTypeCode(String typeCode)
{
this.typeCode = typeCode;
}
public String getTypeCode()
{
return typeCode;
}
public void setTypeName(String typeName)
{
this.typeName = typeName;
}
public String getTypeName()
{
return typeName;
}
public void setWeightMinTon(BigDecimal weightMinTon)
{
this.weightMinTon = weightMinTon;
}
public BigDecimal getWeightMinTon()
{
return weightMinTon;
}
public void setWeightMaxTon(BigDecimal weightMaxTon)
{
this.weightMaxTon = weightMaxTon;
}
public BigDecimal getWeightMaxTon()
{
return weightMaxTon;
}
public void setVolumeMinM3(BigDecimal volumeMinM3)
{
this.volumeMinM3 = volumeMinM3;
}
public BigDecimal getVolumeMinM3()
{
return volumeMinM3;
}
public void setVolumeMaxM3(BigDecimal volumeMaxM3)
{
this.volumeMaxM3 = volumeMaxM3;
}
public BigDecimal getVolumeMaxM3()
{
return volumeMaxM3;
}
public void setUnitPricePerKm(BigDecimal unitPricePerKm)
{
this.unitPricePerKm = unitPricePerKm;
}
public BigDecimal getUnitPricePerKm()
{
return unitPricePerKm;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("typeCode", getTypeCode())
.append("typeName", getTypeName())
.append("weightMinTon", getWeightMinTon())
.append("weightMaxTon", getWeightMaxTon())
.append("volumeMinM3", getVolumeMinM3())
.append("volumeMaxM3", getVolumeMaxM3())
.append("unitPricePerKm", getUnitPricePerKm())
.append("status", getStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,24 @@
// src/main/java/com/delivery/project/document/domain/dto/CalcSuggestFeeDTO.java
package com.delivery.project.document.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 计算建议费用 - 请求体 DTO
* 前端传入:货物重量、体积、行程公里数;若前端手动选择车型则传 vehicleTypeId。
*/
@Data
public class CalcSuggestFeeDTO {
/** 货物重量(单位:吨) */
private BigDecimal weightTon;
/** 货物体积(单位:立方米) */
private BigDecimal volumeM3;
/** 行程距离(单位:公里) */
private BigDecimal distanceKm;
/** 指定车型ID可选传入则按该车型计算建议费用 */
private Long vehicleTypeId;
}

View File

@@ -0,0 +1,28 @@
// CalcTotalWvDTO.java
package com.delivery.project.document.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 计算总重量/总体积 请求DTO
* - 支持仅传 wlNos每个物料默认1件重复出现按数量累加
* - 也支持 itemswlNo + qty若两者同时传以 items 为准
*/
@Data
public class CalcTotalWvDTO {
/** 物料号列表(可重复;每次出现视作数量+1 */
private List<String> wlNos;
/** 物料+数量(更精确的传法) */
private List<Item> items;
@Data
public static class Item {
/** 物料号 */
private String wlNo;
/** 数量可空默认1<=0 会按1处理 */
private BigDecimal qty;
}
}

View File

@@ -0,0 +1,19 @@
package com.delivery.project.document.domain.dto;
import lombok.Data;
/** 已上传图片条目只传URL */
@Data
public class DeliveryAttachItemDTO {
/** 场景ORIGIN / DEST必填 */
private String scene;
/** 类型SIGN_DRIVER / SIGN_COURIER / SIGN_RECEIVER / PHOTO_SITE / PHOTO_BILL必填 */
private String bizType;
/** 图片URL必填 */
private String url;
/** 排序(可选) */
private Long sortNo;
/** 备注(可选) */
private String remark;
}

View File

@@ -0,0 +1,37 @@
package com.delivery.project.document.domain.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/** 执行配送单据绑定URL + 回写经纬度/司机/状态) */
@Data
public class DeliveryExecuteBindDTO {
/** 配送单据号delivery_order.order_no */
@NotNull
private String orderNo;
/** 当前执行场景ORIGIN / DEST */
@NotNull
private String scene;
/** 司机信息ORIGIN 场景带上DEST 可补齐) */
private String driverName;
private String driverPhone;
private String plateNo;//配送车牌
/** APP 当前定位 */
private Double lng;
private Double lat;
/** 费用(仅在 DEST 时会回写,可选) */
private BigDecimal actualFee; // 实际费用
private BigDecimal tollFee; // 高速费用
/** 本次执行的附件条目URL 列表) */
@NotNull
private List<DeliveryAttachItemDTO> attachments;
}

View File

@@ -0,0 +1,105 @@
package com.delivery.project.document.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 配送单据创建入参对象(头 + 行)
* 说明:用于前端创建配送单时提交数据,后端写入 delivery_order 表
*
* @author delivery
* @date 2025-10-28
*/
@Data
public class DeliveryOrderCreateDTO {
/**
* 配送单据号,可传可不传;
* 不传时由后端自动生成(格式如 DO202510280001
*/
private String orderNo;
// ==================== 头部信息(整单通用) ====================
/** 起始地点名称 */
private String originName;
/** 起始地点经度 */
private BigDecimal originLng;
/** 起始地点纬度 */
private BigDecimal originLat;
/** 目的地点名称 */
private String destName;
/** 目的地点经度 */
private BigDecimal destLng;
/** 目的地点纬度 */
private BigDecimal destLat;
/** 配送日期yyyy-MM-dd 格式) */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date deliveryDate;
/** 配送车辆车牌号 */
private String plateNo;
/** 发货人姓名 */
private String shipperName;
/** 发货人联系电话 */
private String shipperPhone;
/** 收货人姓名 */
private String receiverName;
/** 收货人联系电话 */
private String receiverPhone;
/** 收货单位名称 */
private String receiverOrgName;
/** 配送吨位(单位:吨) */
private BigDecimal deliveryTon;
/** 货物体积(单位:立方米) */
private BigDecimal goodsSize;
/** 单据状态(默认 0待发货1起运2送达 */
private String orderStatus;
/** 车辆类型ID外键对应 vehicle_type 表主键) */
private Long vehicleTypeId;
/** 车辆类型名称小型面包车、9.6米货车等) */
private String vehicleTypeName;
/** 系统建议运费(根据车型和里程计算) */
private BigDecimal suggestFee;
/** 实际运费(人工调整或司机确认后) */
private BigDecimal actualFee;
/** 过路费(收费站、高速费等额外费用) */
private BigDecimal tollFee;
/** 配送总里程(单位:公里) */
private BigDecimal totalKm;
/** 备注说明(可填写其他补充信息) */
private String remark;
// ==================== 行明细(多物料行) ====================
/**
* 物料明细项列表(同一单号下多条记录)
* 每条记录包含项目、物料、数量、单位等信息
*/
private List<DeliveryOrderLineDTO> items;
}

View File

@@ -0,0 +1,17 @@
package com.delivery.project.document.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class DeliveryOrderLineDTO {
private String xmMs; // 项目描述
private String xmNo; // 项目号
private String wlNo; // 物料号
private String wlMs; // 物料描述
private BigDecimal realQty; // 实际入库数量
private String dw; // 计量单位
private String sapNo; // SAP订单编号
private String gysMc; // 供应商名称
}

View File

@@ -6,31 +6,114 @@ import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 配送单据(创建入参)
* 说明:前端提交新建配送单据时使用
*/
@Data
public class DeliveryOrderSaveDTO {
// ===================== 项目信息 =====================
/** 项目描述(来源项目/业务项目名称) */
private String xmMs;
/** 项目号(来源项目编号) */
private String xmNo;
// ===================== 物料信息 =====================
/** 物料号 */
private String wlNo;
/** 物料描述 */
private String wlMs;
/** 实际入库数量(与配送关联的数量) */
private BigDecimal realQty;
/** 计量单位(如:个、米、吨等) */
private String dw;
/** SAP 订单编号(便于对账/追踪) */
private String sapNo;
/** 供应商名称 */
private String gysMc;
// ===================== 起止地点 =====================
/** 起始地点名称 */
private String originName;
/** 起始地点经度WGS84一般为经度小数度 */
private BigDecimal originLng;
/** 起始地点纬度WGS84一般为纬度小数度 */
private BigDecimal originLat;
/** 目的地点名称 */
private String destName;
/** 目的地点经度WGS84 */
private BigDecimal destLng;
/** 目的地点纬度WGS84 */
private BigDecimal destLat;
// ===================== 配送信息 =====================
/** 配送日期(计划/实际发车日期) */
private Date deliveryDate;
private String vehiclePlate;
/** 配送车牌 */
private String plateNo;
/** 发货人姓名 */
private String shipperName;
/** 发货人联系方式 */
private String shipperPhone;
/** 接收人姓名 */
private String receiverName;
/** 接收人联系方式 */
private String receiverPhone;
/** 接收单位名称 */
private String receiverOrgName;
/** 配送吨位(货重,单位:吨) */
private BigDecimal deliveryTon;
/** 附件列表前端从上传接口获取的URL传入 */
/** 货物尺寸(㎡),即占地面积 */
private BigDecimal goodsSize;
// ===================== 车型(新增) =====================
/** 车辆类型ID关联 vehicle_type 表主键) */
private Long vehicleTypeId;
/** 车辆类型名称(冗余存储,便于展示与历史追溯) */
private String vehicleTypeName;
// ===================== 费用与里程(新增) =====================
/** 建议费用(按车型单价与里程计算的推荐值) */
private BigDecimal suggestFee;
/** 实际费用(最终确认费用) */
private BigDecimal actualFee;
/** 高速费用(本次运输产生的过路/高速费) */
private BigDecimal tollFee;
/** 总公里数(本次运输的行驶里程,单位:公里) */
private BigDecimal totalKm;
// ===================== 附件 =====================
/** 附件列表(前端从上传接口获取的 URL 传入) */
private List<DeliveryAttachUploadDTO> attachments;
}

View File

@@ -0,0 +1,13 @@
package com.delivery.project.document.domain.dto;
import lombok.Data;
@Data
public class DeliverySimpleLocationDTO {
/** 经度 */
private Double lng;
/** 纬度 */
private Double lat;
}

View File

@@ -0,0 +1,31 @@
package com.delivery.project.document.domain.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/** APP 上报定位请求体 */
@Data
public class LocationReportDTO {
/** 车牌号(维度之一) */
@NotBlank(message = "车牌号不能为空")
private String plateNo;
/** 配送单号(维度之一,必填) */
@NotBlank(message = "配送单号不能为空")
private String orderNo;
/** 经度保留6位小数 */
@NotNull(message = "经度不能为空")
private BigDecimal lng;
/** 纬度保留6位小数 */
@NotNull(message = "纬度不能为空")
private BigDecimal lat;
/** 客户端时间戳(可选) */
private Long clientTs;
}

View File

@@ -0,0 +1,57 @@
// src/main/java/com/delivery/project/document/domain/vo/CalcSuggestFeeVO.java
package com.delivery.project.document.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 计算建议费用 - 响应体 VO
* 返回推荐/选定的车型、单价、建议费用,以及候选车型列表。
*/
@Data
public class CalcSuggestFeeVO {
/** 选定/推荐车型ID */
private Long vehicleTypeId;
/** 选定/推荐车型名称 */
private String vehicleTypeName;
/** 每公里单价(单位:元/公里) */
private BigDecimal unitPricePerKm;
/** 建议费用单位四舍五入保留2位小数 */
private BigDecimal suggestFee;
/** 候选车型列表(按价格/容量排序) */
private List<VehicleTypeOptionVO> candidates;
/**
* 候选车型项 VO
* 表示一条可选车型的基本信息。
*/
@Data
public static class VehicleTypeOptionVO {
/** 车型ID */
private Long id;
/** 车型名称 */
private String name;
/** 每公里单价(单位:元/公里) */
private BigDecimal unitPricePerKm;
/** 承重下限(单位:吨,含) */
private BigDecimal weightMinTon;
/** 承重上限(单位:吨,含) */
private BigDecimal weightMaxTon;
/** 载方下限(单位:立方米,含) */
private BigDecimal volumeMinM3;
/** 载方上限(单位:立方米,含) */
private BigDecimal volumeMaxM3;
}
}

View File

@@ -0,0 +1,57 @@
package com.delivery.project.document.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 配送单据汇总视图对象
*
* 用途:
* - 用于列表页或统计页面展示配送单的核心概要信息;
* - 不含附件、物料明细,只反映每张单据的基础汇总信息。
*
* @author delivery
* @date 2025-10-29
*/
@Data
public class DeliveryOrderGroupVO {
/** 配送单号 */
private String orderNo;
/** 配送日期格式yyyy-MM-dd */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date deliveryDate;
/** 起始地点名称(发货点) */
private String originName;
/** 目的地点名称(收货点) */
private String destName;
/** 车辆车牌号 */
private String plateNo;
/** 配送单状态 */
private String orderStatus;
/** 发货人姓名 */
private String shipperName;
/** 收货人姓名 */
private String receiverName;
/** 物料行数(明细数量,用于显示一单包含多少种货物) */
private Integer itemCount;
/** 数量合计(汇总所有明细的总数量,可为空) */
private BigDecimal totalQty;
}

View File

@@ -0,0 +1,16 @@
// TotalWvVO.java
package com.delivery.project.document.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 仅返回总重量与总体积
*/
@Data
public class TotalWvVO {
/** 总重量kg */
private BigDecimal totalWeightKg;
/** 总体积 */
private BigDecimal totalVolumeM3;
}

View File

@@ -58,4 +58,10 @@ public interface DeliveryAttachmentMapper
* @return 结果
*/
public int deleteDeliveryAttachmentByIds(Long[] ids);
/**
* 批量插入
* @param list
*/
void batchInsert(List<DeliveryAttachment> list);
}

View File

@@ -0,0 +1,74 @@
package com.delivery.project.document.mapper;
import com.delivery.project.document.domain.DeliveryLocationRecord;
import com.delivery.project.document.domain.dto.DeliverySimpleLocationDTO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DeliveryLocationRecordMapper {
/** 插入一条定位记录 */
int insert(DeliveryLocationRecord record);
/** 批量插入定位记录 */
int insertBatch(List<DeliveryLocationRecord> batch);
/**
* 查询配送定位记录(车牌+单号维度)
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 配送定位记录(车牌+单号维度)
*/
public DeliveryLocationRecord selectDeliveryLocationRecordById(Long id);
/**
* 查询配送定位记录(车牌+单号维度)列表
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 配送定位记录(车牌+单号维度)集合
*/
public List<DeliveryLocationRecord> selectDeliveryLocationRecordList(DeliveryLocationRecord deliveryLocationRecord);
/**
* 新增配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
public int insertDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord);
/**
* 修改配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
public int updateDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord);
/**
* 删除配送定位记录(车牌+单号维度)
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 结果
*/
public int deleteDeliveryLocationRecordById(Long id);
/**
* 批量删除配送定位记录(车牌+单号维度)
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteDeliveryLocationRecordByIds(Long[] ids);
/**
* 查询车辆轨迹点
*
* @param plateNo 订单编号
* @param plateNo 车牌号
* @return 轨迹点
*/
List<DeliverySimpleLocationDTO> selectTrackPoints(String orderNo, String plateNo);
}

View File

@@ -2,6 +2,8 @@ package com.delivery.project.document.mapper;
import java.util.List;
import com.delivery.project.document.domain.DeliveryOrder;
import com.delivery.project.document.domain.vo.DeliveryOrderGroupVO;
import org.apache.ibatis.annotations.Param;
/**
* 配送单据主Mapper接口
@@ -58,4 +60,36 @@ public interface DeliveryOrderMapper
* @return 结果
*/
public int deleteDeliveryOrderByIds(Long[] ids);
/**
* 批量插入
*
* @param rows
* @return
*/
int batchInsert(@Param("list") List<DeliveryOrder> rows);
/**
* 分组查询
*
* @param query
* @return
*/
List<DeliveryOrderGroupVO> selectGroupList(DeliveryOrder query);
/**
* 根据单号查询
*
* @param plateNo
* @return
*/
List<DeliveryOrder> selectByOrderNo(String orderNo);
/**
* 根据单号查询
*
* @param orderNo
* @return
*/
DeliveryOrder selectDeliveryOrderByOrderNo(String orderNo);
}

View File

@@ -0,0 +1,73 @@
package com.delivery.project.document.mapper;
import java.util.List;
import com.delivery.project.document.domain.Mtd;
import org.apache.ibatis.annotations.Param;
/**
* 物料字典Mapper接口
*
* @author delivery
* @date 2025-10-23
*/
public interface MtdMapper
{
/**
* 查询物料字典
*
* @param id 物料字典主键
* @return 物料字典
*/
public Mtd selectMtdById(Long id);
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典集合
*/
public List<Mtd> selectMtdList(Mtd mtd);
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int insertMtd(Mtd mtd);
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int updateMtd(Mtd mtd);
/**
* 删除物料字典
*
* @param id 物料字典主键
* @return 结果
*/
public int deleteMtdById(Long id);
/**
* 批量删除物料字典
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMtdByIds(Long[] ids);
/**
* 批量 UPSERT同 wlNo 更新,不存在则新增)
* 依赖 wl_no 唯一索引
*/
int batchUpsertMtd(List<Mtd> list);
/**
* 根据多个物料编号查询物料信息
*/
List<Mtd> selectByWlNos(@Param("wlNos") List<String> wlNos);
}

View File

@@ -66,4 +66,6 @@ public interface RkInfoMapper
* 不新增 resultMap / VO直接用 RkInfoResult 映射需要的字段
*/
List<RkInfo> selectGroupedByBill(@Param("q") RkInfo rkInfo);
}

View File

@@ -0,0 +1,61 @@
package com.delivery.project.document.mapper;
import java.util.List;
import com.delivery.project.document.domain.Vehicle;
/**
* 车辆档案Mapper接口
*
* @author delivery
* @date 2025-10-23
*/
public interface VehicleMapper
{
/**
* 查询车辆档案
*
* @param id 车辆档案主键
* @return 车辆档案
*/
public Vehicle selectVehicleById(Long id);
/**
* 查询车辆档案列表
*
* @param vehicle 车辆档案
* @return 车辆档案集合
*/
public List<Vehicle> selectVehicleList(Vehicle vehicle);
/**
* 新增车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
public int insertVehicle(Vehicle vehicle);
/**
* 修改车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
public int updateVehicle(Vehicle vehicle);
/**
* 删除车辆档案
*
* @param id 车辆档案主键
* @return 结果
*/
public int deleteVehicleById(Long id);
/**
* 批量删除车辆档案
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteVehicleByIds(Long[] ids);
}

View File

@@ -0,0 +1,80 @@
package com.delivery.project.document.mapper;
import java.math.BigDecimal;
import java.util.List;
import com.delivery.project.document.domain.VehicleType;
/**
* 车型定义Mapper接口
*
* @author delivery
* @date 2025-10-23
*/
public interface VehicleTypeMapper
{
/**
* 查询车型定义
*
* @param id 车型定义主键
* @return 车型定义
*/
public VehicleType selectVehicleTypeById(Long id);
/**
* 查询车型定义列表
*
* @param vehicleType 车型定义
* @return 车型定义集合
*/
public List<VehicleType> selectVehicleTypeList(VehicleType vehicleType);
/**
* 新增车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
public int insertVehicleType(VehicleType vehicleType);
/**
* 修改车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
public int updateVehicleType(VehicleType vehicleType);
/**
* 删除车型定义
*
* @param id 车型定义主键
* @return 结果
*/
public int deleteVehicleTypeById(Long id);
/**
* 批量删除车型定义
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteVehicleTypeByIds(Long[] ids);
/**
* 批量查询车型定义
*
* @param w 宽
* @param v 高
* @return 批量结果
*/
List<VehicleType> selectMatchTypes(BigDecimal w, Comparable<BigDecimal> v);
/**
* 批量查询车型定义
*
* @param w 宽
* @param v 高
* @return 批量结果
*/
List<VehicleType> selectFallbackTypes(BigDecimal w, BigDecimal v);
}

View File

@@ -2,8 +2,12 @@ package com.delivery.project.document.service;
import java.util.List;
import com.delivery.project.document.domain.DeliveryAttachment;
import com.delivery.project.document.domain.dto.DeliveryAttachUploadDTO;
import com.delivery.project.document.domain.dto.DeliveryExecuteBindDTO;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
/**
* 配送附件Service接口
*
@@ -60,4 +64,9 @@ public interface IDeliveryAttachmentService
*/
public int deleteDeliveryAttachmentById(Long id);
int executeBind(DeliveryExecuteBindDTO dto);
List<String> upload(MultipartFile[] files, DeliveryAttachUploadDTO dto, HttpServletRequest request);
}

View File

@@ -2,7 +2,11 @@ package com.delivery.project.document.service;
import java.util.List;
import com.delivery.project.document.domain.DeliveryOrder;
import com.delivery.project.document.domain.RkInfo;
import com.delivery.project.document.domain.dto.DeliveryOrderCreateDTO;
import com.delivery.project.document.domain.dto.DeliveryOrderSaveDTO;
import com.delivery.project.document.domain.vo.DeliveryOrderGroupVO;
import org.springframework.beans.factory.annotation.Value;
/**
* 配送单据主Service接口
@@ -68,4 +72,36 @@ public interface IDeliveryOrderService
* @return
*/
int saveOrderWithAttachments(DeliveryOrderSaveDTO dto, String username);
/**
* 新建配送单据:同一单号多行写入
* @param dto
* @return
*/
String createOrder(DeliveryOrderCreateDTO dto);
/**
* 列表:按单号分组(分页)
* @param query
* @return
*/
List<DeliveryOrderGroupVO> listGroup(DeliveryOrder query);
/**
* 详情:按单号查询所有行
* @param plateNo
* @return
*/
/** 详情:按单号查行 */
List<DeliveryOrder> listByOrderNo(String orderNo);
/**
* 从智慧实物系统查询待配送出库单据
*
* @return rk_info 列表
*/
List<RkInfo> listWisdomRkForDelivery();
}

View File

@@ -0,0 +1,75 @@
package com.delivery.project.document.service;
import com.delivery.project.document.domain.DeliveryLocationRecord;
import com.delivery.project.document.domain.dto.DeliverySimpleLocationDTO;
import com.delivery.project.document.domain.dto.LocationReportDTO;
import java.util.List;
import java.util.Map;
/** 定位上报服务接口(实现层由 Impl 提供) */
public interface ILocationReportService {
/**
* APP 上报定位
* @param dto 上报体
* @param username 当前操作人(由 Controller 使用 BaseController.getUsername() 传入)
* @return 处理结果
*/
Map<String, Object> report(LocationReportDTO dto, String username);
/**
* 查询配送定位记录(车牌+单号维度)
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 配送定位记录(车牌+单号维度)
*/
public DeliveryLocationRecord selectDeliveryLocationRecordById(Long id);
/**
* 查询配送定位记录(车牌+单号维度)列表
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 配送定位记录(车牌+单号维度)集合
*/
public List<DeliveryLocationRecord> selectDeliveryLocationRecordList(DeliveryLocationRecord deliveryLocationRecord);
/**
* 新增配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
public int insertDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord);
/**
* 修改配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
public int updateDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord);
/**
* 批量删除配送定位记录(车牌+单号维度)
*
* @param ids 需要删除的配送定位记录(车牌+单号维度)主键集合
* @return 结果
*/
public int deleteDeliveryLocationRecordByIds(Long[] ids);
/**
* 删除配送定位记录(车牌+单号维度)信息
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 结果
*/
public int deleteDeliveryLocationRecordById(Long id);
/**
* 查询轨迹点
* @param plateNo 订单号
* @param plateNo 车牌号
* @return 轨迹点
*/
List<DeliverySimpleLocationDTO> selectTrackPoints(String orderNo, String plateNo);
}

View File

@@ -0,0 +1,80 @@
package com.delivery.project.document.service;
import java.util.List;
import com.delivery.project.document.domain.Mtd;
import com.delivery.project.document.domain.dto.CalcTotalWvDTO;
import com.delivery.project.document.domain.vo.TotalWvVO;
/**
* 物料字典Service接口
*
* @author delivery
* @date 2025-10-23
*/
public interface IMtdService
{
/**
* 查询物料字典
*
* @param id 物料字典主键
* @return 物料字典
*/
public Mtd selectMtdById(Long id);
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典集合
*/
public List<Mtd> selectMtdList(Mtd mtd);
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int insertMtd(Mtd mtd);
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int updateMtd(Mtd mtd);
/**
* 批量删除物料字典
*
* @param ids 需要删除的物料字典主键集合
* @return 结果
*/
public int deleteMtdByIds(Long[] ids);
/**
* 删除物料字典信息
*
* @param id 物料字典主键
* @return 结果
*/
public int deleteMtdById(Long id);
/**
* 导入物料字典数据
*
* @param list 物料字典数据列表
* @param username 更新者
* @return 结果
*/
int importMtd(List<Mtd> list, String username);
/**
* 计算总重量和体积
*
* @param dto 计算参数
* @return 结果
*/
TotalWvVO calcTotalWv(CalcTotalWvDTO dto);
}

View File

@@ -0,0 +1,61 @@
package com.delivery.project.document.service;
import java.util.List;
import com.delivery.project.document.domain.Vehicle;
/**
* 车辆档案Service接口
*
* @author delivery
* @date 2025-10-23
*/
public interface IVehicleService
{
/**
* 查询车辆档案
*
* @param id 车辆档案主键
* @return 车辆档案
*/
public Vehicle selectVehicleById(Long id);
/**
* 查询车辆档案列表
*
* @param vehicle 车辆档案
* @return 车辆档案集合
*/
public List<Vehicle> selectVehicleList(Vehicle vehicle);
/**
* 新增车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
public int insertVehicle(Vehicle vehicle);
/**
* 修改车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
public int updateVehicle(Vehicle vehicle);
/**
* 批量删除车辆档案
*
* @param ids 需要删除的车辆档案主键集合
* @return 结果
*/
public int deleteVehicleByIds(Long[] ids);
/**
* 删除车辆档案信息
*
* @param id 车辆档案主键
* @return 结果
*/
public int deleteVehicleById(Long id);
}

View File

@@ -0,0 +1,70 @@
package com.delivery.project.document.service;
import java.util.List;
import com.delivery.project.document.domain.VehicleType;
import com.delivery.project.document.domain.dto.CalcSuggestFeeDTO;
import com.delivery.project.document.domain.vo.CalcSuggestFeeVO;
/**
* 车型定义Service接口
*
* @author delivery
* @date 2025-10-23
*/
public interface IVehicleTypeService
{
/**
* 查询车型定义
*
* @param id 车型定义主键
* @return 车型定义
*/
public VehicleType selectVehicleTypeById(Long id);
/**
* 查询车型定义列表
*
* @param vehicleType 车型定义
* @return 车型定义集合
*/
public List<VehicleType> selectVehicleTypeList(VehicleType vehicleType);
/**
* 新增车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
public int insertVehicleType(VehicleType vehicleType);
/**
* 修改车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
public int updateVehicleType(VehicleType vehicleType);
/**
* 批量删除车型定义
*
* @param ids 需要删除的车型定义主键集合
* @return 结果
*/
public int deleteVehicleTypeByIds(Long[] ids);
/**
* 删除车型定义信息
*
* @param id 车型定义主键
* @return 结果
*/
public int deleteVehicleTypeById(Long id);
/**
* 计算建议运费
* @param dto
* @return
*/
CalcSuggestFeeVO calcSuggestFee(CalcSuggestFeeDTO dto);
}

View File

@@ -0,0 +1,161 @@
package com.delivery.project.document.service;
import com.delivery.framework.config.LocationReportProperties;
import com.delivery.project.document.domain.DeliveryLocationRecord;
import com.delivery.project.document.mapper.DeliveryLocationRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.*;
/**
* 定位数据批量落库任务
* ---------------------------------------------
* 功能说明:
* 每隔固定时间默认15秒执行一次将 Redis 中缓存的定位数据批量写入数据库。
*
* 核心逻辑:
* 1. 每辆车(车牌 + 订单号)对应一个独立的 Redis ZSET
* 2. ZSET 内部保存该车在 15 秒窗口内的唯一经纬度坐标;
* 3. 定时任务遍历所有活跃 ZSET
* - 取出所有在窗口时间内的坐标;
* - 对比上次已落库坐标(跨窗口去重);
* - 批量插入数据库;
* - 清理已处理坐标;
* - 更新“最后一次落库坐标”;
*
* 优点:
* ✅ ZSET 天然去重(同一经纬度不会重复插入);
* ✅ 批量落库,减轻数据库压力;
* ✅ 支持数千辆车同时上报;
* ✅ 可水平扩展。
*/
@Slf4j
@Component
@EnableScheduling
@RequiredArgsConstructor
public class LocationBatchFlusher {
/** Redis 客户端 */
private final StringRedisTemplate redis;
/** 业务配置项(包含定时间隔、缓存时间等) */
private final LocationReportProperties props;
/** MyBatis Mapper用于批量插入数据库 */
private final DeliveryLocationRecordMapper mapper;
/** 活跃车辆集合Set 结构保存所有存在ZSET的key */
private static final String KEY_INDEX = "delivery:loc:index";
/** 状态存储Hash 结构,保存每个车的最后一次写库坐标) */
private static final String KEY_STATE_PREFIX = "delivery:loc:state:";
/**
* 定时任务每隔固定时间如15秒执行一次
* fixedDelay 表示“上一次任务执行完毕后延迟多少毫秒再执行下一次”
* 取值来自配置类 LocationReportProperties.minPersistIntervalMs
*/
@Scheduled(fixedDelayString = "#{@locationReportProperties.minPersistIntervalMs}")
public void flushWindow() {
// 获取所有活跃ZSET的key每辆车对应一个
Set<String> keys = redis.opsForSet().members(KEY_INDEX);
if (keys == null || keys.isEmpty()) return;
long now = System.currentTimeMillis(); // 当前时间戳
List<DeliveryLocationRecord> batch = new ArrayList<>(); // 批量写入列表
// 遍历每一辆车的ZSET
for (String zsetKey : keys) {
String plate = parsePlate(zsetKey); // 提取车牌号
String order = parseOrder(zsetKey); // 提取订单号
String stateKey = KEY_STATE_PREFIX + plate + ":" + order; // 每辆车的状态key
// ✅ 从ZSET中获取当前时间之前的所有坐标
Set<ZSetOperations.TypedTuple<String>> tuples =
redis.opsForZSet().rangeByScoreWithScores(zsetKey, 0, now);
if (tuples == null || tuples.isEmpty()) continue;
// 读取“上次已落库的最后一条坐标”,用于跨窗口去重
String lastWritten = (String) redis.opsForHash().get(stateKey, "lastWritten");
// 临时变量记录这次批量中最后插入的member
String lastInsertedMember = lastWritten;
// 遍历ZSET中的坐标数据
for (ZSetOperations.TypedTuple<String> t : tuples) {
String member = t.getValue(); // 坐标字符串,如 "120.125600,30.276800"
Double score = t.getScore(); // ZSET中存储的时间戳首次上报时间
if (member == null || score == null) continue;
// ❗跨窗口去重逻辑:如果当前坐标与上次写库坐标完全一致,则跳过
if (member.equals(lastWritten)) continue;
// 拆分经纬度
String[] arr = member.split(",");
if (arr.length != 2) continue;
// 构造数据库实体对象
DeliveryLocationRecord r = new DeliveryLocationRecord();
r.setPlateNo(plate);
r.setOrderNo(order);
r.setLng(new BigDecimal(arr[0]));
r.setLat(new BigDecimal(arr[1]));
r.setReportedAt(new Date(score.longValue())); // 上报时间取ZSET中的分数
r.setSource("app");
r.setRemark("tick_" + props.getMinPersistIntervalMs());
r.setCreateBy("");
r.setIsDelete("0");
batch.add(r);
// 记录这次批量最后插入的坐标用于更新lastWritten
lastInsertedMember = member;
}
// 清理:删除本窗口内已处理的坐标数据
redis.opsForZSet().removeRangeByScore(zsetKey, 0, now);
// 记录最新写库坐标,用于下一轮去重
if (lastInsertedMember != null) {
redis.opsForHash().put(stateKey, "lastWritten", lastInsertedMember);
redis.expire(stateKey, props.getStateTtlHours(), java.util.concurrent.TimeUnit.HOURS);
}
}
// 若本轮有新数据,则批量插入数据库
if (!batch.isEmpty()) {
int n = mapper.insertBatch(batch);
log.info("[location-flush] 本轮批量落库完成:插入 {} 条定位记录,共处理 {} 个ZSET", n, keys.size());
}
}
/**
* 从ZSET的key中解析出车牌号
* 例如delivery:loc:buf:浙A88888:D202511030001 → 返回“浙A88888”
*/
private String parsePlate(String zsetKey) {
String prefix = "delivery:loc:buf:";
if (!zsetKey.startsWith(prefix)) return "";
String tail = zsetKey.substring(prefix.length());
int i = tail.indexOf(':');
return i < 0 ? tail : tail.substring(0, i);
}
/**
* 从ZSET的key中解析出订单号
* 例如delivery:loc:buf:浙A88888:D202511030001 → 返回“D202511030001”
*/
private String parseOrder(String zsetKey) {
int p = zsetKey.lastIndexOf(':');
return p < 0 ? "" : zsetKey.substring(p + 1);
}
}

View File

@@ -1,19 +1,33 @@
package com.delivery.project.document.service.impl;
import java.util.List;
import java.util.Locale;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.*;
import com.delivery.common.exception.ServiceException;
import com.delivery.common.utils.DateUtils;
import com.delivery.common.utils.MinioUtil;
import com.delivery.common.utils.StringUtils;
import com.delivery.project.document.domain.DeliveryOrder;
import com.delivery.project.document.domain.dto.DeliveryAttachItemDTO;
import com.delivery.project.document.domain.dto.DeliveryAttachUploadDTO;
import com.delivery.project.document.domain.dto.DeliveryExecuteBindDTO;
import com.delivery.project.document.mapper.DeliveryOrderMapper;
import com.delivery.project.document.service.IDeliveryOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.delivery.project.document.mapper.DeliveryAttachmentMapper;
import com.delivery.project.document.domain.DeliveryAttachment;
import com.delivery.project.document.service.IDeliveryAttachmentService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
/**
* 配送附件Service业务层处理
@@ -22,11 +36,18 @@ import org.springframework.web.multipart.MultipartFile;
* @date 2025-10-15
*/
@Service
@Slf4j
public class DeliveryAttachmentServiceImpl implements IDeliveryAttachmentService
{
@Autowired
private DeliveryAttachmentMapper deliveryAttachmentMapper;
@Autowired
private DeliveryOrderMapper deliveryOrderMapper;
@Autowired
private IDeliveryOrderService deliveryOrderService;
/**
* 查询配送附件
*
@@ -101,5 +122,133 @@ public class DeliveryAttachmentServiceImpl implements IDeliveryAttachmentService
return deliveryAttachmentMapper.deleteDeliveryAttachmentById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int executeBind(DeliveryExecuteBindDTO dto) {
// 1) 校验订单存在
DeliveryOrder exist = deliveryOrderMapper.selectDeliveryOrderByOrderNo(dto.getOrderNo());
if (exist == null) {
throw new ServiceException("配送单不存在:" + dto.getOrderNo());
}
if (dto.getAttachments() == null || dto.getAttachments().isEmpty()) {
throw new ServiceException("附件列表不能为空");
}
// 2) 批量插入附件(只传 URL
List<DeliveryAttachment> list = new ArrayList<>();
// String username = getUsername();
String username = "大爷的!!!";
for (DeliveryAttachItemDTO it : dto.getAttachments()) {
if (it == null) continue;
if (it.getScene() == null || it.getBizType() == null || it.getUrl() == null) continue;
DeliveryAttachment a = new DeliveryAttachment();
a.setOrderNo(dto.getOrderNo());
a.setScene(it.getScene());
a.setBizType(it.getBizType());
a.setUrl(it.getUrl());
a.setSortNo(it.getSortNo());
a.setRemark(it.getRemark());
a.setStatus("1"); // 已绑定
a.setIsDelete("0");
a.setCreateBy(username);
a.setCreateTime(DateUtils.getNowDate());
list.add(a);
}
if (list.isEmpty()) {
throw new ServiceException("有效附件条目为空");
}
deliveryAttachmentMapper.batchInsert(list);
// 3) 回写配送单(仅填需要更新的字段),交给已有 updateDeliveryOrder(按 order_no 更新)
DeliveryOrder patch = new DeliveryOrder();
patch.setOrderNo(dto.getOrderNo());
String scene = dto.getScene() == null ? "" : dto.getScene().toUpperCase(Locale.ROOT);
if ("ORIGIN".equals(scene)) {
// 起点:司机信息 + 起点经纬度 + 状态=1
if (dto.getDriverName() != null) patch.setDriverName(dto.getDriverName());
if (dto.getDriverPhone() != null) patch.setDriverPhone(dto.getDriverPhone());
if (dto.getPlateNo() != null) patch.setplateNo(dto.getPlateNo());
if (dto.getLng() != null) patch.setOriginLng(BigDecimal.valueOf(dto.getLng()));
if (dto.getLat() != null) patch.setOriginLat(BigDecimal.valueOf(dto.getLat()));
patch.setOrderStatus("2");
} else if ("DEST".equals(scene)) {
// 终点:终点经纬度 + 状态=2
if (dto.getLng() != null) patch.setDestLng(BigDecimal.valueOf(dto.getLng()));
if (dto.getLat() != null) patch.setDestLat(BigDecimal.valueOf(dto.getLat()));
if (dto.getActualFee() != null) {
if (dto.getActualFee().compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("实际费用不能为负数");
}
patch.setActualFee(dto.getActualFee());
}
if (dto.getTollFee() != null) {
if (dto.getTollFee().compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("高速费用不能为负数");
}
patch.setTollFee(dto.getTollFee());
}
patch.setOrderStatus("3");
}
deliveryOrderService.updateDeliveryOrder(patch);
return list.size();
}
// 保存目录 D:\delivery
private static final String BASE_PATH = "D:/delivery";
@Override
public List<String> upload(MultipartFile[] files, DeliveryAttachUploadDTO dto, HttpServletRequest request) {
if (files == null || files.length == 0) {
throw new ServiceException("上传文件不能为空");
}
if (dto == null || StringUtils.isBlank(dto.getScene()) || StringUtils.isBlank(dto.getBizType())) {
throw new ServiceException("scene 和 bizType 不能为空");
}
String scene = dto.getScene().trim().toLowerCase(Locale.ROOT);
String bizType = dto.getBizType().trim().toLowerCase(Locale.ROOT);
String dateFolder = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
Path targetDir = Paths.get(BASE_PATH, dateFolder, scene, bizType);
try {
Files.createDirectories(targetDir);
List<String> urls = new ArrayList<>();
for (MultipartFile file : files) {
if (file.isEmpty()) continue;
String original = file.getOriginalFilename();
String ext = "";
if (original != null && original.contains(".")) {
ext = original.substring(original.lastIndexOf("."));
}
String newName = UUID.randomUUID().toString().replace("-", "") + ext;
Path targetFile = targetDir.resolve(newName);
Files.copy(file.getInputStream(), targetFile, StandardCopyOption.REPLACE_EXISTING);
// 自动识别访问前缀http://ip:port
String baseUrl = ServletUriComponentsBuilder.fromRequestUri(request)
.replacePath(null)
.build()
.toUriString();
// 返回完整URL
String url = baseUrl + "/delivery/" + dateFolder + "/" + scene + "/" + bizType + "/" + newName;
urls.add(url);
}
log.info("【附件上传成功】{}", urls);
return urls;
} catch (Exception e) {
log.error("文件保存失败", e);
throw new ServiceException("文件保存失败:" + e.getMessage());
}
}
}

View File

@@ -1,22 +1,36 @@
package com.delivery.project.document.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.delivery.common.exception.ServiceException;
import com.delivery.common.utils.DateUtils;
import com.delivery.common.utils.StringUtils;
import com.delivery.common.utils.http.HttpUtils;
import com.delivery.framework.web.domain.AjaxResult;
import com.delivery.project.document.domain.DeliveryAttachment;
import com.delivery.project.document.domain.RkInfo;
import com.delivery.project.document.domain.dto.DeliveryAttachUploadDTO;
import com.delivery.project.document.domain.dto.DeliveryOrderCreateDTO;
import com.delivery.project.document.domain.dto.DeliveryOrderLineDTO;
import com.delivery.project.document.domain.dto.DeliveryOrderSaveDTO;
import com.delivery.project.document.domain.vo.DeliveryOrderGroupVO;
import com.delivery.project.document.mapper.DeliveryAttachmentMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.delivery.project.document.mapper.DeliveryOrderMapper;
import com.delivery.project.document.domain.DeliveryOrder;
import com.delivery.project.document.service.IDeliveryOrderService;
import org.springframework.transaction.annotation.Transactional;
import static com.delivery.common.utils.SecurityUtils.getUsername;
/**
* 配送单据主Service业务层处理
*
@@ -33,6 +47,9 @@ public class DeliveryOrderServiceImpl implements IDeliveryOrderService
@Autowired
private DeliveryAttachmentMapper deliveryAttachmentMapper;
@Value("${wisdom.base-url}")
private String wisdomBaseUrl;
/**
* 查询配送单据主
*
@@ -77,8 +94,10 @@ public class DeliveryOrderServiceImpl implements IDeliveryOrderService
* @return 结果
*/
@Override
public int updateDeliveryOrder(DeliveryOrder deliveryOrder)
{
public int updateDeliveryOrder(DeliveryOrder deliveryOrder) {
if (deliveryOrder.getOrderNo() == null) {
throw new ServiceException("orderNo 不能为空");
}
deliveryOrder.setUpdateTime(DateUtils.getNowDate());
return deliveryOrderMapper.updateDeliveryOrder(deliveryOrder);
}
@@ -118,7 +137,7 @@ public class DeliveryOrderServiceImpl implements IDeliveryOrderService
order.setCreateTime(DateUtils.getNowDate());
deliveryOrderMapper.insertDeliveryOrder(order);
Long orderId = order.getId();
String orderNo = order.getOrderNo();
int affected = 1;
// 2. 保存附件
@@ -131,7 +150,7 @@ public class DeliveryOrderServiceImpl implements IDeliveryOrderService
}
DeliveryAttachment att = new DeliveryAttachment();
att.setOrderId(orderId);
att.setOrderNo(orderNo);
att.setScene(item.getScene());
att.setBizType(item.getBizType());
att.setUrl(item.getUrl());
@@ -150,4 +169,140 @@ public class DeliveryOrderServiceImpl implements IDeliveryOrderService
return affected;
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createOrder(DeliveryOrderCreateDTO dto) {
// ========== 1. 生成配送单号 ==========
// 如果前端未指定单号则按规则生成一个唯一编号示例DO20251027104532123
String orderNo = (dto.getOrderNo() == null || dto.getOrderNo().trim().isEmpty())
? "DO" + DateUtils.dateTimeNow("yyyyMMddHHmmssSSS")
: dto.getOrderNo().trim();
// 当前时间,用于所有行的 create_time
Date now = DateUtils.getNowDate();
// 定义要插入的记录集合
List<DeliveryOrder> rows = new ArrayList<>();
// ========== 2. 遍历每一条物料明细 ==========
for (DeliveryOrderLineDTO it : dto.getItems()) {
// 创建实体对象(每一行对应一条数据库记录)
DeliveryOrder row = new DeliveryOrder();
// ========== 2.1 公共头部字段(相同单号下字段一致) ==========
row.setOrderNo(orderNo); // 同单号绑定
row.setOriginName(dto.getOriginName()); // 起点名称
row.setDestName(dto.getDestName()); // 终点名称
row.setDeliveryDate(dto.getDeliveryDate()); // 配送日期
row.setShipperName(dto.getShipperName()); // 发货人姓名
row.setShipperPhone(dto.getShipperPhone()); // 发货人电话
row.setReceiverName(dto.getReceiverName()); // 收货人姓名
row.setReceiverPhone(dto.getReceiverPhone()); // 收货人电话
row.setReceiverOrgName(dto.getReceiverOrgName()); // 收货单位名称
row.setDeliveryTon(dto.getDeliveryTon()); // 配送吨位
row.setGoodsSize(dto.getGoodsSize()); // 货物尺寸
row.setOrderStatus(dto.getOrderStatus() == null ? "1" : dto.getOrderStatus()); // 默认状态:已接单
row.setVehicleTypeId(dto.getVehicleTypeId()); // 车辆类型ID
row.setVehicleTypeName(dto.getVehicleTypeName()); // 车辆类型名称
row.setSuggestFee(dto.getSuggestFee()); // 建议费用
row.setActualFee(dto.getActualFee()); // 实际费用
row.setTollFee(dto.getTollFee()); // 高速费
row.setTotalKm(dto.getTotalKm()); // 总公里数
row.setRemark(dto.getRemark()); // 备注
// ========== 2.2 明细字段(每行不同) ==========
row.setXmMs(it.getXmMs()); // 项目描述
row.setXmNo(it.getXmNo()); // 项目号
row.setWlNo(it.getWlNo()); // 物料号
row.setWlMs(it.getWlMs()); // 物料描述
row.setRealQty(it.getRealQty()); // 实际入库数量
row.setDw(it.getDw()); // 计量单位
row.setSapNo(it.getSapNo()); // SAP订单号
row.setGysMc(it.getGysMc()); // 供应商名称
// ========== 2.3 通用字段 ==========
row.setIsDelete("0"); // 正常状态
row.setCreateTime(now); // 创建时间
row.setCreateBy(getUsername());
// row.setCreateBy("大爷的!");
// 添加到批量集合中
rows.add(row);
}
// ========== 3. 批量落库 ==========
if (!rows.isEmpty()) {
// 使用 Mapper.xml 的 <foreach> 一次插入多条记录
deliveryOrderMapper.batchInsert(rows);
}
// ========== 4. 返回单号 ==========
return orderNo;
}
@Override
public List<DeliveryOrderGroupVO> listGroup(DeliveryOrder query) {
return deliveryOrderMapper.selectGroupList(query);
}
@Override
public List<DeliveryOrder> listByOrderNo(String orderNo) {
return deliveryOrderMapper.selectByOrderNo(orderNo);
}
/**
* 从【智慧实物管理系统】查询“待配送的出库单据”
* 对应智慧实物接口GET /wisdom/stock/delivery
*
* @return List<RkInfo>
*/
@Override
public List<RkInfo> listWisdomRkForDelivery() {
// 1. 拼接请求地址
String url = wisdomBaseUrl + "/wisdom/stock/delivery";
// 2. 发送 GET 请求
String respJson = HttpUtils.sendGet(url);
if (StringUtils.isEmpty(respJson)) {
throw new ServiceException("调用智慧实物接口失败:返回结果为空");
}
// 3. 解析 JSON统一返回结构{ code, msg, data }
JSONObject json = JSON.parseObject(respJson);
if (json == null) {
throw new ServiceException("调用智慧实物接口失败:解析返回结果为空");
}
Integer code = json.getInteger("code");
if (code == null || code != 200) {
String msg = json.getString("msg");
throw new ServiceException("调用智慧实物接口失败code=" + code + "msg=" + msg);
}
Object dataObj = json.get("data");
if (dataObj == null) {
// 没有数据就返回空集合,不算错误
return new ArrayList<>();
}
// data 可能本身就是数组,也可能是单个对象
JSONArray dataArr;
if (dataObj instanceof JSONArray) {
dataArr = (JSONArray) dataObj;
} else {
dataArr = JSON.parseArray(JSON.toJSONString(dataObj));
}
if (dataArr == null || dataArr.isEmpty()) {
return new ArrayList<>();
}
// 4. 转成 List<RkInfo>
return JSON.parseArray(dataArr.toJSONString(), RkInfo.class);
}
}

View File

@@ -0,0 +1,185 @@
package com.delivery.project.document.service.impl;
import com.delivery.common.exception.ServiceException;
import com.delivery.common.utils.DateUtils;
import com.delivery.framework.config.LocationReportProperties;
import com.delivery.project.document.domain.DeliveryLocationRecord;
import com.delivery.project.document.domain.dto.DeliverySimpleLocationDTO;
import com.delivery.project.document.domain.dto.LocationReportDTO;
import com.delivery.project.document.mapper.DeliveryLocationRecordMapper;
import com.delivery.project.document.service.ILocationReportService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 定位上报:仅写 ZSET 缓冲member=lng,latscore=ts按 15s 周期由定时任务批量入库
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class LocationReportServiceImpl implements ILocationReportService {
@Autowired
private DeliveryLocationRecordMapper deliveryLocationRecordMapper;
private final StringRedisTemplate redis;
private final LocationReportProperties props;
private static final String KEY_BUF_PREFIX = "delivery:loc:buf:"; // delivery:loc:buf:{plate}:{order}
private static final String KEY_INDEX = "delivery:loc:index"; // 活跃 ZSET 索引Set
/**
* 上报车辆位置信息。
*
* @param dto 包含车辆位置相关信息的数据传输对象,必须包含车牌号、订单号、经纬度等字段
* @param username 当前操作用户标识(可用于日志或权限校验,当前未使用)
* @return 返回一个Map结构的结果包含是否成功缓冲、原因、车牌号、订单号及时间戳等信息
*/
@Override
public Map<String, Object> report(LocationReportDTO dto, String username) {
final String plate = dto.getPlateNo().trim();
final String orderNo = dto.getOrderNo().trim();
final String zsetKey = KEY_BUF_PREFIX + plate + ":" + orderNo;
final String lockKey = "delivery:loc:lock:" + plate + ":" + orderNo;
// 使用 Redis 分布式锁防止并发写入同一辆车的位置数据
Boolean locked = redis.opsForValue().setIfAbsent(lockKey, "1", props.getLockSeconds(), TimeUnit.SECONDS);
if (locked == null || !locked) {
return resp(false, "concurrent_skip", plate, orderNo, 0);
}
try {
BigDecimal lng = dto.getLng().setScale(6, RoundingMode.HALF_UP);
BigDecimal lat = dto.getLat().setScale(6, RoundingMode.HALF_UP);
long now = System.currentTimeMillis();
String member = lng.toPlainString() + "," + lat.toPlainString();
// ✅ 去重缓存:只在不存在时写入(等价 ZADD NX
redis.opsForZSet().addIfAbsent(zsetKey, member, now);
// 设置过期时间并记录该key为活跃key
redis.expire(zsetKey, props.getStateTtlHours(), TimeUnit.HOURS);
redis.opsForSet().add(KEY_INDEX, zsetKey);
return resp(true, "buffered", plate, orderNo, now);
} catch (Exception e) {
throw new ServiceException("定位上报处理失败:" + e.getMessage());
} finally {
// 释放分布式锁
redis.delete(lockKey);
}
}
/**
* 构造响应结果。
*
* @param ok 是否处理成功
* @param reason 处理结果的原因描述
* @param plate 车牌号码
* @param orderNo 订单编号
* @param ts 时间戳
* @return 封装后的响应Map对象
*/
private Map<String, Object> resp(boolean ok, String reason, String plate, String orderNo, long ts) {
Map<String, Object> m = new HashMap<>();
m.put("buffered", ok);
m.put("reason", reason);
m.put("plateNo", plate);
m.put("orderNo", orderNo);
m.put("ts", ts);
return m;
}
/**
* 查询配送定位记录(车牌+单号维度)
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 配送定位记录(车牌+单号维度)
*/
@Override
public DeliveryLocationRecord selectDeliveryLocationRecordById(Long id)
{
return deliveryLocationRecordMapper.selectDeliveryLocationRecordById(id);
}
/**
* 查询配送定位记录(车牌+单号维度)列表
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 配送定位记录(车牌+单号维度)
*/
@Override
public List<DeliveryLocationRecord> selectDeliveryLocationRecordList(DeliveryLocationRecord deliveryLocationRecord)
{
return deliveryLocationRecordMapper.selectDeliveryLocationRecordList(deliveryLocationRecord);
}
/**
* 新增配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
@Override
public int insertDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord)
{
deliveryLocationRecord.setCreateTime(DateUtils.getNowDate());
return deliveryLocationRecordMapper.insertDeliveryLocationRecord(deliveryLocationRecord);
}
/**
* 修改配送定位记录(车牌+单号维度)
*
* @param deliveryLocationRecord 配送定位记录(车牌+单号维度)
* @return 结果
*/
@Override
public int updateDeliveryLocationRecord(DeliveryLocationRecord deliveryLocationRecord)
{
deliveryLocationRecord.setUpdateTime(DateUtils.getNowDate());
return deliveryLocationRecordMapper.updateDeliveryLocationRecord(deliveryLocationRecord);
}
/**
* 批量删除配送定位记录(车牌+单号维度)
*
* @param ids 需要删除的配送定位记录(车牌+单号维度)主键
* @return 结果
*/
@Override
public int deleteDeliveryLocationRecordByIds(Long[] ids)
{
return deliveryLocationRecordMapper.deleteDeliveryLocationRecordByIds(ids);
}
/**
* 删除配送定位记录(车牌+单号维度)信息
*
* @param id 配送定位记录(车牌+单号维度)主键
* @return 结果
*/
@Override
public int deleteDeliveryLocationRecordById(Long id)
{
return deliveryLocationRecordMapper.deleteDeliveryLocationRecordById(id);
}
@Override
public List<DeliverySimpleLocationDTO> selectTrackPoints(String orderNo, String plateNo) {
return deliveryLocationRecordMapper.selectTrackPoints(orderNo, plateNo);
}
}

View File

@@ -0,0 +1,172 @@
package com.delivery.project.document.service.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import com.delivery.common.exception.ServiceException;
import com.delivery.common.utils.DateUtils;
import com.delivery.project.document.domain.dto.CalcTotalWvDTO;
import com.delivery.project.document.domain.vo.TotalWvVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.delivery.project.document.mapper.MtdMapper;
import com.delivery.project.document.domain.Mtd;
import com.delivery.project.document.service.IMtdService;
import static com.delivery.common.utils.StringUtils.nvl;
/**
* 物料字典Service业务层处理
*
* @author delivery
* @date 2025-10-23
*/
@Service
public class MtdServiceImpl implements IMtdService
{
@Autowired
private MtdMapper mtdMapper;
/**
* 查询物料字典
*
* @param id 物料字典主键
* @return 物料字典
*/
@Override
public Mtd selectMtdById(Long id)
{
return mtdMapper.selectMtdById(id);
}
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典
*/
@Override
public List<Mtd> selectMtdList(Mtd mtd)
{
return mtdMapper.selectMtdList(mtd);
}
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
@Override
public int insertMtd(Mtd mtd)
{
mtd.setCreateTime(DateUtils.getNowDate());
return mtdMapper.insertMtd(mtd);
}
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
@Override
public int updateMtd(Mtd mtd)
{
mtd.setUpdateTime(DateUtils.getNowDate());
return mtdMapper.updateMtd(mtd);
}
/**
* 批量删除物料字典
*
* @param ids 需要删除的物料字典主键
* @return 结果
*/
@Override
public int deleteMtdByIds(Long[] ids)
{
return mtdMapper.deleteMtdByIds(ids);
}
/**
* 删除物料字典信息
*
* @param id 物料字典主键
* @return 结果
*/
@Override
public int deleteMtdById(Long id)
{
return mtdMapper.deleteMtdById(id);
}
// MtdServiceImpl.java 追加实现
@Override
public int importMtd(List<Mtd> list, String operator)
{
if (list == null || list.isEmpty()) {
throw new ServiceException("导入数据为空");
}
// 清洗与校验
List<Mtd> clean = new ArrayList<>(list.size());
for (Mtd m : list) {
if (m == null) continue;
if (m.getWlNo() == null || m.getWlNo().trim().isEmpty()) {
// wlNo 必填
continue;
}
m.setWlNo(m.getWlNo().trim());
if (m.getIsDelete() == null) m.setIsDelete("0");
// 写入操作人与时间
m.setUpdateBy(operator);
m.setUpdateTime(DateUtils.getNowDate());
// 如果是新增场景create_by/create_time 也一起填上ON DUPLICATE 不会覆盖 create_*
if (m.getCreateBy() == null) m.setCreateBy(operator);
if (m.getCreateTime() == null) m.setCreateTime(DateUtils.getNowDate());
clean.add(m);
}
if (clean.isEmpty()) {
throw new ServiceException("有效导入数据为空(缺少 wlNo");
}
// 批量 UPSERT依赖 mtd.wl_no 唯一索引)
return mtdMapper.batchUpsertMtd(clean);
}
@Override
public TotalWvVO calcTotalWv(CalcTotalWvDTO dto) {
if (dto == null || dto.getWlNos() == null || dto.getWlNos().isEmpty()) {
TotalWvVO empty = new TotalWvVO();
empty.setTotalWeightKg(BigDecimal.ZERO);
empty.setTotalVolumeM3(BigDecimal.ZERO);
return empty;
}
// 查询数据库中所有匹配的物料信息
List<Mtd> list = mtdMapper.selectByWlNos(dto.getWlNos());
BigDecimal totalWeight = BigDecimal.ZERO;
BigDecimal totalVolume = BigDecimal.ZERO;
for (Mtd m : list) {
BigDecimal w = m.getWeightKg() == null ? BigDecimal.ZERO : m.getWeightKg();
BigDecimal v = m.getVolumeM3() == null ? BigDecimal.ZERO : m.getVolumeM3();
totalWeight = totalWeight.add(w);
totalVolume = totalVolume.add(v);
}
TotalWvVO vo = new TotalWvVO();
vo.setTotalWeightKg(totalWeight);
vo.setTotalVolumeM3(totalVolume);
return vo;
}
}

View File

@@ -0,0 +1,96 @@
package com.delivery.project.document.service.impl;
import java.util.List;
import com.delivery.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.delivery.project.document.mapper.VehicleMapper;
import com.delivery.project.document.domain.Vehicle;
import com.delivery.project.document.service.IVehicleService;
/**
* 车辆档案Service业务层处理
*
* @author delivery
* @date 2025-10-23
*/
@Service
public class VehicleServiceImpl implements IVehicleService
{
@Autowired
private VehicleMapper vehicleMapper;
/**
* 查询车辆档案
*
* @param id 车辆档案主键
* @return 车辆档案
*/
@Override
public Vehicle selectVehicleById(Long id)
{
return vehicleMapper.selectVehicleById(id);
}
/**
* 查询车辆档案列表
*
* @param vehicle 车辆档案
* @return 车辆档案
*/
@Override
public List<Vehicle> selectVehicleList(Vehicle vehicle)
{
return vehicleMapper.selectVehicleList(vehicle);
}
/**
* 新增车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
@Override
public int insertVehicle(Vehicle vehicle)
{
vehicle.setCreateTime(DateUtils.getNowDate());
return vehicleMapper.insertVehicle(vehicle);
}
/**
* 修改车辆档案
*
* @param vehicle 车辆档案
* @return 结果
*/
@Override
public int updateVehicle(Vehicle vehicle)
{
vehicle.setUpdateTime(DateUtils.getNowDate());
return vehicleMapper.updateVehicle(vehicle);
}
/**
* 批量删除车辆档案
*
* @param ids 需要删除的车辆档案主键
* @return 结果
*/
@Override
public int deleteVehicleByIds(Long[] ids)
{
return vehicleMapper.deleteVehicleByIds(ids);
}
/**
* 删除车辆档案信息
*
* @param id 车辆档案主键
* @return 结果
*/
@Override
public int deleteVehicleById(Long id)
{
return vehicleMapper.deleteVehicleById(id);
}
}

View File

@@ -0,0 +1,177 @@
package com.delivery.project.document.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.delivery.common.utils.DateUtils;
import com.delivery.project.document.domain.dto.CalcSuggestFeeDTO;
import com.delivery.project.document.domain.vo.CalcSuggestFeeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.delivery.project.document.mapper.VehicleTypeMapper;
import com.delivery.project.document.domain.VehicleType;
import com.delivery.project.document.service.IVehicleTypeService;
/**
* 车型定义Service业务层处理
*
* @author delivery
* @date 2025-10-23
*/
@Service
public class VehicleTypeServiceImpl implements IVehicleTypeService
{
@Autowired
private VehicleTypeMapper vehicleTypeMapper;
/**
* 查询车型定义
*
* @param id 车型定义主键
* @return 车型定义
*/
@Override
public VehicleType selectVehicleTypeById(Long id)
{
return vehicleTypeMapper.selectVehicleTypeById(id);
}
/**
* 查询车型定义列表
*
* @param vehicleType 车型定义
* @return 车型定义
*/
@Override
public List<VehicleType> selectVehicleTypeList(VehicleType vehicleType)
{
return vehicleTypeMapper.selectVehicleTypeList(vehicleType);
}
/**
* 新增车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
@Override
public int insertVehicleType(VehicleType vehicleType)
{
vehicleType.setCreateTime(DateUtils.getNowDate());
return vehicleTypeMapper.insertVehicleType(vehicleType);
}
/**
* 修改车型定义
*
* @param vehicleType 车型定义
* @return 结果
*/
@Override
public int updateVehicleType(VehicleType vehicleType)
{
vehicleType.setUpdateTime(DateUtils.getNowDate());
return vehicleTypeMapper.updateVehicleType(vehicleType);
}
/**
* 批量删除车型定义
*
* @param ids 需要删除的车型定义主键
* @return 结果
*/
@Override
public int deleteVehicleTypeByIds(Long[] ids)
{
return vehicleTypeMapper.deleteVehicleTypeByIds(ids);
}
/**
* 删除车型定义信息
*
* @param id 车型定义主键
* @return 结果
*/
@Override
public int deleteVehicleTypeById(Long id)
{
return vehicleTypeMapper.deleteVehicleTypeById(id);
}
@Override
public CalcSuggestFeeVO calcSuggestFee(CalcSuggestFeeDTO dto)
{
// ========== 0) 入参兜底 ==========
BigDecimal w = nvl(dto.getWeightTon()); // 货物重量(吨)
BigDecimal v = nvl(dto.getVolumeM3()); // 货物体积(立方米)
BigDecimal km = nvl(dto.getDistanceKm()); // 行程公里数(公里)
// ========== 1) 候选车型:严格匹配,若无则兜底匹配 ==========
List<VehicleType> candidates = vehicleTypeMapper.selectMatchTypes(w, v);
if (candidates == null || candidates.isEmpty()) {
candidates = vehicleTypeMapper.selectFallbackTypes(w, v);
}
if (candidates == null || candidates.isEmpty()) {
throw new RuntimeException("未找到适配车型,请检查车型配置或输入参数。");
}
// 稳定排序:单价升序 -> 承重上限升序 -> 载方上限升序 -> id 升序(数据库已排序,这里再兜一层)
candidates.sort(Comparator
.comparing(VehicleType::getUnitPricePerKm, Comparator.nullsLast(BigDecimal::compareTo))
.thenComparing(VehicleType::getWeightMaxTon, Comparator.nullsLast(BigDecimal::compareTo))
.thenComparing(VehicleType::getVolumeMaxM3, Comparator.nullsLast(BigDecimal::compareTo))
.thenComparing(VehicleType::getId, Comparator.nullsLast(Long::compareTo)));
// ========== 2) 选定车型:前端指定 or 系统推荐 ==========
VehicleType chosen;
if (dto.getVehicleTypeId() != null) {
// 前端点名车型:优先在候选中找,找不到则直接按主键查
chosen = candidates.stream()
.filter(t -> dto.getVehicleTypeId().equals(t.getId()))
.findFirst()
.orElseGet(() -> vehicleTypeMapper.selectVehicleTypeById(dto.getVehicleTypeId()));
if (chosen == null) {
throw new RuntimeException("指定车型不存在或已被禁用id=" + dto.getVehicleTypeId());
}
} else {
chosen = candidates.get(0);
}
// ========== 3) 计算建议费用:单价 × 公里数保留2位 ==========
BigDecimal price = chosen.getUnitPricePerKm();
if (price == null) {
throw new RuntimeException("车型【" + chosen.getTypeName() + "】未配置每公里单价unit_price_per_km 为空)");
}
BigDecimal fee = price.multiply(km).setScale(2, RoundingMode.HALF_UP);
// ========== 4) 组装返回 ==========
CalcSuggestFeeVO vo = new CalcSuggestFeeVO();
vo.setVehicleTypeId(chosen.getId());
vo.setVehicleTypeName(chosen.getTypeName());
vo.setUnitPricePerKm(price);
vo.setSuggestFee(fee);
// 候选项
List<CalcSuggestFeeVO.VehicleTypeOptionVO> list = new ArrayList<>(candidates.size());
for (VehicleType t : candidates) {
CalcSuggestFeeVO.VehicleTypeOptionVO o = new CalcSuggestFeeVO.VehicleTypeOptionVO();
o.setId(t.getId());
o.setName(t.getTypeName());
o.setUnitPricePerKm(t.getUnitPricePerKm());
o.setWeightMinTon(t.getWeightMinTon());
o.setWeightMaxTon(t.getWeightMaxTon());
o.setVolumeMinM3(t.getVolumeMinM3());
o.setVolumeMaxM3(t.getVolumeMaxM3());
list.add(o);
}
vo.setCandidates(list);
return vo;
}
private static BigDecimal nvl(BigDecimal x) {
return x == null ? BigDecimal.ZERO : x;
}
}

View File

@@ -12,6 +12,13 @@ delivery:
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
# 图片上传地址
upload-path: D:/delivery
location:
min-persist-interval-ms: 15000 # 批量入库的周期(毫秒)
state-ttl-hours: 2 # ZSET 缓冲键 TTL小时
lock-seconds: 2 # 并发短锁(同车+单)秒数
# 开发环境配置
server:
@@ -109,7 +116,7 @@ gen:
allowOverwrite: false
minio:
endpoint: http://192.168.1.28:9000
endpoint: http://192.168.1.20:9000
accessKey: admin
secretKey: admin123
bucketName: delivery
@@ -117,4 +124,7 @@ minio:
upload:
base-dir: /data/upload/images
base-url: http://192.168.1.28/files
base-url: http://192.168.1.20/files
wisdom:
base-url: http://192.168.1.251:8086

View File

@@ -1,51 +1,62 @@
<?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">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.delivery.project.document.mapper.DeliveryAttachmentMapper">
<resultMap type="DeliveryAttachment" id="DeliveryAttachmentResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="scene" column="scene" />
<result property="bizType" column="biz_type" />
<result property="url" column="url" />
<result property="status" column="status" />
<result property="sortNo" column="sort_no" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
<!-- 建议使用全限定名;如果你项目里配了 typeAliases也可保持短名 -->
<resultMap type="com.delivery.project.document.domain.DeliveryAttachment" id="DeliveryAttachmentResult">
<result property="id" column="id"/>
<!-- 这里改成 orderNo <-> order_no -->
<result property="orderNo" column="order_no"/>
<result property="scene" column="scene"/>
<result property="bizType" column="biz_type"/>
<result property="url" column="url"/>
<result property="status" column="status"/>
<result property="sortNo" column="sort_no"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
</resultMap>
<!-- 同步把列清单里的 order_id 改为 order_no -->
<sql id="selectDeliveryAttachmentVo">
select id, order_id, scene, biz_type, url, status, sort_no, remark, create_by, create_time, update_by, update_time, is_delete from delivery_attachment
SELECT id, order_no, scene, biz_type, url, status, sort_no, remark,
create_by, create_time, update_by, update_time, is_delete
FROM delivery_attachment
</sql>
<select id="selectDeliveryAttachmentList" parameterType="DeliveryAttachment" resultMap="DeliveryAttachmentResult">
<select id="selectDeliveryAttachmentList"
parameterType="com.delivery.project.document.domain.DeliveryAttachment"
resultMap="DeliveryAttachmentResult">
<include refid="selectDeliveryAttachmentVo"/>
<where>
<if test="orderId != null "> and order_id = #{orderId}</if>
<if test="scene != null and scene != ''"> and scene = #{scene}</if>
<if test="bizType != null and bizType != ''"> and biz_type = #{bizType}</if>
<if test="url != null and url != ''"> and url = #{url}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="sortNo != null "> and sort_no = #{sortNo}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
<where>
<!-- 这里用 orderNo -->
<if test="orderNo != null"> AND order_no = #{orderNo}</if>
<if test="scene != null and scene != ''"> AND scene = #{scene}</if>
<if test="bizType != null and bizType != ''"> AND biz_type = #{bizType}</if>
<if test="url != null and url != ''"> AND url = #{url}</if>
<if test="status != null and status != ''"> AND status = #{status}</if>
<if test="sortNo != null"> AND sort_no = #{sortNo}</if>
<if test="isDelete != null and isDelete != ''"> AND is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectDeliveryAttachmentById" parameterType="Long" resultMap="DeliveryAttachmentResult">
<select id="selectDeliveryAttachmentById" parameterType="long" resultMap="DeliveryAttachmentResult">
<include refid="selectDeliveryAttachmentVo"/>
where id = #{id}
WHERE id = #{id}
</select>
<insert id="insertDeliveryAttachment" parameterType="DeliveryAttachment" useGeneratedKeys="true" keyProperty="id">
insert into delivery_attachment
<!-- 新增(单条): order_no -->
<insert id="insertDeliveryAttachment"
parameterType="com.delivery.project.document.domain.DeliveryAttachment"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO delivery_attachment
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="orderId != null">order_id,</if>
<if test="orderNo != null">order_no,</if>
<if test="scene != null">scene,</if>
<if test="bizType != null">biz_type,</if>
<if test="url != null">url,</if>
@@ -57,9 +68,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="orderId != null">#{orderId},</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="orderNo != null">#{orderNo},</if>
<if test="scene != null">#{scene},</if>
<if test="bizType != null">#{bizType},</if>
<if test="url != null">#{url},</if>
@@ -71,13 +82,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</trim>
</insert>
<update id="updateDeliveryAttachment" parameterType="DeliveryAttachment">
update delivery_attachment
<!-- 批量新增(可选,便于一次性插多条) -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO delivery_attachment
(order_no, scene, biz_type, url, status, sort_no, remark,
create_by, create_time, is_delete)
VALUES
<foreach collection="list" item="it" separator=",">
(#{it.orderNo}, #{it.scene}, #{it.bizType}, #{it.url}, #{it.status},
#{it.sortNo}, #{it.remark}, #{it.createBy}, #{it.createTime}, #{it.isDelete})
</foreach>
</insert>
<!-- 更新:把 order_id 改为 order_no -->
<update id="updateDeliveryAttachment"
parameterType="com.delivery.project.document.domain.DeliveryAttachment">
UPDATE delivery_attachment
<trim prefix="SET" suffixOverrides=",">
<if test="orderId != null">order_id = #{orderId},</if>
<if test="orderNo != null">order_no = #{orderNo},</if>
<if test="scene != null">scene = #{scene},</if>
<if test="bizType != null">biz_type = #{bizType},</if>
<if test="url != null">url = #{url},</if>
@@ -90,17 +115,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
WHERE id = #{id}
</update>
<delete id="deleteDeliveryAttachmentById" parameterType="Long">
delete from delivery_attachment where id = #{id}
<delete id="deleteDeliveryAttachmentById" parameterType="long">
DELETE FROM delivery_attachment WHERE id = #{id}
</delete>
<delete id="deleteDeliveryAttachmentByIds" parameterType="String">
delete from delivery_attachment where id in
<delete id="deleteDeliveryAttachmentByIds" parameterType="string">
DELETE FROM delivery_attachment WHERE id IN
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
</mapper>

View File

@@ -0,0 +1,148 @@
<?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.delivery.project.document.mapper.DeliveryLocationRecordMapper">
<!-- ✅ 统一一个 ResultMap使用全限定名避免别名不生效 -->
<resultMap id="DeliveryLocationRecordResult"
type="com.delivery.project.document.domain.DeliveryLocationRecord">
<id column="id" property="id"/>
<result column="plate_no" property="plateNo"/>
<result column="order_no" property="orderNo"/>
<result column="lng" property="lng"/>
<result column="lat" property="lat"/>
<result column="reported_at" property="reportedAt"/>
<result column="source" property="source"/>
<result column="remark" property="remark"/>
<result column="create_by" property="createBy"/>
<result column="create_time" property="createTime"/>
<result column="update_by" property="updateBy"/>
<result column="update_time" property="updateTime"/>
<result column="is_delete" property="isDelete"/>
</resultMap>
<sql id="baseSelect">
SELECT id, plate_no, order_no, lng, lat, reported_at, source, remark,
create_by, create_time, update_by, update_time, is_delete
FROM delivery_location_record
</sql>
<!-- 列表查询:默认 is_delete='0' -->
<select id="selectDeliveryLocationRecordList"
parameterType="com.delivery.project.document.domain.DeliveryLocationRecord"
resultMap="DeliveryLocationRecordResult">
<include refid="baseSelect"/>
<where>
AND is_delete = '0'
<if test="plateNo != null and plateNo != ''"> AND plate_no = #{plateNo}</if>
<if test="orderNo != null and orderNo != ''"> AND order_no = #{orderNo}</if>
<if test="lng != null"> AND lng = #{lng}</if>
<if test="lat != null"> AND lat = #{lat}</if>
<if test="reportedAt != null"> AND reported_at = #{reportedAt}</if>
<if test="source != null and source != ''"> AND source = #{source}</if>
<!-- 若你需要带 isDelete 条件可再加,但默认已固定为 0 -->
</where>
ORDER BY reported_at ASC, id ASC
</select>
<select id="selectDeliveryLocationRecordById" parameterType="long"
resultMap="DeliveryLocationRecordResult">
<include refid="baseSelect"/>
WHERE id = #{id}
</select>
<insert id="insertDeliveryLocationRecord"
parameterType="com.delivery.project.document.domain.DeliveryLocationRecord"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO delivery_location_record
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">plate_no,</if>
<if test="orderNo != null and orderNo != ''">order_no,</if>
<if test="lng != null">lng,</if>
<if test="lat != null">lat,</if>
<if test="reportedAt != null">reported_at,</if>
<if test="source != null">source,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
create_time,
is_delete
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">#{plateNo},</if>
<if test="orderNo != null and orderNo != ''">#{orderNo},</if>
<if test="lng != null">#{lng},</if>
<if test="lat != null">#{lat},</if>
<if test="reportedAt != null">#{reportedAt},</if>
<if test="source != null">#{source},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
NOW(),
'0'
</trim>
</insert>
<update id="updateDeliveryLocationRecord"
parameterType="com.delivery.project.document.domain.DeliveryLocationRecord">
UPDATE delivery_location_record
<trim prefix="SET" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">plate_no = #{plateNo},</if>
<if test="orderNo != null and orderNo != ''">order_no = #{orderNo},</if>
<if test="lng != null">lng = #{lng},</if>
<if test="lat != null">lat = #{lat},</if>
<if test="reportedAt != null">reported_at = #{reportedAt},</if>
<if test="source != null">source = #{source},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
update_time = NOW(),
<if test="isDelete != null and isDelete != ''">is_delete = #{isDelete},</if>
</trim>
WHERE id = #{id}
</update>
<delete id="deleteDeliveryLocationRecordById" parameterType="long">
DELETE FROM delivery_location_record WHERE id = #{id}
</delete>
<delete id="deleteDeliveryLocationRecordByIds">
DELETE FROM delivery_location_record WHERE id IN
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- ✅ 轨迹点查询(简化 DTOlng, lat, reportedAt -->
<select id="selectTrackPoints" resultType="com.delivery.project.document.domain.dto.DeliverySimpleLocationDTO">
SELECT
lng,
lat,
reported_at AS reportedAt
FROM delivery_location_record
WHERE is_delete = '0'
AND order_no = #{orderNo}
AND plate_no = #{plateNo}
ORDER BY reported_at ASC, id ASC
</select>
<insert id="insert"
parameterType="com.delivery.project.document.domain.DeliveryLocationRecord"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO delivery_location_record
(plate_no, order_no, lng, lat, reported_at, source, remark, create_by, create_time, is_delete)
VALUES
(#{plateNo}, #{orderNo}, #{lng}, #{lat}, #{reportedAt}, #{source}, #{remark},
#{createBy}, NOW(), '0')
</insert>
<insert id="insertBatch">
INSERT INTO delivery_location_record
(plate_no, order_no, lng, lat, reported_at, source, remark, create_by, create_time, is_delete)
VALUES
<foreach collection="list" item="r" separator=",">
(#{r.plateNo}, #{r.orderNo}, #{r.lng}, #{r.lat}, #{r.reportedAt},
#{r.source}, #{r.remark}, #{r.createBy}, NOW(), '0')
</foreach>
</insert>
</mapper>

View File

@@ -1,12 +1,17 @@
<?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">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.delivery.project.document.mapper.DeliveryOrderMapper">
<!-- ======================== 基础 ResultMap ======================== -->
<resultMap type="com.delivery.project.document.domain.DeliveryOrder" id="DeliveryOrderResult">
<!-- 用 <id> 保证连表折叠 -->
<!-- 主键 -->
<id property="id" column="id"/>
<!-- 单号 -->
<result property="orderNo" column="order_no"/>
<!-- 基础字段 -->
<result property="xmMs" column="xm_ms"/>
<result property="xmNo" column="xm_no"/>
<result property="wlNo" column="wl_no"/>
@@ -18,15 +23,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="remark" column="remark"/>
<result property="originName" column="origin_name"/>
<result property="originLng" column="origin_lng"/>
<result property="originLat" column="origin_lat"/>
<result property="originLng" column="origin_lng" jdbcType="DECIMAL"/>
<result property="originLat" column="origin_lat" jdbcType="DECIMAL"/>
<result property="destName" column="dest_name"/>
<result property="destLng" column="dest_lng"/>
<result property="destLat" column="dest_lat"/>
<result property="destLng" column="dest_lng" jdbcType="DECIMAL"/>
<result property="destLat" column="dest_lat" jdbcType="DECIMAL"/>
<result property="deliveryDate" column="delivery_date"/>
<result property="vehiclePlate" column="vehicle_plate"/>
<result property="plateNo" column="plate_no"/>
<!-- 司机 -->
<result property="driverName" column="driver_name"/>
<result property="driverPhone" column="driver_phone"/>
<result property="shipperName" column="shipper_name"/>
<result property="shipperPhone" column="shipper_phone"/>
@@ -36,6 +45,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="receiverOrgName" column="receiver_org_name"/>
<result property="deliveryTon" column="delivery_ton"/>
<!-- 货物尺寸(㎡) -->
<result property="goodsSize" column="goods_size" jdbcType="DECIMAL"/>
<result property="orderStatus" column="order_status"/>
<!-- 车型外键与名称 -->
<result property="vehicleTypeId" column="vehicle_type_id"/>
<result property="vehicleTypeName" column="vehicle_type_name"/>
<!-- 费用/里程 -->
<result property="suggestFee" column="suggest_fee"/>
<result property="actualFee" column="actual_fee"/>
<result property="tollFee" column="toll_fee"/>
<result property="totalKm" column="total_km"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
@@ -44,11 +67,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="isDelete" column="is_delete"/>
</resultMap>
<!-- 附件行(按你给的 DeliveryAttachment 字段) -->
<!-- ======================== 附件内联 ResultMap ======================== -->
<resultMap id="DeliveryAttachmentInlineResult"
type="com.delivery.project.document.domain.DeliveryAttachment">
<id property="id" column="att_id"/>
<result property="orderId" column="att_order_id"/>
<result property="orderNo" column="att_order_no"/>
<result property="scene" column="att_scene"/>
<result property="bizType" column="att_biz_type"/>
<result property="url" column="att_url"/>
@@ -62,7 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="isDelete" column="att_is_delete"/>
</resultMap>
<!-- 主实体 + 附件集合 -->
<!-- ======================== 主实体 + 附件集合 ======================== -->
<resultMap id="DeliveryOrderWithAttachResult"
type="com.delivery.project.document.domain.DeliveryOrder"
extends="DeliveryOrderResult">
@@ -70,83 +93,192 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
resultMap="DeliveryAttachmentInlineResult"/>
</resultMap>
<!-- ======================== 带附件的查询列(别名统一 dor ======================== -->
<sql id="selectDeliveryOrderVoWithAttach">
select
do.id, do.xm_ms, do.xm_no, do.wl_no, do.wl_ms, do.real_qty, do.dw, do.sap_no, do.gys_mc,
do.remark, do.origin_name, do.origin_lng, do.origin_lat,
do.dest_name, do.dest_lng, do.dest_lat,
do.delivery_date, do.vehicle_plate,
do.shipper_name, do.shipper_phone,
do.receiver_name, do.receiver_phone, do.receiver_org_name,
do.delivery_ton, do.create_by, do.create_time, do.update_by, do.update_time, do.is_delete,
dor.id, dor.order_no,
dor.xm_ms, dor.xm_no, dor.wl_no, dor.wl_ms, dor.real_qty, dor.dw, dor.sap_no, dor.gys_mc,
dor.remark, dor.origin_name, dor.origin_lng, dor.origin_lat,
dor.dest_name, dor.dest_lng, dor.dest_lat,
dor.delivery_date, dor.plate_no, dor.order_status,
dor.driver_name, dor.driver_phone,
dor.shipper_name, dor.shipper_phone,
dor.receiver_name, dor.receiver_phone, dor.receiver_org_name,
dor.delivery_ton,
dor.goods_size,
-- 车型外键与名称
dor.vehicle_type_id, dor.vehicle_type_name,
-- 费用/里程
dor.suggest_fee, dor.actual_fee, dor.toll_fee, dor.total_km,
dor.create_by, dor.create_time, dor.update_by, dor.update_time, dor.is_delete,
-- 附件列att_ 前缀)
da.id as att_id,
da.order_id as att_order_id,
da.scene as att_scene,
da.biz_type as att_biz_type,
da.url as att_url,
da.status as att_status,
da.sort_no as att_sort_no,
da.remark as att_remark,
da.create_by as att_create_by,
da.create_time as att_create_time,
da.update_by as att_update_by,
da.update_time as att_update_time,
da.is_delete as att_is_delete
da.id AS att_id,
da.order_no AS att_order_no,
da.scene AS att_scene,
da.biz_type AS att_biz_type,
da.url AS att_url,
da.status AS att_status,
da.sort_no AS att_sort_no,
da.remark AS att_remark,
da.create_by AS att_create_by,
da.create_time AS att_create_time,
da.update_by AS att_update_by,
da.update_time AS att_update_time,
da.is_delete AS att_is_delete
from delivery_order do
from delivery_order dor
left join delivery_attachment da
on da.order_id = do.id
on da.order_no = dor.order_no
and da.is_delete = '0'
</sql>
<!-- ======================== 不带附件的查询列 ======================== -->
<sql id="selectDeliveryOrderVo">
select id, xm_ms, xm_no, wl_no, wl_ms, real_qty, dw, sap_no, gys_mc, remark, origin_name, origin_lng, origin_lat, dest_name, dest_lng, dest_lat, delivery_date, vehicle_plate, shipper_name, shipper_phone, receiver_name, receiver_phone, receiver_org_name, delivery_ton, create_by, create_time, update_by, update_time, is_delete from delivery_order
select id, order_no, xm_ms, xm_no, wl_no, wl_ms, real_qty, dw, sap_no, gys_mc, remark,
origin_name, origin_lng, origin_lat, dest_name, dest_lng, dest_lat,
delivery_date, plate_no,
-- 司机
driver_name, driver_phone,
shipper_name, shipper_phone, receiver_name,
receiver_phone, receiver_org_name, delivery_ton, goods_size, order_status,
-- 车型外键与名称
vehicle_type_id, vehicle_type_name,
-- 费用/里程
suggest_fee, actual_fee, toll_fee, total_km,
create_by, create_time, update_by, update_time, is_delete
from delivery_order
</sql>
<!-- ======================== 列表查询(使用 dor 别名) ======================== -->
<select id="selectDeliveryOrderList"
parameterType="com.delivery.project.document.domain.DeliveryOrder"
resultMap="DeliveryOrderWithAttachResult">
<include refid="selectDeliveryOrderVoWithAttach"/>
<where>
<if test="xmMs != null and xmMs != ''"> and do.xm_ms = #{xmMs}</if>
<if test="xmNo != null and xmNo != ''"> and do.xm_no = #{xmNo}</if>
<if test="wlNo != null and wlNo != ''"> and do.wl_no = #{wlNo}</if>
<if test="wlMs != null and wlMs != ''"> and do.wl_ms = #{wlMs}</if>
<if test="realQty != null "> and do.real_qty = #{realQty}</if>
<if test="dw != null and dw != ''"> and do.dw = #{dw}</if>
<if test="sapNo != null and sapNo != ''"> and do.sap_no = #{sapNo}</if>
<if test="gysMc != null and gysMc != ''"> and do.gys_mc = #{gysMc}</if>
<if test="originName != null and originName != ''"> and do.origin_name like concat('%', #{originName}, '%')</if>
<if test="originLng != null "> and do.origin_lng = #{originLng}</if>
<if test="originLat != null "> and do.origin_lat = #{originLat}</if>
<if test="destName != null and destName != ''"> and do.dest_name like concat('%', #{destName}, '%')</if>
<if test="destLng != null "> and do.dest_lng = #{destLng}</if>
<if test="destLat != null "> and do.dest_lat = #{destLat}</if>
<if test="deliveryDate != null "> and do.delivery_date = #{deliveryDate}</if>
<if test="vehiclePlate != null and vehiclePlate != ''"> and do.vehicle_plate = #{vehiclePlate}</if>
<if test="shipperName != null and shipperName != ''"> and do.shipper_name like concat('%', #{shipperName}, '%')</if>
<if test="shipperPhone != null and shipperPhone != ''"> and do.shipper_phone = #{shipperPhone}</if>
<if test="receiverName != null and receiverName != ''"> and do.receiver_name like concat('%', #{receiverName}, '%')</if>
<if test="receiverPhone != null and receiverPhone != ''"> and do.receiver_phone = #{receiverPhone}</if>
<if test="receiverOrgName != null and receiverOrgName != ''"> and do.receiver_org_name like concat('%', #{receiverOrgName}, '%')</if>
<if test="deliveryTon != null "> and do.delivery_ton = #{deliveryTon}</if>
<if test="isDelete != null and isDelete != ''"> and do.is_delete = #{isDelete}</if>
<choose>
<when test="isDelete != null and isDelete != ''">
and dor.is_delete = #{isDelete}
</when>
<otherwise>
and dor.is_delete = '0'
</otherwise>
</choose>
<if test="xmMs != null and xmMs != ''"> and dor.xm_ms = #{xmMs}</if>
<if test="xmNo != null and xmNo != ''"> and dor.xm_no = #{xmNo}</if>
<if test="wlNo != null and wlNo != ''"> and dor.wl_no = #{wlNo}</if>
<if test="wlMs != null and wlMs != ''"> and dor.wl_ms = #{wlMs}</if>
<if test="realQty != null "> and dor.real_qty = #{realQty}</if>
<if test="dw != null and dw != ''"> and dor.dw = #{dw}</if>
<if test="sapNo != null and sapNo != ''"> and dor.sap_no = #{sapNo}</if>
<if test="gysMc != null and gysMc != ''"> and dor.gys_mc = #{gysMc}</if>
<if test="originName != null and originName != ''"> and dor.origin_name like concat('%', #{originName}, '%')</if>
<if test="originLng != null "> and dor.origin_lng = #{originLng}</if>
<if test="originLat != null "> and dor.origin_lat = #{originLat}</if>
<if test="destName != null and destName != ''"> and dor.dest_name like concat('%', #{destName}, '%')</if>
<if test="destLng != null "> and dor.dest_lng = #{destLng}</if>
<if test="destLat != null "> and dor.dest_lat = #{destLat}</if>
<if test="deliveryDate != null "> and dor.delivery_date = #{deliveryDate}</if>
<if test="plateNo != null and plateNo != ''"> and dor.plate_no = #{plateNo}</if>
<!-- 司机筛选 -->
<if test="driverName != null and driverName != ''"> and dor.driver_name like concat('%', #{driverName}, '%')</if>
<if test="driverPhone != null and driverPhone != ''"> and dor.driver_phone = #{driverPhone}</if>
<if test="shipperName != null and shipperName != ''"> and dor.shipper_name like concat('%', #{shipperName}, '%')</if>
<if test="shipperPhone != null and shipperPhone != ''"> and dor.shipper_phone = #{shipperPhone}</if>
<if test="receiverName != null and receiverName != ''"> and dor.receiver_name like concat('%', #{receiverName}, '%')</if>
<if test="receiverPhone != null and receiverPhone != ''"> and dor.receiver_phone = #{receiverPhone}</if>
<if test="receiverOrgName != null and receiverOrgName != ''"> and dor.receiver_org_name like concat('%', #{receiverOrgName}, '%')</if>
<if test="deliveryTon != null "> and dor.delivery_ton = #{deliveryTon}</if>
<if test="goodsSize != null"> and dor.goods_size = #{goodsSize}</if>
<if test="orderStatus != null and orderStatus != ''"> and dor.order_status = #{orderStatus}</if>
<!-- 车型筛选 -->
<if test="vehicleTypeId != null"> and dor.vehicle_type_id = #{vehicleTypeId}</if>
<if test="vehicleTypeName != null and vehicleTypeName != ''">
and dor.vehicle_type_name like concat('%', #{vehicleTypeName}, '%')
</if>
<!-- 费用/里程筛选 -->
<if test="suggestFee != null"> and dor.suggest_fee = #{suggestFee}</if>
<if test="actualFee != null"> and dor.actual_fee = #{actualFee}</if>
<if test="tollFee != null"> and dor.toll_fee = #{tollFee}</if>
<if test="totalKm != null"> and dor.total_km = #{totalKm}</if>
</where>
</select>
<!-- 主键查询(别名 dor -->
<select id="selectDeliveryOrderById"
parameterType="long"
resultMap="DeliveryOrderWithAttachResult">
<include refid="selectDeliveryOrderVoWithAttach"/>
where do.id = #{id}
where dor.id = #{id}
limit 1
</select>
<!-- 列表:按单号分组 -->
<select id="selectGroupList"
parameterType="com.delivery.project.document.domain.DeliveryOrder"
resultType="com.delivery.project.document.domain.vo.DeliveryOrderGroupVO">
SELECT
dor.order_no AS orderNo,
MIN(dor.delivery_date) AS deliveryDate,
MAX(dor.origin_name) AS originName,
MAX(dor.dest_name) AS destName,
MAX(dor.plate_no) AS plateNo,
MAX(dor.shipper_name) AS shipperName,
MAX(dor.receiver_name) AS receiverName,
COUNT(1) AS itemCount,
SUM(dor.real_qty) AS totalQty,
MAX(dor.order_status) AS orderStatus
FROM delivery_order dor
<where>
(dor.is_delete = '0' OR dor.is_delete = 0 OR dor.is_delete IS NULL)
<if test="orderStatus != null and orderStatus != ''">
AND dor.order_status = #{orderStatus}
</if>
<if test="plateNo != null and plateNo != ''">
AND dor.plate_no = #{plateNo}
</if>
<if test="deliveryDate != null">
AND DATE(dor.delivery_date) = DATE(#{deliveryDate})
</if>
</where>
GROUP BY dor.order_no
ORDER BY MAX(dor.create_time) DESC
</select>
<!-- 详情:同单号所有行 -->
<select id="selectByOrderNo" parameterType="string" resultMap="DeliveryOrderResult">
SELECT * FROM delivery_order
WHERE order_no = #{orderNo,jdbcType=VARCHAR}
AND (is_delete = '0' OR is_delete = 0 OR is_delete IS NULL)
ORDER BY id
</select>
<!-- 单条查询:按单号 -->
<select id="selectDeliveryOrderByOrderNo" parameterType="string"
resultType="com.delivery.project.document.domain.DeliveryOrder">
SELECT *
FROM delivery_order
WHERE order_no = #{orderNo,jdbcType=VARCHAR}
AND (is_delete = '0' OR is_delete = 0 OR is_delete IS NULL)
LIMIT 1
</select>
<!-- ======================== 插入 ======================== -->
<!-- 单条插入 -->
<insert id="insertDeliveryOrder" parameterType="DeliveryOrder" useGeneratedKeys="true" keyProperty="id">
insert into delivery_order
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="orderNo != null">order_no,</if>
<if test="xmMs != null">xm_ms,</if>
<if test="xmNo != null">xm_no,</if>
<if test="wlNo != null">wl_no,</if>
@@ -163,20 +295,36 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="destLng != null">dest_lng,</if>
<if test="destLat != null">dest_lat,</if>
<if test="deliveryDate != null">delivery_date,</if>
<if test="vehiclePlate != null">vehicle_plate,</if>
<if test="plateNo != null">plate_no,</if>
<if test="driverName != null">driver_name,</if>
<if test="driverPhone != null">driver_phone,</if>
<if test="shipperName != null">shipper_name,</if>
<if test="shipperPhone != null">shipper_phone,</if>
<if test="receiverName != null">receiver_name,</if>
<if test="receiverPhone != null">receiver_phone,</if>
<if test="receiverOrgName != null">receiver_org_name,</if>
<if test="deliveryTon != null">delivery_ton,</if>
<if test="goodsSize != null">goods_size,</if>
<if test="orderStatus != null">order_status,</if>
<if test="vehicleTypeId != null">vehicle_type_id,</if>
<if test="vehicleTypeName != null">vehicle_type_name,</if>
<if test="suggestFee != null">suggest_fee,</if>
<if test="actualFee != null">actual_fee,</if>
<if test="tollFee != null">toll_fee,</if>
<if test="totalKm != null">total_km,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="orderNo != null">#{orderNo,jdbcType=VARCHAR},</if>
<if test="xmMs != null">#{xmMs},</if>
<if test="xmNo != null">#{xmNo},</if>
<if test="wlNo != null">#{wlNo},</if>
@@ -193,23 +341,68 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="destLng != null">#{destLng},</if>
<if test="destLat != null">#{destLat},</if>
<if test="deliveryDate != null">#{deliveryDate},</if>
<if test="vehiclePlate != null">#{vehiclePlate},</if>
<if test="plateNo != null">#{plateNo},</if>
<if test="driverName != null">#{driverName},</if>
<if test="driverPhone != null">#{driverPhone},</if>
<if test="shipperName != null">#{shipperName},</if>
<if test="shipperPhone != null">#{shipperPhone},</if>
<if test="receiverName != null">#{receiverName},</if>
<if test="receiverPhone != null">#{receiverPhone},</if>
<if test="receiverOrgName != null">#{receiverOrgName},</if>
<if test="deliveryTon != null">#{deliveryTon},</if>
<if test="goodsSize != null">#{goodsSize},</if>
<if test="orderStatus != null">#{orderStatus},</if>
<if test="vehicleTypeId != null">#{vehicleTypeId},</if>
<if test="vehicleTypeName != null">#{vehicleTypeName},</if>
<if test="suggestFee != null">#{suggestFee},</if>
<if test="actualFee != null">#{actualFee},</if>
<if test="tollFee != null">#{tollFee},</if>
<if test="totalKm != null">#{totalKm},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</trim>
</insert>
<update id="updateDeliveryOrder" parameterType="DeliveryOrder">
update delivery_order
<!-- 批量插入 -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO delivery_order
(order_no, xm_ms, xm_no, wl_no, wl_ms, real_qty, dw, sap_no, gys_mc, remark,
origin_name, origin_lng, origin_lat,
dest_name, dest_lng, dest_lat,
delivery_date, plate_no,
driver_name, driver_phone,
shipper_name, shipper_phone, receiver_name, receiver_phone, receiver_org_name,
delivery_ton, goods_size, order_status,
vehicle_type_id, vehicle_type_name,
suggest_fee, actual_fee, toll_fee, total_km,
create_by, create_time, update_by, update_time, is_delete)
VALUES
<foreach collection="list" item="it" separator=",">
(#{it.orderNo,jdbcType=VARCHAR}, #{it.xmMs}, #{it.xmNo}, #{it.wlNo}, #{it.wlMs}, #{it.realQty}, #{it.dw},
#{it.sapNo}, #{it.gysMc}, #{it.remark},
#{it.originName}, #{it.originLng}, #{it.originLat},
#{it.destName}, #{it.destLng}, #{it.destLat},
#{it.deliveryDate}, #{it.plateNo},
#{it.driverName}, #{it.driverPhone},
#{it.shipperName}, #{it.shipperPhone}, #{it.receiverName}, #{it.receiverPhone}, #{it.receiverOrgName},
#{it.deliveryTon}, #{it.goodsSize}, #{it.orderStatus},
#{it.vehicleTypeId}, #{it.vehicleTypeName},
#{it.suggestFee}, #{it.actualFee}, #{it.tollFee}, #{it.totalKm},
#{it.createBy}, #{it.createTime}, #{it.updateBy}, #{it.updateTime}, #{it.isDelete})
</foreach>
</insert>
<!-- ======================== 更新 ======================== -->
<update id="updateDeliveryOrder" parameterType="com.delivery.project.document.domain.DeliveryOrder">
UPDATE delivery_order
<trim prefix="SET" suffixOverrides=",">
<if test="xmMs != null">xm_ms = #{xmMs},</if>
<if test="xmNo != null">xm_no = #{xmNo},</if>
@@ -220,37 +413,55 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sapNo != null">sap_no = #{sapNo},</if>
<if test="gysMc != null">gys_mc = #{gysMc},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="originName != null">origin_name = #{originName},</if>
<if test="originLng != null">origin_lng = #{originLng},</if>
<if test="originLat != null">origin_lat = #{originLat},</if>
<if test="destName != null">dest_name = #{destName},</if>
<if test="destLng != null">dest_lng = #{destLng},</if>
<if test="destLat != null">dest_lat = #{destLat},</if>
<if test="deliveryDate != null">delivery_date = #{deliveryDate},</if>
<if test="vehiclePlate != null">vehicle_plate = #{vehiclePlate},</if>
<if test="plateNo != null">plate_no = #{plateNo},</if>
<if test="driverName != null">driver_name = #{driverName},</if>
<if test="driverPhone != null">driver_phone = #{driverPhone},</if>
<if test="shipperName != null">shipper_name = #{shipperName},</if>
<if test="shipperPhone != null">shipper_phone = #{shipperPhone},</if>
<if test="receiverName != null">receiver_name = #{receiverName},</if>
<if test="receiverPhone != null">receiver_phone = #{receiverPhone},</if>
<if test="receiverOrgName != null">receiver_org_name = #{receiverOrgName},</if>
<if test="deliveryTon != null">delivery_ton = #{deliveryTon},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="goodsSize != null">goods_size = #{goodsSize},</if>
<if test="orderStatus != null">order_status = #{orderStatus},</if>
<if test="vehicleTypeId != null">vehicle_type_id = #{vehicleTypeId},</if>
<if test="vehicleTypeName != null">vehicle_type_name = #{vehicleTypeName},</if>
<if test="suggestFee != null">suggest_fee = #{suggestFee},</if>
<if test="actualFee != null">actual_fee = #{actualFee},</if>
<if test="tollFee != null">toll_fee = #{tollFee},</if>
<if test="totalKm != null">total_km = #{totalKm},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
WHERE order_no = #{orderNo}
</update>
<!-- ======================== 删除 ======================== -->
<delete id="deleteDeliveryOrderById" parameterType="Long">
delete from delivery_order where id = #{id}
</delete>
<delete id="deleteDeliveryOrderByIds" parameterType="String">
delete from delivery_order where id in
delete from delivery_order where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
</mapper>

View File

@@ -0,0 +1,136 @@
<?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.delivery.project.document.mapper.MtdMapper">
<!-- 用全限定名IDE 即刻消红 -->
<resultMap id="MtdResult" type="com.delivery.project.document.domain.Mtd">
<id property="id" column="id"/>
<result property="wlNo" column="wl_no"/>
<result property="wlMs" column="wl_ms"/>
<result property="dw" column="dw"/>
<result property="weightKg" column="weight_kg"/>
<result property="volumeM3" column="volume_m3"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
</resultMap>
<sql id="selectMtdVo">
SELECT id, wl_no, wl_ms, dw, weight_kg, volume_m3,
create_by, create_time, update_by, update_time, is_delete
FROM delivery_mtd
</sql>
<select id="selectMtdList"
parameterType="com.delivery.project.document.domain.Mtd"
resultMap="MtdResult">
<include refid="selectMtdVo"/>
<where>
<if test="wlNo != null and wlNo != ''"> AND wl_no = #{wlNo}</if>
<if test="wlMs != null and wlMs != ''"> AND wl_ms = #{wlMs}</if>
<if test="dw != null and dw != ''"> AND dw = #{dw}</if>
<if test="weightKg != null"> AND weight_kg = #{weightKg}</if>
<if test="volumeM3 != null"> AND volume_m3 = #{volumeM3}</if>
<if test="isDelete != null and isDelete != ''"> AND is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMtdById" parameterType="java.lang.Long" resultMap="MtdResult">
<include refid="selectMtdVo"/>
WHERE id = #{id}
</select>
<select id="selectByWlNos" parameterType="list" resultMap="MtdResult">
SELECT id, wl_no, wl_ms, dw, weight_kg, volume_m3, is_delete
FROM delivery_mtd
WHERE (is_delete = '0' OR is_delete IS NULL)
AND wl_no IN
<foreach collection="wlNos" item="wlNo" open="(" separator="," close=")">
#{wlNo}
</foreach>
</select>
<insert id="insertMtd"
parameterType="com.delivery.project.document.domain.Mtd"
useGeneratedKeys="true" keyProperty="id">
INSERT INTO delivery_mtd
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="wlNo != null and wlNo != ''">wl_no,</if>
<if test="wlMs != null">wl_ms,</if>
<if test="dw != null">dw,</if>
<if test="weightKg != null">weight_kg,</if>
<if test="volumeM3 != null">volume_m3,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime!= null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime!= null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="wlNo != null and wlNo != ''">#{wlNo},</if>
<if test="wlMs != null">#{wlMs},</if>
<if test="dw != null">#{dw},</if>
<if test="weightKg != null">#{weightKg},</if>
<if test="volumeM3 != null">#{volumeM3},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime!= null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime!= null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMtd" parameterType="com.delivery.project.document.domain.Mtd">
UPDATE delivery_mtd
<trim prefix="SET" suffixOverrides=",">
<if test="wlNo != null and wlNo != ''">wl_no = #{wlNo},</if>
<if test="wlMs != null">wl_ms = #{wlMs},</if>
<if test="dw != null">dw = #{dw},</if>
<if test="weightKg != null">weight_kg = #{weightKg},</if>
<if test="volumeM3 != null">volume_m3 = #{volumeM3},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime!= null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime!= null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
WHERE id = #{id}
</update>
<delete id="deleteMtdById" parameterType="java.lang.Long">
DELETE FROM delivery_mtd WHERE id = #{id}
</delete>
<delete id="deleteMtdByIds" parameterType="long">
DELETE FROM delivery_mtd WHERE id IN
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<insert id="batchUpsertMtd" parameterType="java.util.List">
INSERT INTO delivery_mtd
(wl_no, wl_ms, dw, weight_kg, volume_m3, create_by, create_time, update_by, update_time, is_delete)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.wlNo}, #{item.wlMs}, #{item.dw}, #{item.weightKg}, #{item.volumeM3},
#{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.isDelete})
</foreach>
ON DUPLICATE KEY UPDATE
wl_ms = VALUES(wl_ms),
dw = VALUES(dw),
weight_kg = VALUES(weight_kg),
volume_m3 = VALUES(volume_m3),
update_by = VALUES(update_by),
update_time = VALUES(update_time),
is_delete = VALUES(is_delete)
</insert>
</mapper>

View File

@@ -1,124 +1,147 @@
<?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">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.delivery.project.document.mapper.RkInfoMapper">
<resultMap type="RkInfo" id="RkInfoResult">
<result property="id" column="id" />
<result property="rkType" column="rk_type" />
<result property="wlType" column="wl_type" />
<result property="cangku" column="cangku" />
<result property="rkTime" column="rk_time" />
<result property="lihuoY" column="lihuo_y" />
<result property="isChuku" column="is_chuku" />
<result property="status" column="status" />
<result property="remark" column="remark" />
<result property="billNo" column="bill_no" />
<result property="isDelivery" column="is_delivery" />
<result property="xj" column="xj" />
<result property="xmNo" column="xm_no" />
<result property="xmMs" column="xm_ms" />
<result property="xmNoCk" column="xm_no_ck" />
<result property="xmMsCk" column="xm_ms_ck" />
<result property="wlNo" column="wl_no" />
<result property="wlMs" column="wl_ms" />
<result property="gysNo" column="gys_no" />
<result property="gysMc" column="gys_mc" />
<result property="jhAmt" column="jh_amt" />
<result property="htDj" column="ht_dj" />
<result property="sapNo" column="sap_no" />
<result property="xh" column="xh" />
<result property="jhQty" column="jh_qty" />
<result property="htQty" column="ht_qty" />
<result property="dw" column="dw" />
<result property="realQty" column="real_qty" />
<result property="pcode" column="pcode" />
<result property="pcodeId" column="pcode_id" />
<result property="trayCode" column="tray_code" />
<result property="entityId" column="entity_id" />
<result property="ckLihuoY" column="ck_lihuo_y" />
<result property="teamCode" column="team_code" />
<result property="ckType" column="ck_type" />
<result property="ckRemark" column="ck_remark" />
<result property="lyTime" column="ly_time" />
<result property="billNoCk" column="bill_no_ck" />
<result property="borrowTime" column="borrow_time" />
<result property="returnTime" column="return_time" />
<result property="hasMoved" column="has_moved" />
<result property="isBorrowed" column="is_borrowed" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
<result property="gysJhId" column="gys_jh_id" />
<result property="id" column="id"/>
<result property="rkType" column="rk_type"/>
<result property="wlType" column="wl_type"/>
<result property="cangku" column="cangku"/>
<result property="rkTime" column="rk_time"/>
<result property="lihuoY" column="lihuo_y"/>
<result property="isChuku" column="is_chuku"/>
<result property="status" column="status"/>
<result property="remark" column="remark"/>
<result property="billNo" column="bill_no"/>
<result property="isDelivery" column="is_delivery"/>
<result property="xj" column="xj"/>
<result property="xmNo" column="xm_no"/>
<result property="xmMs" column="xm_ms"/>
<result property="xmNoCk" column="xm_no_ck"/>
<result property="xmMsCk" column="xm_ms_ck"/>
<result property="wlNo" column="wl_no"/>
<result property="wlMs" column="wl_ms"/>
<result property="gysNo" column="gys_no"/>
<result property="gysMc" column="gys_mc"/>
<result property="jhAmt" column="jh_amt"/>
<result property="htDj" column="ht_dj"/>
<result property="sapNo" column="sap_no"/>
<result property="xh" column="xh"/>
<result property="jhQty" column="jh_qty"/>
<result property="htQty" column="ht_qty"/>
<result property="dw" column="dw"/>
<result property="realQty" column="real_qty"/>
<result property="pcode" column="pcode"/>
<result property="pcodeId" column="pcode_id"/>
<result property="trayCode" column="tray_code"/>
<result property="entityId" column="entity_id"/>
<result property="ckLihuoY" column="ck_lihuo_y"/>
<result property="teamCode" column="team_code"/>
<result property="ckType" column="ck_type"/>
<result property="ckRemark" column="ck_remark"/>
<result property="lyTime" column="ly_time"/>
<result property="billNoCk" column="bill_no_ck"/>
<result property="borrowTime" column="borrow_time"/>
<result property="returnTime" column="return_time"/>
<result property="hasMoved" column="has_moved"/>
<result property="isBorrowed" column="is_borrowed"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
<result property="gysJhId" column="gys_jh_id"/>
<!-- 新增:来自 mtd 的两列 -->
<result property="weightKg" column="weight_kg"/>
<result property="volumeM3" column="volume_m3"/>
</resultMap>
<sql id="selectRkInfoVo">
select id, rk_type, wl_type, cangku, rk_time, lihuo_y, is_chuku, status, remark, bill_no, is_delivery, xj, xm_no, xm_ms, xm_no_ck, xm_ms_ck, wl_no, wl_ms, gys_no, gys_mc, jh_amt, ht_dj, sap_no, xh, jh_qty, ht_qty, dw, real_qty, pcode, pcode_id, tray_code, entity_id, ck_lihuo_y, team_code, ck_type, ck_remark, ly_time, bill_no_ck, borrow_time, return_time, has_moved, is_borrowed, create_by, create_time, update_by, update_time, is_delete, gys_jh_id from rk_info
<!-- 统一的字段清单(带 ri. 别名) -->
<sql id="rkInfoColumns">
ri.id, ri.rk_type, ri.wl_type, ri.cangku, ri.rk_time, ri.lihuo_y, ri.is_chuku, ri.status, ri.remark,
ri.bill_no, ri.is_delivery, ri.xj, ri.xm_no, ri.xm_ms, ri.xm_no_ck, ri.xm_ms_ck, ri.wl_no, ri.wl_ms,
ri.gys_no, ri.gys_mc, ri.jh_amt, ri.ht_dj, ri.sap_no, ri.xh, ri.jh_qty, ri.ht_qty, ri.dw, ri.real_qty,
ri.pcode, ri.pcode_id, ri.tray_code, ri.entity_id, ri.ck_lihuo_y, ri.team_code, ri.ck_type, ri.ck_remark,
ri.ly_time, ri.bill_no_ck, ri.borrow_time, ri.return_time, ri.has_moved, ri.is_borrowed,
ri.create_by, ri.create_time, ri.update_by, ri.update_time, ri.is_delete, ri.gys_jh_id
</sql>
<!-- 统一的 FROM + JOIN 片段 -->
<sql id="rkInfoFromJoinMtd">
FROM rk_info ri
LEFT JOIN delivery_mtd m
ON m.wl_no = ri.wl_no
AND (m.is_delete = '0' OR m.is_delete = 0 OR m.is_delete IS NULL)
</sql>
<!-- 列表查询(分页场景) -->
<select id="selectRkInfoList" parameterType="RkInfo" resultMap="RkInfoResult">
<include refid="selectRkInfoVo"/>
<where>
<if test="rkType != null and rkType != ''"> and rk_type = #{rkType}</if>
<if test="wlType != null and wlType != ''"> and wl_type = #{wlType}</if>
<if test="cangku != null and cangku != ''"> and cangku = #{cangku}</if>
<if test="rkTime != null "> and rk_time = #{rkTime}</if>
<if test="lihuoY != null and lihuoY != ''"> and lihuo_y = #{lihuoY}</if>
<if test="isChuku != null and isChuku != ''"> and is_chuku = #{isChuku}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="billNo != null and billNo != ''"> and bill_no = #{billNo}</if>
<if test="isDelivery != null and isDelivery != ''"> and is_delivery = #{isDelivery}</if>
<if test="xj != null and xj != ''"> and xj = #{xj}</if>
<if test="xmNo != null and xmNo != ''"> and xm_no = #{xmNo}</if>
<if test="xmMs != null and xmMs != ''"> and xm_ms = #{xmMs}</if>
<if test="xmNoCk != null and xmNoCk != ''"> and xm_no_ck = #{xmNoCk}</if>
<if test="xmMsCk != null and xmMsCk != ''"> and xm_ms_ck = #{xmMsCk}</if>
<if test="wlNo != null and wlNo != ''"> and wl_no = #{wlNo}</if>
<if test="wlMs != null and wlMs != ''"> and wl_ms = #{wlMs}</if>
<if test="gysNo != null and gysNo != ''"> and gys_no = #{gysNo}</if>
<if test="gysMc != null and gysMc != ''"> and gys_mc = #{gysMc}</if>
<if test="jhAmt != null "> and jh_amt = #{jhAmt}</if>
<if test="htDj != null "> and ht_dj = #{htDj}</if>
<if test="sapNo != null and sapNo != ''"> and sap_no = #{sapNo}</if>
<if test="xh != null and xh != ''"> and xh = #{xh}</if>
<if test="jhQty != null "> and jh_qty = #{jhQty}</if>
<if test="htQty != null "> and ht_qty = #{htQty}</if>
<if test="dw != null and dw != ''"> and dw = #{dw}</if>
<if test="realQty != null "> and real_qty = #{realQty}</if>
<if test="pcode != null and pcode != ''"> and pcode = #{pcode}</if>
<if test="pcodeId != null and pcodeId != ''"> and pcode_id = #{pcodeId}</if>
<if test="trayCode != null and trayCode != ''"> and tray_code = #{trayCode}</if>
<if test="entityId != null and entityId != ''"> and entity_id = #{entityId}</if>
<if test="ckLihuoY != null and ckLihuoY != ''"> and ck_lihuo_y = #{ckLihuoY}</if>
<if test="teamCode != null and teamCode != ''"> and team_code = #{teamCode}</if>
<if test="ckType != null and ckType != ''"> and ck_type = #{ckType}</if>
<if test="ckRemark != null and ckRemark != ''"> and ck_remark = #{ckRemark}</if>
<if test="lyTime != null "> and ly_time = #{lyTime}</if>
<if test="billNoCk != null and billNoCk != ''"> and bill_no_ck = #{billNoCk}</if>
<if test="borrowTime != null "> and borrow_time = #{borrowTime}</if>
<if test="returnTime != null "> and return_time = #{returnTime}</if>
<if test="hasMoved != null and hasMoved != ''"> and has_moved = #{hasMoved}</if>
<if test="isBorrowed != null and isBorrowed != ''"> and is_borrowed = #{isBorrowed}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
<if test="gysJhId != null "> and gys_jh_id = #{gysJhId}</if>
SELECT
<include refid="rkInfoColumns"/>,
m.weight_kg,
m.volume_m3
<include refid="rkInfoFromJoinMtd"/>
<where>
(ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
<if test="rkType != null and rkType != ''"> and ri.rk_type = #{rkType}</if>
<if test="wlType != null and wlType != ''"> and ri.wl_type = #{wlType}</if>
<if test="cangku != null and cangku != ''"> and ri.cangku = #{cangku}</if>
<if test="rkTime != null "> and ri.rk_time = #{rkTime}</if>
<if test="lihuoY != null and lihuoY != ''"> and ri.lihuo_y = #{lihuoY}</if>
<if test="isChuku != null and isChuku != ''"> and ri.is_chuku = #{isChuku}</if>
<if test="status != null and status != ''"> and ri.status = #{status}</if>
<if test="billNo != null and billNo != ''"> and ri.bill_no = #{billNo}</if>
<if test="isDelivery != null and isDelivery != ''"> and ri.is_delivery = #{isDelivery}</if>
<if test="xj != null and xj != ''"> and ri.xj = #{xj}</if>
<if test="xmNo != null and xmNo != ''"> and ri.xm_no = #{xmNo}</if>
<if test="xmMs != null and xmMs != ''"> and ri.xm_ms = #{xmMs}</if>
<if test="xmNoCk != null and xmNoCk != ''"> and ri.xm_no_ck = #{xmNoCk}</if>
<if test="xmMsCk != null and xmMsCk != ''"> and ri.xm_ms_ck = #{xmMsCk}</if>
<if test="wlNo != null and wlNo != ''"> and ri.wl_no = #{wlNo}</if>
<if test="wlMs != null and wlMs != ''"> and ri.wl_ms = #{wlMs}</if>
<if test="gysNo != null and gysNo != ''"> and ri.gys_no = #{gysNo}</if>
<if test="gysMc != null and gysMc != ''"> and ri.gys_mc = #{gysMc}</if>
<if test="jhAmt != null "> and ri.jh_amt = #{jhAmt}</if>
<if test="htDj != null "> and ri.ht_dj = #{htDj}</if>
<if test="sapNo != null and sapNo != ''"> and ri.sap_no = #{sapNo}</if>
<if test="xh != null and xh != ''"> and ri.xh = #{xh}</if>
<if test="jhQty != null "> and ri.jh_qty = #{jhQty}</if>
<if test="htQty != null "> and ri.ht_qty = #{htQty}</if>
<if test="dw != null and dw != ''"> and ri.dw = #{dw}</if>
<if test="realQty != null "> and ri.real_qty = #{realQty}</if>
<if test="pcode != null and pcode != ''"> and ri.pcode = #{pcode}</if>
<if test="pcodeId != null and pcodeId != ''"> and ri.pcode_id = #{pcodeId}</if>
<if test="trayCode != null and trayCode != ''"> and ri.tray_code = #{trayCode}</if>
<if test="entityId != null and entityId != ''"> and ri.entity_id = #{entityId}</if>
<if test="ckLihuoY != null and ckLihuoY != ''"> and ri.ck_lihuo_y = #{ckLihuoY}</if>
<if test="teamCode != null and teamCode != ''"> and ri.team_code = #{teamCode}</if>
<if test="ckType != null and ckType != ''"> and ri.ck_type = #{ckType}</if>
<if test="ckRemark != null and ckRemark != ''"> and ri.ck_remark = #{ckRemark}</if>
<if test="lyTime != null "> and ri.ly_time = #{lyTime}</if>
<if test="billNoCk != null and billNoCk != ''"> and ri.bill_no_ck = #{billNoCk}</if>
<if test="borrowTime != null "> and ri.borrow_time = #{borrowTime}</if>
<if test="returnTime != null "> and ri.return_time = #{returnTime}</if>
<if test="hasMoved != null and hasMoved != ''"> and ri.has_moved = #{hasMoved}</if>
<if test="isBorrowed != null and isBorrowed != ''"> and ri.is_borrowed = #{isBorrowed}</if>
<if test="isDelete != null and isDelete != ''"> and ri.is_delete = #{isDelete}</if>
<if test="gysJhId != null "> and ri.gys_jh_id = #{gysJhId}</if>
</where>
</select>
<!-- 按 ID 查询 -->
<select id="selectRkInfoById" parameterType="Long" resultMap="RkInfoResult">
<include refid="selectRkInfoVo"/>
where id = #{id}
SELECT
<include refid="rkInfoColumns"/>,
m.weight_kg,
m.volume_m3
<include refid="rkInfoFromJoinMtd"/>
WHERE ri.id = #{id}
</select>
<!--
按单据分组bill_no列表
复用 <sql id="selectRkInfoVo"> 作为子查询,外层分组聚合
返回字段bill_no、bill_no_ck + 你指定的通用字段rk_type、wl_type、cangku、rk_time、lihuo_y、is_chuku、xj、
xm_no、xm_ms、xm_no_ck、xm_ms_ck、wl_no、wl_ms、gys_no、sap_no
-->
<!-- RkInfoMapper.xml -->
<!-- 按单据分组bill_no列表复用同一个 SELECT 作为子查询,再做聚合 -->
<select id="selectGroupedByBill" resultMap="RkInfoResult">
SELECT
a.id,
@@ -171,110 +194,100 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
MAX(t.ly_time) AS ly_time,
MIN(t.ck_lihuo_y) AS ck_lihuo_y
FROM (
<include refid="selectRkInfoVo"/>
) t
SELECT
<include refid="rkInfoColumns"/>,
m.weight_kg,
m.volume_m3
<include refid="rkInfoFromJoinMtd"/>
<where>
<!-- 仅用 RkInfo 里真实存在的字段做筛选 -->
<!-- is_chuku单值 -->
(ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
<!-- 这里参数名按你的 Service 传入保持:假设是 q -->
<if test="q.isChuku != null and q.isChuku != ''">
AND t.is_chuku = #{q.isChuku}
and ri.is_chuku = #{q.isChuku}
</if>
<!-- 维度筛选 -->
<if test="q.rkType != null and q.rkType != ''">
AND t.rk_type LIKE concat('%', #{q.rkType}, '%')
and ri.rk_type LIKE concat('%', #{q.rkType}, '%')
</if>
<if test="q.wlType != null and q.wlType != ''">
AND t.wl_type LIKE concat('%', #{q.wlType}, '%')
and ri.wl_type LIKE concat('%', #{q.wlType}, '%')
</if>
<if test="q.cangku != null and q.cangku != ''">
AND t.cangku LIKE concat('%', #{q.cangku}, '%')
and ri.cangku LIKE concat('%', #{q.cangku}, '%')
</if>
<!-- 其它等值/模糊 -->
<if test="q.lihuoY != null and q.lihuoY != ''">
AND t.lihuo_y LIKE concat('%', #{q.lihuoY}, '%')
and ri.lihuo_y LIKE concat('%', #{q.lihuoY}, '%')
</if>
<if test="q.xj != null and q.xj != ''">
AND t.xj LIKE concat('%', #{q.xj}, '%')
and ri.xj LIKE concat('%', #{q.xj}, '%')
</if>
<if test="q.billNo != null and q.billNo != ''">
AND t.bill_no LIKE concat('%', #{q.billNo}, '%')
and ri.bill_no LIKE concat('%', #{q.billNo}, '%')
</if>
<if test="q.billNoCk != null and q.billNoCk != ''">
AND t.bill_no_ck LIKE concat('%', #{q.billNoCk}, '%')
and ri.bill_no_ck LIKE concat('%', #{q.billNoCk}, '%')
</if>
<if test="q.xmNo != null and q.xmNo != ''">
AND t.xm_no LIKE concat('%', #{q.xmNo}, '%')
and ri.xm_no LIKE concat('%', #{q.xmNo}, '%')
</if>
<if test="q.xmMs != null and q.xmMs != ''">
AND t.xm_ms LIKE concat('%', #{q.xmMs}, '%')
and ri.xm_ms LIKE concat('%', #{q.xmMs}, '%')
</if>
<if test="q.wlNo != null and q.wlNo != ''">
AND t.wl_no LIKE concat('%', #{q.wlNo}, '%')
and ri.wl_no LIKE concat('%', #{q.wlNo}, '%')
</if>
<if test="q.wlMs != null and q.wlMs != ''">
AND t.wl_ms LIKE concat('%', #{q.wlMs}, '%')
and ri.wl_ms LIKE concat('%', #{q.wlMs}, '%')
</if>
<if test="q.gysNo != null and q.gysNo != ''">
AND t.gys_no LIKE concat('%', #{q.gysNo}, '%')
and ri.gys_no LIKE concat('%', #{q.gysNo}, '%')
</if>
<if test="q.gysMc != null and q.gysMc != ''">
AND t.gys_mc LIKE concat('%', #{q.gysMc}, '%')
and ri.gys_mc LIKE concat('%', #{q.gysMc}, '%')
</if>
<if test="q.jhAmt != null"> AND t.jh_amt = #{q.jhAmt} </if>
<if test="q.htDj != null"> AND t.ht_dj = #{q.htDj} </if>
<if test="q.jhAmt != null"> and ri.jh_amt = #{q.jhAmt} </if>
<if test="q.htDj != null"> and ri.ht_dj = #{q.htDj} </if>
<if test="q.sapNo != null and q.sapNo != ''">
AND t.sap_no LIKE concat('%', #{q.sapNo}, '%')
and ri.sap_no LIKE concat('%', #{q.sapNo}, '%')
</if>
<if test="q.xh != null and q.xh != ''">
AND t.xh LIKE concat('%', #{q.xh}, '%')
and ri.xh LIKE concat('%', #{q.xh}, '%')
</if>
<if test="q.jhQty != null"> AND t.jh_qty = #{q.jhQty} </if>
<if test="q.htQty != null"> AND t.ht_qty = #{q.htQty} </if>
<if test="q.jhQty != null"> and ri.jh_qty = #{q.jhQty} </if>
<if test="q.htQty != null"> and ri.ht_qty = #{q.htQty} </if>
<if test="q.dw != null and q.dw != ''">
AND t.dw LIKE concat('%', #{q.dw}, '%')
and ri.dw LIKE concat('%', #{q.dw}, '%')
</if>
<if test="q.realQty != null"> AND t.real_qty = #{q.realQty} </if>
<if test="q.realQty != null"> and ri.real_qty = #{q.realQty} </if>
<if test="q.pcode != null and q.pcode != ''">
AND t.pcode LIKE concat('%', #{q.pcode}, '%')
and ri.pcode LIKE concat('%', #{q.pcode}, '%')
</if>
<if test="q.lyTime != null"> AND t.ly_time = #{q.lyTime} </if>
<if test="q.returnTime != null"> AND t.return_time = #{q.returnTime} </if>
<if test="q.lyTime != null"> and ri.ly_time = #{q.lyTime} </if>
<if test="q.returnTime != null"> and ri.return_time = #{q.returnTime} </if>
<if test="q.trayCode != null and q.trayCode != ''">
AND t.tray_code LIKE concat('%', #{q.trayCode}, '%')
and ri.tray_code LIKE concat('%', #{q.trayCode}, '%')
</if>
<if test="q.entityId != null and q.entityId != ''">
AND t.entity_id LIKE concat('%', #{q.entityId}, '%')
and ri.entity_id LIKE concat('%', #{q.entityId}, '%')
</if>
<if test="q.ckType != null and q.ckType != ''">
AND t.ck_type LIKE concat('%', #{q.ckType}, '%')
and ri.ck_type LIKE concat('%', #{q.ckType}, '%')
</if>
<!-- 若查询“已出库”,则要求已有出库单号 -->
<if test="q.isChuku != null and q.isChuku == '1'">
AND t.bill_no_ck IS NOT NULL
</if>
<!-- 删除标记,默认为 0 -->
<choose>
<when test="q.isDelete != null and q.isDelete != ''">
AND t.is_delete = #{q.isDelete}
and ri.is_delete = #{q.isDelete}
</when>
<otherwise>
AND t.is_delete = 0
and (ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
</otherwise>
</choose>
<!-- 只查需要配送 -->
<if test="q.isDelivery != null and q.isDelivery != ''">
AND t.is_delivery = #{q.isDelivery}
and ri.is_delivery = #{q.isDelivery}
</if>
<if test="q.isChuku != null and q.isChuku == '1'">
and ri.bill_no_ck IS NOT NULL
</if>
</where>
) t
GROUP BY t.bill_no
) a
LEFT JOIN stock_in_type si ON a.rk_type = si.type_code
@@ -283,7 +296,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY a.rk_time DESC
</select>
<!-- 插入 -->
<insert id="insertRkInfo" parameterType="RkInfo" useGeneratedKeys="true" keyProperty="id">
insert into rk_info
<trim prefix="(" suffix=")" suffixOverrides=",">
@@ -334,7 +347,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
<if test="gysJhId != null">gys_jh_id,</if>
</trim>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="rkType != null">#{rkType},</if>
<if test="wlType != null">#{wlType},</if>
@@ -383,9 +396,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
<if test="gysJhId != null">#{gysJhId},</if>
</trim>
</trim>
</insert>
<!-- 更新:照旧,不涉及 mtd -->
<update id="updateRkInfo" parameterType="RkInfo">
update rk_info
<trim prefix="SET" suffixOverrides=",">
@@ -427,7 +441,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="lyTime != null">ly_time = #{lyTime},</if>
<if test="billNoCk != null">bill_no_ck = #{billNoCk},</if>
<if test="borrowTime != null">borrow_time = #{borrowTime},</if>
<if test="returnTime != null">return_time = #{returnTime},</if>
<if test="returnTime != null">return_time = #{ReturnTime},</if>
<if test="hasMoved != null">has_moved = #{hasMoved},</if>
<if test="isBorrowed != null">is_borrowed = #{isBorrowed},</if>
<if test="createBy != null">create_by = #{createBy},</if>
@@ -445,9 +459,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete>
<delete id="deleteRkInfoByIds" parameterType="String">
delete from rk_info where id in
delete from rk_info
where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
</mapper>

View File

@@ -0,0 +1,141 @@
<?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.delivery.project.document.mapper.VehicleMapper">
<resultMap type="Vehicle" id="VehicleResult">
<result property="id" column="id" />
<result property="plateNo" column="plate_no" />
<result property="vin" column="vin" />
<result property="vehicleTypeId" column="vehicle_type_id" />
<result property="declaredWeightTon" column="declared_weight_ton" />
<result property="declaredVolumeM3" column="declared_volume_m3" />
<result property="driverName" column="driver_name" />
<result property="driverPhone" column="driver_phone" />
<result property="driverIdNo" column="driver_id_no" />
<result property="driverLicenseNo" column="driver_license_no" />
<result property="driverLicenseLevel" column="driver_license_level" />
<result property="inspectionExpireDate" column="inspection_expire_date" />
<result property="insuranceExpireDate" column="insurance_expire_date" />
<result property="status" column="status" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<sql id="selectVehicleVo">
select id, plate_no, vin, vehicle_type_id, declared_weight_ton, declared_volume_m3, driver_name, driver_phone, driver_id_no, driver_license_no, driver_license_level, inspection_expire_date, insurance_expire_date, status, remark, create_by, create_time, update_by, update_time, is_delete from vehicle
</sql>
<select id="selectVehicleList" parameterType="Vehicle" resultMap="VehicleResult">
<include refid="selectVehicleVo"/>
<where>
<if test="plateNo != null and plateNo != ''"> and plate_no = #{plateNo}</if>
<if test="vin != null and vin != ''"> and vin = #{vin}</if>
<if test="vehicleTypeId != null "> and vehicle_type_id = #{vehicleTypeId}</if>
<if test="declaredWeightTon != null "> and declared_weight_ton = #{declaredWeightTon}</if>
<if test="declaredVolumeM3 != null "> and declared_volume_m3 = #{declaredVolumeM3}</if>
<if test="driverName != null and driverName != ''"> and driver_name like concat('%', #{driverName}, '%')</if>
<if test="driverPhone != null and driverPhone != ''"> and driver_phone = #{driverPhone}</if>
<if test="driverIdNo != null and driverIdNo != ''"> and driver_id_no = #{driverIdNo}</if>
<if test="driverLicenseNo != null and driverLicenseNo != ''"> and driver_license_no = #{driverLicenseNo}</if>
<if test="driverLicenseLevel != null and driverLicenseLevel != ''"> and driver_license_level = #{driverLicenseLevel}</if>
<if test="inspectionExpireDate != null "> and inspection_expire_date = #{inspectionExpireDate}</if>
<if test="insuranceExpireDate != null "> and insurance_expire_date = #{insuranceExpireDate}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectVehicleById" parameterType="Long" resultMap="VehicleResult">
<include refid="selectVehicleVo"/>
where id = #{id}
</select>
<insert id="insertVehicle" parameterType="Vehicle" useGeneratedKeys="true" keyProperty="id">
insert into vehicle
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">plate_no,</if>
<if test="vin != null">vin,</if>
<if test="vehicleTypeId != null">vehicle_type_id,</if>
<if test="declaredWeightTon != null">declared_weight_ton,</if>
<if test="declaredVolumeM3 != null">declared_volume_m3,</if>
<if test="driverName != null">driver_name,</if>
<if test="driverPhone != null">driver_phone,</if>
<if test="driverIdNo != null">driver_id_no,</if>
<if test="driverLicenseNo != null">driver_license_no,</if>
<if test="driverLicenseLevel != null">driver_license_level,</if>
<if test="inspectionExpireDate != null">inspection_expire_date,</if>
<if test="insuranceExpireDate != null">insurance_expire_date,</if>
<if test="status != null and status != ''">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">#{plateNo},</if>
<if test="vin != null">#{vin},</if>
<if test="vehicleTypeId != null">#{vehicleTypeId},</if>
<if test="declaredWeightTon != null">#{declaredWeightTon},</if>
<if test="declaredVolumeM3 != null">#{declaredVolumeM3},</if>
<if test="driverName != null">#{driverName},</if>
<if test="driverPhone != null">#{driverPhone},</if>
<if test="driverIdNo != null">#{driverIdNo},</if>
<if test="driverLicenseNo != null">#{driverLicenseNo},</if>
<if test="driverLicenseLevel != null">#{driverLicenseLevel},</if>
<if test="inspectionExpireDate != null">#{inspectionExpireDate},</if>
<if test="insuranceExpireDate != null">#{insuranceExpireDate},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateVehicle" parameterType="Vehicle">
update vehicle
<trim prefix="SET" suffixOverrides=",">
<if test="plateNo != null and plateNo != ''">plate_no = #{plateNo},</if>
<if test="vin != null">vin = #{vin},</if>
<if test="vehicleTypeId != null">vehicle_type_id = #{vehicleTypeId},</if>
<if test="declaredWeightTon != null">declared_weight_ton = #{declaredWeightTon},</if>
<if test="declaredVolumeM3 != null">declared_volume_m3 = #{declaredVolumeM3},</if>
<if test="driverName != null">driver_name = #{driverName},</if>
<if test="driverPhone != null">driver_phone = #{driverPhone},</if>
<if test="driverIdNo != null">driver_id_no = #{driverIdNo},</if>
<if test="driverLicenseNo != null">driver_license_no = #{driverLicenseNo},</if>
<if test="driverLicenseLevel != null">driver_license_level = #{driverLicenseLevel},</if>
<if test="inspectionExpireDate != null">inspection_expire_date = #{inspectionExpireDate},</if>
<if test="insuranceExpireDate != null">insurance_expire_date = #{insuranceExpireDate},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteVehicleById" parameterType="Long">
delete from vehicle where id = #{id}
</delete>
<delete id="deleteVehicleByIds" parameterType="String">
delete from vehicle where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,144 @@
<?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.delivery.project.document.mapper.VehicleTypeMapper">
<resultMap id="VehicleTypeResult" type="com.delivery.project.document.domain.VehicleType">
<id property="id" column="id"/>
<result property="typeCode" column="type_code"/>
<result property="typeName" column="type_name"/>
<result property="weightMinTon" column="weight_min_ton"/>
<result property="weightMaxTon" column="weight_max_ton"/>
<result property="volumeMinM3" column="volume_min_m3"/>
<result property="volumeMaxM3" column="volume_max_m3"/>
<result property="unitPricePerKm" column="unit_price_per_km"/>
<result property="status" column="status"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
</resultMap>
<sql id="selectVehicleTypeVo">
select
id, type_code, type_name,
weight_min_ton, weight_max_ton,
volume_min_m3, volume_max_m3,
unit_price_per_km, status, remark,
create_by, create_time, update_by, update_time, is_delete
from vehicle_type
</sql>
<select id="selectVehicleTypeList" parameterType="VehicleType" resultMap="VehicleTypeResult">
<include refid="selectVehicleTypeVo"/>
<where>
<if test="typeCode != null and typeCode != ''"> and type_code = #{typeCode}</if>
<if test="typeName != null and typeName != ''"> and type_name like concat('%', #{typeName}, '%')</if>
<if test="weightMinTon != null "> and weight_min_ton = #{weightMinTon}</if>
<if test="weightMaxTon != null "> and weight_max_ton = #{weightMaxTon}</if>
<if test="volumeMinM3 != null "> and volume_min_m3 = #{volumeMinM3}</if>
<if test="volumeMaxM3 != null "> and volume_max_m3 = #{volumeMaxM3}</if>
<if test="unitPricePerKm != null "> and unit_price_per_km = #{unitPricePerKm}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectVehicleTypeById" parameterType="Long" resultMap="VehicleTypeResult">
<include refid="selectVehicleTypeVo"/>
where id = #{id}
</select>
<insert id="insertVehicleType" parameterType="VehicleType" useGeneratedKeys="true" keyProperty="id">
insert into vehicle_type
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="typeCode != null">type_code,</if>
<if test="typeName != null">type_name,</if>
<if test="weightMinTon != null">weight_min_ton,</if>
<if test="weightMaxTon != null">weight_max_ton,</if>
<if test="volumeMinM3 != null">volume_min_m3,</if>
<if test="volumeMaxM3 != null">volume_max_m3,</if>
<if test="unitPricePerKm != null">unit_price_per_km,</if>
<if test="status != null">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="typeCode != null">#{typeCode},</if>
<if test="typeName != null">#{typeName},</if>
<if test="weightMinTon != null">#{weightMinTon},</if>
<if test="weightMaxTon != null">#{weightMaxTon},</if>
<if test="volumeMinM3 != null">#{volumeMinM3},</if>
<if test="volumeMaxM3 != null">#{volumeMaxM3},</if>
<if test="unitPricePerKm != null">#{unitPricePerKm},</if>
<if test="status != null">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateVehicleType" parameterType="VehicleType">
update vehicle_type
<trim prefix="SET" suffixOverrides=",">
<if test="typeCode != null">type_code = #{typeCode},</if>
<if test="typeName != null">type_name = #{typeName},</if>
<if test="weightMinTon != null">weight_min_ton = #{weightMinTon},</if>
<if test="weightMaxTon != null">weight_max_ton = #{weightMaxTon},</if>
<if test="volumeMinM3 != null">volume_min_m3 = #{volumeMinM3},</if>
<if test="volumeMaxM3 != null">volume_max_m3 = #{volumeMaxM3},</if>
<if test="unitPricePerKm != null">unit_price_per_km = #{unitPricePerKm},</if>
<if test="status != null">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteVehicleTypeById" parameterType="Long">
delete from vehicle_type where id = #{id}
</delete>
<delete id="deleteVehicleTypeByIds" parameterType="String">
delete from vehicle_type where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 严格匹配:改为使用 resultMap同时保留 XML 转义和 status='0'(启用) -->
<select id="selectMatchTypes" resultMap="VehicleTypeResult">
<include refid="selectVehicleTypeVo"/>
where is_delete = '0'
and status = '0'
and weight_min_ton &lt;= #{w} and weight_max_ton &gt;= #{w}
and volume_min_m3 &lt;= #{v} and volume_max_m3 &gt;= #{v}
order by unit_price_per_km asc, weight_max_ton asc, volume_max_m3 asc, id asc
</select>
<!-- 兜底匹配:同样用 resultMap -->
<select id="selectFallbackTypes" resultMap="VehicleTypeResult">
<include refid="selectVehicleTypeVo"/>
where is_delete = '0'
and status = '0'
and weight_max_ton &gt;= #{w}
and volume_max_m3 &gt;= #{v}
order by unit_price_per_km asc, weight_max_ton asc, volume_max_m3 asc, id asc
</select>
</mapper>