入库申请->入库审核流程:
提交按键定义位置:src\views\purchase\rurchase\RurchaseAdd.vue
<a-button @click="handleSubmit" type="primary" :loading="loading">确认物品已入库</a-button>
<template>
<a-drawer
title="采购单入库"
:maskClosable="false"
placement="right"
:closable="false"
:visible="show"
:width="1200"
@close="onClose"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;"
>
<a-form :form="form" layout="vertical">
<a-row :gutter="20">
<a-col :span="12">
<a-form-item label='采购单号' v-bind="formItemLayout">
<a-input v-model="rurchaseData.num" disabled/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='申请人' v-bind="formItemLayout">
<a-input v-model="rurchaseData.applicant" disabled/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='申请时间' v-bind="formItemLayout">
<a-input v-model="rurchaseData.createDate" disabled/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='备注消息' v-bind="formItemLayout">
<a-input v-model="rurchaseData.content" disabled/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='保管人' v-bind="formItemLayout">
<a-input v-decorator="[
'custodian',
{ rules: [{ required: true, message: '请输入保管人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='入库人' v-bind="formItemLayout">
<a-input v-decorator="[
'putUser',
{ rules: [{ required: true, message: '请输入入库人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label='备注消息' v-bind="formItemLayout">
<a-textarea :rows="4" v-decorator="[
'rurchaseContent',
{ rules: [{ required: true, message: '请输入名称!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-table :columns="columns" :data-source="dataList">
<template slot="nameShow" slot-scope="text, record">
<a-input v-model="record.name"></a-input>
</template>
<template slot="typeShow" slot-scope="text, record">
<a-input v-model="record.type"></a-input>
</template>
<template slot="typeIdShow" slot-scope="text, record">
<a-select v-model="record.typeId" style="width: 100%">
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</template>
<template slot="unitShow" slot-scope="text, record">
<a-input v-model="record.unit"></a-input>
</template>
<template slot="amountShow" slot-scope="text, record">
<a-input-number v-model="record.amount" :min="1" :step="1"/>
</template>
<template slot="priceShow" slot-scope="text, record">
<a-input-number v-model="record.price" :min="1"/>
</template>
</a-table>
<a-button @click="dataAdd" type="primary" ghost size="large" style="margin-top: 10px;width: 100%">
新增物品
</a-button>
</a-col>
</a-row>
</a-form>
<div class="drawer-bootom-button">
<a-popconfirm title="确定放弃编辑?" @confirm="onClose" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem">取消</a-button>
</a-popconfirm>
<a-button @click="handleSubmit" type="primary" :loading="loading">确认物品已入库RurchaseAdd</a-button>
</div>
</a-drawer>
</template>
<script>
import {mapState} from 'vuex'
const formItemLayout = {
labelCol: { span: 24 },
wrapperCol: { span: 24 }
}
export default {
name: 'RurchaseAdd',
props: {
rurchaseAddVisiable: {
default: false
},
rurchaseData: {
type: Object
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
show: {
get: function () {
return this.rurchaseAddVisiable
},
set: function () {
}
},
columns () {
return [{
title: '物品名称',
dataIndex: 'name',
scopedSlots: {customRender: 'nameShow'}
}, {
title: '型号',
dataIndex: 'type',
scopedSlots: {customRender: 'typeShow'}
}, {
title: '数量',
dataIndex: 'amount',
scopedSlots: {customRender: 'amountShow'}
}, {
title: '所属类型',
dataIndex: 'typeId',
width: 200,
scopedSlots: {customRender: 'typeIdShow'}
}, {
title: '单位',
dataIndex: 'unit',
scopedSlots: {customRender: 'unitShow'}
}, {
title: '单价',
dataIndex: 'price',
scopedSlots: {customRender: 'priceShow'}
}]
}
},
data () {
return {
formItemLayout,
form: this.$form.createForm(this),
loading: false,
dataList: [],
consumableType: []
}
},
mounted () {
this.getConsumableType()
this.getGoodsByNum(this.rurchaseData.num)
},
methods: {
getGoodsByNum (num) {
this.$get('/cos/goods-belong/getGoodsByNum', { num }).then((r) => {
this.dataList = r.data.data
})
},
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
dataAdd () {
this.dataList.push({name: '', type: '', typeId: '', unit: '', amount: '', price: ''})
},
reset () {
this.loading = false
this.form.resetFields()
},
onClose () {
this.reset()
this.$emit('close')
},
handleSubmit () {
let price = 0
this.dataList.forEach(item => {
price += item.price * item.amount
})
this.form.validateFields((err, values) => {
if (!err) {
values.price = price
values.goods = JSON.stringify(this.dataList)
values.id = this.rurchaseData.id
this.loading = true
this.$post('/cos/rurchase-request/rurchasePut ', {
...values
}).then((r) => {
this.reset()
this.$emit('success')
}).catch(() => {
this.loading = false
})
}
})
}
}
}
</script>
<style scoped>
</style>
后台API地址:/cos/rurchase-request/rurchasePut
后台服务方法名:cc.mrbird.febs.cos.service.impl.RurchaseRequestServiceImpl#rurchasePut
后台java文件路径:D:\code\javaspringboot\dinningroomsupply\SuppliesManagementSystem\backend\src\main\java\cc\mrbird\febs\cos\service\impl\RurchaseRequestServiceImpl.java
存在的bug:80~82行,更新 stock_info表的当前物品库存总数,条件为限定is_in=0,导致is_in=1(入库)和is_in=2(出库)的历史出入库数据都被修改
stockInfoService.update(Wrappers.<StockInfo>lambdaUpdate()
.set(StockInfo::getAmount, stockInfo.getAmount()+item.getAmount())
.set(StockInfo::getPrice, stockInfo.getPrice())
.eq(StockInfo::getName, stockInfo.getName())); //注意,这里更新条件用的是name不是id
从控制台打印的sql语句可以看出,更新语句的条件有误:
2023-11-22 16:26:31 | INFO | http-nio-9527-exec-10 | p6spy | 2023-11-22 16:26:31 | 耗时 8 ms | SQL 语句: UPDATE stock_info SET amount=14,price=11.00 WHERE name = 'test';
package cc.mrbird.febs.cos.service.impl;
import cc.mrbird.febs.cos.entity.GoodsBelong;
import cc.mrbird.febs.cos.entity.RurchaseRequest;
import cc.mrbird.febs.cos.dao.RurchaseRequestMapper;
import cc.mrbird.febs.cos.entity.StockInfo;
import cc.mrbird.febs.cos.entity.StockPut;
import cc.mrbird.febs.cos.service.IGoodsBelongService;
import cc.mrbird.febs.cos.service.IRurchaseRequestService;
import cc.mrbird.febs.cos.service.IStockInfoService;
import cc.mrbird.febs.cos.service.IStockPutService;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
/**
* @author FanK
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RurchaseRequestServiceImpl extends ServiceImpl<RurchaseRequestMapper, RurchaseRequest> implements IRurchaseRequestService {
private final IGoodsBelongService goodsBelongService;
private final IStockPutService stockPutService;
private final IStockInfoService stockInfoService;
@Override
public IPage<LinkedHashMap<String, Object>> rurchaseRequestByPage(Page page, RurchaseRequest rurchaseRequest) {
return baseMapper.rurchaseRequestByPage(page, rurchaseRequest);
}
@Override
public Boolean rurchaseRequestAdd(RurchaseRequest rurchaseRequest) {
rurchaseRequest.setNum("RUR-"+new Date().getTime());
JSONArray array = JSONUtil.parseArray(rurchaseRequest.getGoods());
List<GoodsBelong> goodsBelongList = JSONUtil.toList(array, GoodsBelong.class);
rurchaseRequest.setStep(0);
this.save(rurchaseRequest);
goodsBelongList.forEach(item -> {
item.setCreateDate(DateUtil.formatDateTime(new Date()));
item.setNum(rurchaseRequest.getNum());
});
return goodsBelongService.saveBatch(goodsBelongList);
}
@Override
public Boolean rurchasePut(RurchaseRequest rurchaseRequest) {
JSONArray array = JSONUtil.parseArray(rurchaseRequest.getGoods());
List<GoodsBelong> goodsBelongList = JSONUtil.toList(array, GoodsBelong.class);
// 添加入库单
StockPut stockPut = new StockPut();
stockPut.setContent(rurchaseRequest.getRurchaseContent());
stockPut.setCreateDate(DateUtil.formatDateTime(new Date()));
stockPut.setCustodian(rurchaseRequest.getCustodian());
stockPut.setPutUser(rurchaseRequest.getPutUser());
stockPut.setPrice(rurchaseRequest.getPrice());
stockPut.setNum("PUT-"+new Date().getTime());
stockPutService.save(stockPut);
goodsBelongList.forEach(item -> {
item.setCreateDate(DateUtil.formatDateTime(new Date()));
item.setNum(stockPut.getNum());
// 判断库房物品是否存在
StockInfo stockInfo = stockInfoService.getOne(Wrappers.<StockInfo>lambdaQuery().eq(StockInfo::getName, item.getName()).eq(StockInfo::getTypeId, item.getTypeId()).eq(StockInfo::getIsIn, 0));
if (stockInfo != null) {
// 更改库房数据 这句话有bug,没有限定is_in=0
stockInfoService.update(Wrappers.<StockInfo>lambdaUpdate().set(StockInfo::getAmount, stockInfo.getAmount()+item.getAmount())
.set(StockInfo::getPrice, stockInfo.getPrice())
.eq(StockInfo::getName, stockInfo.getName())); // 更新条件应该用id
} else {
// 重新添加库房数据
StockInfo stock = new StockInfo();
stock.setName(item.getName());
stock.setAmount(item.getAmount());
stock.setCreateDate(DateUtil.formatDateTime(new Date()));
stock.setType(item.getType());
stock.setTypeId(item.getTypeId());
stock.setUnit(item.getUnit());
stock.setPrice(item.getPrice());
stock.setIsIn(0);
stockInfo = stock;
stockInfoService.save(stock);
}
// 添加入库记录
StockInfo stockInfoPut = new StockInfo();
stockInfoPut.setParentId(stockInfo.getId());
stockInfoPut.setName(item.getName());
stockInfoPut.setAmount(item.getAmount());
stockInfoPut.setCreateDate(DateUtil.formatDateTime(new Date()));
stockInfoPut.setType(item.getType());
stockInfoPut.setTypeId(item.getTypeId());
stockInfoPut.setUnit(item.getUnit());
stockInfoPut.setPrice(item.getPrice());
stockInfoPut.setIsIn(1);
stockInfoService.save(stockInfoPut);
// 添加所属信息
GoodsBelong goodsBelong = new GoodsBelong();
goodsBelong.setNum(stockPut.getNum());
goodsBelong.setCreateDate(DateUtil.formatDateTime(new Date()));
goodsBelong.setAmount(item.getAmount());
goodsBelong.setName(item.getName());
goodsBelong.setPrice(item.getPrice());
goodsBelong.setType(item.getType());
goodsBelong.setTypeId(item.getTypeId());
goodsBelong.setUnit(item.getUnit());
goodsBelongService.save(goodsBelong);
});
// 修改状态
this.update(Wrappers.<RurchaseRequest>lambdaUpdate().set(RurchaseRequest::getStep, 1).eq(RurchaseRequest::getId, rurchaseRequest.getId()));
return true;
}
}
直接入库流程: 前台代码定义位置:src\views\purchase\request\RequestAdd.vue
<a-button @click="handleSubmit" type="primary" :loading="loading">提交</a-button>
后台API地址:/cos/stock-info/put
后台服务方法名:cc.mrbird.febs.cos.service.impl.StockInfoServiceImpl#stockPut
后台java文件路径:D:\code\javaspringboot\dinningroomsupply\SuppliesManagementSystem\backend\src\main\java\cc\mrbird\febs\cos\service\impl\StockInfoServiceImpl.java
// 判断库房物品是否存在 StockInfo stockInfo = this.getOne(Wrappers.<StockInfo>lambdaQuery().eq(StockInfo::getName, item.getName()).eq(StockInfo::getTypeId, item.getTypeId()).eq(StockInfo::getIsIn, 0));
if (stockInfo != null) { // 更改库房数据
this.update(Wrappers.<StockInfo>lambdaUpdate()
.set(StockInfo::getAmount, stockInfo.getAmount()+item.getAmount()) .set(StockInfo::getPrice, stockInfo.getPrice())
.eq(StockInfo::getId, stockInfo.getId())); //注意,这里更新条件用的是id
package cc.mrbird.febs.cos.service.impl;
import cc.mrbird.febs.cos.entity.GoodsBelong;
import cc.mrbird.febs.cos.entity.StockInfo;
import cc.mrbird.febs.cos.dao.StockInfoMapper;
import cc.mrbird.febs.cos.entity.StockPut;
import cc.mrbird.febs.cos.entity.StudentInfo;
import cc.mrbird.febs.cos.service.*;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
/**
* @author FanK
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StockInfoServiceImpl extends ServiceImpl<StockInfoMapper, StockInfo> implements IStockInfoService {
private final IStockPutService stockPutService;
private final IGoodsBelongService goodsBelongService;
private final IBulletinInfoService bulletinInfoService;
private final IStudentInfoService studentInfoService;
@Override
public IPage<LinkedHashMap<String, Object>> stockInfoByPage(Page page, StockInfo stockInfo) {
return baseMapper.stockInfoByPage(page, stockInfo);
}
@Override
public Boolean stockPut(String goods, String custodian, String putUser, String content, BigDecimal price) {
// 添加入库单
StockPut stockPut = new StockPut();
stockPut.setContent(content);
stockPut.setCreateDate(DateUtil.formatDateTime(new Date()));
stockPut.setCustodian(custodian);
stockPut.setPutUser(putUser);
stockPut.setPrice(price);
stockPut.setNum("PUT-"+new Date().getTime());
stockPutService.save(stockPut);
// 添加入库
JSONArray array = JSONUtil.parseArray(goods);
List<GoodsBelong> goodsBelongList = JSONUtil.toList(array, GoodsBelong.class);
goodsBelongList.forEach(item -> {
item.setCreateDate(DateUtil.formatDateTime(new Date()));
item.setNum(stockPut.getNum());
// 判断库房物品是否存在
StockInfo stockInfo = this.getOne(Wrappers.<StockInfo>lambdaQuery().eq(StockInfo::getName, item.getName()).eq(StockInfo::getTypeId, item.getTypeId()).eq(StockInfo::getIsIn, 0));
if (stockInfo != null) {
// 更改库房数据
this.update(Wrappers.<StockInfo>lambdaUpdate().set(StockInfo::getAmount, stockInfo.getAmount()+item.getAmount())
.set(StockInfo::getPrice, stockInfo.getPrice())
.eq(StockInfo::getId, stockInfo.getId())); // 这里用的id就不会出现误修改
} else {
// 重新添加库房数据
StockInfo stock = new StockInfo();
stock.setName(item.getName());
stock.setAmount(item.getAmount());
stock.setCreateDate(DateUtil.formatDateTime(new Date()));
stock.setType(item.getType());
stock.setTypeId(item.getTypeId());
stock.setUnit(item.getUnit());
stock.setPrice(item.getPrice());
stock.setIsIn(0);
stockInfo = stock;
this.save(stock);
}
// 添加入库记录
StockInfo stockInfoPut = new StockInfo();
stockInfoPut.setParentId(stockInfo.getId());
stockInfoPut.setName(item.getName());
stockInfoPut.setAmount(item.getAmount());
stockInfoPut.setCreateDate(DateUtil.formatDateTime(new Date()));
stockInfoPut.setType(item.getType());
stockInfoPut.setTypeId(item.getTypeId());
stockInfoPut.setUnit(item.getUnit());
stockInfoPut.setPrice(item.getPrice());
stockInfoPut.setIsIn(1);
this.save(stockInfoPut);
// 添加所属信息
GoodsBelong goodsBelong = new GoodsBelong();
goodsBelong.setNum(stockPut.getNum());
goodsBelong.setCreateDate(DateUtil.formatDateTime(new Date()));
goodsBelong.setAmount(item.getAmount());
goodsBelong.setName(item.getName());
goodsBelong.setPrice(item.getPrice());
goodsBelong.setType(item.getType());
goodsBelong.setTypeId(item.getTypeId());
goodsBelong.setUnit(item.getUnit());
goodsBelongService.save(goodsBelong);
});
return true;
}
@Override
public IPage<LinkedHashMap<String, Object>> stockInfoDetailPage(Page page, StockInfo stockInfo) {
return baseMapper.stockInfoDetailPage(page, stockInfo);
}
@Override
public IPage<LinkedHashMap<String, Object>> getGoodsPutByUserId(Page page, StockInfo stockInfo) {
return baseMapper.getGoodsPutByUserId(page, stockInfo);
}
@Override
public LinkedHashMap<String, Object> home(Integer type, Integer userId) {
LinkedHashMap<String, Object> result = new LinkedHashMap<>();
result.put("bulletinList", bulletinInfoService.list());
if (type == 74) {
result.put("studentInfo", studentInfoService.getOne(Wrappers.<StudentInfo>lambdaQuery().eq(StudentInfo::getUserId, userId)));
}
result.put("stockPutRate", baseMapper.stockPutRate());
result.put("stockPutTypeRate", baseMapper.stockPutTypeRate());
result.put("stockOutRate", baseMapper.stockOutRate());
result.put("stockOutTypeRate", baseMapper.stockOutTypeRate());
result.put("stockInfo", baseMapper.stockInfoByMonth());
return result;
}
}
修复bug后,数据库查询正常了