1.商家平台-订单操作(添加/移除菜品) 问题同购物车操作
1)商家平台发送操作订单项请求;
2)判断当前订单状态是否为待付款【DFK】,为true进行下一步;为false,终止操作;
3)给当前订单加锁,调用tryLock( )方法,判断是否获得锁,获得锁进行下一步,如果没获得锁可再次取得锁;
4)判断当前订单项请求的操作类型,是add还是remove;
订单操作项的操作类型是add:
5)添加可核算订单项,判断菜品状态是否为起售,为true进行下一步;为false,终止当然操作,抛异常;
6)redis预扣菜品库存,需要判断菜品库存预扣之后是否为负,如果为负就不能扣;
7)判断redis预扣是否成功,为true下一步;为false,终止操作;
8)修改redis的可核算订单项;
9)扣减数据库的菜品库存,判断扣减是否成功,为true走下一步;为false,mysql的菜品库存扣减失败,redis库存回滚;
订单操作项的操作类型是remove:
5)移除可核算订单项;
6)修改可核算订单项;
7)在数据库增加菜品库存,判断菜品库存增加是否成功,为true进行下一步;为false终止当前操作,并回滚菜品库存;
8)redis中菜品库存增加,增加的数量是和数据库的菜品库存数量是一致的;
10)计算订单总金额;
11)修改订单总金额;
12)返回新订单信息。
2.转台需要满足什么条件?
1)桌台状态:当前桌台【使用中】、目标桌台【空闲中】;
2)目标桌台,不能是当前桌台;
3)当前桌台的账单状态:待付款【DFK】。
3.转台为什么需要加分布式锁? 怎么添加?
为了避免客户在转台过程中,目标桌台同时被多个请求扫码开桌,有悖于一个桌台在同一时刻只能有一个订单的设计。
key是业务前缀+目标桌台的ID,调用getLock( )方法给key上锁,可以再次调用tryLock( )方法给保证锁一定加上去了。
//1、锁定目标桌台
String keyTargetTableId = AppletCacheConstant.OPEN_TABLE_LOCK + targetTableId;
RLock lock = redissonClient.getLock(keyTargetTableId);
if (lock.tryLock(
AppletCacheConstant.REDIS_LEASETIME,
AppletCacheConstant.REDIS_WAIT_TIME,
TimeUnit.SECONDS)) {
}
4.转台业务流程?
1)客户端发起转台请求;
2)从请求参数提取目标桌台的ID,通过ID给目标桌台加分布式锁,保证在同一时刻只有一个请求进入;
3)判断目标桌台是否获得锁,为true进行下一步;为false终止当前操作,转台失败;
4)查询目标桌台的信息,判断目标桌台当前状态是否空闲(FREE),为true进行下一步;为false终止当前操作,转台失败;
5)将订单从原桌台关联到新桌台;
6)修改新桌台的状态,由空闲(FREE)改为使用中(USE);
7)判断桌台状态是否修改成功,为true,完成转台操作;为false终止当前操作,转台失败。
5.订单结算的状态有哪些?
订单状态 | 解释 | |
---|---|---|
待支付 | 用户下单创建订单时 | |
支付中 | 收银员发起结算,生产二维码,用户未扫码或扫码后,第三方为给出最终结果 | |
支付失败 | 第三方告知当前订单结算失败时 | |
已结算 | 第三方告知当前订单结算成功时 | |
免单 | 当前订单无需支付,直接结单 | |
退款【单独字段】 | 已结算后发起的线下退款操作 |
6.结算时,为什么需要根据订单生成交易单?
1)项目解耦,设计成通用的支付服务;
2)支付失败时,基于原始订单可以重新生成新的交易单发起新的支付;
3)使用交易单,可以设计合并支付的功能。
7.退款满足条件是什么?
1)订单处于【已结算】,才可退款;
2)退款金额不能超过实付款;
3)收款人和退款人必须是同一个人,如果不同不可退款