Java生鮮電商平台-售后模塊的設計與架構


Java生鮮電商平台-售后模塊的設計與架構

 

說明:任何一個的電商平台都有售后服務系統,那么對於我們這個生鮮的電商平台,售后系統需要思考以下幾個維度。

 

          1. 買家的需求維度

             說明:買家在平台上沒找到自己想要的東西,我們需要提供給他一個入口,告訴我們他有這個需求,我們進行改進。系統需要有記錄這種情況,同時也有回復客戶的情況。

          2. 投訴入口

              說明:有客戶性子比較急,他有問題,就會馬上打電話給客服,客服需要解答與回答,維護客戶關系。對於系統而言,需要記錄這種情況,然后分析問題與解決問題。

          3. IM聊天入口

             說明:客戶有時候也不想寫信息,也不想打電話,能否有一個時刻的IM聊天記錄呢?對於系統而言需要記錄這種信息,我們目前系統沒處理,采用的是微信,以及銷售人員的反饋機制。

          4. 退貨問題

              說明:售后系統中,退貨問題是最繁瑣的,買家存在以下兩種情況。

                      4.1 買家要錢不要貨。顧名思義,有些買家就是不要貨了,他需要我們退錢給他,這個配送端有一個一件退貨功能,錢退到買家的余額里面,下次可以繼續購買。

                      4.2  買家要貨不要錢,顧名思義,有些買家的確需要這個貨物,對於我們退錢給他,他是不接受的,因為他真的需要這種東西,你讓他再去買,客戶體驗非常差,可能 就沒有下次購物了。對於這種情況,我們用時間軸來繼續整個過程。(說明,由於這個系統設計到生鮮電商方面,其他的電商方面可能會不一樣。)

 

相關數據庫的設計與架構如下:

 1. 買家平台建議信息表

CREATE TABLE `suggestion` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自動增加ID',
  `suggestion_content` varchar(1024) DEFAULT NULL COMMENT '建議內容',
  `suggestion_imgs` varchar(255) DEFAULT NULL COMMENT '多張圖片',
  `user_id` bigint(20) DEFAULT NULL COMMENT '所屬用戶ID',
  `create_time` datetime DEFAULT NULL COMMENT '創建時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=78 DEFAULT CHARSET=utf8 COMMENT='用戶對平台的建議';

說明: 平台建議表,是買家對平台的建議以及自己的需求的一個入口,可以是圖片與內容兩點。

          比如說:他說我們送的菜有問題,很多爛的,那么他是需要拍圖片證明的。

 

2. 平台回復信息表

CREATE TABLE `suggestion_reply` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自動增加ID',
  `suggestion_id` bigint(20) DEFAULT NULL COMMENT '客戶的建議ID',
  `content` varchar(512) DEFAULT NULL COMMENT '回復的內容',
  `create_time` datetime DEFAULT NULL COMMENT '創建時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COMMENT='客戶建議回復信息表';

說明:作為一個平台,平台需要回復客戶的信息,買家也需要看到,當然這邊系統是不區分是買家還是賣家的,我們都是可以數據的處理的。

 

3. 售后系統時間軸的設計

說明:其實我們系統需要知道整個售后的過程的,比如買家什么時候發起的不要錢,要貨,然后師傅是什么時候知道這個消息的,如何進行售后的,他們會遇到什么問題,

當然這里面有很多的問題,系統可以做的事情其實是很少的,而我們需要做的是更多的事情。

 

CREATE TABLE `order_timeline` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自動增加ID',
  `item_id` bigint(20) DEFAULT NULL COMMENT '訂單項ID',
  `remarks` varchar(256) DEFAULT NULL COMMENT '備注',
  `create_time` datetime DEFAULT NULL COMMENT '創建時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1980 DEFAULT CHARSET=utf8 COMMENT='售后模塊,退換貨時間軸,針對的是某一個訂單項';

 

相關時間軸運營截圖如下:

 

 

 

 整個業務不算復雜,需要的一種思路與解決思路的方案:

關於補貨流程:

補貨需求
業務需求:
    當賣家主動點擊缺貨,則配送師傅看到這個異常訂單項,然后他有兩種選擇,
第一種補貨(有貨,他也想補或者客戶說要貨不要錢)
第二種不補貨(無貨可補,他不想補或者客戶說退錢等等)
第一種補貨業務:
1.    當配送師傅點擊已補貨,則把這個訂單項對應的金額從買家中直接扣除,前提是線上付款,如果這個訂單是線下付款,則不用處理扣款邏輯,直接修改狀態即可。同時記錄時間軸日志。
第二種不補貨業務:
2.    當師傅點擊不補貨,則這個訂單項不做任何扣款邏輯,不管線下還是線上,直接修改狀態即可,同時記錄時間軸日志。
補充說明:補貨與不補貨屬於互斥操作,即已補貨后不允許再出現不補貨,不補貨后不再允許出現補貨。按照規則來處理。

 

 相關業務核心代碼如下:

/**
 * 訂單項退貨*/
@RestController
@RequestMapping("/delivery")
public class OrderReturnController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(OrderReturnController.class);

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderReturnService orderReturnService;

    /**
     * 訂單項退貨
     * 
     */
    @RequestMapping(value = "/order/return/item", method = { RequestMethod.GET, RequestMethod.POST })
    public JsonResult orderReturnItem(HttpServletRequest request, HttpServletResponse response,
            @Param("itemId") Long itemId, @Param("deliveryId") Long deliveryId, @Param("status") int status) {
        try {
            if (itemId == null) {
                return new JsonResult(JsonResultCode.FAILURE, "item參數有誤", "");
            }

            OrderItem orderItem = orderItemService.getOrderItemByItemId(itemId);

            if (orderItem == null) {
                return new JsonResult(JsonResultCode.FAILURE, "無此訂單項", "");
            }
            
            String returnMsg = "";
            if(status == BuyerStatus.THREE){
                returnMsg = TimelineTemplate.return_MSG;
            }if(status == BuyerStatus.FOUR){
                returnMsg = TimelineTemplate.BACK_MSG;
            }if(status == BuyerStatus.ZERO){
                returnMsg = TimelineTemplate.OFF_MSG;
            }
            orderItemService.updateOrderItemStatus(itemId, status, deliveryId, returnMsg);
            return new JsonResult(JsonResultCode.SUCCESS, "操作成功", "");
        } catch (Exception ex) {
            logger.error("[OrderReturnController][orderReturnItem] exception :", ex);
            return new JsonResult(JsonResultCode.FAILURE, "系統錯誤,請稍后重試", "");
        }
    }

    /**
     * 退還列表
     */
    @RequestMapping(value = "/order/return/list", method = { RequestMethod.GET, RequestMethod.POST })
    public JsonResult orderReturnList(HttpServletRequest request, HttpServletResponse response,@Param("deliveryId") Long deliveryId, @Param("status") int status) {
        try 
        {
            // 組裝成為最終的列表結果
            List<OrderReturnVo> listResult = new ArrayList<OrderReturnVo>();

            List<OrderGoodsVo> goodsList = orderReturnService.getReturnOrderGoodsList(deliveryId,status);

            if (CollectionUtils.isEmpty(goodsList)) {
                return new JsonResult(JsonResultCode.SUCCESS, "查詢完成", listResult);
            }

            // 臨時參數,判斷時間
            Map<String, List<OrderReturnEntity>> paramTimeMap = new HashMap<String, List<OrderReturnEntity>>();

            // 過濾賣家
            Map<String, List<OrderGoodsVo>> paramSellerMap = new HashMap<String, List<OrderGoodsVo>>();

            for (OrderGoodsVo vo : goodsList) {
                String bestTime = DateUtil.dateToString(vo.getBestTime(), "yyyy-MM-dd");

                // 時間相同
                if (paramTimeMap.get(bestTime) != null) {
                    List<OrderReturnEntity> mapOrderReturnEntity = paramTimeMap.get(bestTime);

                    // 組裝時間
                    OrderReturnVo resultVo = new OrderReturnVo();
                    resultVo.setBestTime(bestTime);

                    // 判斷是否是同一個賣家的
                    if (paramSellerMap.get(vo.getSellerName()) != null) 
                    {
                        OrderReturnEntity entity = new OrderReturnEntity();
                        List<OrderGoodsVo> listVo = paramSellerMap.get(vo.getSellerName());
                        listVo.add(vo);
                        entity.setListOrderGoodsVo(listVo);
                        resultVo.setListOrderReturnEntity(mapOrderReturnEntity);
                    }else
                    {
                        //不同買家
                        OrderReturnEntity entity = new OrderReturnEntity();
                        entity.setSellerName(vo.getSellerName());
                        
                        List<OrderGoodsVo> listVo =new ArrayList<OrderGoodsVo>();
                        listVo.add(vo);
                        entity.setListOrderGoodsVo(listVo);
                        mapOrderReturnEntity.add(entity);
                        
                        paramSellerMap.put(vo.getSellerName(), listVo);
                    }
                } else {
                    // 組裝時間
                    OrderReturnVo resultVo = new OrderReturnVo();
                    resultVo.setBestTime(bestTime);

                    OrderReturnEntity entity = new OrderReturnEntity();
                    entity.setSellerName(vo.getSellerName());

                    List<OrderGoodsVo> paramOrderGoodsVo = new ArrayList<OrderGoodsVo>();
                    paramOrderGoodsVo.add(vo);
                    entity.setListOrderGoodsVo(paramOrderGoodsVo);

                    List<OrderReturnEntity> listOrderReturnEntity = new ArrayList<OrderReturnEntity>();
                    listOrderReturnEntity.add(entity);

                    resultVo.setListOrderReturnEntity(listOrderReturnEntity);

                    listResult.add(resultVo);

                    paramSellerMap.put(vo.getSellerName(), paramOrderGoodsVo);

                    paramTimeMap.put(bestTime, listOrderReturnEntity);
                }
            }
            return new JsonResult(JsonResultCode.SUCCESS, "查詢信息成功", listResult);
        } catch (Exception ex) {
            logger.error("[OrderReturnController][orderReturnItem] exception :", ex);
            return new JsonResult(JsonResultCode.FAILURE, "系統錯誤,請稍后重試", "");
        }
    }

 

APP運營截圖相對而言比較簡單,我這邊就不貼出來了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM