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

Java生鮮電商平臺-售後模塊的設計與架構數據庫

 

說明:任何一個的電商平臺都有售後服務系統,那麼對於咱們這個生鮮的電商平臺,售後系統須要思考如下幾個維度。微信

 

          1. 買家的需求維度架構

             說明:買家在平臺上沒找到本身想要的東西,咱們須要提供給他一個入口,告訴咱們他有這個需求,咱們進行改進。系統須要有記錄這種狀況,同時也有回覆客戶的狀況。app

          2. 投訴入口設計

              說明:有客戶性子比較急,他有問題,就會立刻打電話給客服,客服須要解答與回答,維護客戶關係。對於系統而言,須要記錄這種狀況,而後分析問題與解決問題。日誌

          3. IM聊天入口code

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

          4. 退貨問題圖片

              說明:售後系統中,退貨問題是最繁瑣的,買家存在如下兩種狀況。rem

                      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運營截圖相對而言比較簡單,我這邊就不貼出來了。

相關文章
相關標籤/搜索