Quellcode durchsuchen

外部订单管理

wangxy vor 3 Wochen
Ursprung
Commit
709d5a51cd

+ 79 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsExternalOrderController.java

@@ -0,0 +1,79 @@
+package com.fs.company.controller.store;
+
+import com.fs.common.annotation.DataScope;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
+import com.fs.his.domain.FsExternalOrder;
+import com.fs.his.domain.FsExternalOrderItem;
+import com.fs.his.domain.vo.FsExternalOrderListVO;
+import com.fs.his.mapper.FsExternalOrderItemMapper;
+import com.fs.his.param.FsExternalOrderAddParam;
+import com.fs.his.service.IFsExternalOrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/store/externalOrder")
+public class FsExternalOrderController extends BaseController {
+
+    @Autowired
+    private IFsExternalOrderService fsExternalOrderService;
+
+    @Autowired
+    private FsExternalOrderItemMapper fsExternalOrderItemMapper;
+
+    @GetMapping("/list")
+    @Log(title = "外部订单列表", businessType = BusinessType.OTHER)
+    @PreAuthorize("@ss.hasPermi('his:externalOrder:list')")
+    @DataScope(deptAlias = "cu",userAlias = "cu")
+    public TableDataInfo list(FsExternalOrder fsExternalOrder) {
+        startPage();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsExternalOrder.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<FsExternalOrderListVO> list = fsExternalOrderService.selectExternalOrderListVO(fsExternalOrder);
+        return getDataTable(list);
+    }
+
+    @GetMapping(value = "/{orderId}")
+    public AjaxResult getInfo(@PathVariable("orderId") Long orderId) {
+        return AjaxResult.success(fsExternalOrderService.selectExternalOrderDetailVO(orderId));
+    }
+
+    @GetMapping(value = "/items/{orderId}")
+    public AjaxResult getOrderItems(@PathVariable("orderId") Long orderId) {
+        List<FsExternalOrderItem> items = fsExternalOrderItemMapper.selectFsExternalOrderItemByOrderId(orderId);
+        return AjaxResult.success(items);
+    }
+
+    @Log(title = "创建外部订单", businessType = BusinessType.INSERT)
+    @PostMapping("/create")
+    @PreAuthorize("@ss.hasPermi('his:externalOrder:create')")
+    public R create(@RequestBody FsExternalOrderAddParam param) {
+        //获取当前销售和公司
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        return fsExternalOrderService.createExternalOrder(param);
+    }
+
+    @Log(title = "修改外部订单", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult edit(@RequestBody FsExternalOrder fsExternalOrder) {
+        return toAjax(fsExternalOrderService.updateFsExternalOrder(fsExternalOrder));
+    }
+
+    @Log(title = "删除外部订单", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{orderIds}")
+    public AjaxResult remove(@PathVariable Long[] orderIds) {
+        return toAjax(fsExternalOrderService.deleteFsExternalOrderByOrderIds(orderIds));
+    }
+}

+ 107 - 0
fs-service/src/main/java/com/fs/his/domain/FsExternalOrder.java

@@ -0,0 +1,107 @@
+package com.fs.his.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 外部订单对象 fs_external_order
+ *
+ * @author fs
+ * @date 2024-01-01
+ */
+@Data
+public class FsExternalOrder extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long orderId;
+
+    @Excel(name = "外部订单号")
+    private String orderCode;
+
+    @Excel(name = "外部来源")
+    private String source;
+
+    @Excel(name = "用户id")
+    private Long userId;
+
+    @Excel(name = "收货人")
+    private String userName;
+
+    @Excel(name = "收货人电话")
+    private String userPhone;
+
+    @Excel(name = "详细地址")
+    private String userAddress;
+
+    @Excel(name = "订单商品总数")
+    private Long totalNum;
+
+    @Excel(name = "订单总价")
+    private BigDecimal totalPrice;
+
+    @Excel(name = "实际支付金额")
+    private BigDecimal payPrice;
+
+    @Excel(name = "运费金额")
+    private BigDecimal freightPrice;
+
+    @Excel(name = "支付状态 0待支付 1已支付")
+    private Integer isPay;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    @Excel(name = "支付方式 1微信 2支付宝 3其他")
+    private Integer payType;
+
+    @Excel(name = "订单状态 1待支付 2待发货 3待收货 4已完成 5已取消")
+    private Integer status;
+
+    @Excel(name = "快递公司编号")
+    private String deliveryCode;
+
+    @Excel(name = "快递名称")
+    private String deliveryName;
+
+    @Excel(name = "快递单号")
+    private String deliverySn;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "发货时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date deliveryTime;
+
+    @Excel(name = "配送方式 1快递 2门店自提")
+    private Integer shippingType;
+
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    private Long companyUserId;
+
+    @Excel(name = "备注")
+    private String remark;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "外部订单创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date externalCreateTime;
+
+    private Integer isSync;
+
+    private String syncMsg;
+
+    /**
+     * 扩展订单id
+     */
+    private  String extendOrderId;
+
+    /**
+     * 店铺id
+     */
+    private Long storeId;
+}

+ 68 - 0
fs-service/src/main/java/com/fs/his/domain/FsExternalOrderItem.java

@@ -0,0 +1,68 @@
+package com.fs.his.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 外部订单详情对象 fs_external_order_item
+ *
+ * @author fs
+ * @date 2024-01-01
+ */
+@Data
+public class FsExternalOrderItem extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long itemId;
+
+    @Excel(name = "订单id")
+    private Long orderId;
+
+    @Excel(name = "商品ID")
+    private Long productId;
+
+    @Excel(name = "商品名称")
+    private String productName;
+
+    @Excel(name = "商品编码")
+    private String productCode;
+
+    @Excel(name = "商品图片")
+    private String productImage;
+
+    @Excel(name = "商品规格")
+    private String productSpec;
+
+    @Excel(name = "数量")
+    private Long num;
+
+    @Excel(name = "单价")
+    private BigDecimal price;
+
+    @Excel(name = "总价")
+    private BigDecimal totalPrice;
+
+    @Excel(name = "成本价")
+    private BigDecimal costPrice;
+
+    @Excel(name = "快递公司编号")
+    private String deliveryCode;
+
+    @Excel(name = "快递名称")
+    private String deliveryName;
+
+    @Excel(name = "快递单号")
+    private String deliverySn;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "发货时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date deliveryTime;
+
+    @Excel(name = "物流状态")
+    private Integer deliveryStatus;
+}

+ 38 - 0
fs-service/src/main/java/com/fs/his/domain/vo/FsExternalOrderListVO.java

@@ -0,0 +1,38 @@
+package com.fs.his.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class FsExternalOrderListVO {
+
+    private Long orderId;
+
+    private String orderCode;
+
+    private String companyName;
+
+    private String companyUserName;
+
+    private String userName;
+
+    private String userPhone;
+
+    private String productNames;
+
+    private BigDecimal receivablePrice;
+
+    private BigDecimal payPrice;
+
+    private Integer payType;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date externalCreateTime;
+
+    private Integer status;
+
+    private String statusDesc;
+}

+ 28 - 0
fs-service/src/main/java/com/fs/his/mapper/FsExternalOrderItemMapper.java

@@ -0,0 +1,28 @@
+package com.fs.his.mapper;
+
+import java.util.List;
+
+import com.fs.his.domain.FsExternalOrderItem;
+import com.fs.his.vo.FsExternalOrderDetailVO;
+import org.apache.ibatis.annotations.Param;
+
+public interface FsExternalOrderItemMapper {
+
+    public FsExternalOrderItem selectFsExternalOrderItemByItemId(Long itemId);
+
+    public List<FsExternalOrderItem> selectFsExternalOrderItemList(FsExternalOrderItem fsExternalOrderItem);
+
+    public List<FsExternalOrderItem> selectFsExternalOrderItemByOrderId(Long orderId);
+
+    public List<FsExternalOrderDetailVO.ProductItemVO> selectProductItemVOByOrderId(Long orderId);
+
+    public int insertFsExternalOrderItem(FsExternalOrderItem fsExternalOrderItem);
+
+    public int updateFsExternalOrderItem(FsExternalOrderItem fsExternalOrderItem);
+
+    public int deleteFsExternalOrderItemByItemId(Long itemId);
+
+    public int deleteFsExternalOrderItemByOrderIds(Long[] orderIds);
+
+    public int deleteFsExternalOrderItemByOrderId(Long orderId);
+}

+ 33 - 0
fs-service/src/main/java/com/fs/his/mapper/FsExternalOrderMapper.java

@@ -0,0 +1,33 @@
+package com.fs.his.mapper;
+
+import java.util.List;
+
+import com.fs.his.domain.FsExternalOrder;
+import com.fs.his.domain.vo.FsExternalOrderListVO;
+import com.fs.his.vo.FsExternalOrderDetailVO;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+public interface FsExternalOrderMapper {
+
+    public FsExternalOrder selectFsExternalOrderByOrderId(Long orderId);
+
+    public FsExternalOrder selectFsExternalOrderByOrderCode(String orderCode);
+
+    public List<FsExternalOrder> selectFsExternalOrderList(FsExternalOrder fsExternalOrder);
+
+    public List<FsExternalOrderListVO> selectExternalOrderListVO(FsExternalOrder fsExternalOrder);
+
+    public FsExternalOrderDetailVO selectExternalOrderDetailVO(Long orderId);
+
+    public int insertFsExternalOrder(FsExternalOrder fsExternalOrder);
+
+    public int updateFsExternalOrder(FsExternalOrder fsExternalOrder);
+
+    public int deleteFsExternalOrderByOrderId(Long orderId);
+
+    public int deleteFsExternalOrderByOrderIds(Long[] orderIds);
+
+    @Select("SELECT order_id FROM fs_external_order WHERE extend_order_id is null AND status =2")
+    List<Long> selectUnsyncedOrderIds();
+}

+ 38 - 0
fs-service/src/main/java/com/fs/his/param/FsExternalOrderAddParam.java

@@ -0,0 +1,38 @@
+package com.fs.his.param;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class FsExternalOrderAddParam {
+
+    private String orderCode;
+
+    private String source;
+
+    private Long userId;
+
+    private String userName;
+
+    private String userPhone;
+
+    private String userAddress;
+
+    private BigDecimal freightPrice;
+
+    private Integer payType;
+
+    private BigDecimal payMoney;
+
+    private Long companyId;
+
+    private Long companyUserId;
+
+    private String remark;
+
+    private List<Long> productIds;
+
+    private Long addressId;
+}

+ 42 - 0
fs-service/src/main/java/com/fs/his/service/IFsExternalOrderService.java

@@ -0,0 +1,42 @@
+package com.fs.his.service;
+
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsExternalOrder;
+import com.fs.his.domain.vo.FsExternalOrderListVO;
+import com.fs.his.param.FsExternalOrderAddParam;
+import com.fs.his.vo.FsExternalOrderDetailVO;
+
+public interface IFsExternalOrderService {
+
+    public FsExternalOrder selectFsExternalOrderByOrderId(Long orderId);
+
+    public FsExternalOrder selectFsExternalOrderByOrderCode(String orderCode);
+
+    public List<FsExternalOrder> selectFsExternalOrderList(FsExternalOrder fsExternalOrder);
+
+    public List<FsExternalOrderListVO> selectExternalOrderListVO(FsExternalOrder fsExternalOrder);
+
+    public FsExternalOrderDetailVO selectExternalOrderDetailVO(Long orderId);
+
+    public int insertFsExternalOrder(FsExternalOrder fsExternalOrder);
+
+    public int updateFsExternalOrder(FsExternalOrder fsExternalOrder);
+
+    public int deleteFsExternalOrderByOrderId(Long orderId);
+
+    public int deleteFsExternalOrderByOrderIds(Long[] orderIds);
+
+    R createExternalOrder(FsExternalOrderAddParam param);
+
+    /**
+     * 查询未同步的订单ID列表
+     */
+    List<Long> selectUnsyncedOrderIds();
+
+    /**
+     * 批量推送外部订单到聚水潭
+     */
+    void pushToJstBatch(List<Long> orderIds) throws Exception;
+}

+ 472 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsExternalOrderServiceImpl.java

@@ -0,0 +1,472 @@
+package com.fs.his.service.impl;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyDept;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyDeptService;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.common.core.domain.R;
+import com.fs.core.utils.OrderCodeUtils;
+import com.fs.erp.domain.ErpOrder;
+import com.fs.erp.domain.ErpOrderItem;
+import com.fs.erp.domain.ErpOrderPayment;
+import com.fs.erp.dto.ErpOrderResponseDTO;
+import com.fs.erp.dto.OrderItemDTO;
+import com.fs.erp.dto.PaymentDTO;
+import com.fs.erp.dto.ShopOrderDTO;
+import com.fs.erp.http.JstErpHttpService;
+import com.fs.erp.service.IErpOrderService;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.FsExpress;
+import com.fs.his.domain.FsExternalOrder;
+import com.fs.his.domain.FsExternalOrderItem;
+import com.fs.his.domain.FsStore;
+import com.fs.his.domain.FsStoreProduct;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserAddress;
+import com.fs.his.domain.vo.FsExternalOrderListVO;
+import com.fs.his.mapper.FsExternalOrderMapper;
+import com.fs.his.mapper.FsExternalOrderItemMapper;
+import com.fs.his.mapper.FsStoreMapper;
+import com.fs.his.mapper.FsStoreProductMapper;
+import com.fs.his.param.FsExternalOrderAddParam;
+import com.fs.his.service.IFsExternalOrderService;
+import com.fs.his.service.IFsExpressService;
+import com.fs.his.service.IFsUserAddressService;
+import com.fs.his.service.IFsUserService;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.his.vo.FsExternalOrderDetailVO;
+
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+@Slf4j
+@Service
+public class FsExternalOrderServiceImpl implements IFsExternalOrderService {
+
+    @Autowired
+    private FsExternalOrderMapper fsExternalOrderMapper;
+
+    @Autowired
+    private FsExternalOrderItemMapper fsExternalOrderItemMapper;
+
+    @Autowired
+    private IFsUserAddressService userAddressService;
+
+    @Autowired
+    private FsStoreProductMapper fsStoreProductMapper;
+
+    @Autowired
+    private IFsUserService fsUserService;
+
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private FsStoreMapper fsStoreMapper;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private ICompanyUserService companyUserService;
+
+    @Autowired
+    private ICompanyDeptService companyDeptService;
+
+    @Autowired
+    private IFsExpressService expressService;
+
+    @Autowired
+    private IFsUserAddressService fsUserAddressService;
+
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jstOrderService;
+
+    @Autowired
+    private JstErpHttpService jstErpHttpService;
+
+    private Map<Integer, IErpOrderService> erpServiceMap;
+
+    @PostConstruct
+    public void initErpServiceMap() {
+        erpServiceMap = new HashMap<>();
+        erpServiceMap.put(5, jstOrderService);
+    }
+
+    @Override
+    public FsExternalOrder selectFsExternalOrderByOrderId(Long orderId) {
+        return fsExternalOrderMapper.selectFsExternalOrderByOrderId(orderId);
+    }
+
+    @Override
+    public FsExternalOrder selectFsExternalOrderByOrderCode(String orderCode) {
+        return fsExternalOrderMapper.selectFsExternalOrderByOrderCode(orderCode);
+    }
+
+    @Override
+
+    public List<FsExternalOrder> selectFsExternalOrderList(FsExternalOrder fsExternalOrder) {
+        return fsExternalOrderMapper.selectFsExternalOrderList(fsExternalOrder);
+    }
+
+    @Override
+    public List<FsExternalOrderListVO> selectExternalOrderListVO(FsExternalOrder fsExternalOrder) {
+        return fsExternalOrderMapper.selectExternalOrderListVO(fsExternalOrder);
+    }
+
+    @Override
+    public FsExternalOrderDetailVO selectExternalOrderDetailVO(Long orderId) {
+        FsExternalOrderDetailVO detailVO = fsExternalOrderMapper.selectExternalOrderDetailVO(orderId);
+        if (detailVO != null) {
+            List<FsExternalOrderDetailVO.ProductItemVO> productList = fsExternalOrderItemMapper.selectProductItemVOByOrderId(orderId);
+            detailVO.setProductList(productList);
+        }
+        return detailVO;
+    }
+
+    @Override
+    public int insertFsExternalOrder(FsExternalOrder fsExternalOrder) {
+        return fsExternalOrderMapper.insertFsExternalOrder(fsExternalOrder);
+    }
+
+    @Override
+    public int updateFsExternalOrder(FsExternalOrder fsExternalOrder) {
+        return fsExternalOrderMapper.updateFsExternalOrder(fsExternalOrder);
+    }
+
+    @Override
+    public int deleteFsExternalOrderByOrderId(Long orderId) {
+        return fsExternalOrderMapper.deleteFsExternalOrderByOrderId(orderId);
+    }
+
+    @Override
+    public int deleteFsExternalOrderByOrderIds(Long[] orderIds) {
+        return fsExternalOrderMapper.deleteFsExternalOrderByOrderIds(orderIds);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R createExternalOrder(FsExternalOrderAddParam param) {
+        if (StringUtils.isBlank(param.getOrderCode())) {
+            String orderSn = OrderCodeUtils.getOrderSn();
+            if (StringUtils.isEmpty(orderSn)) {
+                return R.error("订单号生成失败,请重试");
+            }
+            param.setOrderCode(orderSn);
+        }
+
+        FsExternalOrder existOrder = fsExternalOrderMapper.selectFsExternalOrderByOrderCode(param.getOrderCode());
+        if (existOrder != null) {
+            return R.error("订单号已存在");
+        }
+
+        if (CollectionUtils.isEmpty(param.getProductIds())) {
+            return R.error("商品列表不能为空");
+        }
+
+        List<FsStoreProduct> storeProductList = fsStoreProductMapper.getStoreProductInProductIds(param.getProductIds());
+        if (CollectionUtils.isEmpty(storeProductList)) {
+            return R.error("商品不存在");
+        }
+
+        FsExternalOrder order = new FsExternalOrder();
+        order.setOrderCode(param.getOrderCode());
+        order.setSource(param.getSource());
+        order.setUserId(param.getUserId());
+        FsUserAddress address = userAddressService.selectFsUserAddressByAddressId(param.getAddressId());
+        if (address != null) {
+            order.setUserName(address.getRealName());
+            order.setUserPhone(address.getPhone());
+            order.setUserAddress(address.getProvince() + address.getCity() + address.getDistrict() + address.getDetail());
+        }
+        order.setFreightPrice(param.getFreightPrice());
+        order.setPayType(param.getPayType());
+        order.setCompanyId(param.getCompanyId());
+        order.setCompanyUserId(param.getCompanyUserId());
+        order.setRemark(param.getRemark());
+        order.setStatus(2);
+        order.setIsPay(1);
+        order.setIsSync(0);
+        order.setShippingType(1);
+        order.setExternalCreateTime(new Date());
+
+        Long totalNum = 0L;
+        BigDecimal totalPrice = BigDecimal.ZERO;
+        List<FsExternalOrderItem> items = new ArrayList<>();
+        Long storeId = 0L;
+        for (FsStoreProduct product : storeProductList) {
+            Long num = 1L;
+            BigDecimal price = product.getPrice() != null ? product.getPrice() : BigDecimal.ZERO;
+            BigDecimal itemTotalPrice = price.multiply(BigDecimal.valueOf(num));
+
+            totalNum += num;
+            totalPrice = totalPrice.add(itemTotalPrice);
+
+            FsExternalOrderItem item = new FsExternalOrderItem();
+            item.setProductId(product.getProductId());
+            item.setProductName(product.getProductName());
+            item.setProductCode(product.getBarCode());
+            item.setProductImage(product.getImgUrl());
+            item.setProductSpec(product.getPrescribeSpec());
+            item.setNum(num);
+            item.setPrice(price);
+            item.setTotalPrice(itemTotalPrice);
+            item.setCostPrice(product.getCostPrice());
+            item.setDeliveryStatus(0);
+            items.add(item);
+            storeId = product.getStoreId();
+        }
+        if(storeId !=null){
+            order.setStoreId(storeId);
+        }
+        order.setTotalNum(totalNum);
+        order.setTotalPrice(totalPrice);
+        order.setPayPrice(param.getPayMoney() != null ? param.getPayMoney() : totalPrice);
+
+        if (fsExternalOrderMapper.insertFsExternalOrder(order) > 0) {
+            for (FsExternalOrderItem item : items) {
+                item.setOrderId(order.getOrderId());
+                fsExternalOrderItemMapper.insertFsExternalOrderItem(item);
+            }
+            FsUser fsUser = fsUserService.selectFsUserByUserId(order.getUserId());
+            if (fsUser != null && (fsUser.getIsBuy() == null || fsUser.getIsBuy() == 0)) {
+                FsUser u = new FsUser();
+                u.setUserId(order.getUserId());
+                u.setIsBuy(1);
+                fsUserService.updateFsUser(u);
+            }
+            return R.ok().put("orderId", order.getOrderId()).put("orderCode", order.getOrderCode());
+        } else {
+            return R.error("订单创建失败,请重试");
+        }
+    }
+
+    @Override
+    public List<Long> selectUnsyncedOrderIds() {
+        return fsExternalOrderMapper.selectUnsyncedOrderIds();
+    }
+
+    @Override
+    public void pushToJstBatch(List<Long> orderIds) throws Exception {
+        if (CollectionUtils.isEmpty(orderIds)) {
+            log.info("没有需要推送的外部订单");
+            return;
+        }
+
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        Integer erpOpen = sysConfig.getErpOpen();
+        if (erpOpen == null || erpOpen == 0) {
+            log.warn("ERP未开启,跳过外部订单同步");
+            return;
+        }
+
+        Integer erpType = sysConfig.getErpType();
+        if (erpType == null || erpType != 5) {
+            log.warn("ERP类型不是聚水潭,跳过同步: {}", erpType);
+            return;
+        }
+
+        List<ShopOrderDTO> shopOrderList = new ArrayList<>();
+        Map<String, Long> orderCodeToIdMap = new HashMap<>();
+
+        for (Long orderId : orderIds) {
+            FsExternalOrder order = fsExternalOrderMapper.selectFsExternalOrderByOrderId(orderId);
+            if (order == null) {
+                log.warn("外部订单不存在: {}", orderId);
+                continue;
+            }
+
+            ShopOrderDTO shopOrderDTO = buildShopOrderDTO(order);
+            if (shopOrderDTO != null) {
+                shopOrderList.add(shopOrderDTO);
+                orderCodeToIdMap.put(order.getOrderCode(), orderId);
+            }
+        }
+
+        if (shopOrderList.isEmpty()) {
+            log.info("没有有效的订单需要推送");
+            return;
+        }
+
+        int batchSize = 50;
+        for (int i = 0; i < shopOrderList.size(); i += batchSize) {
+            int endIndex = Math.min(i + batchSize, shopOrderList.size());
+            List<ShopOrderDTO> batch = new ArrayList<>(shopOrderList.subList(i, endIndex));
+
+            ErpOrderResponseDTO response = jstErpHttpService.batchUpload(batch);
+            log.info("外部订单推送聚水潭,批次: {}-{}, 结果: {}", i, endIndex, response);
+
+            if (response != null && !CollectionUtils.isEmpty(response.getDatas())) {
+                for (ErpOrderResponseDTO.OrderData data : response.getDatas()) {
+                    if (data != null && data.getIssuccess()) {
+                        String orderCode = data.getSoId();
+                        Long orderId = orderCodeToIdMap.get(orderCode);
+                        if (orderId != null) {
+                            FsExternalOrder updateOrder = new FsExternalOrder();
+                            updateOrder.setOrderId(orderId);
+                            updateOrder.setIsSync(1);
+                            updateOrder.setExtendOrderId(data.getOId().toString());
+                            updateOrder.setSyncMsg("推送成功");
+                            fsExternalOrderMapper.updateFsExternalOrder(updateOrder);
+                            log.info("外部订单推送成功,订单号: {}, 外部单号: {}", orderCode, data.getOId());
+                        }
+                    } else if (data != null) {
+                        String orderCode = data.getSoId();
+                        Long orderId = orderCodeToIdMap.get(orderCode);
+                        if (orderId != null) {
+                            FsExternalOrder updateOrder = new FsExternalOrder();
+                            updateOrder.setOrderId(orderId);
+                            updateOrder.setIsSync(2);
+                            updateOrder.setSyncMsg(data.getMsg());
+                            fsExternalOrderMapper.updateFsExternalOrder(updateOrder);
+                            log.error("外部订单推送失败,订单号: {}, 原因: {}", orderCode, data.getMsg());
+                        }
+                    }
+                }
+            }
+
+            Thread.sleep(600);
+        }
+    }
+
+    private ShopOrderDTO buildShopOrderDTO(FsExternalOrder order) {
+        if (order.getStoreId() == null) {
+            log.warn("外部订单店铺ID为空: {}", order.getOrderId());
+            return null;
+        }
+
+        FsStore fsStore = fsStoreMapper.selectFsStoreByStoreId(order.getStoreId());
+        if (fsStore == null) {
+            log.warn("外部订单店铺不存在: {}", order.getStoreId());
+            return null;
+        }
+
+        ShopOrderDTO shopOrderDTO = new ShopOrderDTO();
+        shopOrderDTO.setShopId(Long.valueOf(fsStore.getShopCode()));
+        shopOrderDTO.setSoId(order.getOrderCode());
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        shopOrderDTO.setOrderDate(sdf.format(new Date()));
+        shopOrderDTO.setShopStatus("WAIT_SELLER_SEND_GOODS");
+        shopOrderDTO.setShopBuyerId(order.getUserName());
+        shopOrderDTO.setPayAmount(order.getPayPrice().doubleValue());
+        shopOrderDTO.setFreight(order.getFreightPrice() != null ? order.getFreightPrice().doubleValue() : 0.0);
+
+        StringBuilder remarkBuilder = new StringBuilder();
+        if (order.getCompanyId() != null) {
+            Company company = companyService.selectCompanyById(order.getCompanyId());
+            if (company != null) {
+                remarkBuilder.append(company.getCompanyName());
+            }
+        }
+        if (order.getCompanyUserId() != null) {
+            CompanyUser companyUser = companyUserService.selectCompanyUserById(order.getCompanyUserId());
+            if (companyUser != null) {
+                CompanyDept dept = companyDeptService.selectCompanyDeptById(companyUser.getDeptId());
+                if (dept != null) {
+                    List<String> names = companyDeptService.selectCompanyDeptNamesByIds(dept.getAncestors());
+                    if (names != null && names.size() > 0) {
+                        remarkBuilder.append("-").append(StringUtils.join(names, ",")).append(",").append(dept.getDeptName());
+                    }
+                }
+                remarkBuilder.append("-").append(companyUser.getNickName());
+            }
+        }
+        if (order.getRemark() != null) {
+            remarkBuilder.append(" ").append(order.getRemark());
+        }
+        shopOrderDTO.setRemark(remarkBuilder.toString());
+
+        String receiverName = order.getUserName();
+        receiverName = receiverName == null ? "" : receiverName.replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9]", "");
+        if (StringUtils.isBlank(receiverName)) {
+            receiverName = "收件人";
+        }
+        shopOrderDTO.setReceiverName(receiverName.length() > 20 ? receiverName.substring(0, 20) : receiverName);
+        shopOrderDTO.setReceiverPhone(order.getUserPhone());
+
+        String[] address = order.getUserAddress().split(" ");
+        if (address.length < 3) {
+            try {
+                String kdnAddress = fsUserAddressService.getKdnAddress(order.getUserAddress());
+                Map<String, Object> result = JSON.parseObject(kdnAddress);
+                Map<String, String> addData = (Map<String, String>) ((Map) result.get("Data")).get("result");
+                if (addData != null) {
+                    shopOrderDTO.setReceiverState((String) addData.get("ProvinceName"));
+                    shopOrderDTO.setReceiverCity((String) addData.get("CityName"));
+                    shopOrderDTO.setReceiverDistrict((String) addData.get("ExpAreaName"));
+                    shopOrderDTO.setReceiverAddress((String) addData.get("StreetName") + addData.get("Address"));
+                }
+            } catch (Exception e) {
+                log.error("地址解析失败", e);
+            }
+        } else {
+            shopOrderDTO.setReceiverState(address[0]);
+            shopOrderDTO.setReceiverCity(address[1]);
+            shopOrderDTO.setReceiverDistrict(address[2]);
+            if (address.length > 3) {
+                StringBuilder addrs = new StringBuilder();
+                for (int i = 3; i < address.length; i++) {
+                    addrs.append(address[i]);
+                }
+                shopOrderDTO.setReceiverAddress(addrs.toString());
+            } else {
+                shopOrderDTO.setReceiverAddress(address[2]);
+            }
+        }
+
+        if (shopOrderDTO.getReceiverAddress() != null) {
+            shopOrderDTO.setReceiverAddress(shopOrderDTO.getReceiverAddress().replace("+", "加").replace("\n", ""));
+        }
+
+        List<FsExternalOrderItem> orderItems = fsExternalOrderItemMapper.selectFsExternalOrderItemByOrderId(order.getOrderId());
+        List<OrderItemDTO> itemDTOList = new ArrayList<>();
+        for (FsExternalOrderItem orderItem : orderItems) {
+            OrderItemDTO itemDTO = new OrderItemDTO();
+            itemDTO.setSkuId(orderItem.getProductCode() != null ? orderItem.getProductCode().trim() : "");
+            itemDTO.setShopSkuId(orderItem.getProductCode() != null ? orderItem.getProductCode().trim() : "");
+            itemDTO.setName(orderItem.getProductName());
+            itemDTO.setShopIId(orderItem.getProductCode() != null ? orderItem.getProductCode().trim() : "");
+            itemDTO.setPropertiesValue(orderItem.getProductSpec());
+            itemDTO.setAmount(orderItem.getTotalPrice());
+            itemDTO.setPrice(orderItem.getPrice());
+            itemDTO.setQty(orderItem.getNum().intValue());
+            itemDTO.setOuterOiId(String.format("%s%d", order.getOrderCode(), orderItem.getItemId()));
+            itemDTOList.add(itemDTO);
+        }
+        shopOrderDTO.setItems(itemDTOList);
+
+        PaymentDTO paymentDTO = new PaymentDTO();
+        paymentDTO.setAmount(order.getPayPrice().doubleValue());
+        paymentDTO.setOuterPayId(order.getOrderCode());
+        paymentDTO.setPayDate(sdf.format(new Date()));
+        paymentDTO.setPayment("微信支付");
+        paymentDTO.setBuyerAccount(order.getUserName());
+        paymentDTO.setSellerAccount("平台销售");
+        shopOrderDTO.setPay(paymentDTO);
+
+        return shopOrderDTO;
+    }
+}

+ 91 - 0
fs-service/src/main/java/com/fs/his/vo/FsExternalOrderDetailVO.java

@@ -0,0 +1,91 @@
+package com.fs.his.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class FsExternalOrderDetailVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private Long orderId;
+
+    private String orderCode;
+
+    private String source;
+
+    private Long userId;
+
+    private String userName;
+
+    private String userPhone;
+
+    private String userAddress;
+
+    private Long totalNum;
+
+    private BigDecimal totalPrice;
+
+    private BigDecimal receivablePrice;
+
+    private BigDecimal payPrice;
+
+    private BigDecimal freightPrice;
+
+    private Integer isPay;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    private Integer payType;
+
+    private Integer status;
+
+    private String deliveryCode;
+
+    private String deliveryName;
+
+    private String deliverySn;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date deliveryTime;
+
+    private Integer shippingType;
+
+    private String remark;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date externalCreateTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    private String companyName;
+
+    private String companyUserName;
+
+    private List<ProductItemVO> productList;
+
+    @Data
+    public static class ProductItemVO implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        private Long productId;
+
+        private String productName;
+
+        private BigDecimal price;
+
+        private Long num;
+
+        private String productImage;
+
+        private String productSpec;
+    }
+}

+ 144 - 0
fs-service/src/main/resources/mapper/his/FsExternalOrderItemMapper.xml

@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsExternalOrderItemMapper">
+    
+    <resultMap type="FsExternalOrderItem" id="FsExternalOrderItemResult">
+        <result property="itemId"    column="item_id"    />
+        <result property="orderId"    column="order_id"    />
+        <result property="productId"    column="product_id"    />
+        <result property="productName"    column="product_name"    />
+        <result property="productCode"    column="product_code"    />
+        <result property="productImage"    column="product_image"    />
+        <result property="productSpec"    column="product_spec"    />
+        <result property="num"    column="num"    />
+        <result property="price"    column="price"    />
+        <result property="totalPrice"    column="total_price"    />
+        <result property="costPrice"    column="cost_price"    />
+        <result property="deliveryCode"    column="delivery_code"    />
+        <result property="deliveryName"    column="delivery_name"    />
+        <result property="deliverySn"    column="delivery_sn"    />
+        <result property="deliveryTime"    column="delivery_time"    />
+        <result property="deliveryStatus"    column="delivery_status"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectFsExternalOrderItemVo">
+        select item_id, order_id, product_id, product_name, product_code, product_image, product_spec, num, price, total_price, cost_price, delivery_code, delivery_name, delivery_sn, delivery_time, delivery_status, create_time, update_time from fs_external_order_item
+    </sql>
+
+    <select id="selectFsExternalOrderItemList" parameterType="FsExternalOrderItem" resultMap="FsExternalOrderItemResult">
+        <include refid="selectFsExternalOrderItemVo"/>
+        <where>  
+            <if test="orderId != null "> and order_id = #{orderId}</if>
+            <if test="productId != null "> and product_id = #{productId}</if>
+            <if test="productName != null  and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
+            <if test="productCode != null  and productCode != ''"> and product_code = #{productCode}</if>
+        </where>
+        order by create_time desc
+    </select>
+
+    <select id="selectFsExternalOrderItemByItemId" parameterType="Long" resultMap="FsExternalOrderItemResult">
+        <include refid="selectFsExternalOrderItemVo"/>
+        where item_id = #{itemId}
+    </select>
+
+    <select id="selectFsExternalOrderItemByOrderId" parameterType="Long" resultMap="FsExternalOrderItemResult">
+        <include refid="selectFsExternalOrderItemVo"/>
+        where order_id = #{orderId}
+    </select>
+    
+    <insert id="insertFsExternalOrderItem" parameterType="FsExternalOrderItem" useGeneratedKeys="true" keyProperty="itemId">
+        insert into fs_external_order_item
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderId != null">order_id,</if>
+            <if test="productId != null">product_id,</if>
+            <if test="productName != null and productName != ''">product_name,</if>
+            <if test="productCode != null and productCode != ''">product_code,</if>
+            <if test="productImage != null and productImage != ''">product_image,</if>
+            <if test="productSpec != null and productSpec != ''">product_spec,</if>
+            <if test="num != null">num,</if>
+            <if test="price != null">price,</if>
+            <if test="totalPrice != null">total_price,</if>
+            <if test="costPrice != null">cost_price,</if>
+            <if test="deliveryCode != null and deliveryCode != ''">delivery_code,</if>
+            <if test="deliveryName != null and deliveryName != ''">delivery_name,</if>
+            <if test="deliverySn != null and deliverySn != ''">delivery_sn,</if>
+            <if test="deliveryTime != null">delivery_time,</if>
+            <if test="deliveryStatus != null">delivery_status,</if>
+            create_time
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderId != null">#{orderId},</if>
+            <if test="productId != null">#{productId},</if>
+            <if test="productName != null and productName != ''">#{productName},</if>
+            <if test="productCode != null and productCode != ''">#{productCode},</if>
+            <if test="productImage != null and productImage != ''">#{productImage},</if>
+            <if test="productSpec != null and productSpec != ''">#{productSpec},</if>
+            <if test="num != null">#{num},</if>
+            <if test="price != null">#{price},</if>
+            <if test="totalPrice != null">#{totalPrice},</if>
+            <if test="costPrice != null">#{costPrice},</if>
+            <if test="deliveryCode != null and deliveryCode != ''">#{deliveryCode},</if>
+            <if test="deliveryName != null and deliveryName != ''">#{deliveryName},</if>
+            <if test="deliverySn != null and deliverySn != ''">#{deliverySn},</if>
+            <if test="deliveryTime != null">#{deliveryTime},</if>
+            <if test="deliveryStatus != null">#{deliveryStatus},</if>
+            sysdate()
+        </trim>
+    </insert>
+
+    <update id="updateFsExternalOrderItem" parameterType="FsExternalOrderItem">
+        update fs_external_order_item
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderId != null">order_id = #{orderId},</if>
+            <if test="productId != null">product_id = #{productId},</if>
+            <if test="productName != null and productName != ''">product_name = #{productName},</if>
+            <if test="productCode != null and productCode != ''">product_code = #{productCode},</if>
+            <if test="productImage != null and productImage != ''">product_image = #{productImage},</if>
+            <if test="productSpec != null and productSpec != ''">product_spec = #{productSpec},</if>
+            <if test="num != null">num = #{num},</if>
+            <if test="price != null">price = #{price},</if>
+            <if test="totalPrice != null">total_price = #{totalPrice},</if>
+            <if test="costPrice != null">cost_price = #{costPrice},</if>
+            <if test="deliveryCode != null and deliveryCode != ''">delivery_code = #{deliveryCode},</if>
+            <if test="deliveryName != null and deliveryName != ''">delivery_name = #{deliveryName},</if>
+            <if test="deliverySn != null and deliverySn != ''">delivery_sn = #{deliverySn},</if>
+            <if test="deliveryTime != null">delivery_time = #{deliveryTime},</if>
+            <if test="deliveryStatus != null">delivery_status = #{deliveryStatus},</if>
+            update_time = sysdate()
+        </trim>
+        where item_id = #{itemId}
+    </update>
+
+    <delete id="deleteFsExternalOrderItemByItemId" parameterType="Long">
+        delete from fs_external_order_item where item_id = #{itemId}
+    </delete>
+
+    <delete id="deleteFsExternalOrderItemByOrderIds" parameterType="String">
+        delete from fs_external_order_item where order_id in 
+        <foreach item="orderId" collection="array" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </delete>
+
+    <delete id="deleteFsExternalOrderItemByOrderId" parameterType="Long">
+        delete from fs_external_order_item where order_id = #{orderId}
+    </delete>
+
+    <select id="selectProductItemVOByOrderId" parameterType="Long" resultType="com.fs.his.vo.FsExternalOrderDetailVO$ProductItemVO">
+        SELECT
+            oi.product_id AS productId,
+            IFNULL(sp.product_name, oi.product_name) AS productName,
+            oi.price,
+            oi.num,
+            oi.product_image AS productImage,
+            oi.product_spec AS productSpec
+        FROM fs_external_order_item oi
+        LEFT JOIN fs_store_product sp ON oi.product_id = sp.product_id
+        WHERE oi.order_id = #{orderId}
+        ORDER BY oi.item_id ASC
+    </select>
+</mapper>

+ 253 - 0
fs-service/src/main/resources/mapper/his/FsExternalOrderMapper.xml

@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsExternalOrderMapper">
+    
+    <resultMap type="FsExternalOrder" id="FsExternalOrderResult">
+        <result property="orderId"    column="order_id"    />
+        <result property="orderCode"    column="order_code"    />
+        <result property="source"    column="source"    />
+        <result property="userId"    column="user_id"    />
+        <result property="userName"    column="user_name"    />
+        <result property="userPhone"    column="user_phone"    />
+        <result property="userAddress"    column="user_address"    />
+        <result property="totalNum"    column="total_num"    />
+        <result property="totalPrice"    column="total_price"    />
+        <result property="payPrice"    column="pay_price"    />
+        <result property="freightPrice"    column="freight_price"    />
+        <result property="isPay"    column="is_pay"    />
+        <result property="payTime"    column="pay_time"    />
+        <result property="payType"    column="pay_type"    />
+        <result property="status"    column="status"    />
+        <result property="deliveryCode"    column="delivery_code"    />
+        <result property="deliveryName"    column="delivery_name"    />
+        <result property="deliverySn"    column="delivery_sn"    />
+        <result property="deliveryTime"    column="delivery_time"    />
+        <result property="shippingType"    column="shipping_type"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="remark"    column="remark"    />
+        <result property="externalCreateTime"    column="external_create_time"    />
+        <result property="isSync"    column="is_sync"    />
+        <result property="syncMsg"    column="sync_msg"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="extendOrderId"    column="extend_order_id"    />
+        <result property="storeId"    column="store_id"    />
+    </resultMap>
+
+    <sql id="selectFsExternalOrderVo">
+        select order_id, order_code, source, user_id, user_name, user_phone, user_address, total_num, total_price, pay_price, freight_price, is_pay, pay_time, pay_type, status, delivery_code, delivery_name, delivery_sn, delivery_time, shipping_type, company_id, company_user_id, remark, external_create_time, is_sync, sync_msg, create_time, update_time, extend_order_id,store_id from fs_external_order
+    </sql>
+
+    <select id="selectFsExternalOrderList" parameterType="FsExternalOrder" resultMap="FsExternalOrderResult">
+        <include refid="selectFsExternalOrderVo"/>
+        <where>  
+            <if test="orderCode != null  and orderCode != ''"> and order_code = #{orderCode}</if>
+            <if test="source != null  and source != ''"> and source = #{source}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="userName != null  and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
+            <if test="userPhone != null  and userPhone != ''"> and user_phone = #{userPhone}</if>
+            <if test="isPay != null "> and is_pay = #{isPay}</if>
+            <if test="status != null "> and status = #{status}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="isSync != null "> and is_sync = #{isSync}</if>
+        </where>
+        order by create_time desc
+    </select>
+    
+    <select id="selectFsExternalOrderByOrderId" parameterType="Long" resultMap="FsExternalOrderResult">
+        <include refid="selectFsExternalOrderVo"/>
+        where order_id = #{orderId}
+    </select>
+
+    <select id="selectFsExternalOrderByOrderCode" parameterType="String" resultMap="FsExternalOrderResult">
+        <include refid="selectFsExternalOrderVo"/>
+        where order_code = #{orderCode}
+    </select>
+
+    <insert id="insertFsExternalOrder" parameterType="FsExternalOrder" useGeneratedKeys="true" keyProperty="orderId">
+        insert into fs_external_order
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderCode != null and orderCode != ''">order_code,</if>
+            <if test="source != null and source != ''">source,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="userName != null and userName != ''">user_name,</if>
+            <if test="userPhone != null and userPhone != ''">user_phone,</if>
+            <if test="userAddress != null and userAddress != ''">user_address,</if>
+            <if test="totalNum != null">total_num,</if>
+            <if test="totalPrice != null">total_price,</if>
+            <if test="payPrice != null">pay_price,</if>
+            <if test="freightPrice != null">freight_price,</if>
+            <if test="isPay != null">is_pay,</if>
+            <if test="payTime != null">pay_time,</if>
+            <if test="payType != null">pay_type,</if>
+            <if test="status != null">status,</if>
+            <if test="deliveryCode != null and deliveryCode != ''">delivery_code,</if>
+            <if test="deliveryName != null and deliveryName != ''">delivery_name,</if>
+            <if test="deliverySn != null and deliverySn != ''">delivery_sn,</if>
+            <if test="deliveryTime != null">delivery_time,</if>
+            <if test="shippingType != null">shipping_type,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="remark != null and remark != ''">remark,</if>
+            <if test="externalCreateTime != null">external_create_time,</if>
+            <if test="isSync != null">is_sync,</if>
+            <if test="syncMsg != null and syncMsg != ''">sync_msg,</if>
+            <if test="extendOrderId !=null and extendOrderId !=''">extend_order_id,</if>
+            <if test="storeId != null">store_id,</if>
+            create_time
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderCode != null and orderCode != ''">#{orderCode},</if>
+            <if test="source != null and source != ''">#{source},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="userName != null and userName != ''">#{userName},</if>
+            <if test="userPhone != null and userPhone != ''">#{userPhone},</if>
+            <if test="userAddress != null and userAddress != ''">#{userAddress},</if>
+            <if test="totalNum != null">#{totalNum},</if>
+            <if test="totalPrice != null">#{totalPrice},</if>
+            <if test="payPrice != null">#{payPrice},</if>
+            <if test="freightPrice != null">#{freightPrice},</if>
+            <if test="isPay != null">#{isPay},</if>
+            <if test="payTime != null">#{payTime},</if>
+            <if test="payType != null">#{payType},</if>
+            <if test="status != null">#{status},</if>
+            <if test="deliveryCode != null and deliveryCode != ''">#{deliveryCode},</if>
+            <if test="deliveryName != null and deliveryName != ''">#{deliveryName},</if>
+            <if test="deliverySn != null and deliverySn != ''">#{deliverySn},</if>
+            <if test="deliveryTime != null">#{deliveryTime},</if>
+            <if test="shippingType != null">#{shippingType},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="remark != null and remark != ''">#{remark},</if>
+            <if test="externalCreateTime != null">#{externalCreateTime},</if>
+            <if test="isSync != null">#{isSync},</if>
+            <if test="syncMsg != null and syncMsg != ''">#{syncMsg},</if>
+            <if test="extendOrderId !=null and extendOrderId !=''">#{extendOrderId},</if>
+            <if test="storeId != null">#{storeId},</if>
+            sysdate()
+        </trim>
+    </insert>
+
+    <update id="updateFsExternalOrder" parameterType="FsExternalOrder">
+        update fs_external_order
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderCode != null and orderCode != ''">order_code = #{orderCode},</if>
+            <if test="source != null and source != ''">source = #{source},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="userName != null and userName != ''">user_name = #{userName},</if>
+            <if test="userPhone != null and userPhone != ''">user_phone = #{userPhone},</if>
+            <if test="userAddress != null and userAddress != ''">user_address = #{userAddress},</if>
+            <if test="totalNum != null">total_num = #{totalNum},</if>
+            <if test="totalPrice != null">total_price = #{totalPrice},</if>
+            <if test="payPrice != null">pay_price = #{payPrice},</if>
+            <if test="freightPrice != null">freight_price = #{freightPrice},</if>
+            <if test="isPay != null">is_pay = #{isPay},</if>
+            <if test="payTime != null">pay_time = #{payTime},</if>
+            <if test="payType != null">pay_type = #{payType},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="deliveryCode != null and deliveryCode != ''">delivery_code = #{deliveryCode},</if>
+            <if test="deliveryName != null and deliveryName != ''">delivery_name = #{deliveryName},</if>
+            <if test="deliverySn != null and deliverySn != ''">delivery_sn = #{deliverySn},</if>
+            <if test="deliveryTime != null">delivery_time = #{deliveryTime},</if>
+            <if test="shippingType != null">shipping_type = #{shippingType},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="remark != null and remark != ''">remark = #{remark},</if>
+            <if test="externalCreateTime != null">external_create_time = #{externalCreateTime},</if>
+            <if test="isSync != null">is_sync = #{isSync},</if>
+            <if test="syncMsg != null and syncMsg != ''">sync_msg = #{syncMsg},</if>
+            <if test="extendOrderId !=null and extendOrderId !=''">extend_order_id = #{extendOrderId},</if>
+            <if test="storeId != null">store_id = #{storeId},</if>
+            update_time = sysdate()
+        </trim>
+        where order_id = #{orderId}
+    </update>
+
+    <delete id="deleteFsExternalOrderByOrderId" parameterType="Long">
+        delete from fs_external_order where order_id = #{orderId}
+    </delete>
+
+    <delete id="deleteFsExternalOrderByOrderIds" parameterType="String">
+        delete from fs_external_order where order_id in 
+        <foreach item="orderId" collection="array" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </delete>
+
+    <select id="selectExternalOrderListVO" parameterType="FsExternalOrder" resultType="com.fs.his.domain.vo.FsExternalOrderListVO">
+        SELECT 
+            o.order_id,
+            o.order_code,
+            c.company_name AS companyName,
+            cu.user_name AS companyUserName,
+            o.user_name AS userName,
+            o.user_phone AS userPhone,
+            GROUP_CONCAT(oi.product_name SEPARATOR ',') AS productNames,
+            SUM(oi.price) AS receivablePrice,
+            o.pay_price AS payPrice,
+            o.pay_type AS payType,
+            o.external_create_time AS externalCreateTime,
+            o.status,
+            CASE o.status
+                WHEN 1 THEN '待支付'
+                WHEN 2 THEN '待发货'
+                WHEN 3 THEN '待收货'
+                WHEN 4 THEN '已完成'
+                WHEN 5 THEN '已取消'
+                ELSE '未知'
+            END AS statusDesc
+        FROM fs_external_order o
+        LEFT JOIN company c ON o.company_id = c.company_id
+        LEFT JOIN company_user cu ON o.company_user_id = cu.user_id
+        LEFT JOIN fs_external_order_item oi ON o.order_id = oi.order_id
+        <where>
+            <if test="orderCode != null and orderCode != ''"> AND o.order_code = #{orderCode}</if>
+            <if test="userId != null"> AND o.user_id = #{userId}</if>
+            <if test="userName != null and userName != ''"> AND o.user_name LIKE CONCAT('%', #{userName}, '%')</if>
+            <if test="userPhone != null and userPhone != ''"> AND o.user_phone = #{userPhone}</if>
+            <if test="isPay != null"> AND o.is_pay = #{isPay}</if>
+            <if test="status != null"> AND o.status = #{status}</if>
+            <if test="companyId != null"> AND o.company_id = #{companyId}</if>
+            <if test="companyUserId != null"> AND o.company_user_id = #{companyUserId}</if>
+            <if test="isSync != null"> AND o.is_sync = #{isSync}</if>
+        </where>
+        GROUP BY o.order_id
+        ORDER BY o.create_time DESC
+    </select>
+
+    <select id="selectExternalOrderDetailVO" parameterType="Long" resultType="com.fs.his.vo.FsExternalOrderDetailVO">
+        SELECT
+            o.order_id AS orderId,
+            o.order_code AS orderCode,
+            o.source,
+            o.user_id AS userId,
+            o.user_name AS userName,
+            o.user_phone AS userPhone,
+            o.user_address AS userAddress,
+            o.total_num AS totalNum,
+            o.total_price AS totalPrice,
+            o.pay_price AS payPrice,
+            o.freight_price AS freightPrice,
+            o.is_pay AS isPay,
+            o.pay_time AS payTime,
+            o.pay_type AS payType,
+            o.status,
+            o.delivery_code AS deliveryCode,
+            o.delivery_name AS deliveryName,
+            o.delivery_sn AS deliverySn,
+            o.delivery_time AS deliveryTime,
+            o.shipping_type AS shippingType,
+            o.remark,
+            o.external_create_time AS externalCreateTime,
+            o.create_time AS createTime,
+            c.company_name AS companyName,
+            cu.nick_name AS companyUserName
+        FROM fs_external_order o
+        LEFT JOIN company c ON o.company_id = c.company_id
+        LEFT JOIN company_user cu ON o.company_user_id = cu.user_id
+        WHERE o.order_id = #{orderId}
+    </select>
+</mapper>