This commit is contained in:
dzc committed 2026-06-01 19:12:19 +08:00
commit c917418d73
15 files changed
+849 -23

No files matched your search

@@ -22,4 +22,8 @@ public final class CanteenDeliveryOrderStatus {
* 预约单:已到单但未达「提前 N 分钟派骑手」时间点,不展示在骑手待配送列表。
*/
public static final int SCHEDULED_PENDING = 5;
/** 待商家接单(支付同步后或预约单到商家通知时间后) */
public static final int MERCHANT_PENDING = 6;
/** 已指派骑手,待骑手确认接单 */
public static final int RIDER_PENDING_ACCEPT = 7;
}
@@ -0,0 +1,42 @@
package com.bsd.pjcloud.canteen.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.bsd.pjcloud.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
@Data
@TenantTable
@TableName("canteen_delivery_accept_setting")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "外送自动接单配置")
public class CanteenDeliveryAcceptSettingEntity extends Model<CanteenDeliveryAcceptSettingEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@Schema(description = "商户ID")
private String merchantId;
@Schema(description = "骑手用户ID")
private Long riderUserId;
@Schema(description = "1自动接单 0手动")
private Integer autoAccept;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableLogic
@TableField(fill = FieldFill.INSERT)
private String delFlag;
private Long tenantId;
}
@@ -36,6 +36,22 @@ public class CanteenDeliveryOrderEntity extends Model<CanteenDeliveryOrderEntity
private String fullAddress;
private Integer buyerGender;
private String carListJson;
@Schema(description = "订单金额快照(分)")
private Integer orderAmount;
@Schema(description = "商家是否已接单 0否1是")
private Integer merchantAccepted;
@Schema(description = "商家接单时间")
private LocalDateTime merchantAcceptTime;
@Schema(description = "骑手是否已接单 0否1是")
private Integer riderAccepted;
@Schema(description = "骑手接单时间")
private LocalDateTime riderAcceptTime;
private String assignType;
private Long riderUserId;
private Integer status;
@@ -67,6 +83,18 @@ public class CanteenDeliveryOrderEntity extends Model<CanteenDeliveryOrderEntity
private String pickupPhotoUrl;
private String deliveryPhotoUrl;
@Schema(description = "骑手佣金快照(分),派单时从商户 mch_take_out_amt 写入")
private Integer riderCommissionAmt;
@Schema(description = "骑手派单时间(佣金统计按此日期)")
private LocalDateTime riderAssignedTime;
@Schema(description = "取餐时间")
private LocalDateTime pickupTime;
@Schema(description = "送达时间")
private LocalDateTime deliverTime;
@TableField(fill = FieldFill.INSERT)
private String createBy;
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.canteen.vo.app;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "自动接单配置")
public class CanteenDeliveryAutoAcceptVO {
@Schema(description = "是否开启自动接单")
private Boolean autoAccept;
@Schema(description = "商户ID(商家端)")
private String merchantId;
@Schema(description = "骑手用户ID(骑手端)")
private Long riderUserId;
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.canteen.vo.app;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "商家外送按月统计")
public class CanteenDeliveryMerchantStatsMonthVO {
@Schema(description = "查询月份 yyyy-MM")
private String month;
@Schema(description = "该月已接单订单数")
private Long orderCount;
@Schema(description = "该月已接单金额合计(分)")
private Long totalAmount;
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.canteen.vo.app;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "商家外送订单统计汇总")
public class CanteenDeliveryMerchantStatsSummaryVO {
@Schema(description = "今日已接单订单数")
private Long todayOrderCount;
@Schema(description = "今日已接单金额合计(分)")
private Long todayOrderAmount;
@Schema(description = "本月已接单金额合计(分)")
private Long monthOrderAmount;
}
@@ -24,6 +24,21 @@ public class CanteenDeliveryOrderAppVO {
private String fullAddress;
private Integer status;
@Schema(description = "订单金额(分)")
private Integer orderAmount;
@Schema(description = "商家是否已接单")
private Integer merchantAccepted;
@Schema(description = "商家接单时间")
private LocalDateTime merchantAcceptTime;
@Schema(description = "骑手是否已接单")
private Integer riderAccepted;
@Schema(description = "骑手接单时间")
private LocalDateTime riderAcceptTime;
@Schema(description = "指派骑手用户主键(未指派时为 null)")
private Long riderUserId;
@@ -44,6 +59,18 @@ public class CanteenDeliveryOrderAppVO {
private String deliveryPhotoUrl;
private LocalDateTime createTime;
@Schema(description = "骑手佣金(分),派单时快照")
private Integer riderCommissionAmt;
@Schema(description = "骑手派单时间")
private LocalDateTime riderAssignedTime;
@Schema(description = "取餐时间")
private LocalDateTime pickupTime;
@Schema(description = "送达时间")
private LocalDateTime deliverTime;
@Schema(description = "购物车行项目(由 car_list_json 反序列化)")
private List<CanteenDeliveryCartItemDTO> carList;
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.canteen.vo.app;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDate;
@Data
@Schema(description = "骑手自定义日期佣金查询结果")
public class CanteenDeliveryRiderCommissionQueryVO {
@Schema(description = "查询开始日期")
private LocalDate startDate;
@Schema(description = "查询结束日期")
private LocalDate endDate;
@Schema(description = "佣金合计(分)")
private Long totalAmt;
@Schema(description = "有效派单数(非取消)")
private Long orderCount;
}
@@ -0,0 +1,21 @@
package com.bsd.pjcloud.canteen.vo.app;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "骑手佣金汇总(今日/本月,单位:分)")
public class CanteenDeliveryRiderCommissionSummaryVO {
@Schema(description = "今日佣金合计(分)")
private Long todayAmt;
@Schema(description = "本月佣金合计(分)")
private Long monthAmt;
@Schema(description = "今日有效派单数(非取消)")
private Long todayOrderCount;
@Schema(description = "本月有效派单数(非取消)")
private Long monthOrderCount;
}
@@ -6,7 +6,12 @@ import com.bsd.pjcloud.canteen.push.CanteenDeliveryMerchantNotifyPublisher;
import com.bsd.pjcloud.canteen.push.CanteenDeliveryRiderPushPublisher;
import com.bsd.pjcloud.canteen.service.CanteenDeliveryOrderService;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryOrderEntity;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryAutoAcceptVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsMonthVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsSummaryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryOrderAppVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionQueryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionSummaryVO;
import com.bsd.pjcloud.common.core.util.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.log.annotation.SysLog;
@@ -22,6 +27,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springdoc.core.annotations.ParameterObject;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
/**
* 食堂外送:订单同步 + 骑手 App
*/
@@ -103,6 +111,30 @@ public class CanteenDeliveryOrderController {
return R.ok(canteenDeliveryOrderService.pageForRider(uid, tab, page));
}
@GetMapping("/app/commission/summary")
@Operation(summary = "骑手端-佣金汇总", description = "今日/本月佣金合计(分),按派单时间统计,已取消单不计入")
public R<CanteenDeliveryRiderCommissionSummaryVO> appCommissionSummary() {
Long uid = SecurityUtils.getUser().getId();
return R.ok(canteenDeliveryOrderService.commissionSummaryForRider(uid));
}
@GetMapping("/app/commission/query")
@Operation(summary = "骑手端-自定义日期佣金", description = "startDate/endDate 格式 yyyy-MM-dd,含首尾自然日")
public R<CanteenDeliveryRiderCommissionQueryVO> appCommissionQuery(
@RequestParam String startDate,
@RequestParam String endDate) {
try {
LocalDate start = LocalDate.parse(startDate.trim());
LocalDate end = LocalDate.parse(endDate.trim());
Long uid = SecurityUtils.getUser().getId();
return R.ok(canteenDeliveryOrderService.commissionQueryForRider(uid, start, end));
} catch (DateTimeParseException ex) {
return R.failed("日期格式应为 yyyy-MM-dd");
} catch (IllegalArgumentException ex) {
return R.failed(ex.getMessage());
}
}
@GetMapping("/app/{id}")
@Operation(summary = "骑手端-配送单详情")
public R<CanteenDeliveryOrderAppVO> appDetail(@PathVariable Long id) {
@@ -116,14 +148,43 @@ public class CanteenDeliveryOrderController {
@GetMapping("/app/mch/list")
@Operation(summary = "商家端 App-外送单列表",
description = "当前登录用户部门及其下级部门关联的商户(钱包 get-by-dept-ids)下的外送单。"
+ "tab:pending 进行中 | all全部 | completed 已完成 | cancelled 已取消。分页同骑手端。"
+ "预约单 SCHEDULED 仅在 merchant_notify_done=1(已向商家触发通知)后返回;立即送不受限。")
public R<Page<CanteenDeliveryOrderAppVO>> mchAppList(@RequestParam(defaultValue = "pending") String tab,
description = "tab: wait_accept待接单 | accepted已接单 | cancelled | completed | all | pending(兼容)")
public R<Page<CanteenDeliveryOrderAppVO>> mchAppList(@RequestParam(defaultValue = "wait_accept") String tab,
@ParameterObject Page<CanteenDeliveryOrderEntity> page) {
return canteenDeliveryOrderService.pageForMerchantApp(tab, page);
}
@GetMapping("/app/mch/stats/summary")
@Operation(summary = "商家端-订单统计汇总")
public R<CanteenDeliveryMerchantStatsSummaryVO> mchStatsSummary() {
return canteenDeliveryOrderService.merchantStatsSummary();
}
@GetMapping("/app/mch/stats/month")
@Operation(summary = "商家端-按月统计", description = "month 格式 yyyy-MM")
public R<CanteenDeliveryMerchantStatsMonthVO> mchStatsMonth(@RequestParam String month) {
return canteenDeliveryOrderService.merchantStatsByMonth(month);
}
@GetMapping("/app/mch/auto-accept")
@Operation(summary = "商家端-获取自动接单配置")
public R<CanteenDeliveryAutoAcceptVO> mchGetAutoAccept() {
return canteenDeliveryOrderService.getMerchantAutoAccept();
}
@PutMapping("/app/mch/auto-accept")
@Operation(summary = "商家端-保存自动接单配置")
public R<CanteenDeliveryAutoAcceptVO> mchSaveAutoAccept(@RequestParam Boolean autoAccept) {
return canteenDeliveryOrderService.saveMerchantAutoAccept(autoAccept);
}
@SysLog("商家接单")
@PostMapping("/app/mch/accept/{id}")
@Operation(summary = "商家端-手动接单")
public R<Void> mchAccept(@PathVariable Long id) {
return canteenDeliveryOrderService.merchantAcceptOrder(id);
}
@GetMapping("/app/mch/{id}")
@Operation(summary = "商家端 App-外送单详情",
description = "预约单未到商家通知完成前返回失败(与列表可见性一致)。")
@@ -131,6 +192,28 @@ public class CanteenDeliveryOrderController {
return canteenDeliveryOrderService.detailForMerchantApp(id);
}
@GetMapping("/app/rider/auto-accept")
@Operation(summary = "骑手端-获取自动接单配置")
public R<CanteenDeliveryAutoAcceptVO> riderGetAutoAccept() {
Long uid = SecurityUtils.getUser().getId();
return canteenDeliveryOrderService.getRiderAutoAccept(uid);
}
@PutMapping("/app/rider/auto-accept")
@Operation(summary = "骑手端-保存自动接单配置")
public R<CanteenDeliveryAutoAcceptVO> riderSaveAutoAccept(@RequestParam Boolean autoAccept) {
Long uid = SecurityUtils.getUser().getId();
return canteenDeliveryOrderService.saveRiderAutoAccept(uid, autoAccept);
}
@SysLog("骑手接单")
@PostMapping("/app/accept/{id}")
@Operation(summary = "骑手端-手动接单")
public R<Void> riderAccept(@PathVariable Long id) {
Long uid = SecurityUtils.getUser().getId();
return canteenDeliveryOrderService.riderAcceptOrder(uid, id);
}
@SysLog("取餐拍照")
@PostMapping("/app/pickup")
@Operation(summary = "骑手端-到店取餐拍照",
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryAcceptSettingEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenDeliveryAcceptSettingMapper extends PjcloudBaseMapper<CanteenDeliveryAcceptSettingEntity> {
}
@@ -5,9 +5,16 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryOrderSyncDTO;
import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryPhotoDTO;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryOrderEntity;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryAutoAcceptVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsMonthVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsSummaryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryOrderAppVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionQueryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionSummaryVO;
import com.bsd.pjcloud.common.core.util.R;
import java.time.LocalDate;
public interface CanteenDeliveryOrderService extends IService<CanteenDeliveryOrderEntity> {
/**
@@ -53,4 +60,35 @@ public interface CanteenDeliveryOrderService extends IService<CanteenDeliveryOrd
* 单条:骑手派单+推送(事务内行锁;无可用骑手时保持待调度状态下次重试)。
*/
void dispatchScheduledRiderIfDue(Long deliveryOrderId);
/** 骑手端:今日/本月佣金汇总(分) */
CanteenDeliveryRiderCommissionSummaryVO commissionSummaryForRider(Long riderUserId);
/** 骑手端:自定义日期佣金(分) */
CanteenDeliveryRiderCommissionQueryVO commissionQueryForRider(Long riderUserId, LocalDate startDate, LocalDate endDate);
/** 商家端:今日/本月订单统计 */
R<CanteenDeliveryMerchantStatsSummaryVO> merchantStatsSummary();
/** 商家端:按月统计 yyyy-MM */
R<CanteenDeliveryMerchantStatsMonthVO> merchantStatsByMonth(String month);
/** 商家接单 */
R<Void> merchantAcceptOrder(Long deliveryOrderId);
/** 骑手接单 */
R<Void> riderAcceptOrder(Long riderUserId, Long deliveryOrderId);
/** 商家自动接单配置 */
R<CanteenDeliveryAutoAcceptVO> getMerchantAutoAccept();
R<CanteenDeliveryAutoAcceptVO> saveMerchantAutoAccept(Boolean autoAccept);
/** 骑手自动接单配置 */
R<CanteenDeliveryAutoAcceptVO> getRiderAutoAccept(Long riderUserId);
R<CanteenDeliveryAutoAcceptVO> saveRiderAutoAccept(Long riderUserId, Boolean autoAccept);
/** 内部:尝试商家自动接单(同步/通知后) */
void tryMerchantAutoAccept(Long deliveryOrderId);
}
@@ -18,10 +18,12 @@ import com.bsd.pjcloud.canteen.constants.CanteenDeliveryScheduleConstants;
import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryCartItemDTO;
import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryOrderSyncDTO;
import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryPhotoDTO;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryAcceptSettingEntity;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryAssignSeqEntity;
import com.bsd.pjcloud.canteen.entity.CanteenDeliveryOrderEntity;
import com.bsd.pjcloud.canteen.entity.CanteenRiderBuildingBindEntity;
import com.bsd.pjcloud.canteen.entity.CanteenRiderPoolEntity;
import com.bsd.pjcloud.canteen.mapper.CanteenDeliveryAcceptSettingMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenDeliveryAssignSeqMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenDeliveryOrderMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenRiderBuildingBindMapper;
@@ -31,11 +33,17 @@ import com.bsd.pjcloud.canteen.push.CanteenDeliveryRiderPushPublisher;
import com.bsd.pjcloud.canteen.service.CanteenDeliveryOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryAutoAcceptVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsMonthVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryMerchantStatsSummaryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryOrderAppVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionQueryVO;
import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryRiderCommissionSummaryVO;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletService;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.hard.api.dto.order.remote.HardUpdateTakeOutStatusDto;
import com.bsd.pjcloud.hard.api.feign.RemoteHardOrderService;
@@ -49,7 +57,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -66,6 +77,7 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
private final CanteenRiderBuildingBindMapper riderBuildingBindMapper;
private final CanteenRiderPoolMapper riderPoolMapper;
private final CanteenDeliveryAssignSeqMapper assignSeqMapper;
private final CanteenDeliveryAcceptSettingMapper acceptSettingMapper;
private final RemoteUserService remoteUserService;
private final RemoteDeptService remoteDeptService;
private final ObjectMapper objectMapper;
@@ -74,6 +86,7 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
private final RemoteParamService remoteParamService;
private final RemoteHardOrderService remoteHardOrderService;
private final RemoteMchService remoteMchService;
private final RemoteWalletService remoteWalletService;
private CanteenDeliveryOrderService deliveryOrderServiceSelf;
@@ -131,6 +144,11 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
} catch (JsonProcessingException e) {
return R.failed("购物车序列化失败");
}
entity.setOrderAmount(calcOrderAmountFromCart(dto.getCarList()));
entity.setMerchantAccepted(0);
entity.setRiderAccepted(0);
entity.setAssignType(CanteenDeliveryAssignType.NONE);
entity.setRiderUserId(null);
String expectType = entity.getExpectDeliveryType();
if (!CanteenDeliveryScheduleConstants.EXPECT_TYPE_SCHEDULED.equals(expectType)
@@ -138,10 +156,10 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
entity.setMerchantNotifyDone(1);
entity.setScheduledMerchantNotifyTime(null);
entity.setScheduledRiderNotifyTime(null);
assignRiderOnCreate(entity);
entity.setStatus(CanteenDeliveryOrderStatus.MERCHANT_PENDING);
save(entity);
scheduleMerchantImmediatePushAfterCommit(entity);
scheduleRiderPushAfterAssign(entity);
scheduleTryMerchantAutoAcceptAfterCommit(entity.getId());
return R.ok(entity.getId());
}
@@ -154,19 +172,24 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
entity.setScheduledRiderNotifyTime(slotStart.minusMinutes(riderBefore));
entity.setScheduledMerchantNotifyTime(slotStart.minusMinutes(merchantBefore));
entity.setMerchantNotifyDone(0);
entity.setStatus(CanteenDeliveryOrderStatus.SCHEDULED_PENDING);
if (entity.getScheduledRiderNotifyTime().isAfter(now)) {
entity.setStatus(CanteenDeliveryOrderStatus.SCHEDULED_PENDING);
entity.setAssignType(CanteenDeliveryAssignType.NONE);
entity.setRiderUserId(null);
save(entity);
return R.ok(entity.getId());
}
assignRiderOnCreate(entity);
if (entity.getScheduledMerchantNotifyTime() != null && !entity.getScheduledMerchantNotifyTime().isAfter(now)) {
entity.setMerchantNotifyDone(1);
entity.setStatus(CanteenDeliveryOrderStatus.MERCHANT_PENDING);
}
save(entity);
scheduleNotifyMerchantIfDueAfterCommit(entity.getId());
scheduleRiderPushAfterAssign(entity);
if (Objects.equals(entity.getMerchantNotifyDone(), 1)) {
scheduleMerchantPushAfterNotify(entity);
scheduleTryMerchantAutoAcceptAfterCommit(entity.getId());
} else {
scheduleNotifyMerchantIfDueAfterCommit(entity.getId());
}
return R.ok(entity.getId());
}
@@ -212,8 +235,11 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
* 事务提交后再推送,避免回滚后骑手仍收到通知。
*/
private void scheduleRiderPushAfterAssign(CanteenDeliveryOrderEntity entity) {
if (entity.getRiderUserId() == null
|| !Objects.equals(entity.getStatus(), CanteenDeliveryOrderStatus.WAIT_PICKUP)) {
if (entity.getRiderUserId() == null) {
return;
}
int st = entity.getStatus() != null ? entity.getStatus() : -1;
if (st != CanteenDeliveryOrderStatus.WAIT_PICKUP && st != CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT) {
return;
}
final Long riderId = entity.getRiderUserId();
@@ -248,7 +274,8 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
if (bind != null && verifyRiderInUnit(bind.getRiderUserId(), deptId)) {
entity.setRiderUserId(bind.getRiderUserId());
entity.setAssignType(CanteenDeliveryAssignType.BIND);
entity.setStatus(CanteenDeliveryOrderStatus.WAIT_PICKUP);
applyRiderCommissionSnapshot(entity);
applyRiderAcceptState(entity);
return;
}
}
@@ -283,7 +310,47 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
}
entity.setRiderUserId(chosen.getRiderUserId());
entity.setAssignType(CanteenDeliveryAssignType.ROUND_ROBIN);
entity.setStatus(CanteenDeliveryOrderStatus.WAIT_PICKUP);
applyRiderCommissionSnapshot(entity);
applyRiderAcceptState(entity);
}
private void applyRiderAcceptState(CanteenDeliveryOrderEntity entity) {
if (entity.getRiderUserId() == null) {
entity.setStatus(CanteenDeliveryOrderStatus.PENDING_ASSIGN);
return;
}
if (isRiderAutoAccept(entity.getRiderUserId())) {
entity.setRiderAccepted(1);
entity.setRiderAcceptTime(LocalDateTime.now());
entity.setStatus(CanteenDeliveryOrderStatus.WAIT_PICKUP);
} else {
entity.setRiderAccepted(0);
entity.setStatus(CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT);
}
}
/**
* 派单成功时快照商户配送费,后续商户改价不影响本单佣金。
*/
private void applyRiderCommissionSnapshot(CanteenDeliveryOrderEntity entity) {
entity.setRiderAssignedTime(LocalDateTime.now());
entity.setRiderCommissionAmt(resolveMchTakeOutAmt(entity.getMerchantId()));
}
private int resolveMchTakeOutAmt(String merchantId) {
if (StrUtil.isBlank(merchantId)) {
return 0;
}
try {
Long mid = Long.parseLong(merchantId.trim());
R<Integer> r = remoteWalletService.innerMchTakeOutAmt(mid);
if (r != null && r.isOk() && r.getData() != null) {
return Math.max(0, r.getData());
}
} catch (Exception ex) {
log.warn("resolveMchTakeOutAmt merchantId={}", merchantId, ex);
}
return 0;
}
private List<CanteenRiderPoolEntity> filterPoolByBuyerGender(List<CanteenRiderPoolEntity> pool, Integer buyerGender) {
@@ -381,8 +448,11 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
var q = Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getRiderUserId, riderUserId);
switch (t) {
case "wait_accept" ->
q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT);
case "pending" ->
q.in(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.WAIT_PICKUP, CanteenDeliveryOrderStatus.DELIVERING);
q.in(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.WAIT_PICKUP, CanteenDeliveryOrderStatus.DELIVERING)
.eq(CanteenDeliveryOrderEntity::getRiderAccepted, 1);
case "completed" -> q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.COMPLETED);
case "cancelled" -> q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.CANCELLED);
default -> {
@@ -486,10 +556,19 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
.in(CanteenDeliveryOrderEntity::getMerchantId, merchantIds);
applyMerchantScheduledVisibilityFilter(q);
switch (t) {
case "wait_accept" -> q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.MERCHANT_PENDING);
case "accepted" -> q.eq(CanteenDeliveryOrderEntity::getMerchantAccepted, 1)
.in(CanteenDeliveryOrderEntity::getStatus,
CanteenDeliveryOrderStatus.PENDING_ASSIGN,
CanteenDeliveryOrderStatus.WAIT_PICKUP,
CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT,
CanteenDeliveryOrderStatus.DELIVERING,
CanteenDeliveryOrderStatus.SCHEDULED_PENDING);
case "pending" -> q.in(CanteenDeliveryOrderEntity::getStatus,
CanteenDeliveryOrderStatus.PENDING_ASSIGN,
CanteenDeliveryOrderStatus.SCHEDULED_PENDING,
CanteenDeliveryOrderStatus.WAIT_PICKUP,
CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT,
CanteenDeliveryOrderStatus.DELIVERING);
case "completed" -> q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.COMPLETED);
case "cancelled" -> q.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.CANCELLED);
@@ -575,11 +654,15 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
if (e == null || !Objects.equals(e.getRiderUserId(), riderUserId)) {
return R.failed("订单不存在或无权操作");
}
if (!Objects.equals(e.getRiderAccepted(), 1)) {
return R.failed("请先接单");
}
if (e.getStatus() != CanteenDeliveryOrderStatus.WAIT_PICKUP) {
return R.failed("当前状态不可上传取餐照");
}
e.setPickupPhotoUrl(dto.getPhotoUrl());
e.setStatus(CanteenDeliveryOrderStatus.DELIVERING);
e.setPickupTime(LocalDateTime.now());
updateById(e);
syncHardTakeOutStatusOrThrow(e.getSourceOrderId(), HardUpdateTakeOutStatusDto.TakeOutStatus.TAKE_OUT_ING);
return R.ok();
@@ -597,6 +680,7 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
}
e.setDeliveryPhotoUrl(dto.getPhotoUrl());
e.setStatus(CanteenDeliveryOrderStatus.COMPLETED);
e.setDeliverTime(LocalDateTime.now());
updateById(e);
syncHardTakeOutStatusOrThrow(e.getSourceOrderId(), HardUpdateTakeOutStatusDto.TakeOutStatus.DONE);
return R.ok();
@@ -623,7 +707,9 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
}
List<CanteenDeliveryOrderEntity> riderDue = list(Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.SCHEDULED_PENDING)
.eq(CanteenDeliveryOrderEntity::getMerchantAccepted, 1)
.isNull(CanteenDeliveryOrderEntity::getRiderUserId)
.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.PENDING_ASSIGN)
.isNotNull(CanteenDeliveryOrderEntity::getScheduledRiderNotifyTime)
.le(CanteenDeliveryOrderEntity::getScheduledRiderNotifyTime, now)
.select(CanteenDeliveryOrderEntity::getId)
@@ -661,8 +747,12 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
return;
}
e.setMerchantNotifyDone(1);
if (!isMerchantAccepted(e)) {
e.setStatus(CanteenDeliveryOrderStatus.MERCHANT_PENDING);
}
updateById(e);
scheduleMerchantPushAfterNotify(e);
scheduleTryMerchantAutoAcceptAfterCommit(e.getId());
}
/**
@@ -693,18 +783,22 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
CanteenDeliveryOrderEntity e = getOne(Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getId, deliveryOrderId)
.last("FOR UPDATE"));
if (e == null || !Objects.equals(e.getStatus(), CanteenDeliveryOrderStatus.SCHEDULED_PENDING)) {
if (e == null) {
return;
}
if (e.getScheduledRiderNotifyTime() == null || e.getScheduledRiderNotifyTime().isAfter(LocalDateTime.now())) {
return;
}
assignRiderOnCreate(e);
if (e.getRiderUserId() == null) {
e.setStatus(CanteenDeliveryOrderStatus.SCHEDULED_PENDING);
updateById(e);
if (!isMerchantAccepted(e)) {
return;
}
if (e.getRiderUserId() != null) {
return;
}
if (e.getStatus() != CanteenDeliveryOrderStatus.PENDING_ASSIGN) {
return;
}
assignRiderOnCreate(e);
updateById(e);
scheduleRiderPushAfterAssign(e);
}
@@ -728,6 +822,388 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl<CanteenDelivery
}
}
@Override
public CanteenDeliveryRiderCommissionSummaryVO commissionSummaryForRider(Long riderUserId) {
LocalDate today = LocalDate.now();
LocalDateTime dayStart = today.atStartOfDay();
LocalDateTime dayEnd = today.plusDays(1).atStartOfDay();
LocalDateTime monthStart = today.withDayOfMonth(1).atStartOfDay();
LocalDateTime monthEnd = today.withDayOfMonth(1).plusMonths(1).atStartOfDay();
CanteenDeliveryRiderCommissionSummaryVO vo = new CanteenDeliveryRiderCommissionSummaryVO();
vo.setTodayAmt(sumRiderCommission(riderUserId, dayStart, dayEnd));
vo.setMonthAmt(sumRiderCommission(riderUserId, monthStart, monthEnd));
vo.setTodayOrderCount(countRiderCommissionOrders(riderUserId, dayStart, dayEnd));
vo.setMonthOrderCount(countRiderCommissionOrders(riderUserId, monthStart, monthEnd));
return vo;
}
@Override
public CanteenDeliveryRiderCommissionQueryVO commissionQueryForRider(Long riderUserId, LocalDate startDate, LocalDate endDate) {
if (startDate == null || endDate == null) {
throw new IllegalArgumentException("开始日期与结束日期不能为空");
}
if (endDate.isBefore(startDate)) {
throw new IllegalArgumentException("结束日期不能早于开始日期");
}
LocalDateTime start = startDate.atStartOfDay();
LocalDateTime end = endDate.plusDays(1).atStartOfDay();
CanteenDeliveryRiderCommissionQueryVO vo = new CanteenDeliveryRiderCommissionQueryVO();
vo.setStartDate(startDate);
vo.setEndDate(endDate);
vo.setTotalAmt(sumRiderCommission(riderUserId, start, end));
vo.setOrderCount(countRiderCommissionOrders(riderUserId, start, end));
return vo;
}
private long sumRiderCommission(Long riderUserId, LocalDateTime startInclusive, LocalDateTime endExclusive) {
if (riderUserId == null) {
return 0L;
}
List<CanteenDeliveryOrderEntity> rows = list(buildCommissionQuery(riderUserId, startInclusive, endExclusive)
.select(CanteenDeliveryOrderEntity::getRiderCommissionAmt));
return rows.stream()
.mapToLong(e -> e.getRiderCommissionAmt() != null ? e.getRiderCommissionAmt() : 0L)
.sum();
}
private long countRiderCommissionOrders(Long riderUserId, LocalDateTime startInclusive, LocalDateTime endExclusive) {
if (riderUserId == null) {
return 0L;
}
return count(buildCommissionQuery(riderUserId, startInclusive, endExclusive));
}
private LambdaQueryWrapper<CanteenDeliveryOrderEntity> buildCommissionQuery(Long riderUserId,
LocalDateTime startInclusive,
LocalDateTime endExclusive) {
return Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getRiderUserId, riderUserId)
.isNotNull(CanteenDeliveryOrderEntity::getRiderAssignedTime)
.ge(CanteenDeliveryOrderEntity::getRiderAssignedTime, startInclusive)
.lt(CanteenDeliveryOrderEntity::getRiderAssignedTime, endExclusive)
.ne(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.CANCELLED)
.isNotNull(CanteenDeliveryOrderEntity::getRiderCommissionAmt);
}
@Override
public R<CanteenDeliveryMerchantStatsSummaryVO> merchantStatsSummary() {
R<List<String>> mchIdsR = resolveMerchantIdStringsForLoginUser();
if (!mchIdsR.isOk()) {
return R.failed(mchIdsR.getMsg());
}
List<String> merchantIds = mchIdsR.getData();
LocalDate today = LocalDate.now();
LocalDateTime dayStart = today.atStartOfDay();
LocalDateTime dayEnd = today.plusDays(1).atStartOfDay();
LocalDateTime monthStart = today.withDayOfMonth(1).atStartOfDay();
LocalDateTime monthEnd = today.withDayOfMonth(1).plusMonths(1).atStartOfDay();
CanteenDeliveryMerchantStatsSummaryVO vo = new CanteenDeliveryMerchantStatsSummaryVO();
vo.setTodayOrderCount(countMerchantAcceptedOrders(merchantIds, dayStart, dayEnd));
vo.setTodayOrderAmount(sumMerchantAcceptedAmount(merchantIds, dayStart, dayEnd));
vo.setMonthOrderAmount(sumMerchantAcceptedAmount(merchantIds, monthStart, monthEnd));
return R.ok(vo);
}
@Override
public R<CanteenDeliveryMerchantStatsMonthVO> merchantStatsByMonth(String month) {
R<List<String>> mchIdsR = resolveMerchantIdStringsForLoginUser();
if (!mchIdsR.isOk()) {
return R.failed(mchIdsR.getMsg());
}
YearMonth ym;
try {
ym = YearMonth.parse(month.trim());
} catch (DateTimeParseException ex) {
return R.failed("月份格式应为 yyyy-MM");
}
LocalDateTime start = ym.atDay(1).atStartOfDay();
LocalDateTime end = ym.plusMonths(1).atDay(1).atStartOfDay();
CanteenDeliveryMerchantStatsMonthVO vo = new CanteenDeliveryMerchantStatsMonthVO();
vo.setMonth(ym.toString());
vo.setOrderCount(countMerchantAcceptedOrders(mchIdsR.getData(), start, end));
vo.setTotalAmount(sumMerchantAcceptedAmount(mchIdsR.getData(), start, end));
return R.ok(vo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<Void> merchantAcceptOrder(Long deliveryOrderId) {
R<List<String>> mchIdsR = resolveMerchantIdStringsForLoginUser();
if (!mchIdsR.isOk()) {
return R.failed(mchIdsR.getMsg());
}
return merchantAcceptInternal(deliveryOrderId, mchIdsR.getData());
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<Void> riderAcceptOrder(Long riderUserId, Long deliveryOrderId) {
CanteenDeliveryOrderEntity e = getById(deliveryOrderId);
if (e == null || !Objects.equals(e.getRiderUserId(), riderUserId)) {
return R.failed("订单不存在或无权操作");
}
if (!Objects.equals(e.getStatus(), CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT)) {
return R.failed("当前状态不可接单");
}
e.setRiderAccepted(1);
e.setRiderAcceptTime(LocalDateTime.now());
e.setStatus(CanteenDeliveryOrderStatus.WAIT_PICKUP);
updateById(e);
return R.ok();
}
@Override
public R<CanteenDeliveryAutoAcceptVO> getMerchantAutoAccept() {
R<List<String>> mchIdsR = resolveMerchantIdStringsForLoginUser();
if (!mchIdsR.isOk()) {
return R.failed(mchIdsR.getMsg());
}
if (CollUtil.isEmpty(mchIdsR.getData())) {
return R.failed("商户不存在");
}
String merchantId = mchIdsR.getData().get(0);
CanteenDeliveryAutoAcceptVO vo = new CanteenDeliveryAutoAcceptVO();
vo.setMerchantId(merchantId);
vo.setAutoAccept(isMerchantAutoAccept(merchantId));
return R.ok(vo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<CanteenDeliveryAutoAcceptVO> saveMerchantAutoAccept(Boolean autoAccept) {
R<List<String>> mchIdsR = resolveMerchantIdStringsForLoginUser();
if (!mchIdsR.isOk()) {
return R.failed(mchIdsR.getMsg());
}
if (CollUtil.isEmpty(mchIdsR.getData())) {
return R.failed("商户不存在");
}
String merchantId = mchIdsR.getData().get(0);
saveMerchantAutoAcceptSetting(merchantId, Boolean.TRUE.equals(autoAccept));
if (Boolean.TRUE.equals(autoAccept)) {
autoAcceptPendingMerchantOrders(merchantId);
}
CanteenDeliveryAutoAcceptVO vo = new CanteenDeliveryAutoAcceptVO();
vo.setMerchantId(merchantId);
vo.setAutoAccept(Boolean.TRUE.equals(autoAccept));
return R.ok(vo);
}
@Override
public R<CanteenDeliveryAutoAcceptVO> getRiderAutoAccept(Long riderUserId) {
CanteenDeliveryAutoAcceptVO vo = new CanteenDeliveryAutoAcceptVO();
vo.setRiderUserId(riderUserId);
vo.setAutoAccept(isRiderAutoAccept(riderUserId));
return R.ok(vo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<CanteenDeliveryAutoAcceptVO> saveRiderAutoAccept(Long riderUserId, Boolean autoAccept) {
saveRiderAutoAcceptSetting(riderUserId, Boolean.TRUE.equals(autoAccept));
if (Boolean.TRUE.equals(autoAccept)) {
autoAcceptPendingRiderOrders(riderUserId);
}
CanteenDeliveryAutoAcceptVO vo = new CanteenDeliveryAutoAcceptVO();
vo.setRiderUserId(riderUserId);
vo.setAutoAccept(Boolean.TRUE.equals(autoAccept));
return R.ok(vo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void tryMerchantAutoAccept(Long deliveryOrderId) {
CanteenDeliveryOrderEntity e = getById(deliveryOrderId);
if (e == null || isMerchantAccepted(e)) {
return;
}
if (!Objects.equals(e.getStatus(), CanteenDeliveryOrderStatus.MERCHANT_PENDING)) {
return;
}
if (!isMerchantAutoAccept(e.getMerchantId())) {
return;
}
merchantAcceptInternal(e.getId(), List.of(e.getMerchantId()));
}
private R<Void> merchantAcceptInternal(Long deliveryOrderId, List<String> merchantIds) {
CanteenDeliveryOrderEntity e = getOne(Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getId, deliveryOrderId)
.last("FOR UPDATE"));
if (e == null || StrUtil.isBlank(e.getMerchantId()) || !merchantIds.contains(e.getMerchantId())) {
return R.failed("订单不存在或无权操作");
}
if (!merchantScheduledOrderVisibleToMerchant(e)) {
return R.failed("订单不存在或无权操作");
}
if (isMerchantAccepted(e)) {
return R.failed("订单已接单");
}
if (!Objects.equals(e.getStatus(), CanteenDeliveryOrderStatus.MERCHANT_PENDING)) {
return R.failed("当前状态不可接单");
}
e.setMerchantAccepted(1);
e.setMerchantAcceptTime(LocalDateTime.now());
assignRiderOnCreate(e);
updateById(e);
scheduleRiderPushAfterAssign(e);
return R.ok();
}
private void scheduleTryMerchantAutoAcceptAfterCommit(Long deliveryOrderId) {
if (deliveryOrderId == null || deliveryOrderServiceSelf == null) {
return;
}
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
deliveryOrderServiceSelf.tryMerchantAutoAccept(deliveryOrderId);
}
});
} else {
deliveryOrderServiceSelf.tryMerchantAutoAccept(deliveryOrderId);
}
}
private void autoAcceptPendingMerchantOrders(String merchantId) {
List<CanteenDeliveryOrderEntity> pending = list(Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getMerchantId, merchantId)
.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.MERCHANT_PENDING)
.eq(CanteenDeliveryOrderEntity::getMerchantAccepted, 0)
.last("LIMIT 200"));
for (CanteenDeliveryOrderEntity row : pending) {
try {
merchantAcceptInternal(row.getId(), List.of(merchantId));
} catch (Exception ex) {
log.warn("autoAcceptPendingMerchantOrders id={}", row.getId(), ex);
}
}
}
private void autoAcceptPendingRiderOrders(Long riderUserId) {
List<CanteenDeliveryOrderEntity> pending = list(Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.eq(CanteenDeliveryOrderEntity::getRiderUserId, riderUserId)
.eq(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.RIDER_PENDING_ACCEPT)
.eq(CanteenDeliveryOrderEntity::getRiderAccepted, 0)
.last("LIMIT 200"));
for (CanteenDeliveryOrderEntity row : pending) {
try {
riderAcceptOrder(riderUserId, row.getId());
} catch (Exception ex) {
log.warn("autoAcceptPendingRiderOrders id={}", row.getId(), ex);
}
}
}
private long countMerchantAcceptedOrders(List<String> merchantIds, LocalDateTime start, LocalDateTime end) {
if (CollUtil.isEmpty(merchantIds)) {
return 0L;
}
return count(buildMerchantStatsQuery(merchantIds, start, end));
}
private long sumMerchantAcceptedAmount(List<String> merchantIds, LocalDateTime start, LocalDateTime end) {
if (CollUtil.isEmpty(merchantIds)) {
return 0L;
}
List<CanteenDeliveryOrderEntity> rows = list(buildMerchantStatsQuery(merchantIds, start, end)
.select(CanteenDeliveryOrderEntity::getOrderAmount));
return rows.stream().mapToLong(e -> e.getOrderAmount() != null ? e.getOrderAmount() : 0L).sum();
}
private LambdaQueryWrapper<CanteenDeliveryOrderEntity> buildMerchantStatsQuery(List<String> merchantIds,
LocalDateTime start,
LocalDateTime end) {
return Wrappers.<CanteenDeliveryOrderEntity>lambdaQuery()
.in(CanteenDeliveryOrderEntity::getMerchantId, merchantIds)
.eq(CanteenDeliveryOrderEntity::getMerchantAccepted, 1)
.ne(CanteenDeliveryOrderEntity::getStatus, CanteenDeliveryOrderStatus.CANCELLED)
.isNotNull(CanteenDeliveryOrderEntity::getMerchantAcceptTime)
.ge(CanteenDeliveryOrderEntity::getMerchantAcceptTime, start)
.lt(CanteenDeliveryOrderEntity::getMerchantAcceptTime, end);
}
private int calcOrderAmountFromCart(List<CanteenDeliveryCartItemDTO> carList) {
if (CollUtil.isEmpty(carList)) {
return 0;
}
int sum = 0;
for (CanteenDeliveryCartItemDTO c : carList) {
if (c == null) {
continue;
}
if (c.getTotalPrice() != null && StrUtil.isNotBlank(String.valueOf(c.getTotalPrice()))) {
try {
sum += Integer.parseInt(String.valueOf(c.getTotalPrice()).trim());
continue;
} catch (NumberFormatException ignored) {
}
}
int price = c.getProductPrice() != null ? c.getProductPrice() : 0;
int cnt = c.getProductCount() != null ? c.getProductCount() : 0;
sum += price * cnt;
}
return Math.max(0, sum);
}
private boolean isMerchantAccepted(CanteenDeliveryOrderEntity e) {
return e != null && Objects.equals(e.getMerchantAccepted(), 1);
}
private boolean isMerchantAutoAccept(String merchantId) {
if (StrUtil.isBlank(merchantId)) {
return false;
}
CanteenDeliveryAcceptSettingEntity row = acceptSettingMapper.selectOne(
Wrappers.<CanteenDeliveryAcceptSettingEntity>lambdaQuery()
.eq(CanteenDeliveryAcceptSettingEntity::getMerchantId, merchantId));
return row != null && Objects.equals(row.getAutoAccept(), 1);
}
private boolean isRiderAutoAccept(Long riderUserId) {
if (riderUserId == null) {
return false;
}
CanteenDeliveryAcceptSettingEntity row = acceptSettingMapper.selectOne(
Wrappers.<CanteenDeliveryAcceptSettingEntity>lambdaQuery()
.eq(CanteenDeliveryAcceptSettingEntity::getRiderUserId, riderUserId));
return row != null && Objects.equals(row.getAutoAccept(), 1);
}
private void saveMerchantAutoAcceptSetting(String merchantId, boolean autoAccept) {
CanteenDeliveryAcceptSettingEntity row = acceptSettingMapper.selectOne(
Wrappers.<CanteenDeliveryAcceptSettingEntity>lambdaQuery()
.eq(CanteenDeliveryAcceptSettingEntity::getMerchantId, merchantId));
if (row == null) {
row = new CanteenDeliveryAcceptSettingEntity();
row.setMerchantId(merchantId);
row.setAutoAccept(autoAccept ? 1 : 0);
acceptSettingMapper.insert(row);
return;
}
row.setAutoAccept(autoAccept ? 1 : 0);
acceptSettingMapper.updateById(row);
}
private void saveRiderAutoAcceptSetting(Long riderUserId, boolean autoAccept) {
CanteenDeliveryAcceptSettingEntity row = acceptSettingMapper.selectOne(
Wrappers.<CanteenDeliveryAcceptSettingEntity>lambdaQuery()
.eq(CanteenDeliveryAcceptSettingEntity::getRiderUserId, riderUserId));
if (row == null) {
row = new CanteenDeliveryAcceptSettingEntity();
row.setRiderUserId(riderUserId);
row.setAutoAccept(autoAccept ? 1 : 0);
acceptSettingMapper.insert(row);
return;
}
row.setAutoAccept(autoAccept ? 1 : 0);
acceptSettingMapper.updateById(row);
}
/**
* 来源订单号即硬件外卖订单主键(与同步时 dto.id 一致)。非数字则跳过(非硬件单)。
* 同步失败抛异常,触发事务回滚,避免本地状态与硬件订单不一致。
@@ -69,6 +69,13 @@ public interface RemoteWalletService {
@GetMapping("/wallet-manage/inner/is-use-door")
R<String> innserIsUseDoor(@RequestParam Long userId);
/**
* 商户配送费(分),供食堂外送派单时快照骑手佣金
*/
@NoToken
@GetMapping("/wallet-manage/inner/mch-take-out-amt")
R<Integer> innerMchTakeOutAmt(@RequestParam("merchantId") Long merchantId);
@NoToken
@PostMapping("/wallet-active/remote/open-card-list")
R<Page<WalletActiveEntity>> remoteOpenCardList(@RequestBody WalletRemoteOpenCardListDto body);
@@ -148,6 +148,20 @@ public class WalletManageController {
return R.ok(true);
}
@Inner
@GetMapping("/inner/mch-take-out-amt")
@Operation(summary = "内部-商户配送费(分)", description = "派单时快照骑手佣金;返回 mch_take_out_setting.mch_take_out_amt")
public R<Integer> innerMchTakeOutAmt(@RequestParam Long merchantId) {
if (merchantId == null) {
return R.ok(0);
}
MchTakeOutSettingEntity setting = walletManageService.getOrCreateTakeOut(merchantId);
if (setting == null || setting.getMchTakeOutAmt() == null) {
return R.ok(0);
}
return R.ok(Math.max(0, setting.getMchTakeOutAmt()));
}
@GetMapping("/dept-change")
public R<Boolean> deptChange(@RequestParam Long deptId, @RequestParam Boolean isDel) {
walletManageService.deptChange(deptId, isDel);