文章目录
仓储服务对应于gulimall-ware服务,首先需要将该服务注册进nacos注册中心
① 配置nacos的注册中心地址:(application.yml),增加一些配置
server:
port: 11000
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.146.129:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: gulimall-ware
cloud:
nacos:
discovery:
server-addr: localhost:8848
jackson:
date-format: yyyy-MM-dd HH:mm:ss
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
logic-delete-value: 1
logic-not-delete-value: 0
logging:
level:
com.atguigu: debug
②配置bootstrap.properties文件
spring.application.name=gulimall-ware
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.namespace=e64cac44-a064-4d89-9608-3f98dbab2232
spring.cloud.nacos.config.extension-configs[0].data-id=gulimall-ware.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
③gulimall-ware主启动类:开启服务注册与发现,事务
package com.atguigu.gulimall.ware;
@EnableTransactionManagement
@MapperScan("com.atguigu.gulimall.ware.dao")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallWareApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallWareApplication.class, args);
}
}
④gulimall-gateway中配置路由网关
- id: ware_route
uri: lb://gulimall-ware
predicates:
- Path=/api/ware/**
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
10.1查询 仓库维护 列表(模糊查询)wms_ware_info
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/mZgdqOWe
需要根据条件进行模糊检索:
①gulimall-ware : WareInfoController
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = wareInfoService.queryPage(params);
return R.ok().put("page", page);
}
②gulimall-ware : WareInfoServiceImpl
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<WareInfoEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if(!StringUtils.isEmpty(key)){
queryWrapper.and((wrapper)->{
wrapper.eq("id",key)//前端界面只有一个白框,关键字key (参数名)
.or().like("name",key)
.or().like("address",key)
.or().like("areacode",key);
});
}
IPage<WareInfoEntity> page = this.page(
new Query<WareInfoEntity>().getPage(params),queryWrapper);
return new PageUtils(page);
}
③测试:模糊查询
10.2 查询 商品库存 列表 wms_ware_sku
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/hwXrEXBZ
①gulimall-ware : WareSkuController
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = wareSkuService.queryPage(params);
return R.ok().put("page", page);
}
②gulimall-ware : WareSkuServiceImpl
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
String skuId = (String) params.get("skuId");
if(!StringUtils.isEmpty(skuId)){
queryWrapper.eq("sku_id",skuId);//前端界面有sku_id选项,不再是关键字key (参数名)
}
String wareId = (String) params.get("wareId");//前端界面有ware_id选项,
if(!StringUtils.isEmpty(wareId)){
queryWrapper.eq("ware_id",wareId);
}
IPage<WareSkuEntity> page = this.page(
new Query<WareSkuEntity>().getPage(params),queryWrapper);
return new PageUtils(page);
}
③测试查询
10.3 查询新增 采购需求 wms_purchase_detail
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/Ss4zsV7R
①gulimall-ware : PurchaseDetailController
@RequestMapping("/list")
//@RequiresPermissions("ware:purchasedetail:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = purchaseDetailService.queryPage(params);
return R.ok().put("page", page);
}
②gulimall-ware : PurchaseDetailServiceImpl
@Override
public PageUtils queryPage(Map<String, Object> params) {
// key: '华为',//检索关键字
// status: 0,//状态
// wareId: 1,//仓库id
QueryWrapper<PurchaseDetailEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if(!StringUtils.isEmpty(key)){
queryWrapper.and((wrapper)->{
wrapper.eq("purchase_id",key).or().eq("sku_id",key);
});
}
String status = (String) params.get("status");
if(!StringUtils.isEmpty(status)){
queryWrapper.eq("status", status);
}
String wareId = (String) params.get("wareId");
if(!StringUtils.isEmpty(wareId)){
queryWrapper.eq("ware_id",wareId);
}
IPage<PurchaseDetailEntity> page = this.page(
new Query<PurchaseDetailEntity>().getPage(params),queryWrapper);
return new PageUtils(page);
}
③测试
10.4 采购单维护栏
主要就是两个栏目 采购单和采购需求
1、查询采购单(自己添加)
连接:ware/purchase/list
①gulimall-ware : PurchaseController
@RequestMapping("/list")
//@RequiresPermissions("ware:purchase:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = purchaseService.queryPage(params);
return R.ok().put("page", page);
}
②gulimall-ware : PurchaseServiceImpl
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<PurchaseEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if(!StringUtils.isEmpty(key)){
queryWrapper.and((wrapper)->{
wrapper.eq("id",key).or().like("assignee_name",key);
});
}
String status = (String) params.get("status");
if(!StringUtils.isEmpty(status)){
queryWrapper.eq("status", status);
}
IPage<PurchaseEntity> page = this.page(
new Query<PurchaseEntity>().getPage(params),queryWrapper);
return new PageUtils(page);
}
③前端添加状态status,在purchase.vue中添加**status: this.dataForm.status,**因为原先没有这个语句,所以后端写了判断status的语句查询也不行,所以加上前端这句,params就会携带数据到后端处理,当再次返回页面就能模糊查询status相关的。
// 获取数据列表
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
status: this.dataForm.status,
key: this.dataForm.key
})
④测试
2、查询未领取的 采购单(分配采购单)wms_purchase
:https://easydoc.xyz/s/78237135/ZUqEdvA4/hI12DNrH
①gulimall-ware : PurchaseController
@RequestMapping("/unreceive/list")//查询未领取采购的列表
public R unreceivelist(@RequestParam Map<String, Object> params){
PageUtils page = purchaseService.queryPageUnreceivedPurchase(params);
return R.ok().put("page", page);
}
②gulimall-ware : PurchaseServiceImpl
@Override
public PageUtils queryPageUnreceivedPurchase(Map<String, Object> params) {
IPage<PurchaseEntity> page = this.page(
new Query<PurchaseEntity>().getPage(params),
new QueryWrapper<PurchaseEntity>()
//新建和已分配状态的采购需求
.eq("status",0).or().eq("status",1)
);
return new PageUtils(page);
}
③采购单(新增和分配)测试
首选新增采购单,接着添加一个管理员,其次点击分配采购人员
3、合并 采购需求 到采购单
:https://easydoc.xyz/s/78237135/ZUqEdvA4/cUlv9QvK
将下面的两个采购需求合并为一个采购单:
①gulimall-ware : PurchaseController
@PostMapping("/merge")
public R merge(@RequestBody MergeVo mergeVo){
purchaseService.mergePurchase(mergeVo);
return R.ok();
}
②gulimall-ware : PurchaseServiceImpl
@Transactional
@Override
public void mergePurchase(MergeVo mergeVo) {
Long purchaseId = mergeVo.getPurchaseId();
//如果没有默认的采购单(没有选择采购单),还需要新建采购单
if(purchaseId==null){
PurchaseEntity purchaseEntity = new PurchaseEntity();
//采购单的状态为新建状态
purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
purchaseEntity.setCreateTime(new Date());
purchaseEntity.setUpdateTime(new Date());
this.save(purchaseEntity);
//得到采购单id
purchaseId = purchaseEntity.getId();
}else{//如果选择采购单,则执行下面步骤
List<Long> items = mergeVo.getItems();
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> collect = items.stream().map((item) -> {
//新建采购需求实体类
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(item);
purchaseDetailEntity.setPurchaseId(finalPurchaseId);
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
purchaseDetailService.updateBatchById(collect);
//在合并完采购单后,希望新的采购单时间显示是正确的
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setCreateTime(new Date());
purchaseEntity.setUpdateTime(new Date());
purchaseEntity.setId(purchaseId);
this.updateById(purchaseEntity);
}
}
③测试结果:
10.5 领取采购单
- 当领取采购单之后,采购需求的采购状态应该变为正在采购:
- 采购员领取采购单之后,采购单状态应该变为已领取,并且采购单不能再分配其他人采购:
领取采购单前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/vXMBBgw1
①gulimall-ware : PurchaseController
/**
*领取采购单
* */
@PostMapping("/received")
public R received(@RequestBody List<Long> ids){
purchaseService.received(ids);
return R.ok();
}
②gulimall-ware : PurchaseServiceImpl
/**
*领取采购单
* @param ids 采购单id
* */
@Override
public void received(List<Long> ids) {
//1、确认当前采购单是新建或者已分配状态
List<PurchaseEntity> collect = ids.stream().map(id -> {
PurchaseEntity byId = this.getById(id);
return byId;
}).filter(item -> {//过滤:当采购单的状态是新建和已分配时,就返回true
if (item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() ||
item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
return true;
}
return false;
}).map(item->{//改变采购单的状态为 已领取
item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
item.setUpdateTime(new Date());
return item;
}).collect(Collectors.toList());
//2、更新采购单
this.updateBatchById(collect);
//3、改变采购项(采购需求)的状态
collect.forEach((item)->{
//entities:采购需求的集合
List<PurchaseDetailEntity> entities = purchaseDetailService.listDetailByPurchaseId(item.getId());
List<PurchaseDetailEntity> detailEntities = entities.stream().map(entity -> {
PurchaseDetailEntity entity1 = new PurchaseDetailEntity();
entity1.setId(entity.getId());
//将采购状态改为正在采购
entity1.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
return entity1;
}).collect(Collectors.toList());
//更新采购需求
purchaseDetailService.updateBatchById(detailEntities);
});
}
上面调用的方法PurchaseDetailServiceImpl中
@Override
public List<PurchaseDetailEntity> listDetailByPurchaseId(Long id) {
List<PurchaseDetailEntity> purchaseId
= this.list(new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id));
return purchaseId;
}
③测试:模仿采购人员的第三方APP
采购需求--------正在采购:
采购单-------已领取
此时思考一个问题:当采购单的状态不再是新建和已分配时,还能再合并 采购需求到采购单吗
修改原先的mergePurchase方法,进行状态判断
//TODO 确认采购单状态是0,1才可以合并
PurchaseEntity purchaseEntity1 = purchaseDao.selectById(purchaseId);
if (purchaseEntity1.getStatus()==WareConstant.PurchaseStatusEnum.CREATED.getCode()||
purchaseEntity1.getStatus()==WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
List<Long> items = mergeVo.getItems();
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> collect = items.stream().map((item) -> {
//新建采购需求实体类
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(item);
purchaseDetailEntity.setPurchaseId(finalPurchaseId);
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
purchaseDetailService.updateBatchById(collect);
10.6 完成采购
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/cTQHGXbK
在gulimall-ware里创建vo并添加2个文件
PurchaseDoneVo、PurchaseItemDoneVo
①gulimall-ware:PurchaseController
/**
* 完成采购
* */
@PostMapping("/done")
public R finish(@RequestBody PurchaseDoneVo purchaseDoneVo){
purchaseService.done(purchaseDoneVo);
return R.ok();
}
②gulimall-ware:PurchaseServiceImpl
@Transactional
@Override
public void done(PurchaseDoneVo purchaseDoneVo) {
//1、改变采购单每一个采购项(采购需求)的状态
Boolean flag = true;
List<PurchaseItemDoneVo> items = purchaseDoneVo.getItems();
List<PurchaseDetailEntity> list = new ArrayList<>();
for(PurchaseItemDoneVo item:items){
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
if(item.getStatus()==WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()){
flag=false;
purchaseDetailEntity.setStatus(item.getStatus());
}else{
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
//将成功采购的进行入库
PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
//这个方法是入库wms_ware_sku,进入WareSkuServiceImpl
wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());
}
purchaseDetailEntity.setId(item.getItemId());
list.add(purchaseDetailEntity);
}
//批量更新采购项的状态
purchaseDetailService.updateBatchById(list);
//2、改变采购单状态
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setId(purchaseDoneVo.getId());
if(flag==true){
purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.FINISH.getCode());
}else{
purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.HASERROR.getCode());
}
purchaseEntity.setUpdateTime(new Date());
this.updateById(purchaseEntity);
}
③gulimall–ware:WareSkuServiceImpl
@Override
public void addStock(Long skuId, Long wareId, Integer skuNum) {
//1、判断如果还没有这个库存记录新增
List<WareSkuEntity> entities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
if(entities == null || entities.size() == 0){
WareSkuEntity skuEntity = new WareSkuEntity();
skuEntity.setSkuId(skuId);
skuEntity.setStock(skuNum);
skuEntity.setWareId(wareId);
skuEntity.setStockLocked(0);
//TODO 远程查询sku的名字,如果失败,整个事务无需回滚
//1、自己catch异常
//TODO 还可以用什么办法让异常出现以后不回滚?高级
try {
//远程调用gulimall-product
R info = productFeignService.info(skuId);
Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");
if(info.getCode() == 0){
skuEntity.setSkuName((String) data.get("skuName"));
}
}catch (Exception e){
}
wareSkuDao.insert(skuEntity);
}else{
//进入数据库
wareSkuDao.addStock(skuId,wareId,skuNum);
}
}
④WareSkuDao
@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {
void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
}
⑤mapper:WareSkuDao
<update id="addStock">
UPDATE `wms_ware_sku` SET stock=stock+#{skuNum} WHERE sku_id=#{skuId} AND ware_id=#{wareId}
</update>
⑥远程调用gulimall-product
Feign接口
@FeignClient("gulimall-product")
public interface ProductFeignService {
/**
* /product/skuinfo/info/{skuId}
*
*
* 1)、让所有请求过网关;
* 1、@FeignClient("gulimall-gateway"):给gulimall-gateway所在的机器发请求
* 2、/api/product/skuinfo/info/{skuId}
* 2)、直接让后台指定服务处理
* 1、@FeignClient("gulimall-product")
* 2、/product/skuinfo/info/{skuId}
*
* @return
*/
@RequestMapping("/product/skuinfo/info/{skuId}")
public R info(@PathVariable("skuId") Long skuId);
}
ware主启动类添加**@EnableFeignClients注解**
⑦测试
商品服务 - Spu管理
11.1 获取spu规格
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/GhhJhkg7
①gulimall-product:AttrController
/**
* 获取spu规格
* */
@GetMapping("/base/listforspu/{spuId}")
public R baseAttrlistforspu(@PathVariable("spuId") Long spuId){
List<ProductAttrValueEntity> entities = productAttrValueService.baseAttrlistforspu(spuId);
return R.ok().put("data",entities);
}
②gulimall-product:ProductAttrValueServiceImpl
@Override
public List<ProductAttrValueEntity> baseAttrlistforspu(Long spuId) {
List<ProductAttrValueEntity> entities
= this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>()
.eq("spu_id", spuId));
return entities;
}
③测试
发现报400的错误
原因是sys_menu表少了一行数据
解决办法:数据库中gulimall-admin中的sys_menu表中添加一行数据:
重启前端项目和后端项目后,再次点击spu管理中的规格回显:
11.2 修改商品规格
前端:https://easydoc.xyz/s/78237135/ZUqEdvA4/GhnJ0L85
①gulimall-product:AttrController
@PostMapping("/update/{spuId}")
public R updateSpuAttr(@PathVariable("spuId") Long spuId,
@RequestBody List<ProductAttrValueEntity> entities){
productAttrValueService.updateSpuAttr(spuId,entities);
return R.ok();
}
②gulimall-product:ProductAttrValueServiceImpl
@Transactional
@Override
public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
//1、删除这个spuId之前对应的所有属性
this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));
List<ProductAttrValueEntity> collect = entities.stream().map((item) -> {
item.setSpuId(spuId);
return item;
}).collect(Collectors.toList());
this.saveBatch(collect);
}