进销存核算成本

文章探讨了存货成本的会计处理、商品折扣的处理方式,以及移动加权平均算法在实际业务中的应用。着重描述了如何在程序中实现采购入库、分仓核算及库存调整的逻辑,同时提到了先进先出法对存货价值评估的影响。
摘要由CSDN通过智能技术生成

1 那些与成本有关
根据企业会计准则,存货成本包括购买价款+相关税费+其他可归属于存货采购成本的费用。其中相关税费指的是属于该存货成本的进口关税、消费税、资源税和不能抵扣的增值税进项税额等,增值税是价外税,因此增值税不会计入到成本中。因此税额与成本计算无关
1
商品折扣与成本是什么关系呢?商品折扣影响利润,也影响库存商品的价值,因此商品折扣应该计入成本。采购订单中采购明细的折扣可以理解,应该计入成本。
那整单再做优惠,是否影响成本呢?这里的优惠按照现金折扣,计入财务费用损益类科目,因此也不计入到成本中。
1
2 移动加权平均算法
根据企业会计准则中描述,移动加权平均法是指以每次进货的成本加上原来库存存货的成本,除以每次进货数量+原有库存存货的数量,据以计算加权平均单位成本,作为在下次进货前计算各次发出存货成本依据的一种方法。

存货单位成本=(原有库存存货的实际成本+本次发货前的实际成本)/(原有库存存货数量+本次进货数量)
本次发出存货的成本=本次发出存货的数量*本次发货前的存货单位成本
本月月末库存存货成本=月末库存存货的数量*本月月末存货单位成本

将上面的算法转化为程序,需要考虑单据的新增、修改和删除,不同的操作,算法逻辑有不一样的地方
2.1 新增采购入库
分仓核算,当会计准则转换到程序代码,考虑的情况就有很多了,因为你不确定用户在什么时候会新增或者插入。

  private void inAdd(List<PsiIoBalance> psiIoBalances, PsiIoBalance first,String costWay){
        // 获取实时库存
        PsiInvReal psiInvReal = psiInvRealService.select(first.getAsId(),first.getStockId(),first.getWarehouseId());
        /**
         * 因录入采购订单日期也是不确定的,因此要取上一条收发明细数据
         * 分仓根据仓库取单价,总仓根据所有仓库一起来核算单价
         */
        PsiIoBalance nearest = psiIoBalanceService.selectPreNearest(first.getAsId(), first.getBillDate(), first.getStockId()
                ,OrderConstants.CostWay.MASTER.equals(costWay)?null:first.getWarehouseId());
        // 入库累计
        BigDecimal inCount = BigDecimal.ZERO;
        BigDecimal inCost = BigDecimal.ZERO;
        for (PsiIoBalance psiIoBalance: psiIoBalances){
            // 结存成本=最近一次收发结存+当前采购数据
            psiIoBalance.setFinalCount(nearest.getFinalCount().add(psiIoBalance.getInCount()));
            psiIoBalance.setFinalCost(nearest.getFinalCost().add(psiIoBalance.getInCost()));
            // 购货时重新计算成本
            psiIoBalance.setFinalUnitCost(psiIoBalance.getFinalCount().compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:psiIoBalance.getFinalCost().divide(psiIoBalance.getFinalCount()));
            // 累计
            inCount = inCount.add(psiIoBalance.getInCount());
            inCost = inCost.add(psiIoBalance.getInCost());
        }
        // 实时库存计算
        updateReal(psiInvReal,inCount,inCost);
        // 保存当前的采购收发明细
        psiIoBalanceService.saveBatch(psiIoBalances);
        // 向后作用
        updateAfter(psiIoBalances.get(psiIoBalances.size()-1),inCount,inCost);
    }

2.2 删除采购出库

    private void inRemove(List<PsiIoBalance> psiIoBalances, PsiIoBalance first,String costWay){
        // 实时库存
        PsiInvReal psiInvReal = psiInvRealService.select(first.getAsId(),first.getStockId(),first.getWarehouseId());
        BigDecimal count = BigDecimal.ZERO;
        BigDecimal cost = BigDecimal.ZERO;
        for (PsiIoBalance psiIoBalance: psiIoBalances){
            count = count.add(psiIoBalance.getInCount());
            cost = cost.add(psiIoBalance.getInCost());
        }
        // 实时库存
        updateReal(psiInvReal,BigDecimal.ZERO.subtract(count),BigDecimal.ZERO.subtract(cost));
        //
        psiIoBalanceService.delete(psiIoBalances);
        // 向后作用,反向操作成本和数量
        updateAfter(psiIoBalances.get(psiIoBalances.size()-1),BigDecimal.ZERO.subtract(count),BigDecimal.ZERO.subtract(cost));
    }

2.3 编辑采购入库
编辑的情况有一个新旧数据的比对,通过根据这个差额去向后作用,因为当前单据日期之后是有单据的,需要同步更正。

private void inEdit(List<PsiIoBalance> psiIoBalances, PsiIoBalance first,String costWay){
        List<String> idList = psiIoBalances.stream().map(p->p.getId()).collect(Collectors.toList());
        List<PsiIoBalance> oldPsiIoBalances = psiIoBalanceService.select(first.getAsId(),idList);
        Map<String,PsiIoBalance> oldBalanceMap = oldPsiIoBalances.stream().collect(Collectors.toMap(b->b.getId(), b->b));
        // 实时库存
        PsiInvReal psiInvReal = psiInvRealService.select(first.getAsId(),first.getStockId(),first.getWarehouseId());
        // 当前订单的库存
        BigDecimal count = BigDecimal.ZERO;
        BigDecimal cost = BigDecimal.ZERO;
        for (PsiIoBalance newVal: psiIoBalances){
            // 原始收发记录
            PsiIoBalance oldVal = oldBalanceMap.get(newVal.getId());
            // 入库数量前后差额
            BigDecimal diffCount = newVal.getInCount().subtract(oldVal.getInCount());
            // 入库成本
            newVal.setInCost(newVal.getInCount().multiply(newVal.getInUnitCost()).setScale(2,BigDecimal.ROUND_HALF_UP));
            // 入库成本差额
            BigDecimal diffCost = newVal.getInCost().subtract(oldVal.getInCost());
            // 当前库存
            count = count.add(diffCount);
            cost = cost.add(diffCost);
            // 结存数量
            newVal.setFinalCount(oldVal.getFinalCount().add(diffCount));
            // 结存成本
            newVal.setFinalCost(oldVal.getFinalCost().add(diffCost));
            // 重新计算结存单位成本
            newVal.setFinalUnitCost(newVal.getFinalCount().compareTo(BigDecimal.ZERO)==0?BigDecimal.ZERO:newVal.getFinalCost().divide(newVal.getFinalCount()));
        }
        // 更新实时库存
        updateReal(psiInvReal,count,cost);
        // 更新商品收发明细表
        psiIoBalanceService.updateBatchById(psiIoBalances);
        // 编辑向后作用
        updateAfter(psiIoBalances.get(psiIoBalances.size()-1),count,cost);
    }

3 先进先出算法
根据企业会计准则,先进先出是指以先购入的存货应先发出(销售或耗用)这样一种存货实物流转假设未前提,兑发出存货进行计价的一种方法。先进先出法下,当期期末存货成本接近于市价,如果存货的市价呈上升趋势则发出成本偏低,会高估企业当期利润和库存存货价值,反之,会低估企业当期利润和库存存货价值。
先进先出使用计算起来,并不简单,因为涉及到可能爻遍历所有的数据,因为要找到每个商品最上一次的商品采购订单,直接取最小日期是不对的,因为销售的时候,你找到的可能已经出库了。

收入存货时:逐笔登记收入存货的数量、单价和金额。
发出存货时:按照先进先出的原则逐笔登记存货的发出成本和结存金额
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值