package cn.iocoder.yudao.module.order.service.order;

import cn.iocoder.yudao.framework.mybatis.core.service.IService;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dto.OrderBackInfoDto;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialApplyVO;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialBatchApplyVO;
import cn.iocoder.yudao.module.order.vo.order.OrderCreateReqVO;
import cn.iocoder.yudao.module.order.vo.order.OrderUpdateReqVO;
import cn.iocoder.yudao.module.order.vo.order.OrderWarehouseInVO;
import cn.iocoder.yudao.module.product.dto.FeeDto;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 订单 Service 接口
 *
 * @author 系统管理员
 */
public interface OrderService extends IService<OrderDO> {

    /**
     * 创建订单
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    OrderDO createOrder(OrderCreateReqVO createReqVO, MemberUserDO memberUserDO);

    /**
     * 更新订单
     *
     * @param updateReqVO 更新信息
     */
    void updateOrder(@Valid OrderUpdateReqVO updateReqVO, MemberUserDO memberUserDO);

    /**
     * 更新订单
     *
     * @param updateReqVO 更新信息
     */
    void updateOrderApply(@Valid OrderUpdateReqVO updateReqVO, MemberUserDO memberUserDO);


    /**
     * 订单入仓
     *
     * @param orderWarehouseInVO 入仓信息
     */
    OrderDO orderInWarehouse(@Valid OrderWarehouseInVO orderWarehouseInVO);

    /**
     * 合单-创建合并订单
     *
     * @param orderDO 订单信息
     */
    void mergeOrder(@Valid OrderDO orderDO);


    /**
     * 拆单-创建拆分后的订单
     *
     * @param orderDO 订单信息
     * @param msg     拆单日志描述，订单从xxx拆成xxx,xxxx,xxxxx
     */
    OrderDO splitOrder(@Valid OrderDO orderDO, String msg);


    /**
     * 修改订单状态
     *
     * @param orderId          订单ID 与订单号选择一个填写
     * @param orderNo          订单号 与订单ID选择一个填写
     * @param status           订单状态 订单主状态
     * @param abnormalState    订单异常状态 0 原始状态 (相关异常处理完时请传值 0)
     * @param inWarehouseState 入仓状态 0 原始状态
     * @param shipmentState    出货状态 0 原始状态
     * @param auditType        审核类型 0 原始状态 方便前端根据类型跳转相关的审批页面去处理相应的业务 (相关审批结束时请传值 0)
     * @param auditResult      审批结果(尽量精简的备注说明)
     * @return 0 无操作 1 生成预付异常
     */
    Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState,
                         Integer inWarehouseState, Integer shipmentState, Integer auditType, String auditResult);

    /**
     * 修改订单状态
     *
     * @param orderId              订单ID 与订单号选择一个填写
     * @param orderNo              订单号 与订单ID选择一个填写
     * @param status               订单状态 订单主状态
     * @param abnormalState        订单异常状态 0 原始状态 (相关异常处理完时请传值 0)
     * @param inWarehouseState     入仓状态 0 原始状态
     * @param shipmentState        出货状态 0 原始状态
     * @param auditType            审核类型 0 原始状态 方便前端根据类型跳转相关的审批页面去处理相应的业务 (相关审批结束时请传值 0)
     * @param auditResult          审批结果(尽量精简的备注说明)
     * @param isAddOrderOperateLog 是否纪录订单操作日志
     * @return 0 无操作 1 生成预付异常
     */
    Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer inWarehouseState,
                         Integer shipmentState, Integer auditType, String auditResult, boolean isAddOrderOperateLog);


    /**
     * 修改订单状态
     *
     * @param orderId          订单ID 与订单号选择一个填写
     * @param orderNo          订单号 与订单ID选择一个填写
     * @param status           订单状态 订单主状态
     * @param abnormalState    订单异常状态 0 原始状态 (相关异常处理完时请传值 0)
     * @param inWarehouseState 入仓状态 0 原始状态
     * @param shipmentState    出货状态 0 原始状态
     * @param auditType        审核类型 0 原始状态 方便前端根据类型跳转相关的审批页面去处理相应的业务 (相关审批结束时请传值 0)
     * @param auditResult      审批结果(尽量精简的备注说明)
     * @param date             更新时间
     * @param isAddOrderOperateLog             是否纪录订单操作日志
     * @return 0 无操作 1 生成预付异常
     */
    Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer inWarehouseState,
                         Integer shipmentState, Integer auditType, String auditResult, Date date, boolean isAddOrderOperateLog);


    /**
     * 修改订单状态
     *
     * @param orderId          订单ID 与订单号选择一个填写
     * @param orderNo          订单号 与订单ID选择一个填写
     * @param status           订单状态 订单主状态
     * @param abnormalState    订单异常状态 0 原始状态 (相关异常处理完时请传值 0)
     * @param inWarehouseState 入仓状态 0 原始状态
     * @param shipmentState    出货状态 0 原始状态
     * @param auditType        审核类型 0 原始状态 方便前端根据类型跳转相关的审批页面去处理相应的业务 (相关审批结束时请传值 0)
     * @param auditResult      审批结果(尽量精简的备注说明)
     * @param date             更新时间
     * @param isAddOrderOperateLog             是否纪录订单操作日志
     * @param hasExit       是否退场入仓 1 是 0 否
     * @return 0 无操作 1 生成预付异常
     */
    Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer inWarehouseState,
                         Integer shipmentState, Integer auditType, String auditResult, Date date, boolean isAddOrderOperateLog, Integer hasExit)
    ;

    /**
     * 修改订单状态
     *
     * @param orderId          订单ID 与订单号选择一个填写
     * @param orderNo          订单号 与订单ID选择一个填写
     * @param status           订单状态 订单主状态
     * @param abnormalState    订单异常状态 0 原始状态 (相关异常处理完时请传值 0)
     * @param inWarehouseState 入仓状态 0 原始状态
     * @param shipmentState    出货状态 0 原始状态
     * @param auditType        审核类型 0 原始状态 方便前端根据类型跳转相关的审批页面去处理相应的业务 (相关审批结束时请传值 0)
     * @param auditResult      审批结果(尽量精简的备注说明)
     * @param date             更新时间
     * @param type             操作类型
     * @param note             更新备注
     * @return 0 无操作 1 生成预付异常
     */
    Integer updateStatus(Long orderId, String orderNo, Integer status, Integer abnormalState, Integer inWarehouseState,
                         Integer shipmentState, Integer auditType, String auditResult, Date date, String type, String note);


    /**
     * 取消关联订单，更新订单状态
     *
     * @param orderId       订单id
     * @param relateOrderId 取消的关联订单id
     */
    void cancelGuanlianOrderStatus(Long orderId, Long relateOrderId);

    /**
     * 更新关联当前订单的上级所有订单的关联状态
     *
     * @param currentOrderDO 当前订单
     */
    void updateGuanlianOrderStatus(OrderDO currentOrderDO)
    ;


    /**
     * 更新订单类型
     *
     * @param orderId   订单ID
     * @param orderType 订单项类型
     */
    void updateOrderType(Long orderId, Integer orderType);


    /**
     * 特价申请管理
     *
     * @param specialApplyVO 特价申请信息
     */
    void specialApplyOrder(OrderSpecialApplyVO specialApplyVO);

    /**
     * 批量特价申请
     *
     * @param specialBatchApplyVO
     */
    void specialBatchApplyOrder(OrderSpecialBatchApplyVO specialBatchApplyVO);

    /**
     * 取消特价申请
     *
     * @param approveId 业务ID
     * @return 取消特价申请
     */
    void cancelOrderSpecialApproval(Long approveId, String reason);


    /**
     * @param approveId 表单业务ID
     * @param result    1 处理中  2 通过 3 不通过 4 已取消
     */
    void approvalOrder(String approveId, Integer result);

    /**
     * 删除订单
     *
     * @param orderId 编号
     */
    void deleteOrder(Long orderId);

    /**
     * 撤销拆单删除子订单
     *
     * @param parentOrderId        编号
     * @param orderBackInfoDtoList 母订单下的所有相关子拆单信息
     */
    void deleteOrderByParentOrderId(Long parentOrderId, List<OrderBackInfoDto> orderBackInfoDtoList);

    /**
     * 恢复订单
     *
     * @param orderId 订单ID
     */
    void recoveryOrder(Long orderId);

    /**
     * 取消订单
     *
     * @param orderId 订单ID
     */
    void cancelOrder(Long orderId);


    /**
     * 添加订单其他费用
     *
     * @param orderId    订单ID
     * @param feeDtoList 其他费用列表(参数根据货币分开)
     */
    void addOrderOtherFee(Long orderId, List<FeeDto> feeDtoList);


    /**
     * 更新订单提单号
     *
     * @param orderId           订单ID
     * @param orderLadingBillNo 提单号
     */
    void updateLadingBillNo(Long orderId, String orderLadingBillNo);

    void updateAdjustWarehouseId(Long orderId, Long adjustToStartWarehouseId, Long adjustToDestWarehouseId);

    void updateDestAdjustWarehouseId(Long orderId, Long destAdjustToStartWarehouseId, Long destAdjustToDestWarehouseId);

    /**
     * 完成订单入仓时对订单进行重新计价
     *
     * @param orderId 订单ID
     */
    void finishOrderWarehouseIn(Long orderId);

    /**
     * 完成订单入仓修改时对订单进行重新计价
     *
     * @param orderId 订单ID
     */
    void finishOrderWarehouseInUpdate(Long orderId);


    /**
     * 空运订单分拣审批通过锁定价格，参数二选一
     *
     * @param containerNumber 自编号
     * @param orderIds 订单id列表
     */
    void finishOrderSorting(String containerNumber, Collection<Long> orderIds);
    /**
     * 空运订单分拣反审解除锁定价格，参数二选一
     *
     * @param containerNumber 自编号
     * @param orderIds 订单id列表
     */
    void finishOrderSortingReverseReviewUnlock(String containerNumber, Collection<Long> orderIds);


    /**
     * 手动更新订单价格(谨慎执行)
     *
     * @param orderNumbers 订单编号列表
     * @param isResetPrice 是否强制重订价
     */
    void updateOrderPrice(List<String> orderNumbers, Boolean isResetPrice);

    /**
     * 手动更新订单关联状态
     *
     * @param orderNumbers 订单编号列表
     */
    void updateGuanlianOrderStatus(List<String> orderNumbers);


    /**
     * 活动订单应收未核销数量
     *
     * @param orderIds 订单id列表
     * @return
     */
    long getUnWriteOffCount(Collection<Long> orderIds);


    /**
     * 空运订单可出操作
     *
     * @param orderId 订单ID
     */
    void airCan(Long orderId);

    void orderCouponUpdate(OrderDO orderDO, String msg);

    /**
     * 空运订单修改为不可出
     *
     * @param orderId 订单ID
     */
    void airNotCan(Long orderId);


    /**
     * 更新前一次打包的统计数据。其实就是将当前的入仓数据更新为次一次的统计数据
     *
     * @param orderId
     */
    void updateSumDataPrevPacked(Long orderId);

    Long getOrderIdByOrderNo( String  orderNo);

    /*
     更新订单业绩类型 yeji_type,yeji_create_date,cal_v_value
     lanbm 2024-05-13 add
     yejiType 0是老客户业界，1 是新客户业绩
     */
    void UpdateOrderYeJiType(Long orderId,int yejiType);


    /*
     更新订单V值 lanbm 2024-05-13 add
     yeji_create_date 业绩产生时间
     */
    void UpdateOrderVValue( Long orderId, BigDecimal calVvalue, Date
            yejiCreateDate);


}
