Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Litemall
Commits
fbc7dc6a
Commit
fbc7dc6a
authored
Jan 30, 2019
by
Junling Bu
Browse files
chore[litemall-admin-api, litemall-wx-api]: 取消编程式事务管理,采用@Transactional注解事务管理
parent
714870bf
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/job/OrderJob.java
View file @
fbc7dc6a
...
...
@@ -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
()
+
" 已经超期自动取消订单"
);
}
}
...
...
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminGoodsService.java
0 → 100644
View file @
fbc7dc6a
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
);
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminOrderService.java
0 → 100644
View file @
fbc7dc6a
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
();
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminGoodsController.java
View file @
fbc7dc6a
...
...
@@ -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
);
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminOrderController.java
View file @
fbc7dc6a
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
);
}
}
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/service/WxOrderService.java
0 → 100644
View file @
fbc7dc6a
This diff is collapsed.
Click to expand it.
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxOrderController.java
View file @
fbc7dc6a
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment