通过对比 入库申请->入库审核流程 与 直接入库 代码实现,解决前者误修改stock_info表is_in=1或2数据的bug

入库申请->入库审核流程:

提交按键定义位置: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后,数据库查询正常了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值