增加配件主单下的服务主单退单逻辑 增加商品列表按距离排序
This commit is contained in:
parent
037b1b5b5e
commit
708d2f12f5
|
|
@ -11,6 +11,9 @@ import java.util.List;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import com.ghy.common.utils.LocationUtils;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* 店铺管理接口
|
||||
|
|
@ -125,23 +128,23 @@ public class ShopController extends BaseController {
|
|||
return AjaxResult.success(shops);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过地址获取经纬度坐标
|
||||
*/
|
||||
@PostMapping("/getCoordinates")
|
||||
public AjaxResult getCoordinatesByAddress(@RequestBody Shop shop) {
|
||||
try {
|
||||
Map<String, Double> coordinates = getCoordinatesByAddress(shop);
|
||||
if (coordinates != null) {
|
||||
return AjaxResult.success("获取坐标成功", coordinates);
|
||||
} else {
|
||||
return AjaxResult.error("无法获取该地址的坐标信息");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("获取坐标失败: {}", e.getMessage(), e);
|
||||
return AjaxResult.error("获取坐标失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * 通过地址获取经纬度坐标
|
||||
// */
|
||||
// @PostMapping("/getCoordinates")
|
||||
// public AjaxResult getCoordinatesByAddress(@RequestBody Shop shop) {
|
||||
// try {
|
||||
// Map<String, Double> coordinates = getCoordinatesByAddress(shop);
|
||||
// if (coordinates != null) {
|
||||
// return AjaxResult.success("获取坐标成功", coordinates);
|
||||
// } else {
|
||||
// return AjaxResult.error("无法获取该地址的坐标信息");
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// logger.error("获取坐标失败: {}", e.getMessage(), e);
|
||||
// return AjaxResult.error("获取坐标失败: " + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 通过经纬度逆解析获取地址信息并保存到店铺
|
||||
|
|
@ -329,4 +332,160 @@ public class ShopController extends BaseController {
|
|||
return AjaxResult.error("查询失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询附近的店铺
|
||||
*/
|
||||
@PostMapping("/nearby")
|
||||
public AjaxResult getNearbyShops(@RequestBody Map<String, Object> params) {
|
||||
try {
|
||||
Double latitude = Double.valueOf(params.get("latitude").toString());
|
||||
Double longitude = Double.valueOf(params.get("longitude").toString());
|
||||
Double radiusKm = params.containsKey("radiusKm") ?
|
||||
Double.valueOf(params.get("radiusKm").toString()) : 5.0; // 默认5公里
|
||||
|
||||
// 验证坐标有效性
|
||||
if (!LocationUtils.isValidCoordinate(latitude, longitude)) {
|
||||
return AjaxResult.error("无效的坐标参数");
|
||||
}
|
||||
|
||||
// 获取所有店铺
|
||||
List<Shop> allShops = shopService.listShops();
|
||||
|
||||
// 筛选出有坐标的店铺并计算距离
|
||||
List<Map<String, Object>> nearbyShops = allShops.stream()
|
||||
.filter(shop -> LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude()))
|
||||
.map(shop -> {
|
||||
double distance = LocationUtils.getDistanceInKilometers(
|
||||
latitude, longitude, shop.getLatitude(), shop.getLongitude());
|
||||
|
||||
Map<String, Object> shopWithDistance = new HashMap<>();
|
||||
shopWithDistance.put("shop", shop);
|
||||
shopWithDistance.put("distance", distance);
|
||||
shopWithDistance.put("distanceText", LocationUtils.formatDistance(distance * 1000));
|
||||
|
||||
// 计算方向
|
||||
double bearing = LocationUtils.getBearing(latitude, longitude,
|
||||
shop.getLatitude(), shop.getLongitude());
|
||||
shopWithDistance.put("direction", LocationUtils.getDirectionDescription(bearing));
|
||||
shopWithDistance.put("bearing", bearing);
|
||||
|
||||
return shopWithDistance;
|
||||
})
|
||||
.filter(shopMap -> (Double) shopMap.get("distance") <= radiusKm)
|
||||
.sorted(Comparator.comparingDouble(shopMap -> (Double) shopMap.get("distance")))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("centerLatitude", latitude);
|
||||
result.put("centerLongitude", longitude);
|
||||
result.put("radiusKm", radiusKm);
|
||||
result.put("totalCount", nearbyShops.size());
|
||||
result.put("shops", nearbyShops);
|
||||
|
||||
return AjaxResult.success("查询成功", result);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("查询附近店铺失败: {}", e.getMessage(), e);
|
||||
return AjaxResult.error("查询失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个店铺之间的距离
|
||||
*/
|
||||
@PostMapping("/distance")
|
||||
public AjaxResult getShopsDistance(@RequestBody Map<String, Object> params) {
|
||||
try {
|
||||
Long shopId1 = Long.valueOf(params.get("shopId1").toString());
|
||||
Long shopId2 = Long.valueOf(params.get("shopId2").toString());
|
||||
|
||||
Shop shop1 = shopService.getShop(shopId1);
|
||||
Shop shop2 = shopService.getShop(shopId2);
|
||||
|
||||
if (shop1 == null || shop2 == null) {
|
||||
return AjaxResult.error("店铺不存在");
|
||||
}
|
||||
|
||||
if (!LocationUtils.isValidCoordinate(shop1.getLatitude(), shop1.getLongitude()) ||
|
||||
!LocationUtils.isValidCoordinate(shop2.getLatitude(), shop2.getLongitude())) {
|
||||
return AjaxResult.error("店铺坐标信息不完整");
|
||||
}
|
||||
|
||||
double distanceKm = LocationUtils.getDistanceInKilometers(
|
||||
shop1.getLatitude(), shop1.getLongitude(),
|
||||
shop2.getLatitude(), shop2.getLongitude());
|
||||
|
||||
double bearing = LocationUtils.getBearing(
|
||||
shop1.getLatitude(), shop1.getLongitude(),
|
||||
shop2.getLatitude(), shop2.getLongitude());
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("shop1", shop1);
|
||||
result.put("shop2", shop2);
|
||||
result.put("distanceKm", distanceKm);
|
||||
result.put("distanceText", LocationUtils.formatDistance(distanceKm * 1000));
|
||||
result.put("direction", LocationUtils.getDirectionDescription(bearing));
|
||||
result.put("bearing", bearing);
|
||||
|
||||
return AjaxResult.success("计算成功", result);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("计算店铺距离失败: {}", e.getMessage(), e);
|
||||
return AjaxResult.error("计算失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取店铺覆盖范围内的其他店铺
|
||||
// */
|
||||
// @PostMapping("/coverage")
|
||||
// public AjaxResult getShopsCoverage(@RequestBody Map<String, Object> params) {
|
||||
// try {
|
||||
// Long shopId = Long.valueOf(params.get("shopId").toString());
|
||||
// Double radiusKm = params.containsKey("radiusKm") ?
|
||||
// Double.valueOf(params.get("radiusKm").toString()) : 10.0; // 默认10公里
|
||||
//
|
||||
// Shop centerShop = shopService.getShop(shopId);
|
||||
// if (centerShop == null) {
|
||||
// return AjaxResult.error("店铺不存在");
|
||||
// }
|
||||
//
|
||||
// if (!LocationUtils.isValidCoordinate(centerShop.getLatitude(), centerShop.getLongitude())) {
|
||||
// return AjaxResult.error("中心店铺坐标信息不完整");
|
||||
// }
|
||||
//
|
||||
// // 获取附近的店铺
|
||||
// Map<String, Object> nearbyParams = new HashMap<>();
|
||||
// nearbyParams.put("latitude", centerShop.getLatitude());
|
||||
// nearbyParams.put("longitude", centerShop.getLongitude());
|
||||
// nearbyParams.put("radiusKm", radiusKm);
|
||||
//
|
||||
// AjaxResult nearbyResult = getNearbyShops(nearbyParams);
|
||||
// if (nearbyResult.isSuccess()) {
|
||||
// Map<String, Object> data = (Map<String, Object>) nearbyResult.get("data");
|
||||
// List<Map<String, Object>> shops = (List<Map<String, Object>>) data.get("shops");
|
||||
//
|
||||
// // 排除自己
|
||||
// shops = shops.stream()
|
||||
// .filter(shopMap -> {
|
||||
// Shop shop = (Shop) shopMap.get("shop");
|
||||
// return !shop.getShopId().equals(shopId);
|
||||
// })
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// data.put("centerShop", centerShop);
|
||||
// data.put("shops", shops);
|
||||
// data.put("totalCount", shops.size());
|
||||
//
|
||||
// return AjaxResult.success("查询成功", data);
|
||||
// } else {
|
||||
// return nearbyResult;
|
||||
// }
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// logger.error("查询店铺覆盖范围失败: {}", e.getMessage(), e);
|
||||
// return AjaxResult.error("查询失败: " + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
@ -10,8 +10,11 @@ import com.ghy.common.utils.ShiroUtils;
|
|||
import com.ghy.common.utils.StringUtils;
|
||||
import com.ghy.common.utils.bean.BeanUtils;
|
||||
import com.ghy.common.utils.poi.ExcelUtil;
|
||||
import com.ghy.common.utils.LocationUtils;
|
||||
import com.ghy.goods.domain.*;
|
||||
import com.ghy.goods.service.*;
|
||||
import com.ghy.shop.domain.Shop;
|
||||
import com.ghy.shop.service.ShopService;
|
||||
import com.ghy.system.domain.SysArea;
|
||||
import com.ghy.system.service.ISysAreaService;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
|
|
@ -51,6 +54,8 @@ public class GoodsController extends BaseController {
|
|||
private IInsuranceManagerService insuranceManagerService;
|
||||
@Resource
|
||||
private IDeptCategoryInsuranceRelationService deptCategoryInsuranceRelationService;
|
||||
@Resource
|
||||
private ShopService shopService;
|
||||
|
||||
@RequiresPermissions("goods:goods:view")
|
||||
@GetMapping()
|
||||
|
|
@ -168,6 +173,11 @@ public class GoodsController extends BaseController {
|
|||
if (type==null){
|
||||
goods.setType(1);
|
||||
}
|
||||
|
||||
// 获取用户当前位置
|
||||
Double userLatitude = goods.getLatitude();
|
||||
Double userLongitude = goods.getLongitude();
|
||||
|
||||
// 判断类目id是否为第三级,不是的话需要找到所有符合条件的第三级类目id作为新的条件
|
||||
if (goods.getDeptGoodsCategoryId() != null) {
|
||||
logger.info("入参:" + goods.getDeptGoodsCategoryId());
|
||||
|
|
@ -210,6 +220,10 @@ public class GoodsController extends BaseController {
|
|||
|
||||
List<Goods> list = goodsService.selectGoodsList(goods);
|
||||
logger.info("传入的类目id汇总{},获取到的所有商品{}",goods.getDeptGoodsCategoryIds(),list);
|
||||
|
||||
// 用于缓存店铺信息,避免重复查询
|
||||
Map<Long, Shop> shopCache = new HashMap<>();
|
||||
|
||||
list.forEach(one -> {
|
||||
// 补全商品服务区域
|
||||
List<GoodsArea> goodsAreas = goodsAreaService.selectByGoodsId(one.getGoodsId());
|
||||
|
|
@ -227,9 +241,88 @@ public class GoodsController extends BaseController {
|
|||
one.setParGoodsCategoryId(parGoodsCategory.getGoodsCategoryId());
|
||||
one.setParGoodsCategoryName(parGoodsCategory.getGoodsCategoryName());
|
||||
}
|
||||
|
||||
// 计算距离逻辑
|
||||
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude) && one.getShopId() != null) {
|
||||
try {
|
||||
// 从缓存获取店铺信息,避免重复查询
|
||||
Shop shop = shopCache.computeIfAbsent(one.getShopId(),
|
||||
shopId -> shopService.getShop(shopId));
|
||||
|
||||
if (shop != null && LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude())) {
|
||||
// 计算距离(米)
|
||||
double distanceInMeters = LocationUtils.getDistanceInMeters(
|
||||
userLatitude, userLongitude,
|
||||
shop.getLatitude(), shop.getLongitude()
|
||||
);
|
||||
|
||||
// 格式化距离并设置到商品对象
|
||||
one.setDistance(LocationUtils.formatDistance(distanceInMeters));
|
||||
|
||||
logger.debug("商品[{}]距离用户: {}", one.getGoodsName(), one.getDistance());
|
||||
} else {
|
||||
// 店铺坐标不完整
|
||||
one.setDistance(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("计算商品[{}]距离失败: {}", one.getGoodsName(), e.getMessage());
|
||||
// 计算异常时设为null
|
||||
one.setDistance(null);
|
||||
}
|
||||
} else {
|
||||
// 用户未提供位置或商品无店铺信息
|
||||
one.setDistance(null);
|
||||
}
|
||||
});
|
||||
|
||||
// 如果用户提供了位置信息,按距离排序(距离为null的排在最后)
|
||||
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude)) {
|
||||
list.sort((goods1, goods2) -> {
|
||||
String distance1 = goods1.getDistance();
|
||||
String distance2 = goods2.getDistance();
|
||||
|
||||
// 距离为null的排在最后
|
||||
if (distance1 == null && distance2 == null) return 0;
|
||||
if (distance1 == null) return 1;
|
||||
if (distance2 == null) return -1;
|
||||
|
||||
// 解析距离数值进行比较
|
||||
try {
|
||||
double dist1 = parseDistanceToMeters(distance1);
|
||||
double dist2 = parseDistanceToMeters(distance2);
|
||||
return Double.compare(dist1, dist2);
|
||||
} catch (Exception e) {
|
||||
// 解析失败时保持原顺序
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
logger.info("已按距离排序,用户位置: 纬度={}, 经度={}", userLatitude, userLongitude);
|
||||
}
|
||||
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析距离字符串为米数(用于排序)
|
||||
*/
|
||||
private double parseDistanceToMeters(String distanceText) {
|
||||
if (distanceText == null || distanceText.trim().isEmpty()) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
try {
|
||||
if (distanceText.endsWith("米")) {
|
||||
return Double.parseDouble(distanceText.replace("米", ""));
|
||||
} else if (distanceText.endsWith("公里")) {
|
||||
return Double.parseDouble(distanceText.replace("公里", "")) * 1000;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("无法解析距离字符串: {}", distanceText);
|
||||
}
|
||||
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
@PostMapping("/hot/list")
|
||||
@ResponseBody
|
||||
|
|
|
|||
|
|
@ -1760,25 +1760,94 @@ public class OrderMasterController extends BaseController {
|
|||
* */
|
||||
@PostMapping("/console/cancel")
|
||||
@ResponseBody
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult consoleCancel(Long id) {
|
||||
if(id == null){
|
||||
return AjaxResult.error("订单编码id不能为空!");
|
||||
}
|
||||
|
||||
// 判断该主单状态
|
||||
OrderMaster orderMaster = orderMasterService.selectById(id);
|
||||
if(!orderMaster.getOrderStatus().equals(OrderStatus.PLAIN.code()) && !orderMaster.getOrderStatus().equals(OrderStatus.RECEIVE.code())){
|
||||
return AjaxResult.error("该订单处于无法退单状态!");
|
||||
}
|
||||
|
||||
// 含有子单
|
||||
List<OrderDetail> orderDetails = orderDetailService.selectByOrderMasterId(id);
|
||||
if(CollectionUtils.isNotEmpty(orderDetails)){
|
||||
return AjaxResult.error("该订单已经派发过子单,无法退单状态!");
|
||||
}
|
||||
// 清空id
|
||||
orderMasterService.removeWorker(orderMaster.getId());
|
||||
// 更新状态待接单
|
||||
orderMasterService.updateStatus(orderMaster.getId(), OrderStatus.RECEIVE.code());
|
||||
return AjaxResult.success();
|
||||
|
||||
try {
|
||||
// 判断是否为服务订单且需要退还服务金额
|
||||
if (isServiceOrder(orderMaster) &&
|
||||
orderMaster.getGoodsOrderMasterId() != null &&
|
||||
orderMaster.getServerGoodsMoney() != null &&
|
||||
orderMaster.getServerGoodsMoney().compareTo(BigDecimal.ZERO) > 0) {
|
||||
|
||||
logger.info("检测到服务订单退单,开始退还服务金额:订单[{}],金额[{}],目标商品订单[{}]",
|
||||
orderMaster.getId(), orderMaster.getServerGoodsMoney(), orderMaster.getGoodsOrderMasterId());
|
||||
|
||||
// 退还服务金额到商品订单
|
||||
refundServerMoneyToGoodsOrder(orderMaster.getGoodsOrderMasterId(), orderMaster.getServerGoodsMoney());
|
||||
}
|
||||
|
||||
// 清空id
|
||||
orderMasterService.removeWorker(orderMaster.getId());
|
||||
// 更新状态待接单
|
||||
orderMasterService.updateStatus(orderMaster.getId(), OrderStatus.RECEIVE.code());
|
||||
|
||||
return AjaxResult.success("退单成功");
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("退单失败:订单ID={}, 错误信息={}", id, e.getMessage(), e);
|
||||
return AjaxResult.error("退单失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为服务订单
|
||||
*/
|
||||
private boolean isServiceOrder(OrderMaster orderMaster) {
|
||||
return orderMaster.getOrderType() != null && orderMaster.getOrderType() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务订单退单时,退还服务金额给商品订单
|
||||
*
|
||||
* @param goodsOrderMasterId 商品订单主单ID
|
||||
* @param serverGoodsMoney 需要退还的服务金额
|
||||
*/
|
||||
private void refundServerMoneyToGoodsOrder(Long goodsOrderMasterId, BigDecimal serverGoodsMoney) {
|
||||
try {
|
||||
// 1. 查询商品订单
|
||||
OrderMaster goodsOrder = orderMasterService.selectById(goodsOrderMasterId);
|
||||
if (goodsOrder == null) {
|
||||
logger.error("商品订单不存在,无法退还服务金额,goodsOrderMasterId={}", goodsOrderMasterId);
|
||||
throw new RuntimeException("商品订单不存在");
|
||||
}
|
||||
|
||||
// 2. 查询商品订单的财务记录
|
||||
FinancialMaster goodsFinancial = financialMasterService.selectByOrderMasterId(goodsOrderMasterId);
|
||||
if (goodsFinancial == null) {
|
||||
logger.error("商品订单财务记录不存在,无法退还服务金额,goodsOrderMasterId={}", goodsOrderMasterId);
|
||||
throw new RuntimeException("商品订单财务记录不存在");
|
||||
}
|
||||
|
||||
// 3. 更新商品订单的可用金额(增加退还的服务金额)
|
||||
BigDecimal currentPayMoney = goodsFinancial.getPayMoney();
|
||||
BigDecimal newPayMoney = currentPayMoney.add(serverGoodsMoney);
|
||||
|
||||
goodsFinancial.setPayMoney(newPayMoney);
|
||||
financialMasterService.updateFinancialMaster(goodsFinancial);
|
||||
|
||||
logger.info("服务订单退单成功,已退还{}元服务金额到商品订单[{}]", serverGoodsMoney, goodsOrderMasterId);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("退还服务金额失败:goodsOrderMasterId={}, serverGoodsMoney={}, error={}",
|
||||
goodsOrderMasterId, serverGoodsMoney, e.getMessage(), e);
|
||||
throw new RuntimeException("退还服务金额失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -100,4 +100,14 @@ public class Goods extends BaseEntity {
|
|||
private Integer type;
|
||||
|
||||
private List<InsuranceManager> insuranceManagers;
|
||||
|
||||
private String distance;
|
||||
|
||||
/** 纬度 */
|
||||
private Double latitude;
|
||||
|
||||
/** 经度 */
|
||||
private Double longitude;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue