Browse Source

新配送订单管理接口

admin 1 month ago
parent
commit
d15fe8d130

+ 145 - 0
client-app/src/main/java/com/sapit/client/app/manage/controller/rider/DeliveryOrderManageController1.java

@@ -0,0 +1,145 @@
+package com.sapit.client.app.manage.controller.rider;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.sapit.client.app.manage.service.rider.DeliveryOrderManageService1;
+import com.sapit.common.bean.mobile.SettingBean;
+import com.sapit.common.bean.order.DeliveryOrderBean;
+import com.sapit.common.bean.order.DeliveryOrderCountBean;
+import com.sapit.common.constant.ReturnCode;
+import com.sapit.common.framwork.AuthToken;
+import com.sapit.common.framwork.PageControlData;
+import com.sapit.common.framwork.ResultBean;
+import com.sapit.common.search.order.BuOrderSearchBean;
+
+
+@RestController
+@RequestMapping(value = "deliveryOrderManage1", produces = "application/json")
+public class DeliveryOrderManageController1 {
+	// 日志输出
+	static final Logger log = LoggerFactory.getLogger(DeliveryOrderManageController1.class);
+
+	@Autowired
+	private DeliveryOrderManageService1 deliveryOrderManageService1;
+
+	/**
+	 * 方法名称:获取配送订单列表
+	 * 功能描述:返回统计数据、系统设置、订单列表、分页信息
+	 */
+	@PostMapping(value = "/getDeliveryOrderList")
+	@AuthToken(type = "admin")
+	public ResultBean getDeliveryOrderList(BuOrderSearchBean sb, PageControlData page) {
+		ResultBean bean = new ResultBean();
+
+		DeliveryOrderCountBean countBean = deliveryOrderManageService1.getDeliveryOrderCount(sb);
+		List<DeliveryOrderBean> list = deliveryOrderManageService1.getDeliveryOrderList(page, sb);
+		SettingBean setting = deliveryOrderManageService1.getSetting();
+
+		bean.setObj(countBean);
+		bean.setObj1(setting);
+		bean.setList(list);
+		bean.setPage(page);
+
+		return bean;
+	}
+
+	/**
+	 * 获取门店列表
+	 * @return
+	 */
+	@PostMapping(value = "/getStoreList")
+	@AuthToken(type = "admin")
+	public ResultBean getStoreList() {
+		ResultBean bean = new ResultBean();
+		List<Object[]> list = deliveryOrderManageService1.getStoreList();
+
+		// 转为Map列表返回
+		List<Map<String, Object>> storeList = new java.util.ArrayList<>();
+		for (Object[] obj : list) {
+			Map<String, Object> map = new HashMap<>();
+			map.put("storeId", obj[0]);
+			map.put("storeName", obj[1]);
+			storeList.add(map);
+		}
+		bean.setList(storeList);
+		return bean;
+	}
+
+	/**
+	 * 获取配送员列表
+	 * @param status
+	 * @param isInside
+	 * @param type
+	 * @return
+	 */
+	@PostMapping(value = "/getRiderListNoPage")
+	@AuthToken(type = "admin")
+	public ResultBean getRiderListNoPage(Long status, Long isInside, Long type) {
+		ResultBean bean = new ResultBean();
+		List<Object[]> list = deliveryOrderManageService1.getRiderList(status, isInside, type);
+
+		// 转为Map列表返回
+		List<Map<String, Object>> riderList = new java.util.ArrayList<>();
+		for (Object[] obj : list) {
+			Map<String, Object> map = new HashMap<>();
+			map.put("riderId", obj[0]);
+			map.put("riderName", obj[1]);
+			riderList.add(map);
+		}
+		bean.setList(riderList);
+		return bean;
+	}
+
+	/**
+	 * 更新订单状态
+	 * @param id
+	 * @return
+	 */
+	@PostMapping(value = "/updateOrderFinish")
+	@AuthToken(type = "admin")
+	public ResultBean updateOrderFinish(Long id) {
+		ResultBean bean = new ResultBean();
+		if (id == null) {
+			bean.getRtnBean().setRtnCode(ReturnCode.PARAM_WRONG);
+			bean.getRtnBean().setRtnMsg("参数错误!");
+		} else {
+			if (!deliveryOrderManageService1.updateOrderFinish(id)) {
+				bean.getRtnBean().setRtnCode(ReturnCode.SYSTEMERR);
+				bean.getRtnBean().setRtnMsg("配送状态已变更,不能执行该操作!");
+			}
+		}
+		return bean;
+	}
+
+	/**
+	 * 分配配送员
+	 * @param orderId
+	 * @param riderId
+	 * @param status
+	 * @return
+	 */
+	@PostMapping(value = "/allocationOrder")
+	@AuthToken(type = "admin")
+	public ResultBean allocationOrder(Long orderId, Long riderId, Long status) {
+		ResultBean bean = new ResultBean();
+		if (orderId == null) {
+			bean.getRtnBean().setRtnCode(ReturnCode.PARAM_WRONG);
+			bean.getRtnBean().setRtnMsg("参数错误!");
+		} else {
+			if (!deliveryOrderManageService1.allocationOrder(orderId, riderId, status)) {
+				bean.getRtnBean().setRtnCode(ReturnCode.SYSTEMERR);
+				bean.getRtnBean().setRtnMsg("配送状态已变更,不能执行该操作!");
+			}
+		}
+		return bean;
+	}
+}

+ 127 - 0
client-app/src/main/java/com/sapit/client/app/manage/service/rider/DeliveryOrderManageService1.java

@@ -0,0 +1,127 @@
+package com.sapit.client.app.manage.service.rider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.sapit.client.app.persistence.delivery.DeliveryOrderManageDao;
+import com.sapit.common.bean.order.DeliveryOrderBean;
+import com.sapit.common.bean.order.DeliveryOrderCountBean;
+import com.sapit.common.bean.mobile.SettingBean;
+import com.sapit.common.constant.OrderProcessStatus;
+import com.sapit.common.framwork.PageControlData;
+import com.sapit.common.search.order.BuOrderSearchBean;
+
+/**
+ * 类名称:配送订单管理服务类(优化版)
+ * 类描述:基于冗余字段优化的配送订单管理,主查询仅需2张表1次JOIN
+ * 
+ * 作  者:AI
+ * 日  期:2026-08-05
+ */
+@Service
+@Transactional
+public class DeliveryOrderManageService1 {
+
+	@Autowired
+	private DeliveryOrderManageDao deliveryOrderManageDao;
+
+	/**
+	 * 方法名称:获取配送订单统计件数
+	 */
+	public DeliveryOrderCountBean getDeliveryOrderCount(BuOrderSearchBean sb) {
+		return deliveryOrderManageDao.getDeliveryOrderCount(sb);
+	}
+
+	/**
+	 * 方法名称:获取配送订单列表
+	 */
+	public List<DeliveryOrderBean> getDeliveryOrderList(PageControlData page, BuOrderSearchBean sb) {
+		return deliveryOrderManageDao.getDeliveryOrderList(page, sb);
+	}
+
+	/**
+	 * 方法名称:获取门店列表(下拉框)
+	 */
+	public List<Object[]> getStoreList() {
+		return deliveryOrderManageDao.getStoreList();
+	}
+
+	/**
+	 * 方法名称:获取骑手列表(指派弹窗)
+	 */
+	public List<Object[]> getRiderList(Long status, Long isInside, Long type) {
+		return deliveryOrderManageDao.getRiderList(status, isInside, type);
+	}
+
+	/**
+	 * 方法名称:获取系统设置
+	 */
+	public SettingBean getSetting() {
+		return deliveryOrderManageDao.getSetting();
+	}
+
+	/**
+	 * 方法名称:将订单设置为完成
+	 */
+	public boolean updateOrderFinish(Long id) {
+		if (deliveryOrderManageDao.updateProgressFinish(id)) {
+			return deliveryOrderManageDao.updateOrderFinish(id);
+		}
+		return false;
+	}
+
+	/**
+	 * 方法名称:给订单分配骑手
+	 * 功能描述:根据当前配送状态执行不同操作
+	 *   status=20(待取餐)→ 指派取餐员,状态变为30
+	 *   status=30(已取餐)→ 转单配送,状态变为50
+	 *   status=40(已分拣)→ 开始配送,状态变为50
+	 *   status=50(配送中)→ 送达楼下,状态变为60
+	 *   status=60(送达楼下)→ 上楼,状态变为70
+	 *   status=70(爬楼中)→ 完成,状态变为80
+	 */
+	public boolean allocationOrder(Long orderId, Long riderId, Long status) {
+		if (status == null || orderId == null) {
+			return false;
+		}
+
+		// 获取骑手信息(冗余写入需要)
+		Object[] riderInfo = null;
+		String riderName = null;
+		Long isInside = null;
+		Long riderType = null;
+		if (riderId != null) {
+			riderInfo = deliveryOrderManageDao.getRiderById(riderId);
+			if (riderInfo != null) {
+				riderName = riderInfo[1] == null ? null : riderInfo[1].toString();
+				isInside = riderInfo[2] == null ? null : Long.valueOf(riderInfo[2].toString());
+				riderType = riderInfo[3] == null ? null : Long.valueOf(riderInfo[3].toString());
+			}
+		}
+
+		if (status.equals(OrderProcessStatus.DINED)) {
+			// status=20 待取餐 → 指派取餐员,状态变为30
+			return deliveryOrderManageDao.allocationWaiter(orderId, riderId, riderName, isInside, riderType);
+		} else if (status.equals(OrderProcessStatus.TACKED)) {
+			// status=30 已取餐 → 转单配送,状态变为50
+			return deliveryOrderManageDao.allocationRider(orderId, riderId, riderName, isInside, riderType);
+		} else if (status.equals(OrderProcessStatus.COMPLETED)) {
+			// status=40 已分拣 → 开始配送,状态变为50
+			return deliveryOrderManageDao.startDelivery(orderId);
+		} else if (status.equals(OrderProcessStatus.DELIVERING)) {
+			// status=50 配送中 → 送达楼下,状态变为60
+			return deliveryOrderManageDao.arriveDownstairs(orderId);
+		} else if (status.equals(OrderProcessStatus.DOWNSTAIRS)) {
+			// status=60 送达楼下 → 上楼,状态变为70
+			return deliveryOrderManageDao.goUpstairs(orderId, riderId, riderName);
+		} else if (status.equals(OrderProcessStatus.UPING)) {
+			// status=70 爬楼中 → 完成,状态变为80
+			return deliveryOrderManageDao.finishOrder(orderId);
+		}
+		return false;
+	}
+}

+ 395 - 0
client-app/src/main/java/com/sapit/client/app/persistence/delivery/DeliveryOrderManageDao.java

@@ -0,0 +1,395 @@
+package com.sapit.client.app.persistence.delivery;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.sapit.common.bean.order.DeliveryOrderBean;
+import com.sapit.common.bean.order.DeliveryOrderCountBean;
+import com.sapit.common.bean.mobile.SettingBean;
+import com.sapit.common.constant.OrderProcessStatus;
+import com.sapit.common.framwork.BaseDao;
+import com.sapit.common.framwork.PageControlData;
+import com.sapit.common.search.order.BuOrderSearchBean;
+import com.sapit.common.util.StringUtil;
+
+/**
+ * 类名称:配送订单管理DAO(优化版,使用delivery_前缀表)
+ * 类描述:基于冗余字段优化,主查询仅需2张表1次JOIN
+ * 
+ * 作  者:AI
+ * 日  期:2026-08-05
+ */
+@SuppressWarnings("rawtypes")
+@Repository
+public class DeliveryOrderManageDao extends BaseDao {
+
+	/**
+	 * 方法名称:获取配送订单统计件数
+	 * 功能描述:按配送状态分组统计各状态订单数量
+	 */
+	@SuppressWarnings("unchecked")
+	public DeliveryOrderCountBean getDeliveryOrderCount(BuOrderSearchBean sb) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select count(*), ifnull(p.STATUS, 0)")
+			.append(" from delivery_order o")
+			.append(" left join delivery_order_progress p on o.ORDER_ID = p.ORDER_ID")
+			.append(" where o.STATUS > 0 and o.ORDER_TYPE < 3 ");
+
+		// 拼接搜索条件
+		this.appendSearchCondition(sql, sb);
+
+		sql.append(" group by p.STATUS");
+
+		List<Object> list = this.searchBySql(sql.toString());
+		DeliveryOrderCountBean bean = new DeliveryOrderCountBean();
+		for (int i = 0; i < list.size(); i++) {
+			Object[] obj = (Object[]) list.get(i);
+			if (OrderProcessStatus.RECEIVED.equals(Long.valueOf(obj[1].toString()))) {
+				bean.setReceivedCount(Long.valueOf(obj[0].toString()));
+			} else if (OrderProcessStatus.DINED.equals(Long.valueOf(obj[1].toString()))) {
+				bean.setDinedCount(Long.valueOf(obj[0].toString()));
+			} else if (OrderProcessStatus.TACKED.equals(Long.valueOf(obj[1].toString()))) {
+				bean.setComplitedCount(Long.valueOf(obj[0].toString()));
+			} else if (OrderProcessStatus.COMPLETED.equals(Long.valueOf(obj[1].toString())) ||
+					OrderProcessStatus.DELIVERING.equals(Long.valueOf(obj[1].toString())) ||
+					OrderProcessStatus.DOWNSTAIRS.equals(Long.valueOf(obj[1].toString())) ||
+					OrderProcessStatus.UPING.equals(Long.valueOf(obj[1].toString()))) {
+				bean.setDeliveringCount(bean.getDeliveringCount() + Long.valueOf(obj[0].toString()));
+			}
+		}
+		return bean;
+	}
+
+	/**
+	 * 方法名称:获取配送订单列表(优化版,1次JOIN)
+	 * 功能描述:查询配送订单列表,仅需2张表
+	 */
+	@SuppressWarnings("unchecked")
+	public List<DeliveryOrderBean> getDeliveryOrderList(PageControlData page, BuOrderSearchBean sb) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select o.ORDER_ID, o.TAKEUP_CODE, o.ORDER_CODE, o.STORE_ID, o.STORE_NAME,")
+			.append(" o.ADDRESS_ID, o.ORDER_ADDRESS, o.ROOM_NUMBER, o.ORDER_FEE, o.ORDER_NAME, o.ORDER_TEL,")
+			.append(" o.ORDER_TYPE, o.PAY_DATE, o.STATUS,")
+			.append(" p.STATUS AS PROCESS_STATUS,")
+			.append(" p.WAITER_NAME, p.RIDER_NAME, p.CLIMB_NAME,")
+			.append(" TIMESTAMPDIFF(MINUTE, p.RECEIVE_ORDER_DATE, p.DONE_MEAL_DATE),")
+			.append(" TIMESTAMPDIFF(MINUTE, p.DONE_MEAL_DATE, p.TRANSFER_DATE),")
+			.append(" TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.DOWNSTAIRS_DATE),")
+			.append(" TIMESTAMPDIFF(MINUTE, p.DOWNSTAIRS_DATE, p.COMPLETE_DATE),")
+			.append(" o.REQUIRE_DATE,")
+			.append(" TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.COMPLETE_DATE),")
+			.append(" o.SORTING_FEE, o.DELIVERY_FEE, o.CLIMBING_FEE,")
+			.append(" p.IS_INSIDE, p.RIDER_TYPE, o.DONE_MEAL_TIME")
+			.append(" from delivery_order o")
+			.append(" left join delivery_order_progress p on o.ORDER_ID = p.ORDER_ID")
+			.append(" where (o.STATUS > 0 OR o.STATUS = -50) AND o.ORDER_TYPE < 3");
+
+		// 拼接搜索条件
+		this.appendSearchConditionList(sql, sb);
+
+		sql.append(" order by o.ORDER_ID desc");
+
+		List<Object> list = this.searchBySql(page, sql.toString());
+		List<DeliveryOrderBean> deliveryOrderBeanList = new ArrayList<>();
+		for (int i = 0; i < list.size(); i++) {
+			Object[] obj = (Object[]) list.get(i);
+			DeliveryOrderBean bean = new DeliveryOrderBean();
+			bean.setOrderId(obj[0] == null ? null : Long.valueOf(obj[0].toString()));
+			bean.setTakeupCode(obj[1] == null ? null : obj[1].toString());
+			bean.setOrderCode(obj[2] == null ? null : obj[2].toString());
+			bean.setStoreId(obj[3] == null ? null : Long.valueOf(obj[3].toString()));
+			bean.setStoreName(obj[4] == null ? null : obj[4].toString());
+			bean.setFullName(obj[6] == null ? null : obj[6].toString());
+			bean.setRoomNumber(obj[7] == null ? null : obj[7].toString());
+			bean.setOrderFee(obj[8] == null ? null : Long.valueOf(obj[8].toString()));
+			bean.setOrderName(obj[9] == null ? null : obj[9].toString());
+			bean.setOrderTel(obj[10] == null ? null : obj[10].toString());
+			bean.setOrderType(obj[11] == null ? null : Long.valueOf(obj[11].toString()));
+			bean.setPayDate(obj[12] == null ? null : Timestamp.valueOf(obj[12].toString()));
+			bean.setStatus(obj[13] == null ? null : Long.valueOf(obj[13].toString()));
+			bean.setProcessStatus(obj[14] == null ? null : Long.valueOf(obj[14].toString()));
+			bean.setWaiterName(obj[15] == null ? null : obj[15].toString());
+			bean.setRiderName(obj[16] == null ? null : obj[16].toString());
+			bean.setClimbName(obj[17] == null ? null : obj[17].toString());
+			bean.setPickOutDuration(obj[18] == null ? null : Long.valueOf(obj[18].toString()));
+			bean.setTransferDuration(obj[19] == null ? null : Long.valueOf(obj[19].toString()));
+			bean.setDeliveryDuration(obj[20] == null ? null : Long.valueOf(obj[20].toString()));
+			bean.setClimbDuration(obj[21] == null ? null : Long.valueOf(obj[21].toString()));
+			bean.setRequireDate(obj[22] == null ? null : Timestamp.valueOf(obj[22].toString()));
+			bean.setSortingFee(obj[24] == null ? null : Long.valueOf(obj[24].toString()));
+			bean.setDeliveryFee(obj[25] == null ? null : Long.valueOf(obj[25].toString()));
+			bean.setClimbingFee(obj[26] == null ? null : Long.valueOf(obj[26].toString()));
+			bean.setIsInside(obj[27] == null ? null : Long.valueOf(obj[27].toString()));
+			bean.setDeliveryType(obj[28] == null ? null : Long.valueOf(obj[28].toString()));
+			bean.setDoneMealTime(obj[29] == null ? null : Long.valueOf(obj[29].toString()));
+			deliveryOrderBeanList.add(bean);
+		}
+		return deliveryOrderBeanList;
+	}
+
+	/**
+	 * 方法名称:获取门店列表(下拉框)
+	 */
+	@SuppressWarnings("unchecked")
+	public List<Object[]> getStoreList() {
+		String sql = "SELECT STORE_ID, STORE_NAME FROM bu_store WHERE STATUS = 1";
+		return this.searchBySql(sql);
+	}
+
+	/**
+	 * 方法名称:获取骑手列表(指派弹窗,不分页)
+	 */
+	@SuppressWarnings("unchecked")
+	public List<Object[]> getRiderList(Long status, Long isInside, Long type) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("SELECT RIDER_ID, RIDER_NAME FROM bu_rider WHERE 1=1");
+		if (status != null) {
+			sql.append(" AND STATUS = ").append(status);
+		}
+		if (isInside != null) {
+			sql.append(" AND IS_INSIDE = ").append(isInside);
+		}
+		if (type != null) {
+			sql.append(" AND RIDER_TYPE = ").append(type);
+		}
+		return this.searchBySql(sql.toString());
+	}
+
+	/**
+	 * 方法名称:获取系统设置
+	 */
+	@SuppressWarnings("unchecked")
+	public SettingBean getSetting() {
+		String sql = "SELECT SETTING_ID, TAKE_FOOD_TIME, RIDER_TIME, CLIMB_TIME, TAKE_PRICE, RIDER_PRICE, CLIMB_PRICE FROM bu_setting LIMIT 1";
+		List<Object> list = this.searchBySql(sql);
+		if (list != null && !list.isEmpty()) {
+			Object[] obj = (Object[]) list.get(0);
+			SettingBean bean = new SettingBean();
+			bean.setTakeFoodTime(obj[1] == null ? null : Long.valueOf(obj[1].toString()));
+			bean.setRiderTime(obj[2] == null ? null : Long.valueOf(obj[2].toString()));
+			bean.setClimbTime(obj[3] == null ? null : Long.valueOf(obj[3].toString()));
+			bean.setTakePrice(obj[4] == null ? null : Long.valueOf(obj[4].toString()));
+			bean.setRiderPrice(obj[5] == null ? null : Long.valueOf(obj[5].toString()));
+			bean.setClimbPrice(obj[6] == null ? null : Long.valueOf(obj[6].toString()));
+			return bean;
+		}
+		return null;
+	}
+
+	/**
+	 * 方法名称:将订单设置为完成
+	 */
+	@Transactional
+	public boolean updateOrderFinish(Long id) {
+		String sql = "UPDATE delivery_order SET STATUS=60 WHERE ORDER_ID=" + id + " AND STATUS > 20 AND STATUS < 60";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:更新订单进度为完成
+	 */
+	@Transactional
+	public boolean updateProgressFinish(Long orderId) {
+		String sql = "UPDATE delivery_order_progress SET STATUS=80, COMPLETE_DATE=now() WHERE ORDER_ID=" + orderId;
+		return (this.executeSql(sql) >= 1);
+	}
+
+	/**
+	 * 方法名称:指派取餐员(状态20→30)
+	 */
+	@Transactional
+	public boolean allocationWaiter(Long orderId, Long riderId, String riderName, Long isInside, Long riderType) {
+		String sql = "UPDATE delivery_order_progress SET WAITER_ID=" + riderId
+				+ ", WAITER_NAME='" + riderName + "'"
+				+ ", IS_INSIDE=" + (isInside == null ? "NULL" : isInside)
+				+ ", RIDER_TYPE=" + (riderType == null ? "NULL" : riderType)
+				+ ", STATUS=30, TRANSFER_DATE=now()"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS=20";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:转单-配送(状态30→40→50)
+	 */
+	@Transactional
+	public boolean allocationRider(Long orderId, Long riderId, String riderName, Long isInside, Long riderType) {
+		String sql = "UPDATE delivery_order_progress SET RIDER_ID=" + riderId
+				+ ", RIDER_NAME='" + riderName + "'"
+				+ ", IS_INSIDE=" + (isInside == null ? "NULL" : isInside)
+				+ ", RIDER_TYPE=" + (riderType == null ? "NULL" : riderType)
+				+ ", STATUS=50"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS=30";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:配送(状态40→50)
+	 */
+	@Transactional
+	public boolean startDelivery(Long orderId) {
+		String sql = "UPDATE delivery_order_progress SET STATUS=50"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS=40";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:送达楼下(状态50→60)
+	 */
+	@Transactional
+	public boolean arriveDownstairs(Long orderId) {
+		String sql = "UPDATE delivery_order_progress SET STATUS=60, DOWNSTAIRS_DATE=now()"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS=50";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:上楼(状态60→70)
+	 */
+	@Transactional
+	public boolean goUpstairs(Long orderId, Long riderId, String riderName) {
+		String sql = "UPDATE delivery_order_progress SET CLIMB_STAIRS_ID=" + riderId
+				+ ", CLIMB_NAME='" + riderName + "'"
+				+ ", STATUS=70"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS=60";
+		return (this.executeSql(sql) == 1);
+	}
+
+	/**
+	 * 方法名称:完成(状态70/50→80)
+	 */
+	@Transactional
+	public boolean finishOrder(Long orderId) {
+		// 更新进度状态
+		String sqlProgress = "UPDATE delivery_order_progress SET STATUS=80, COMPLETE_DATE=now()"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS IN (70, 50)";
+		this.executeSql(sqlProgress);
+		// 更新订单状态
+		String sqlOrder = "UPDATE delivery_order SET STATUS=60"
+				+ " WHERE ORDER_ID=" + orderId + " AND STATUS > 0 AND STATUS < 60";
+		return (this.executeSql(sqlOrder) == 1);
+	}
+
+	/**
+	 * 方法名称:根据骑手ID获取骑手信息
+	 */
+	@SuppressWarnings("unchecked")
+	public Object[] getRiderById(Long riderId) {
+		String sql = "SELECT RIDER_ID, RIDER_NAME, IS_INSIDE, RIDER_TYPE FROM bu_rider WHERE RIDER_ID=" + riderId;
+		List<Object> list = this.searchBySql(sql);
+		if (list != null && !list.isEmpty()) {
+			return (Object[]) list.get(0);
+		}
+		return null;
+	}
+
+	/**
+	 * 拼接搜索条件(统计查询用)
+	 */
+	private void appendSearchCondition(StringBuilder sql, BuOrderSearchBean sb) {
+		if (sb.getStoreId() != null) {
+			sql.append(" and o.STORE_ID=").append(sb.getStoreId());
+		}
+		if (sb.getAddressId() != null) {
+			sql.append(" and o.ADDRESS_ID=").append(sb.getAddressId());
+		}
+		if (!StringUtil.isBlank(sb.getOrderCode())) {
+			sql.append(" and o.ORDER_CODE='").append(sb.getOrderCode()).append("'");
+		}
+		if (!StringUtil.isBlank(sb.getWaiterName())) {
+				sql.append(" and p.WAITER_NAME like '%").append(sb.getWaiterName()).append("%'");
+			}
+			if (!StringUtil.isBlank(sb.getRiderName())) {
+				sql.append(" and p.RIDER_NAME like '%").append(sb.getRiderName()).append("%'");
+			}
+			if (!StringUtil.isBlank(sb.getClimbName())) {
+				sql.append(" and p.CLIMB_NAME like '%").append(sb.getClimbName()).append("%'");
+			}
+			if (sb.getMakeTimeStart() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.RECEIVE_ORDER_DATE, p.DONE_MEAL_DATE) >=").append(sb.getMakeTimeStart());
+			}
+			if (sb.getMakeTimeEnd() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.RECEIVE_ORDER_DATE, p.DONE_MEAL_DATE) <=").append(sb.getMakeTimeEnd());
+			}
+			if (sb.getGetTimeStart() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.DONE_MEAL_DATE, p.TRANSFER_DATE) >=").append(sb.getGetTimeStart());
+			}
+			if (sb.getGetTimeEnd() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.DONE_MEAL_DATE, p.TRANSFER_DATE) <=").append(sb.getGetTimeEnd());
+			}
+			if (sb.getSendTimeStart() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.DOWNSTAIRS_DATE) >=").append(sb.getSendTimeStart());
+			}
+			if (sb.getSendTimeEnd() != null) {
+				sql.append(" and TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.DOWNSTAIRS_DATE) <=").append(sb.getSendTimeEnd());
+			}
+		}
+
+	/**
+	 * 拼接搜索条件(列表查询用,包含更多条件)
+	 */
+	private void appendSearchConditionList(StringBuilder sql, BuOrderSearchBean sb) {
+		if (sb.getStatus() != null) {
+			if (sb.getStatus() == 40) {
+				sql.append(" and p.STATUS>=40 and p.STATUS<=70");
+			} else {
+				sql.append(" and p.STATUS=").append(sb.getStatus());
+			}
+		}
+		if (StringUtils.isNotBlank(sb.getsDateWss())) {
+			sql.append(" AND date_format(o.CREATE_DATE,'%Y/%m/%d') >= '").append(sb.getsDateWss()).append("'");
+		}
+		if (StringUtils.isNotBlank(sb.geteDateWss())) {
+			sql.append(" AND date_format(o.CREATE_DATE,'%Y/%m/%d') <= '").append(sb.geteDateWss()).append("'");
+		}
+		if (sb.getOrderType() != null) {
+			sql.append(" and o.ORDER_TYPE = ").append(sb.getOrderType());
+		}
+		if (sb.getStoreId() != null) {
+			sql.append(" and o.STORE_ID=").append(sb.getStoreId());
+		}
+		if (sb.getAddressId() != null) {
+			sql.append(" and o.ADDRESS_ID=").append(sb.getAddressId());
+		}
+		if (!StringUtil.isBlank(sb.getOrderCode())) {
+			sql.append(" and o.ORDER_CODE like '%").append(sb.getOrderCode()).append("%'");
+		}
+		if (!StringUtil.isBlank(sb.getWaiterName())) {
+				sql.append(" and p.WAITER_NAME like '%").append(sb.getWaiterName()).append("%'");
+			}
+			if (!StringUtil.isBlank(sb.getRiderName())) {
+				sql.append(" and p.RIDER_NAME like '%").append(sb.getRiderName()).append("%'");
+			}
+			if (!StringUtil.isBlank(sb.getClimbName())) {
+				sql.append(" and p.CLIMB_NAME like '%").append(sb.getClimbName()).append("%'");
+			}
+			if (StringUtils.isNotBlank(sb.getOrderName())) {
+			sql.append(" and o.ORDER_NAME like '%").append(sb.getOrderName()).append("%'");
+		}
+		if (StringUtils.isNotBlank(sb.getOrderTel())) {
+			sql.append(" and o.ORDER_TEL like '%").append(sb.getOrderTel()).append("%'");
+		}
+		if (sb.getMakeTimeStart() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.RECEIVE_ORDER_DATE, p.DONE_MEAL_DATE) >=").append(sb.getMakeTimeStart());
+		}
+		if (sb.getMakeTimeEnd() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.RECEIVE_ORDER_DATE, p.DONE_MEAL_DATE) <=").append(sb.getMakeTimeEnd());
+		}
+		if (sb.getGetTimeStart() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.DONE_MEAL_DATE, p.TRANSFER_DATE) >=").append(sb.getGetTimeStart());
+		}
+		if (sb.getGetTimeEnd() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.DONE_MEAL_DATE, p.TRANSFER_DATE) <=").append(sb.getGetTimeEnd());
+		}
+		if (sb.getSendTimeStart() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.DOWNSTAIRS_DATE) >=").append(sb.getSendTimeStart());
+		}
+		if (sb.getSendTimeEnd() != null) {
+			sql.append(" and TIMESTAMPDIFF(MINUTE, p.TRANSFER_DATE, p.DOWNSTAIRS_DATE) <=").append(sb.getSendTimeEnd());
+		}
+	}
+}