Commit fbc7dc6a authored by Junling Bu's avatar Junling Bu
Browse files

chore[litemall-admin-api, litemall-wx-api]: 取消编程式事务管理,采用@Transactional注解事务管理

parent 714870bf
......@@ -5,15 +5,14 @@ import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.db.domain.LitemallGoodsProduct;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.service.LitemallGoodsProductService;
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
......@@ -25,9 +24,6 @@ import java.util.List;
public class OrderJob {
private final Log logger = LogFactory.getLog(OrderJob.class);
@Autowired
private PlatformTransactionManager txManager;
@Autowired
private LitemallOrderGoodsService orderGoodsService;
@Autowired
......@@ -46,6 +42,7 @@ public class OrderJob {
* 这里可以进一步地配合用户订单查询时订单未付款检查,如果订单超时半小时则取消。
*/
@Scheduled(fixedDelay = 30 * 60 * 1000)
@Transactional
public void checkOrderUnpaid() {
logger.info("系统开启任务检查订单是否已经超期自动取消订单");
......@@ -58,35 +55,24 @@ public class OrderJob {
continue;
}
// 开启事务管理
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
// 设置订单已取消状态
order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
order.setEndTime(LocalDateTime.now());
if (orderService.updateWithOptimisticLocker(order) == 0) {
throw new Exception("更新数据已失效");
}
// 设置订单已取消状态
order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
order.setEndTime(LocalDateTime.now());
if (orderService.updateWithOptimisticLocker(order) == 0) {
throw new RuntimeException("更新数据已失效");
}
// 商品货品数量增加
Integer orderId = order.getId();
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
for (LitemallOrderGoods orderGoods : orderGoodsList) {
Integer productId = orderGoods.getProductId();
LitemallGoodsProduct product = productService.findById(productId);
Short number = orderGoods.getNumber();
if (productService.addStock(productId, number) == 0) {
throw new Exception("商品货品库存增加失败");
}
// 商品货品数量增加
Integer orderId = order.getId();
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
for (LitemallOrderGoods orderGoods : orderGoodsList) {
Integer productId = orderGoods.getProductId();
LitemallGoodsProduct product = productService.findById(productId);
Short number = orderGoods.getNumber();
if (productService.addStock(productId, number) == 0) {
throw new RuntimeException("商品货品库存增加失败");
}
} catch (Exception ex) {
txManager.rollback(status);
logger.info("订单 ID=" + order.getId() + " 数据更新失败,放弃自动确认收货");
return;
}
txManager.commit(status);
logger.info("订单 ID=" + order.getId() + " 已经超期自动取消订单");
}
}
......
package org.linlinjava.litemall.admin.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.dao.GoodsAllinone;
import org.linlinjava.litemall.admin.util.CatVo;
import org.linlinjava.litemall.core.qcode.QCodeService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_NAME_EXIST;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_UPDATE_NOT_ALLOWED;
@Service
public class AdminGoodsService {
private final Log logger = LogFactory.getLog(AdminGoodsService.class);
@Autowired
private LitemallGoodsService goodsService;
@Autowired
private LitemallGoodsSpecificationService specificationService;
@Autowired
private LitemallGoodsAttributeService attributeService;
@Autowired
private LitemallGoodsProductService productService;
@Autowired
private LitemallCategoryService categoryService;
@Autowired
private LitemallBrandService brandService;
@Autowired
private LitemallCartService cartService;
@Autowired
private LitemallOrderGoodsService orderGoodsService;
@Autowired
private QCodeService qCodeService;
public Object list(String goodsSn, String name,
Integer page, Integer limit, String sort, String order) {
List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);
int total = goodsService.countSelective(goodsSn, name, page, limit, sort, order);
Map<String, Object> data = new HashMap<>();
data.put("total", total);
data.put("items", goodsList);
return ResponseUtil.ok(data);
}
private Object validate(GoodsAllinone goodsAllinone) {
LitemallGoods goods = goodsAllinone.getGoods();
String name = goods.getName();
if (StringUtils.isEmpty(name)) {
return ResponseUtil.badArgument();
}
String goodsSn = goods.getGoodsSn();
if (StringUtils.isEmpty(goodsSn)) {
return ResponseUtil.badArgument();
}
// 品牌商可以不设置,如果设置则需要验证品牌商存在
Integer brandId = goods.getBrandId();
if (brandId != null && brandId != 0) {
if (brandService.findById(brandId) == null) {
return ResponseUtil.badArgumentValue();
}
}
// 分类可以不设置,如果设置则需要验证分类存在
Integer categoryId = goods.getCategoryId();
if (categoryId != null && categoryId != 0) {
if (categoryService.findById(categoryId) == null) {
return ResponseUtil.badArgumentValue();
}
}
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
for (LitemallGoodsAttribute attribute : attributes) {
String attr = attribute.getAttribute();
if (StringUtils.isEmpty(attr)) {
return ResponseUtil.badArgument();
}
String value = attribute.getValue();
if (StringUtils.isEmpty(value)) {
return ResponseUtil.badArgument();
}
}
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
for (LitemallGoodsSpecification specification : specifications) {
String spec = specification.getSpecification();
if (StringUtils.isEmpty(spec)) {
return ResponseUtil.badArgument();
}
String value = specification.getValue();
if (StringUtils.isEmpty(value)) {
return ResponseUtil.badArgument();
}
}
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
for (LitemallGoodsProduct product : products) {
Integer number = product.getNumber();
if (number == null || number < 0) {
return ResponseUtil.badArgument();
}
BigDecimal price = product.getPrice();
if (price == null) {
return ResponseUtil.badArgument();
}
String[] productSpecifications = product.getSpecifications();
if (productSpecifications.length == 0) {
return ResponseUtil.badArgument();
}
}
return null;
}
/**
* 编辑商品
* <p>
* TODO
* 目前商品修改的逻辑是
* 1. 更新litemall_goods表
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* <p>
* 这里商品三个表的数据采用删除再添加的策略是因为
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
* 只能删除三个表旧的数据,然后添加新的数据。
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
* 所以这里可能需要重新设计。
*/
@Transactional
public Object update(GoodsAllinone goodsAllinone) {
Object error = validate(goodsAllinone);
if (error != null) {
return error;
}
LitemallGoods goods = goodsAllinone.getGoods();
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
Integer id = goods.getId();
// 检查是否存在购物车商品或者订单商品
// 如果存在则拒绝修改商品。
if (orderGoodsService.checkExist(id)) {
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在订单中,不能修改");
}
if (cartService.checkExist(id)) {
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在购物车中,不能修改");
}
//将生成的分享图片地址写入数据库
String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
goods.setShareUrl(url);
// 商品基本信息表litemall_goods
if (goodsService.updateById(goods) == 0) {
throw new RuntimeException("更新数据失败");
}
Integer gid = goods.getId();
specificationService.deleteByGid(gid);
attributeService.deleteByGid(gid);
productService.deleteByGid(gid);
// 商品规格表litemall_goods_specification
for (LitemallGoodsSpecification specification : specifications) {
specification.setGoodsId(goods.getId());
specificationService.add(specification);
}
// 商品参数表litemall_goods_attribute
for (LitemallGoodsAttribute attribute : attributes) {
attribute.setGoodsId(goods.getId());
attributeService.add(attribute);
}
// 商品货品表litemall_product
for (LitemallGoodsProduct product : products) {
product.setGoodsId(goods.getId());
productService.add(product);
}
qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
return ResponseUtil.ok();
}
@Transactional
public Object delete(LitemallGoods goods) {
Integer id = goods.getId();
if (id == null) {
return ResponseUtil.badArgument();
}
Integer gid = goods.getId();
goodsService.deleteById(gid);
specificationService.deleteByGid(gid);
attributeService.deleteByGid(gid);
productService.deleteByGid(gid);
return ResponseUtil.ok();
}
@Transactional
public Object create(GoodsAllinone goodsAllinone) {
Object error = validate(goodsAllinone);
if (error != null) {
return error;
}
LitemallGoods goods = goodsAllinone.getGoods();
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
String name = goods.getName();
if (goodsService.checkExistByName(name)) {
return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已经存在");
}
// 商品基本信息表litemall_goods
goodsService.add(goods);
//将生成的分享图片地址写入数据库
String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
if (!StringUtils.isEmpty(url)) {
goods.setShareUrl(url);
if (goodsService.updateById(goods) == 0) {
throw new RuntimeException("更新数据失败");
}
}
// 商品规格表litemall_goods_specification
for (LitemallGoodsSpecification specification : specifications) {
specification.setGoodsId(goods.getId());
specificationService.add(specification);
}
// 商品参数表litemall_goods_attribute
for (LitemallGoodsAttribute attribute : attributes) {
attribute.setGoodsId(goods.getId());
attributeService.add(attribute);
}
// 商品货品表litemall_product
for (LitemallGoodsProduct product : products) {
product.setGoodsId(goods.getId());
productService.add(product);
}
return ResponseUtil.ok();
}
public Object list2() {
// http://element-cn.eleme.io/#/zh-CN/component/cascader
// 管理员设置“所属分类”
List<LitemallCategory> l1CatList = categoryService.queryL1();
List<CatVo> categoryList = new ArrayList<>(l1CatList.size());
for (LitemallCategory l1 : l1CatList) {
CatVo l1CatVo = new CatVo();
l1CatVo.setValue(l1.getId());
l1CatVo.setLabel(l1.getName());
List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());
List<CatVo> children = new ArrayList<>(l2CatList.size());
for (LitemallCategory l2 : l2CatList) {
CatVo l2CatVo = new CatVo();
l2CatVo.setValue(l2.getId());
l2CatVo.setLabel(l2.getName());
children.add(l2CatVo);
}
l1CatVo.setChildren(children);
categoryList.add(l1CatVo);
}
// http://element-cn.eleme.io/#/zh-CN/component/select
// 管理员设置“所属品牌商”
List<LitemallBrand> list = brandService.all();
List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());
for (LitemallBrand brand : list) {
Map<String, Object> b = new HashMap<>(2);
b.put("value", brand.getId());
b.put("label", brand.getName());
brandList.add(b);
}
Map<String, Object> data = new HashMap<>();
data.put("categoryList", categoryList);
data.put("brandList", brandList);
return ResponseUtil.ok(data);
}
public Object detail(Integer id) {
LitemallGoods goods = goodsService.findById(id);
List<LitemallGoodsProduct> products = productService.queryByGid(id);
List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);
List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);
Integer categoryId = goods.getCategoryId();
LitemallCategory category = categoryService.findById(categoryId);
Integer[] categoryIds = new Integer[]{};
if (category != null) {
Integer parentCategoryId = category.getPid();
categoryIds = new Integer[]{parentCategoryId, categoryId};
}
Map<String, Object> data = new HashMap<>();
data.put("goods", goods);
data.put("specifications", specifications);
data.put("products", products);
data.put("attributes", attributes);
data.put("categoryIds", categoryIds);
return ResponseUtil.ok(data);
}
}
package org.linlinjava.litemall.admin.service;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallComment;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.domain.UserVo;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;
@Service
public class AdminOrderService {
private final Log logger = LogFactory.getLog(AdminOrderService.class);
@Autowired
private LitemallOrderGoodsService orderGoodsService;
@Autowired
private LitemallOrderService orderService;
@Autowired
private LitemallGoodsProductService productService;
@Autowired
private LitemallUserService userService;
@Autowired
private LitemallCommentService commentService;
@Autowired
private WxPayService wxPayService;
@Autowired
private NotifyService notifyService;
public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,
Integer page, Integer limit, String sort, String order) {
List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
int total = orderService.countSelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
Map<String, Object> data = new HashMap<>();
data.put("total", total);
data.put("items", orderList);
return ResponseUtil.ok(data);
}
public Object detail(Integer id) {
LitemallOrder order = orderService.findById(id);
List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);
UserVo user = userService.findUserVoById(order.getUserId());
Map<String, Object> data = new HashMap<>();
data.put("order", order);
data.put("orderGoods", orderGoods);
data.put("user", user);
return ResponseUtil.ok(data);
}
/**
* 订单退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 微信退款操作;
* 3. 设置订单退款确认状态;
* 4. 订单商品库存回库。
* <p>
* TODO
* 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:
* 1. 管理员登录微信官方支付平台点击退款操作进行退款
* 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
*
* @param body 订单信息,{ orderId:xxx }
* @return 订单退款操作结果
*/
@Transactional
public Object refund(String body) {
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
String refundMoney = JacksonUtil.parseString(body, "refundMoney");
if (orderId == null) {
return ResponseUtil.badArgument();
}
if (StringUtils.isEmpty(refundMoney)) {
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId);
if (order == null) {
return ResponseUtil.badArgument();
}
if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {
return ResponseUtil.badArgumentValue();
}
// 如果订单不是退款状态,则不能退款
if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {
return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
}
// 微信退款
WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
wxPayRefundRequest.setOutTradeNo(order.getOrderSn());
wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());
// 元转成分
Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
wxPayRefundRequest.setTotalFee(totalFee);
wxPayRefundRequest.setRefundFee(totalFee);
WxPayRefundResult wxPayRefundResult = null;
try {
wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
} catch (WxPayException e) {
e.printStackTrace();
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {
logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
// 设置订单取消状态
order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
if (orderService.updateWithOptimisticLocker(order) == 0) {
throw new RuntimeException("更新数据已失效");
}
// 商品货品数量增加
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
for (LitemallOrderGoods orderGoods : orderGoodsList) {
Integer productId = orderGoods.getProductId();
Short number = orderGoods.getNumber();
if (productService.addStock(productId, number) == 0) {
throw new RuntimeException("商品货品库存增加失败");
}
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
// 注意订单号只发后6位
notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});
return ResponseUtil.ok();
}
/**
* 发货
* 1. 检测当前订单是否能够发货
* 2. 设置订单发货状态
*
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
public Object ship(String body) {
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
String shipSn = JacksonUtil.parseString(body, "shipSn");
String shipChannel = JacksonUtil.parseString(body, "shipChannel");
if (orderId == null || shipSn == null || shipChannel == null) {
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId);
if (order == null) {
return ResponseUtil.badArgument();
}
// 如果订单不是已付款状态,则不能发货
if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {
return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
}
order.setOrderStatus(OrderUtil.STATUS_SHIP);
order.setShipSn(shipSn);
order.setShipChannel(shipChannel);
order.setShipTime(LocalDateTime.now());
if (orderService.updateWithOptimisticLocker(order) == 0) {
return ResponseUtil.updatedDateExpired();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 发货会发送通知短信给用户: *
// "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"
notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});
return ResponseUtil.ok();
}
/**
* 回复订单商品
*
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
public Object reply(String body) {
Integer commentId = JacksonUtil.parseInteger(body, "commentId");
if (commentId == null || commentId == 0) {
return ResponseUtil.badArgument();
}
// 目前只支持回复一次
if (commentService.findById(commentId) != null) {
return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复!");
}
String content = JacksonUtil.parseString(body, "content");
if (StringUtils.isEmpty(content)) {
return ResponseUtil.badArgument();
}
// 创建评价回复
LitemallComment comment = new LitemallComment();
comment.setType((byte) 2);
comment.setValueId(commentId);
comment.setContent(content);
comment.setUserId(0); // 评价回复没有用
comment.setStar((short) 0); // 评价回复没有用
comment.setHasPicture(false); // 评价回复没有用
comment.setPicUrls(new String[]{}); // 评价回复没有用
commentService.save(comment);
return ResponseUtil.ok();
}
}
......@@ -5,31 +5,15 @@ import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
import org.linlinjava.litemall.admin.dao.GoodsAllinone;
import org.linlinjava.litemall.admin.util.CatVo;
import org.linlinjava.litemall.core.qcode.QCodeService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.admin.service.AdminGoodsService;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.domain.LitemallGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_NAME_EXIST;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_UPDATE_NOT_ALLOWED;
@RestController
@RequestMapping("/admin/goods")
......@@ -38,366 +22,88 @@ public class AdminGoodsController {
private final Log logger = LogFactory.getLog(AdminGoodsController.class);
@Autowired
private PlatformTransactionManager txManager;
@Autowired
private LitemallGoodsService goodsService;
@Autowired
private LitemallGoodsSpecificationService specificationService;
@Autowired
private LitemallGoodsAttributeService attributeService;
@Autowired
private LitemallGoodsProductService productService;
@Autowired
private LitemallCategoryService categoryService;
@Autowired
private LitemallBrandService brandService;
@Autowired
private LitemallCartService cartService;
@Autowired
private LitemallOrderGoodsService orderGoodsService;
@Autowired
private QCodeService qCodeService;
private AdminGoodsService adminGoodsService;
/**
* 查询商品
*
* @param goodsSn
* @param name
* @param page
* @param limit
* @param sort
* @param order
* @return
*/
@RequiresPermissions("admin:goods:list")
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="查询")
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "查询")
@GetMapping("/list")
public Object list(String goodsSn, String name,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer limit,
@Sort @RequestParam(defaultValue = "add_time") String sort,
@Order @RequestParam(defaultValue = "desc") String order) {
List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);
int total = goodsService.countSelective(goodsSn, name, page, limit, sort, order);
Map<String, Object> data = new HashMap<>();
data.put("total", total);
data.put("items", goodsList);
return ResponseUtil.ok(data);
}
private Object validate(GoodsAllinone goodsAllinone) {
LitemallGoods goods = goodsAllinone.getGoods();
String name = goods.getName();
if (StringUtils.isEmpty(name)) {
return ResponseUtil.badArgument();
}
String goodsSn = goods.getGoodsSn();
if (StringUtils.isEmpty(goodsSn)) {
return ResponseUtil.badArgument();
}
// 品牌商可以不设置,如果设置则需要验证品牌商存在
Integer brandId = goods.getBrandId();
if (brandId != null && brandId != 0) {
if (brandService.findById(brandId) == null) {
return ResponseUtil.badArgumentValue();
}
}
// 分类可以不设置,如果设置则需要验证分类存在
Integer categoryId = goods.getCategoryId();
if (categoryId != null && categoryId != 0) {
if (categoryService.findById(categoryId) == null) {
return ResponseUtil.badArgumentValue();
}
}
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
for (LitemallGoodsAttribute attribute : attributes) {
String attr = attribute.getAttribute();
if (StringUtils.isEmpty(attr)) {
return ResponseUtil.badArgument();
}
String value = attribute.getValue();
if (StringUtils.isEmpty(value)) {
return ResponseUtil.badArgument();
}
}
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
for (LitemallGoodsSpecification specification : specifications) {
String spec = specification.getSpecification();
if (StringUtils.isEmpty(spec)) {
return ResponseUtil.badArgument();
}
String value = specification.getValue();
if (StringUtils.isEmpty(value)) {
return ResponseUtil.badArgument();
}
}
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
for (LitemallGoodsProduct product : products) {
Integer number = product.getNumber();
if (number == null || number < 0) {
return ResponseUtil.badArgument();
}
BigDecimal price = product.getPrice();
if (price == null) {
return ResponseUtil.badArgument();
}
String[] productSpecifications = product.getSpecifications();
if (productSpecifications.length == 0) {
return ResponseUtil.badArgument();
}
}
return null;
return adminGoodsService.list(goodsSn, name, page, limit, sort, order);
}
/**
* 编辑商品
* <p>
* TODO
* 目前商品修改的逻辑是
* 1. 更新litemall_goods表
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
*
* 这里商品三个表的数据采用删除再添加的策略是因为
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
* 只能删除三个表旧的数据,然后添加新的数据。
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
* 所以这里可能需要重新设计。
* @param goodsAllinone
* @return
*/
@RequiresPermissions("admin:goods:update")
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="编辑")
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "编辑")
@PostMapping("/update")
public Object update(@RequestBody GoodsAllinone goodsAllinone) {
Object error = validate(goodsAllinone);
if (error != null) {
return error;
}
LitemallGoods goods = goodsAllinone.getGoods();
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
Integer id = goods.getId();
// 检查是否存在购物车商品或者订单商品
// 如果存在则拒绝修改商品。
if(orderGoodsService.checkExist(id)){
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在订单中,不能修改");
}
if(cartService.checkExist(id)){
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在购物车中,不能修改");
}
// 开启事务管理
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
//将生成的分享图片地址写入数据库
String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
goods.setShareUrl(url);
// 商品基本信息表litemall_goods
if (goodsService.updateById(goods) == 0) {
throw new Exception("更新数据失败");
}
Integer gid = goods.getId();
specificationService.deleteByGid(gid);
attributeService.deleteByGid(gid);
productService.deleteByGid(gid);
// 商品规格表litemall_goods_specification
for (LitemallGoodsSpecification specification : specifications) {
specification.setGoodsId(goods.getId());
specificationService.add(specification);
}
// 商品参数表litemall_goods_attribute
for (LitemallGoodsAttribute attribute : attributes) {
attribute.setGoodsId(goods.getId());
attributeService.add(attribute);
}
// 商品货品表litemall_product
for (LitemallGoodsProduct product : products) {
product.setGoodsId(goods.getId());
productService.add(product);
}
} catch (Exception ex) {
txManager.rollback(status);
logger.error("系统内部错误", ex);
return ResponseUtil.fail();
}
txManager.commit(status);
qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
return ResponseUtil.ok();
return adminGoodsService.update(goodsAllinone);
}
/**
* 删除商品
*
* @param goods
* @return
*/
@RequiresPermissions("admin:goods:delete")
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="删除")
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "删除")
@PostMapping("/delete")
public Object delete(@RequestBody LitemallGoods goods) {
Integer id = goods.getId();
if (id == null) {
return ResponseUtil.badArgument();
}
// 开启事务管理
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
Integer gid = goods.getId();
goodsService.deleteById(gid);
specificationService.deleteByGid(gid);
attributeService.deleteByGid(gid);
productService.deleteByGid(gid);
} catch (Exception ex) {
txManager.rollback(status);
logger.error("系统内部错误", ex);
return ResponseUtil.fail();
}
txManager.commit(status);
return ResponseUtil.ok();
return adminGoodsService.delete(goods);
}
/**
* 添加商品
*
* @param goodsAllinone
* @return
*/
@RequiresPermissions("admin:goods:create")
@RequiresPermissionsDesc(menu={"商品管理" , "商品上架"}, button="上架")
@RequiresPermissionsDesc(menu = {"商品管理", "商品上架"}, button = "上架")
@PostMapping("/create")
public Object create(@RequestBody GoodsAllinone goodsAllinone) {
Object error = validate(goodsAllinone);
if (error != null) {
return error;
}
LitemallGoods goods = goodsAllinone.getGoods();
LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();
LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
LitemallGoodsProduct[] products = goodsAllinone.getProducts();
String name = goods.getName();
if (goodsService.checkExistByName(name)) {
return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已经存在");
}
// 开启事务管理
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
// 商品基本信息表litemall_goods
goodsService.add(goods);
//将生成的分享图片地址写入数据库
String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
if (!StringUtils.isEmpty(url)) {
goods.setShareUrl(url);
if (goodsService.updateById(goods) == 0) {
throw new Exception("更新数据失败");
}
}
// 商品规格表litemall_goods_specification
for (LitemallGoodsSpecification specification : specifications) {
specification.setGoodsId(goods.getId());
specificationService.add(specification);
}
// 商品参数表litemall_goods_attribute
for (LitemallGoodsAttribute attribute : attributes) {
attribute.setGoodsId(goods.getId());
attributeService.add(attribute);
}
// 商品货品表litemall_product
for (LitemallGoodsProduct product : products) {
product.setGoodsId(goods.getId());
productService.add(product);
}
} catch (Exception ex) {
txManager.rollback(status);
logger.error("系统内部错误", ex);
return ResponseUtil.fail();
}
txManager.commit(status);
return ResponseUtil.ok();
return adminGoodsService.create(goodsAllinone);
}
@RequiresPermissions("admin:goods:list")
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="查询")
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "查询")
@GetMapping("/catAndBrand")
public Object list2() {
// http://element-cn.eleme.io/#/zh-CN/component/cascader
// 管理员设置“所属分类”
List<LitemallCategory> l1CatList = categoryService.queryL1();
List<CatVo> categoryList = new ArrayList<>(l1CatList.size());
for (LitemallCategory l1 : l1CatList) {
CatVo l1CatVo = new CatVo();
l1CatVo.setValue(l1.getId());
l1CatVo.setLabel(l1.getName());
List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());
List<CatVo> children = new ArrayList<>(l2CatList.size());
for (LitemallCategory l2 : l2CatList) {
CatVo l2CatVo = new CatVo();
l2CatVo.setValue(l2.getId());
l2CatVo.setLabel(l2.getName());
children.add(l2CatVo);
}
l1CatVo.setChildren(children);
categoryList.add(l1CatVo);
}
// http://element-cn.eleme.io/#/zh-CN/component/select
// 管理员设置“所属品牌商”
List<LitemallBrand> list = brandService.all();
List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());
for (LitemallBrand brand : list) {
Map<String, Object> b = new HashMap<>(2);
b.put("value", brand.getId());
b.put("label", brand.getName());
brandList.add(b);
}
Map<String, Object> data = new HashMap<>();
data.put("categoryList", categoryList);
data.put("brandList", brandList);
return ResponseUtil.ok(data);
return adminGoodsService.list2();
}
/**
* 商品详情
*
* @param id
* @return
*/
@RequiresPermissions("admin:goods:read")
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="编辑")
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "编辑")
@GetMapping("/detail")
public Object detail(@NotNull Integer id) {
LitemallGoods goods = goodsService.findById(id);
List<LitemallGoodsProduct> products = productService.queryByGid(id);
List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);
List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);
Integer categoryId = goods.getCategoryId();
LitemallCategory category = categoryService.findById(categoryId);
Integer[] categoryIds = new Integer[]{};
if (category != null) {
Integer parentCategoryId = category.getPid();
categoryIds = new Integer[]{parentCategoryId, categoryId};
}
Map<String, Object> data = new HashMap<>();
data.put("goods", goods);
data.put("specifications", specifications);
data.put("products", products);
data.put("attributes", attributes);
data.put("categoryIds", categoryIds);
return adminGoodsService.detail(id);
return ResponseUtil.ok(data);
}
}
package org.linlinjava.litemall.admin.web;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.admin.service.AdminOrderService;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.LitemallComment;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.domain.UserVo;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;
@RestController
@RequestMapping("/admin/order")
......@@ -45,25 +21,22 @@ public class AdminOrderController {
private final Log logger = LogFactory.getLog(AdminOrderController.class);
@Autowired
private PlatformTransactionManager txManager;
@Autowired
private LitemallOrderGoodsService orderGoodsService;
@Autowired
private LitemallOrderService orderService;
@Autowired
private LitemallGoodsProductService productService;
@Autowired
private LitemallUserService userService;
@Autowired
private LitemallCommentService commentService;
@Autowired
private WxPayService wxPayService;
@Autowired
private NotifyService notifyService;
private AdminOrderService adminOrderService;
/**
* 查询订单
*
* @param userId
* @param orderSn
* @param orderStatusArray
* @param page
* @param limit
* @param sort
* @param order
* @return
*/
@RequiresPermissions("admin:order:list")
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="查询")
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "查询")
@GetMapping("/list")
public Object list(Integer userId, String orderSn,
@RequestParam(required = false) List<Short> orderStatusArray,
......@@ -71,218 +44,60 @@ public class AdminOrderController {
@RequestParam(defaultValue = "10") Integer limit,
@Sort @RequestParam(defaultValue = "add_time") String sort,
@Order @RequestParam(defaultValue = "desc") String order) {
List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
int total = orderService.countSelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
Map<String, Object> data = new HashMap<>();
data.put("total", total);
data.put("items", orderList);
return ResponseUtil.ok(data);
return adminOrderService.list(userId, orderSn, orderStatusArray, page, limit, sort, order);
}
/**
* 订单详情
*
* @param id
* @return
*/
@RequiresPermissions("admin:order:read")
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="详情")
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "详情")
@GetMapping("/detail")
public Object detail(@NotNull Integer id) {
LitemallOrder order = orderService.findById(id);
List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);
UserVo user = userService.findUserVoById(order.getUserId());
Map<String, Object> data = new HashMap<>();
data.put("order", order);
data.put("orderGoods", orderGoods);
data.put("user", user);
return ResponseUtil.ok(data);
return adminOrderService.detail(id);
}
/**
* 订单退款
* <p>
* 1. 检测当前订单是否能够退款;
* 2. 微信退款操作;
* 3. 设置订单退款确认状态;
* 4. 订单商品库存回库。
* <p>
* TODO
* 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:
* 1. 管理员登录微信官方支付平台点击退款操作进行退款
* 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
*
* @param body 订单信息,{ orderId:xxx }
* @param body 订单信息,{ orderId:xxx }
* @return 订单退款操作结果
*/
@RequiresPermissions("admin:order:refund")
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单退款")
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单退款")
@PostMapping("refund")
public Object refund(@RequestBody String body) {
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
String refundMoney = JacksonUtil.parseString(body, "refundMoney");
if (orderId == null) {
return ResponseUtil.badArgument();
}
if(StringUtils.isEmpty(refundMoney)){
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId);
if (order == null) {
return ResponseUtil.badArgument();
}
if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {
return ResponseUtil.badArgumentValue();
}
// 如果订单不是退款状态,则不能退款
if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {
return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
}
// 微信退款
WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
wxPayRefundRequest.setOutTradeNo(order.getOrderSn());
wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());
// 元转成分
Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
wxPayRefundRequest.setTotalFee(totalFee);
wxPayRefundRequest.setRefundFee(totalFee);
WxPayRefundResult wxPayRefundResult = null;
try {
wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
} catch (WxPayException e) {
e.printStackTrace();
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
if(!wxPayRefundResult.getReturnCode().equals("SUCCESS")){
logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
if(!wxPayRefundResult.getResultCode().equals("SUCCESS")){
logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
// 开启事务管理
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
// 设置订单取消状态
order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
if (orderService.updateWithOptimisticLocker(order) == 0) {
throw new Exception("更新数据已失效");
}
// 商品货品数量增加
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
for (LitemallOrderGoods orderGoods : orderGoodsList) {
Integer productId = orderGoods.getProductId();
Short number = orderGoods.getNumber();
if (productService.addStock(productId, number) == 0) {
throw new Exception("商品货品库存增加失败");
}
}
} catch (Exception ex) {
txManager.rollback(status);
logger.error("系统内部错误", ex);
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
}
txManager.commit(status);
//TODO 发送邮件和短信通知,这里采用异步发送
// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
// 注意订单号只发后6位
notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});
return ResponseUtil.ok();
return adminOrderService.refund(body);
}
/**
* 发货
* 1. 检测当前订单是否能够发货
* 2. 设置订单发货状态
*
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
@RequiresPermissions("admin:order:ship")
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单发货")
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单发货")
@PostMapping("ship")
public Object ship(@RequestBody String body) {
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
String shipSn = JacksonUtil.parseString(body, "shipSn");
String shipChannel = JacksonUtil.parseString(body, "shipChannel");
if (orderId == null || shipSn == null || shipChannel == null) {
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId);
if (order == null) {
return ResponseUtil.badArgument();
}
// 如果订单不是已付款状态,则不能发货
if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {
return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
}
order.setOrderStatus(OrderUtil.STATUS_SHIP);
order.setShipSn(shipSn);
order.setShipChannel(shipChannel);
order.setShipTime(LocalDateTime.now());
if (orderService.updateWithOptimisticLocker(order) == 0) {
return ResponseUtil.updatedDateExpired();
}
//TODO 发送邮件和短信通知,这里采用异步发送
// 发货会发送通知短信给用户: *
// "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"
notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});
return ResponseUtil.ok();
return adminOrderService.ship(body);
}
/**
* 回复订单商品
*
* @param body 订单信息,{ orderId:xxx }
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
@RequiresPermissions("admin:order:reply")
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单商品回复")
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单商品回复")
@PostMapping("reply")
public Object reply(@RequestBody String body) {
Integer commentId = JacksonUtil.parseInteger(body, "commentId");
if (commentId == null || commentId == 0) {
return ResponseUtil.badArgument();
}
// 目前只支持回复一次
if (commentService.findById(commentId) != null) {
return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复!");
}
String content = JacksonUtil.parseString(body, "content");
if (StringUtils.isEmpty(content)) {
return ResponseUtil.badArgument();
}
// 创建评价回复
LitemallComment comment = new LitemallComment();
comment.setType((byte) 2);
comment.setValueId(commentId);
comment.setContent(content);
comment.setUserId(0); // 评价回复没有用
comment.setStar((short) 0); // 评价回复没有用
comment.setHasPicture(false); // 评价回复没有用
comment.setPicUrls(new String[]{}); // 评价回复没有用
commentService.save(comment);
return ResponseUtil.ok();
return adminOrderService.reply(body);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment