库存记录 存入 统计 列表 详情列表

This commit is contained in:
wangw 2024-09-24 15:15:35 +08:00
parent 5b6e8caf35
commit 7b47f40fe8
10 changed files with 285 additions and 110 deletions

View File

@ -1,35 +1,22 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.controller.product;
import cn.ysk.cashier.annotation.AnonymousAccess;
import cn.ysk.cashier.annotation.Log;
import cn.ysk.cashier.dto.product.TbProductStockCountQueryCriteria;
import cn.ysk.cashier.dto.product.TbProductStockDetailQueryCriteria;
import cn.ysk.cashier.pojo.product.TbProductStockDetail;
import cn.ysk.cashier.service.product.TbProductStockDetailService;
import cn.ysk.cashier.dto.product.TbProductStockDetailQueryCriteria;
import org.springframework.data.domain.Pageable;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
/**
* @website https://eladmin.vip
@ -56,15 +43,30 @@ public class TbProductStockDetailController {
return new ResponseEntity<>(tbProductStockDetailService.queryAll(criteria,pageable),HttpStatus.OK);
}
@PostMapping("/stock/count")
@ApiOperation("库存统计")
public ResponseEntity<Object> stockCount(@RequestBody TbProductStockCountQueryCriteria criteria) throws ParseException {
return new ResponseEntity<>(tbProductStockDetailService.stockCount(criteria),HttpStatus.OK);
}
@PostMapping("/stock/list")
@ApiOperation("库存统计列表")
public ResponseEntity<Object> stockList(@RequestBody TbProductStockCountQueryCriteria criteria) throws ParseException {
return new ResponseEntity<>(tbProductStockDetailService.stockList(criteria),HttpStatus.OK);
}
@PostMapping("/stock")
@ApiOperation("查询/product/Stock")
@ApiOperation("库存记录列表")
public ResponseEntity<Object> queryPage(@RequestBody TbProductStockDetailQueryCriteria criteria){
return new ResponseEntity<>(tbProductStockDetailService.queryPage(criteria),HttpStatus.OK);
}
@GetMapping("/sum")
public ResponseEntity<Object> sumType(TbProductStockDetailQueryCriteria criteria){
return new ResponseEntity<>(tbProductStockDetailService.sumStockNumber(criteria.getProductId()),HttpStatus.OK);
}
// @GetMapping("/sum")
// public ResponseEntity<Object> sumType(TbProductStockDetailQueryCriteria criteria){
// return new ResponseEntity<>(tbProductStockDetailService.sumStockNumber(criteria.getProductId()),HttpStatus.OK);
// }
/**

View File

@ -0,0 +1,23 @@
package cn.ysk.cashier.dto.product;
import cn.ysk.cashier.dto.BaseQueryDto;
import lombok.Data;
/**
* @website https://eladmin.vip
* @author lyf
* @date 2024-01-19
**/
@Data
public class TbProductStockCountQueryCriteria extends BaseQueryDto {
private String productId;
private String productName;
private String categoryId;
private Integer page = 0;
private Integer size = 10;
}

View File

@ -1,18 +1,3 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.dto.product;
import lombok.Data;
@ -29,36 +14,33 @@ import org.apache.commons.lang3.StringUtils;
public class TbProductStockDetailQueryCriteria{
/** 精确 */
@Query
private String skuId;
// @Query
// private String skuId;
/** 精确 */
@Query
private String productId;
@Query
private String shopId;
/** 精确 */
@Query
private String productName;
// @Query
// private String productName;
@Query
private String type;
private String column;
@Query(type = Query.Type.IN)
private List<String> type;
/** BETWEEN */
@Query(type = Query.Type.BETWEEN)
private List<Long> createdAt;
@Query
private Long createTime;
@Query
private Long endTime;
// @Query
// private Long createTime;
// @Query
// private Long endTime;
private Integer page;
private Integer size;
private String sort = "id,desc";
public void setType(String type) {
if(StringUtils.isNotBlank(type)){
this.type = type;
}
}
}

View File

@ -0,0 +1,27 @@
package cn.ysk.cashier.dto.product;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.math.BigDecimal;
@Data
@Entity
public class TbProductStockListDto {
@Id
private String productId;
private String productName;
// private String specSnap;
@Transient
private BigDecimal countNumber;
private BigDecimal stockNumber;
private BigDecimal subCountNumber;
private BigDecimal addNumber;
private BigDecimal subNumber;
private BigDecimal saleNumber;
private BigDecimal lossNumber;
private BigDecimal refundNumber;
}

View File

@ -10,4 +10,5 @@ public class StockRecordMsg {
private String type;
private Integer subType;
private Integer number;
private String remark;
}

View File

@ -0,0 +1,82 @@
package cn.ysk.cashier.repository.product;
import cn.ysk.cashier.dto.product.TbProductStockListDto;
import cn.ysk.cashier.vo.TbProductStockCountVo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
/**
* @author lyf
* @website https://eladmin.vip
* @date 2024-03-02
**/
public interface ProductStockCountRepository extends JpaRepository<TbProductStockListDto, Integer> {
@Query(value = "SELECT" +
" d.product_id as product_id," +
" d.product_name AS product_name," +
// " d.spec_snap AS spec_snap," +
" pro.stock_number AS stock_number," +
" SUM( CASE WHEN d.sub_type = - 1 THEN d.stock_number ELSE 0 END ) AS sub_count_number," +
" SUM( CASE WHEN d.type IN ( '供应商入库', '盘点入库', '其他入库' ) THEN d.stock_number ELSE 0 END ) AS add_number," +
" SUM( CASE WHEN d.type IN ( '供应商出库', '盘点出库', '其他出库' ) THEN d.stock_number ELSE 0 END ) AS sub_number," +
" SUM( CASE WHEN d.type = '售出记录' THEN d.stock_number ELSE 0 END ) AS sale_number," +
" SUM( CASE WHEN d.type = '报损' THEN d.stock_number ELSE 0 END ) AS loss_number," +
" SUM( CASE WHEN d.type = '退单' THEN d.stock_number ELSE 0 END ) AS refund_number " +
"FROM" +
" tb_product_stock_detail d " +
" INNER JOIN tb_product pro ON d.product_id = pro.id " +
" and pro.shop_id = :shopId " +
" and (:categoryId IS NULL OR pro.category_id = :categoryId) " +
" WHERE " +
" d.shop_id = :shopId " +
"AND (:productName IS NULL OR d.product_name LIKE %:productName%) " +
"AND d.created_at > :startTime " +
"AND d.created_at < :endTime " +
"GROUP BY " +
"d.product_id ",
countQuery = "SELECT count(*)" +
" FROM " +
" tb_product_stock_detail d " +
" INNER JOIN tb_product pro ON d.product_id = pro.id " +
" and pro.shop_id = :shopId " +
" and (:categoryId IS NULL OR pro.category_id = :categoryId) " +
" WHERE " +
" d.shop_id = :shopId " +
" AND (:productName IS NULL OR d.product_name LIKE %:productName%) " +
" AND d.created_at > :startTime " +
" AND d.created_at < :endTime " +
" GROUP BY " +
" d.product_id "
, nativeQuery = true)
Page<TbProductStockListDto> stock2(String shopId,
String productName,
String categoryId, long startTime, long endTime, Pageable pageable);
@Query("SELECT new cn.ysk.cashier.vo.TbProductStockCountVo(" +
" SUM( pro.stockNumber ) , " +
" SUM( CASE WHEN detail.subType = 1 THEN detail.stockNumber ELSE 0 END ) , " +
" SUM( CASE WHEN detail.subType = - 1 THEN detail.stockNumber ELSE 0 END ) , " +
" SUM( CASE WHEN detail.type IN ( '供应商入库', '盘点入库', '其他入库' ) THEN detail.stockNumber ELSE 0 END ) , " +
" SUM( CASE WHEN detail.type IN ( '供应商出库', '盘点出库', '其他出库' ) THEN detail.stockNumber ELSE 0 END ) , " +
" SUM( CASE WHEN detail.type = '售出记录' THEN detail.stockNumber ELSE 0 END ) , " +
" SUM( CASE WHEN detail.type = '报损' THEN detail.stockNumber ELSE 0 END ) ," +
" SUM( CASE WHEN detail.type = '退单' THEN detail.stockNumber ELSE 0 END ))" +
"FROM " +
" TbProductStockDetail detail " +
" INNER JOIN TbProduct pro ON detail.productId = pro.id " +
" AND pro.shopId = :shopId " +
" AND ( :categoryId IS NULL OR pro.categoryId = :categoryId ) " +
"WHERE " +
" detail.shopId = :shopId " +
" AND ( :productName IS NULL OR detail.productName LIKE %:productName% ) " +
" AND detail.createdAt > :startTime " +
" AND detail.createdAt < :endTime")
TbProductStockCountVo stockCount(String shopId,
String productName,
String categoryId, long startTime, long endTime);
}

View File

@ -1,35 +1,22 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.service.impl.productimpl;
import cn.hutool.core.util.StrUtil;
import cn.ysk.cashier.dto.product.StockCountDTO;
import cn.ysk.cashier.dto.product.*;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mybatis.mapper.TbProducSkutMapper;
import cn.ysk.cashier.pojo.order.TbOrderInfo;
import cn.ysk.cashier.pojo.product.TbProductStockDetail;
import cn.ysk.cashier.repository.order.StockCountRepository;
import cn.ysk.cashier.repository.order.TbOrderInfoRepository;
import cn.ysk.cashier.repository.product.ProductStockCountRepository;
import cn.ysk.cashier.utils.*;
import cn.ysk.cashier.vo.TbProductStockCountVo;
import lombok.RequiredArgsConstructor;
import cn.ysk.cashier.repository.product.TbProductStockDetailRepository;
import cn.ysk.cashier.service.product.TbProductStockDetailService;
import cn.ysk.cashier.dto.product.TbProductStockDetailDto;
import cn.ysk.cashier.dto.product.TbProductStockDetailQueryCriteria;
import cn.ysk.cashier.mapper.product.TbProductStockDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@ -38,6 +25,8 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
@ -58,6 +47,7 @@ public class TbProductStockDetailServiceImpl implements TbProductStockDetailServ
private final TbProductStockDetailMapper tbProductStockDetailMapper;
private final StockCountRepository stockCountRepository;
private final ProductStockCountRepository stockRepository;
private final EntityManager entityManager;
private final TbOrderInfoRepository tbOrderInfoRepository;
private final TbProducSkutMapper skutMapper;
@ -72,6 +62,33 @@ public class TbProductStockDetailServiceImpl implements TbProductStockDetailServ
@Override
public Map<String,Object> queryPage(TbProductStockDetailQueryCriteria criteria){
if(StringUtils.isBlank(criteria.getColumn())){
throw new BadRequestException("必填参数未填写");
}
switch (criteria.getColumn()){
case "addCountNumber":
criteria.setType(Arrays.asList("供应商入库", "盘点入库", "其他入库", "退单"));
break;
case "addNumber":
criteria.setType(Arrays.asList("供应商入库", "盘点入库", "其他入库"));
break;
case "refundNumber":
criteria.setType(Arrays.asList("退单"));
break;
case "subCountNumber":
criteria.setType(Arrays.asList("供应商出库","其他出库","盘点出库","售出记录","报损"));
break;
case "subNumber":
criteria.setType(Arrays.asList("供应商出库","其他出库","盘点出库","售出记录"));
break;
case "saleNumber":
criteria.setType(Arrays.asList("售出记录"));
break;
case "lossNumber":
criteria.setType(Arrays.asList("报损"));
break;
}
Sort sort = Sort.by(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize(), sort);
@ -98,6 +115,39 @@ public class TbProductStockDetailServiceImpl implements TbProductStockDetailServ
return info;
}
@Override
public TbProductStockCountVo stockCount(TbProductStockCountQueryCriteria criteria) throws ParseException {
if (criteria.getStartTime() == null || criteria.getEndTime() == null) {
criteria.setEndTime(new Date());//
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
criteria.setStartTime(sdf.parse("2024-01-01"));//创建2024年1月1日的Date对象
}
return stockRepository.stockCount(criteria.getShopId().toString(), criteria.getProductName(),
criteria.getCategoryId(), criteria.getStartTime().getTime(), criteria.getEndTime().getTime());
}
@Override
public Map<String, Object> stockList(TbProductStockCountQueryCriteria criteria) throws ParseException {
Sort sort = Sort.by(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize(), sort);
if (criteria.getStartTime() == null || criteria.getEndTime() == null) {
criteria.setEndTime(new Date());//
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
criteria.setStartTime(sdf.parse("2024-01-01"));//创建2024年1月1日的Date对象
}
Page<TbProductStockListDto> tbProductStockCountDtos = stockRepository.stock2(
criteria.getShopId().toString(),
criteria.getProductName(),
criteria.getCategoryId(),
criteria.getStartTime().getTime(), criteria.getEndTime().getTime(), pageable);
if (!tbProductStockCountDtos.isEmpty()) {
tbProductStockCountDtos.getContent().parallelStream().forEach(s->{
s.setCountNumber(s.getStockNumber().add(s.getSubCountNumber()));
});
}
return PageUtil.toPage(tbProductStockCountDtos);
}
@Override
public List<TbProductStockDetailDto> queryAll(TbProductStockDetailQueryCriteria criteria){

View File

@ -259,24 +259,6 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
BigDecimal totalCostPrice;
productStockDetail.setType(resources.getType());
switch (resources.getType()) {
case "sale":
productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setSubType(-1);
break;
//后台出库
case "refund":
productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setSubType(1);
totalCostPrice = productListDto.getCostPrice().multiply(BigDecimal.valueOf(productListDto.getNumber()));
productStockDetail.setCostAmount(totalCostPrice);
productStockDetail.setType("供应商出库");
// 获取增加后的库存
double refundStockNum = getStockNum(product, tbProductSku, productListDto.getNumber(), false);
setProSpecInfo(product, tbProductSku, refundStockNum,
productListDto.getCostPrice(), isDistribute);
break;
case "reject":
productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setSubType(-1);
@ -517,7 +499,8 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
: productSku.getStockNumber().intValue() - stockRecordMsg.getNumber());
productStockDetail.setRecordId(stockOperate.getId().toString());
productStockDetail.setStockSnap(JSONObject.toJSONString(snapItem));
productStockDetail.setSourcePath("NORMAL");
productStockDetail.setSourcePath("CASHIER");
productStockDetail.setRemark(stockRecordMsg.getRemark());
productStockDetailRepository.save(productStockDetail);
}

View File

@ -1,27 +1,15 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.service.product;
import cn.ysk.cashier.dto.product.TbProductStockCountQueryCriteria;
import cn.ysk.cashier.dto.rabbit.StockRecordMsg;
import cn.ysk.cashier.pojo.product.TbProductStockDetail;
import cn.ysk.cashier.dto.product.TbProductStockDetailDto;
import cn.ysk.cashier.dto.product.TbProductStockDetailQueryCriteria;
import cn.ysk.cashier.vo.TbProductStockCountVo;
import org.springframework.data.domain.Pageable;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
@ -45,6 +33,8 @@ public interface TbProductStockDetailService {
Map<String,Object> queryAll(TbProductStockDetailQueryCriteria criteria, Pageable pageable);
Map<String,Object> queryPage(TbProductStockDetailQueryCriteria criteria);
TbProductStockCountVo stockCount(TbProductStockCountQueryCriteria criteria) throws ParseException;
Map<String,Object> stockList(TbProductStockCountQueryCriteria criteria) throws ParseException;
/**
* 查询所有数据不分页

View File

@ -0,0 +1,35 @@
package cn.ysk.cashier.vo;
import lombok.Data;
@Data
public class TbProductStockCountVo {
//现有
private Long stockNumber;
//增加
private Double addCountNumber;
//减少
private Double subCountNumber;
//增加
private Double addNumber;
//减少
private Double subNumber;
//销售量
private Double saleNumber;
//报损
private Double lossNumber;
//退货
private Double refundNumber;
public TbProductStockCountVo(Long stockNumber, Double addCountNumber, Double subCountNumber, Double addNumber, Double subNumber, Double saleNumber, Double lossNumber, Double refundNumber) {
this.stockNumber = stockNumber;
this.addCountNumber = addCountNumber;
this.subCountNumber = subCountNumber;
this.addNumber = addNumber;
this.subNumber = subNumber;
this.saleNumber = saleNumber;
this.lossNumber = lossNumber;
this.refundNumber = refundNumber;
}
}