库存列表 导入导出

库存记录
更新供应商 最后一次进货时间
This commit is contained in:
2024-06-20 09:48:02 +08:00
parent e9e72b6c48
commit f345ba9b7f
24 changed files with 515 additions and 304 deletions

View File

@@ -0,0 +1,109 @@
package cn.ysk.cashier.controller.product;
import cn.ysk.cashier.annotation.Log;
import cn.ysk.cashier.dto.product.OutAndOnDto;
import cn.ysk.cashier.dto.product.StockQueryDto;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.service.TbProductStockOperateService;
import cn.ysk.cashier.service.product.StockService;
import cn.ysk.cashier.vo.StockVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequiredArgsConstructor
@Api(tags = "库存管理")
@RequestMapping("/api/stock")
@Slf4j
public class StockController {
private final StockService stockService;
private final TbProductStockOperateService stockOperateService;
@ApiOperation("库存导出")
@PostMapping(value = "download")
public void exportTbOrderInfo(HttpServletResponse response, @RequestBody StockQueryDto criteria) throws IOException {
stockService.download(criteria,response);
}
@Log("库存导入")
@PostMapping("/doImport")
@ApiOperation("文件导入库存")
public ResponseEntity<Object> importExcel(@RequestParam String shopId,@RequestParam("file") MultipartFile file) {
String fileName = file.getOriginalFilename();
if (file.isEmpty()) {
throw new BadRequestException("文件不能为空");
}
if (!fileName.contains("xls") && !fileName.contains("xlsx")) {
throw new BadRequestException("文件格式不正确");
}
try {
//根据路径获取这个操作excel的实例
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file.getInputStream());
//根据页面index 获取sheet页
XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
XSSFRow row = null;
List<StockVo> list=new ArrayList<>();
for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
row = sheet.getRow(i);
if(row!=null){
if(row.getCell(0)!=null){
list.add(new StockVo(
Integer.valueOf(row.getCell(0).getRawValue()),
row.getCell(1).toString(),
row.getCell(4).toString(),
row.getCell(3).toString(),
row.getCell(5).toString()));
}
}
}
log.info("库存导入.importExcel.data:"+list);
OutAndOnDto outAndOnDto=new OutAndOnDto();
outAndOnDto.setShopId(shopId);
outAndOnDto.setList(new ArrayList<>(list));
outAndOnDto.setType("purchase");
outAndOnDto.setRemark("一次性导入库存");
outAndOnDto.setIsImport("true");
outAndOnDto.setTime(System.currentTimeMillis());
outAndOnDto.setTotalAmount(BigDecimal.ZERO);
outAndOnDto.setPaidAmount(BigDecimal.ZERO);
stockOperateService.createOutAndONOperate(outAndOnDto);
stockService.inHouse(shopId,list);
} catch (Exception e) {
log.error("文件导入库存异常:",e);
}
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping
@ApiOperation("查询库存")
public ResponseEntity<Object> queryTbProduct(StockQueryDto criteria,
@RequestParam(required = false, defaultValue = "0") Integer page,
@RequestParam(required = false, defaultValue = "10") Integer size){
return new ResponseEntity<>(stockService.queryAll(criteria,page,size), HttpStatus.OK);
}
@GetMapping("/isStock")
public ResponseEntity<Object> updateIsHot(
@RequestParam String shopId,
@RequestParam Integer proId,
@RequestParam Integer isStock){
stockService.updateIsStock(proId,shopId,isStock);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -20,7 +20,7 @@ import java.util.List;
**/ **/
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@Api(tags = "/product管理") @Api(tags = "商品管理")
@RequestMapping("/api/tbProduct") @RequestMapping("/api/tbProduct")
public class TbProductController { public class TbProductController {

View File

@@ -38,7 +38,7 @@ import javax.servlet.http.HttpServletResponse;
**/ **/
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@Api(tags = "product/spec管理") @Api(tags = "商品规格管理")
@RequestMapping("/api/tbProductSpec") @RequestMapping("/api/tbProductSpec")
public class TbProductSpecController { public class TbProductSpecController {

View File

@@ -38,7 +38,7 @@ import javax.servlet.http.HttpServletResponse;
**/ **/
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@Api(tags = "/shop/purveyorTransact管理") @Api(tags = "帐目往来管理")
@RequestMapping("/api/tbShopPurveyorTransact") @RequestMapping("/api/tbShopPurveyorTransact")
public class TbShopPurveyorTransactController { public class TbShopPurveyorTransactController {
@@ -58,7 +58,7 @@ public class TbShopPurveyorTransactController {
* @return * @return
*/ */
@GetMapping @GetMapping
@ApiOperation("查询/shop/purveyorTransact") @ApiOperation("查询帐目往来")
public ResponseEntity<Object> queryTbShopPurveyorTransactSum(TbShopPurveyorTransactQueryCriteria criteria, Pageable pageable){ public ResponseEntity<Object> queryTbShopPurveyorTransactSum(TbShopPurveyorTransactQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(tbShopPurveyorTransactService.queryTransactDate(criteria,pageable),HttpStatus.OK); return new ResponseEntity<>(tbShopPurveyorTransactService.queryTransactDate(criteria,pageable),HttpStatus.OK);
} }
@@ -84,20 +84,20 @@ public class TbShopPurveyorTransactController {
} }
@PostMapping @PostMapping
@ApiOperation("新增/shop/purveyorTransact") @ApiOperation("新增帐目往来")
public ResponseEntity<Object> createTbShopPurveyorTransact(@Validated @RequestBody TbShopPurveyorTransact resources){ public ResponseEntity<Object> createTbShopPurveyorTransact(@Validated @RequestBody TbShopPurveyorTransact resources){
return new ResponseEntity<>(tbShopPurveyorTransactService.create(resources),HttpStatus.CREATED); return new ResponseEntity<>(tbShopPurveyorTransactService.create(resources),HttpStatus.CREATED);
} }
@PutMapping @PutMapping
@ApiOperation("修改/shop/purveyorTransact") @ApiOperation("修改帐目往来")
public ResponseEntity<Object> updateTbShopPurveyorTransact(@Validated @RequestBody TbShopPurveyorTransact resources){ public ResponseEntity<Object> updateTbShopPurveyorTransact(@Validated @RequestBody TbShopPurveyorTransact resources){
tbShopPurveyorTransactService.update(resources); tbShopPurveyorTransactService.update(resources);
return new ResponseEntity<>(HttpStatus.NO_CONTENT); return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} }
@DeleteMapping @DeleteMapping
@ApiOperation("删除/shop/purveyorTransact") @ApiOperation("删除帐目往来")
public ResponseEntity<Object> deleteTbShopPurveyorTransact(@RequestBody Integer[] ids) { public ResponseEntity<Object> deleteTbShopPurveyorTransact(@RequestBody Integer[] ids) {
tbShopPurveyorTransactService.deleteAll(ids); tbShopPurveyorTransactService.deleteAll(ids);
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);

View File

@@ -1,8 +1,6 @@
package cn.ysk.cashier.dto.product; package cn.ysk.cashier.dto.product;
import lombok.Data;
import lombok.NonNull; import lombok.NonNull;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@@ -54,6 +52,8 @@ public class OutAndOnDto {
@NonNull @NonNull
private String shopId; private String shopId;
private String isImport;
public String getBatchNumber() { public String getBatchNumber() {
return batchNumber; return batchNumber;
@@ -142,4 +142,12 @@ public class OutAndOnDto {
public void setShopId(String shopId) { public void setShopId(String shopId) {
this.shopId = shopId; this.shopId = shopId;
} }
public String getIsImport() {
return isImport;
}
public void setIsImport(String isImport) {
this.isImport = isImport;
}
} }

View File

@@ -0,0 +1,10 @@
package cn.ysk.cashier.dto.product;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Data
public class StockImportDto {
private String shopId;
private MultipartFile file;
}

View File

@@ -0,0 +1,30 @@
package cn.ysk.cashier.dto.product;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
@Data
public class StockQueryDto {
private String name;
private String shopId;
private Integer isStock;
public void setName(String name) {
if (StringUtils.isNotBlank(name)) {
this.name = name;
}
}
public void setShopId(String shopId) {
if (StringUtils.isNotBlank(shopId) && !shopId.equals("1")) {
this.shopId = shopId;
}
}
public void setIsStock(Integer isStock) {
if (isStock!=null) {
this.isStock = isStock;
}
}
}

View File

@@ -55,4 +55,10 @@ public class TbShopPurveyorTransactQueryCriteria{
private Integer size; private Integer size;
private String sort; private String sort;
public void setStatus(Integer status) {
if (status != null) {
this.status = status;
}
}
} }

View File

@@ -25,7 +25,7 @@ import java.io.Serializable;
/** /**
* @website https://eladmin.vip * @website https://eladmin.vip
* @description / * @description 操作记录
* @author lyf * @author lyf
* @date 2024-01-25 * @date 2024-01-25
**/ **/

View File

@@ -33,7 +33,7 @@ public interface TbOrderDetailRepository extends JpaRepository<TbOrderDetail, In
@Query("SELECT new cn.ysk.cashier.vo.TbOrderSalesCountByDayVo(" + @Query("SELECT new cn.ysk.cashier.vo.TbOrderSalesCountByDayVo(" +
"info.productName, info.productSkuName, cate.name, " + "info.productName, info.productSkuName, cate.name, unit.name," +
"SUM(CASE WHEN orders.orderType!='return' THEN info.num ELSE 0 END) as salesNum, " + "SUM(CASE WHEN orders.orderType!='return' THEN info.num ELSE 0 END) as salesNum, " +
"SUM(CASE WHEN orders.orderType='return' THEN info.num ELSE 0 END), " + "SUM(CASE WHEN orders.orderType='return' THEN info.num ELSE 0 END), " +
"SUM(info.num), " + "SUM(info.num), " +
@@ -42,6 +42,7 @@ public interface TbOrderDetailRepository extends JpaRepository<TbOrderDetail, In
"FROM TbOrderInfo orders " + "FROM TbOrderInfo orders " +
"LEFT JOIN TbOrderDetail info on orders.id=info.orderId " + "LEFT JOIN TbOrderDetail info on orders.id=info.orderId " +
"LEFT JOIN TbProduct pro ON info.productId = pro.id " + "LEFT JOIN TbProduct pro ON info.productId = pro.id " +
"LEFT JOIN TbShopUnit unit ON unit.id = pro.unitId " +
"LEFT JOIN TbShopCategory cate ON cate.id = pro.categoryId " + "LEFT JOIN TbShopCategory cate ON cate.id = pro.categoryId " +
"WHERE info.shopId = :shopId " + "WHERE info.shopId = :shopId " +
"AND (:cateId IS NULL OR pro.categoryId = :cateId) " + "AND (:cateId IS NULL OR pro.categoryId = :cateId) " +
@@ -55,7 +56,7 @@ public interface TbOrderDetailRepository extends JpaRepository<TbOrderDetail, In
@Query("SELECT new cn.ysk.cashier.vo.TbOrderSalesCountByDayVo(" + @Query("SELECT new cn.ysk.cashier.vo.TbOrderSalesCountByDayVo(" +
"info.productName, info.productSkuName, cate.name, " + "info.productName, info.productSkuName, cate.name, unit.name," +
"SUM(CASE WHEN orders.orderType!='return' THEN info.num ELSE 0 END) as salesNum, " + "SUM(CASE WHEN orders.orderType!='return' THEN info.num ELSE 0 END) as salesNum, " +
"SUM(CASE WHEN orders.orderType='return' THEN info.num ELSE 0 END), " + "SUM(CASE WHEN orders.orderType='return' THEN info.num ELSE 0 END), " +
"SUM(info.num), " + "SUM(info.num), " +
@@ -64,6 +65,7 @@ public interface TbOrderDetailRepository extends JpaRepository<TbOrderDetail, In
"FROM TbOrderInfo orders " + "FROM TbOrderInfo orders " +
"LEFT JOIN TbOrderDetail info on orders.id=info.orderId " + "LEFT JOIN TbOrderDetail info on orders.id=info.orderId " +
"LEFT JOIN TbProduct pro ON info.productId = pro.id " + "LEFT JOIN TbProduct pro ON info.productId = pro.id " +
"LEFT JOIN TbShopUnit unit ON unit.id = pro.unitId " +
"LEFT JOIN TbShopCategory cate ON cate.id = pro.categoryId " + "LEFT JOIN TbShopCategory cate ON cate.id = pro.categoryId " +
"WHERE info.shopId = :shopId " + "WHERE info.shopId = :shopId " +
"AND (:cateId IS NULL OR pro.categoryId = :cateId) " + "AND (:cateId IS NULL OR pro.categoryId = :cateId) " +

View File

@@ -27,6 +27,11 @@ public interface TbProductRepository extends JpaRepository<TbProduct, Integer>,
@Modifying @Modifying
void updateIsHot(@Param("id") Integer id); void updateIsHot(@Param("id") Integer id);
@Query(value = "update tb_product set is_stock=:isStock where id = :proId and shop_id=:shopId",nativeQuery = true)
@Modifying
void updateIsStock(@Param("proId") Integer proId,@Param("shopId") String shopId,@Param("isStock")Integer isStock);
@Query(value = "update tb_product set is_hot=0 where shop_id = :shopId and is_hot = 1",nativeQuery = true) @Query(value = "update tb_product set is_hot=0 where shop_id = :shopId and is_hot = 1",nativeQuery = true)
@Modifying @Modifying
void updateNullHot(@Param("shopId")String shopId); void updateNullHot(@Param("shopId")String shopId);

View File

@@ -1,21 +1,9 @@
/*
* 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.repository.product; package cn.ysk.cashier.repository.product;
import cn.ysk.cashier.pojo.product.TbProductSku; import cn.ysk.cashier.pojo.product.TbProductSku;
import cn.ysk.cashier.vo.StockVo;
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.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
@@ -47,6 +35,36 @@ public interface TbProductSkuRepository extends JpaRepository<TbProductSku, Inte
@Query("SELECT sku FROM TbProductSku sku WHERE sku.barCode = :barCode") @Query("SELECT sku FROM TbProductSku sku WHERE sku.barCode = :barCode")
TbProductSku searchBarCode(@Param("barCode")String barCode); TbProductSku searchBarCode(@Param("barCode")String barCode);
@Query("SELECT new cn.ysk.cashier.vo.StockVo(" +
"sku.id,pro.id,pro.coverImg,pro.name,unit.name,pro.typeEnum,sku.specSnap,pro.isStock,sku.stockNumber" +
") " +
"from " +
"TbProduct pro " +
"LEFT JOIN TbProductSku sku on pro.id = sku.productId " +
"LEFT JOIN TbShopUnit unit ON pro.unitId = unit.id " +
"WHERE " +
"pro.shopId = :shopId " +
"AND (:proName IS NULL OR pro.name LIKE %:proName%) " +
"AND (:isStock IS NULL OR pro.isStock = :isStock) " +
"ORDER BY " +
"pro.name DESC,sku.stockNumber DESC")
Page<StockVo> searchProStock(@Param("shopId") String shopId, @Param("proName") String proName, @Param("isStock")Integer isStock, Pageable pageable);
@Query("SELECT new cn.ysk.cashier.vo.StockVo(" +
"sku.id,pro.id,pro.coverImg,pro.name,unit.name,pro.typeEnum,sku.specSnap,pro.isStock,sku.stockNumber" +
") " +
"from " +
"TbProduct pro " +
"LEFT JOIN TbProductSku sku on pro.id = sku.productId " +
"LEFT JOIN TbShopUnit unit ON pro.unitId = unit.id " +
"WHERE " +
"pro.shopId = :shopId " +
"AND (:proName IS NULL OR pro.name LIKE %:proName%) " +
"AND (:isStock IS NULL OR pro.isStock = :isStock) " +
"ORDER BY " +
"pro.name DESC,sku.stockNumber DESC")
List<StockVo> searchProStock(@Param("shopId") String shopId, @Param("proName") String proName, @Param("isStock")Integer isStock);
@Transactional @Transactional
@Modifying @Modifying
@Query("update FROM TbProductSku sku set sku.costPrice=:costPrice,sku.coverImg =:coverImg, " + @Query("update FROM TbProductSku sku set sku.costPrice=:costPrice,sku.coverImg =:coverImg, " +
@@ -61,4 +79,8 @@ public interface TbProductSkuRepository extends JpaRepository<TbProductSku, Inte
@Modifying @Modifying
@Query("update FROM TbProductSku sku set sku.stockNumber=sku.stockNumber+:stockNumber WHERE sku.id =:id") @Query("update FROM TbProductSku sku set sku.stockNumber=sku.stockNumber+:stockNumber WHERE sku.id =:id")
Integer updateStockNumber(@Param("id") Integer id, @Param("stockNumber") Double stockNumber); Integer updateStockNumber(@Param("id") Integer id, @Param("stockNumber") Double stockNumber);
@Modifying
@Query("update FROM TbProductSku sku set sku.stockNumber=:stockNumber WHERE sku.shopId=:shopId and sku.id =:id")
Integer updateStockNumber2(@Param("id") Integer id,@Param("shopId")String shopId, @Param("stockNumber") Double stockNumber);
} }

View File

@@ -19,6 +19,7 @@ import cn.ysk.cashier.pojo.shop.TbShopPurveyor;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import java.util.List; import java.util.List;
@@ -35,4 +36,8 @@ public interface TbShopPurveyorRepository extends JpaRepository<TbShopPurveyor,
@Query("select count(1) from TbShopPurveyor purveyor where purveyor.shopId = :shopId") @Query("select count(1) from TbShopPurveyor purveyor where purveyor.shopId = :shopId")
Integer findByCount(@Param("shop") String shopId); Integer findByCount(@Param("shop") String shopId);
@Modifying
@Query(value = "update tb_shop_purveyor set last_transact_at=UNIX_TIMESTAMP()*1000 where id=:id", nativeQuery = true)
void upLastTransactAt(String id);
} }

View File

@@ -401,6 +401,7 @@ public class SummaryServiceImpl implements SummaryService {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("商品分类", all.getCateName()); map.put("商品分类", all.getCateName());
map.put("商品名称", all.getProductName()); map.put("商品名称", all.getProductName());
map.put("单 位", all.getUnitName());
map.put("商品规格", StringUtils.isBlank(all.getProductSkuName()) ? "" : all.getProductSkuName()); map.put("商品规格", StringUtils.isBlank(all.getProductSkuName()) ? "" : all.getProductSkuName());
map.put("销 量", all.getSalesNum()); map.put("销 量", all.getSalesNum());
map.put("退单量", all.getRefNum()); map.put("退单量", all.getRefNum());

View File

@@ -0,0 +1,73 @@
package cn.ysk.cashier.service.impl.productimpl;
import cn.ysk.cashier.dto.product.StockQueryDto;
import cn.ysk.cashier.repository.product.TbProductSkuRepository;
import cn.ysk.cashier.service.product.StockService;
import cn.ysk.cashier.service.product.TbProductService;
import cn.ysk.cashier.utils.FileUtil;
import cn.ysk.cashier.utils.RedisUtils;
import cn.ysk.cashier.vo.StockVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.util.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class StockServiceImpl implements StockService {
private final TbProductSkuRepository tbProductSkuRepository;
private final TbProductService productService;
private final RedisUtils redisUtils;
@Override
public Page queryAll(StockQueryDto criteria, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page, size);
return tbProductSkuRepository.searchProStock(criteria.getShopId(), criteria.getName(), criteria.getIsStock(), pageable);
}
@Override
public void download(StockQueryDto criteria, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
List<StockVo> stockVos = tbProductSkuRepository.searchProStock(criteria.getShopId(), criteria.getName(), criteria.getIsStock());
for (StockVo all : stockVos) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("id(如需导入,该值不可变)", all.getId());
map.put("商品名称", all.getName());
map.put("商品类型", all.getType());
map.put("商品规格", all.getSpecSnap());
map.put("商品单位", all.getUnitName());
map.put("库存数量", all.getNumber());
// map.put("库存开关", all.getIsStock().equals(0)?"否":"是");
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
@Override
@Transactional
public void inHouse(String shopId,List<StockVo> list) {
Map<Integer, Double> idStockMap=new HashMap<>();
for (StockVo stockVo : list) {
tbProductSkuRepository.updateStockNumber2(stockVo.getId(),shopId,Double.parseDouble(stockVo.getNumber().toString()));
idStockMap.put(stockVo.getId(),Double.parseDouble(stockVo.getNumber().toString()));
}
redisUtils.redisUp(2,shopId,idStockMap);
}
@Transactional
@Override
public void updateIsStock(Integer proId, String shopId,Integer isStock) {
productService.updateIsStock(proId,shopId,isStock);
}
}

View File

@@ -466,6 +466,12 @@ public class TbProductServiceImpl implements TbProductService {
tbProductRepository.updateIsHot(id); tbProductRepository.updateIsHot(id);
} }
@Transactional(rollbackFor = Exception.class)
@Override
public void updateIsStock(Integer proId, String shopId,Integer isStock) {
tbProductRepository.updateIsStock(proId,shopId,isStock);
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void upProSort(TbProductSortCriteria param) { public void upProSort(TbProductSortCriteria param) {

View File

@@ -1,20 +1,6 @@
/*
* 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; package cn.ysk.cashier.service.impl.productimpl;
import cn.ysk.cashier.repository.shop.TbShopPurveyorRepository;
import cn.ysk.cashier.utils.*; import cn.ysk.cashier.utils.*;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
@@ -45,6 +31,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
@@ -65,6 +52,7 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
private final TbProductStockOperateRepository tbProductStockOperateRepository; private final TbProductStockOperateRepository tbProductStockOperateRepository;
private final TbProductStockOperateMapper tbProductStockOperateMapper; private final TbProductStockOperateMapper tbProductStockOperateMapper;
private final TbShopPurveyorTransactRepository purveyorTransactRepository; private final TbShopPurveyorTransactRepository purveyorTransactRepository;
private final TbShopPurveyorRepository purveyorRepository;
private final TbShopInfoRepository shopInfoRepository; private final TbShopInfoRepository shopInfoRepository;
private final TbProductSkuRepository tbProductSkuRepository; private final TbProductSkuRepository tbProductSkuRepository;
private final TbProductSkuService productSkuService; private final TbProductSkuService productSkuService;
@@ -86,6 +74,7 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
BeanUtils.copyProperties(stockOperate,stockOperateVO); BeanUtils.copyProperties(stockOperate,stockOperateVO);
stockOperateVO.setStockSnap(ListUtil.stringChangeList(stockOperate.getStockSnap())); stockOperateVO.setStockSnap(ListUtil.stringChangeList(stockOperate.getStockSnap()));
stockOperateVO.setOperatorSnap(StringUtils.stringChangeMap(stockOperate.getOperatorSnap())); stockOperateVO.setOperatorSnap(StringUtils.stringChangeMap(stockOperate.getOperatorSnap()));
stockOperateVO.setType();
stockOperateVOList.add(stockOperateVO); stockOperateVOList.add(stockOperateVO);
} }
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
@@ -140,6 +129,9 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public OutAndOnDto createOutAndONOperate(OutAndOnDto resources) { public OutAndOnDto createOutAndONOperate(OutAndOnDto resources) {
if(CollectionUtils.isEmpty(resources.getList())){
throw new BadRequestException("出入库数据不可为空");
}
//用户相关 //用户相关
TbShopInfo byId = shopInfoRepository.findById(Integer.valueOf(resources.getShopId())).orElseGet(TbShopInfo::new); TbShopInfo byId = shopInfoRepository.findById(Integer.valueOf(resources.getShopId())).orElseGet(TbShopInfo::new);
if (byId.getId() == null){ if (byId.getId() == null){
@@ -151,6 +143,7 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
stockOperate.setShopId(resources.getShopId()); stockOperate.setShopId(resources.getShopId());
stockOperate.setStockSnap(resources.getList().toString()); stockOperate.setStockSnap(resources.getList().toString());
stockOperate.setType(resources.getType()); stockOperate.setType(resources.getType());
//其它入库 //purveyor 供应商入库
if ("purchase".equals(resources.getType()) || "purveyor".equals(resources.getType())){ if ("purchase".equals(resources.getType()) || "purveyor".equals(resources.getType())){
stockOperate.setSubType(1); stockOperate.setSubType(1);
}else { }else {
@@ -168,87 +161,89 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
stockOperate.setUpdatedAt(times); stockOperate.setUpdatedAt(times);
stockOperate.setStatus("normal"); stockOperate.setStatus("normal");
TbProductStockOperate saveStockOperate = tbProductStockOperateRepository.save(stockOperate); TbProductStockOperate saveStockOperate = tbProductStockOperateRepository.save(stockOperate);
//帐目往来 if (StringUtils.isNotBlank(resources.getIsImport()) && resources.getIsImport().equals("true")) {
if (!"other-out".equals(resources.getType()) || !"purchase".equals(resources.getType())) { //供应商退货 reject
TbShopPurveyorTransact purveyorTransact = new TbShopPurveyorTransact(); //供应商入库 purveyor
purveyorTransact.setShopId(resources.getShopId()); if ("reject".equals(resources.getType()) || "purveyor".equals(resources.getType())) {
purveyorTransact.setPurveyorName(resources.getPurveyorName()); TbShopPurveyorTransact purveyorTransact = new TbShopPurveyorTransact();
purveyorTransact.setPurveyorId(resources.getPurveyorId()); purveyorTransact.setShopId(resources.getShopId());
purveyorTransact.setRemark(resources.getRemark()); purveyorTransact.setPurveyorName(resources.getPurveyorName());
purveyorTransact.setCreatedAt(times); purveyorTransact.setPurveyorId(resources.getPurveyorId());
purveyorTransact.setUpdatedAt(times); purveyorTransact.setRemark(resources.getRemark());
purveyorTransact.setTotalAmount(resources.getTotalAmount()); purveyorTransact.setCreatedAt(times);
purveyorTransact.setPaidAmount(resources.getPaidAmount()); purveyorTransact.setUpdatedAt(times);
purveyorTransact.setWaitAmount(resources.getTotalAmount().subtract(resources.getPaidAmount())); purveyorTransact.setTotalAmount(resources.getTotalAmount());
if (resources.getTotalAmount().compareTo(resources.getPaidAmount())<0){ purveyorTransact.setPaidAmount(resources.getPaidAmount());
purveyorTransact.setStatus(1); purveyorTransact.setWaitAmount(resources.getTotalAmount().subtract(resources.getPaidAmount()));
}else { if (resources.getTotalAmount().compareTo(resources.getPaidAmount()) < 0) {
purveyorTransact.setStatus(0); purveyorTransact.setStatus(1);
} else {
purveyorTransact.setStatus(0);
}
purveyorTransact.setPaidAt(resources.getPaidAt());
purveyorTransact.setType(resources.getType());
purveyorTransactRepository.save(purveyorTransact);
if (resources.getPurveyorId() != null) {
purveyorRepository.upLastTransactAt(resources.getPurveyorId());
}
} }
purveyorTransact.setPaidAt(resources.getPaidAt()); Map<Integer, Double> idStockMap = new HashMap<>();
purveyorTransact.setType(resources.getType()); for (Object date : resources.getList()) {
purveyorTransactRepository.save(purveyorTransact); //商品详情
} ProductListDto productListDto = JSONObject.parseObject(JSONObject.toJSONString(date), ProductListDto.class);
//库存记录 TbProductSku tbProductSku = tbProductSkuRepository.findById(productListDto.getId()).orElseGet(TbProductSku::new);
if (resources.getList() == null){ TbProductStockDetail productStockDetail = new TbProductStockDetail();
throw new BadRequestException("数据有误"); productStockDetail.setBatchNumber(resources.getBatchNumber());
} productStockDetail.setCreatedAt(times);
Map<Integer, Double> idStockMap=new HashMap<>(); productStockDetail.setUpdatedAt(times);
for (Object date :resources.getList()) { productStockDetail.setIsStock(1);
//商品详情 Integer round = (int) Math.floor(tbProductSku.getStockNumber());
ProductListDto productListDto= JSONObject.parseObject(JSONObject.toJSONString(date),ProductListDto.class); productStockDetail.setLeftNumber(round);
TbProductSku tbProductSku = tbProductSkuRepository.findById(productListDto.getId()).orElseGet(TbProductSku::new); productStockDetail.setProductId(productListDto.getProductId());
TbProductStockDetail productStockDetail = new TbProductStockDetail(); productStockDetail.setProductName(productListDto.getName());
productStockDetail.setBatchNumber(resources.getBatchNumber()); productStockDetail.setRecordId(saveStockOperate.getId().toString());
productStockDetail.setCreatedAt(times); productStockDetail.setShopId(resources.getShopId());
productStockDetail.setUpdatedAt(times); productStockDetail.setSkuId(productListDto.getId().toString());
productStockDetail.setIsStock(1); productStockDetail.setSourcePath("NORMAL");
Integer round = (int) Math.floor(tbProductSku.getStockNumber()); productListDto.setNumber(productListDto.getNumber() != null ? productListDto.getNumber() : 0);
productStockDetail.setLeftNumber(round); switch (resources.getType()) {
productStockDetail.setProductId(productListDto.getProductId()); case "sale":
productStockDetail.setProductName(productListDto.getName()); productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setRecordId(saveStockOperate.getId().toString()); productStockDetail.setSubType(-1);
productStockDetail.setShopId(resources.getShopId()); break;
productStockDetail.setSkuId(productListDto.getId().toString()); case "refund":
productStockDetail.setSourcePath("NORMAL"); productStockDetail.setStockNumber((double) productListDto.getNumber());
productListDto.setNumber(productListDto.getNumber() != null? productListDto.getNumber(): 0); productStockDetail.setSubType(1);
switch (resources.getType()) { break;
case "sale": case "reject":
productStockDetail.setStockNumber((double) -productListDto.getNumber()); productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setSubType(-1); productStockDetail.setSubType(-1);
break; break;
case "refund": case "purveyor":
productStockDetail.setStockNumber((double) productListDto.getNumber()); productStockDetail.setStockNumber((double) productListDto.getNumber());
productStockDetail.setSubType(1); productStockDetail.setSubType(1);
break; break;
case "reject": case "purchase":
productStockDetail.setStockNumber((double) -productListDto.getNumber()); productStockDetail.setStockNumber((double) productListDto.getNumber());
productStockDetail.setSubType(-1); productStockDetail.setSubType(1);
break; break;
case "purveyor": case "other-out":
productStockDetail.setStockNumber((double) productListDto.getNumber()); productStockDetail.setStockNumber((double) -productListDto.getNumber());
productStockDetail.setSubType(1); productStockDetail.setSubType(-1);
break; break;
case "purchase": default:
productStockDetail.setStockNumber((double) productListDto.getNumber()); break;
productStockDetail.setSubType(1); }
break; productStockDetail.setType(resources.getType());
case "other-out": productStockDetail.setUnitName(productListDto.getUnitName());
productStockDetail.setStockNumber((double) -productListDto.getNumber()); entityManager.persist(productStockDetail);
productStockDetail.setSubType(-1); //sku数量
break; tbProductSku.setStockNumber(tbProductSku.getStockNumber() + productStockDetail.getStockNumber());
default: productSkuService.update(tbProductSku);
break; idStockMap.put(productListDto.getId(), productStockDetail.getStockNumber());
} }
productStockDetail.setType(resources.getType()); redisUtils.redisUp(2, resources.getShopId(), idStockMap);
productStockDetail.setUnitName(productListDto.getUnitName());
entityManager.persist(productStockDetail);
//sku数量
tbProductSku.setStockNumber(tbProductSku.getStockNumber()+productStockDetail.getStockNumber());
productSkuService.update(tbProductSku);
idStockMap.put(productListDto.getId(),productStockDetail.getStockNumber());
} }
redisUtils.redisUp(2,resources.getShopId(),idStockMap);
return resources; return resources;
} }

View File

@@ -0,0 +1,25 @@
package cn.ysk.cashier.service.product;
import cn.ysk.cashier.dto.product.StockQueryDto;
import cn.ysk.cashier.vo.StockVo;
import org.springframework.data.domain.Page;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
public interface StockService {
/**
* 查询数据分页
* @param criteria 条件
* @return Map<String,Object>
*/
Page queryAll(StockQueryDto criteria, Integer page, Integer size);
void download(StockQueryDto summaryDto, HttpServletResponse response) throws IOException;
void inHouse(String shopId,List<StockVo> list);
void updateIsStock(Integer proId, String shopId,Integer isStock);
}

View File

@@ -74,4 +74,5 @@ public interface TbProductService {
void download(List<TbProductDto> all, HttpServletResponse response) throws IOException; void download(List<TbProductDto> all, HttpServletResponse response) throws IOException;
void updateIsHot(Integer id, String shopId); void updateIsHot(Integer id, String shopId);
void updateIsStock(Integer proId, String shopId,Integer isStock);
} }

View File

@@ -45,4 +45,21 @@ public class ProductStockOperateVO {
private String purveyorName; private String purveyorName;
private String status; private String status;
public void setType() {
switch (this.type) {
case "purchase":
this.type = "其他入库";
break;
case "other-out":
this.type = "其他出库";
break;
case "reject":
this.type = "供应商退货";
break;
case "purveyor":
this.type = "供应商入库";
break;
}
}
} }

View File

@@ -0,0 +1,69 @@
package cn.ysk.cashier.vo;
import lombok.Data;
@Data
public class StockVo {
private Integer id;
private Integer proId;
private String img;
private String name;
private String unitName;
private String type;
private String specSnap;
private Object isStock;
private Object number;
public StockVo(Integer id,String name,String unitName,String specSnap, Object number) {
this.id = id;
this.unitName = unitName;
this.specSnap = specSnap;
this.name = name;
this.number = number;
}
public StockVo(Integer id, Integer proId,String img,String name,String unitName, String type, String specSnap, Object isStock, Object number) {
this.id = id;
this.proId = proId;
this.img = img;
this.name = name;
this.unitName = unitName;
setType(type);
this.specSnap = specSnap;
this.isStock = isStock;
this.number = number;
}
public void setType(String type) {
switch (type) {
case "normal":
this.type = "单规格";
break;
case "sku":
this.type = "多规格";
break;
case "weight":
this.type = "称重商品";
break;
case "currentPrice":
this.type = "套餐商品/团购卷";
break;
case "group":
this.type = "时价商品";
break;
default:
this.type = type;
break;
}
}
@Override
public String toString() {
return "{" +
"\"name\":\"" + name + "\""+
"\"unitName\":\"" + unitName +"\""+
"\"specSnap\":\"" + specSnap + "\"" +
"\"number\":\"" + number + "\"" +
"}";
}
}

View File

@@ -7,6 +7,7 @@ public class TbOrderSalesCountByDayVo {
private String productName; private String productName;
private String productSkuName; private String productSkuName;
private String cateName; private String cateName;
private String unitName;
private Long salesNum; private Long salesNum;
private Long refNum; private Long refNum;
private BigDecimal salesAmount; private BigDecimal salesAmount;
@@ -77,15 +78,24 @@ public class TbOrderSalesCountByDayVo {
this.refAmount = refAmount; this.refAmount = refAmount;
} }
public String getUnitName() {
return unitName;
}
public void setUnitName(String unitName) {
this.unitName = unitName;
}
public TbOrderSalesCountByDayVo(Long salesNum, Long refNum) { public TbOrderSalesCountByDayVo(Long salesNum, Long refNum) {
this.salesNum = salesNum; this.salesNum = salesNum;
this.refNum = refNum; this.refNum = refNum;
} }
public TbOrderSalesCountByDayVo(String productName, String productSkuName, String cateName, Long salesNum, Long refNum, Long num, BigDecimal salesAmount, BigDecimal refAmount) { public TbOrderSalesCountByDayVo(String productName, String productSkuName, String cateName,String unitName, Long salesNum, Long refNum, Long num, BigDecimal salesAmount, BigDecimal refAmount) {
this.productName = productName; this.productName = productName;
this.productSkuName = productSkuName; this.productSkuName = productSkuName;
this.cateName = cateName; this.cateName = cateName;
this.unitName = unitName;
this.salesNum = salesNum; this.salesNum = salesNum;
this.refNum = refNum; this.refNum = refNum;
this.salesAmount = salesAmount; this.salesAmount = salesAmount;

View File

@@ -1,156 +0,0 @@
<template>
<div class="app-container">
<!--工具栏-->
<div class="head-container">
<div v-if="crud.props.searchToggle">
<!-- 搜索 -->
<label class="el-form-item-label">自增id</label>
<el-input v-model="query.id" clearable placeholder="自增id" style="width: 185px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<label class="el-form-item-label">简称</label>
<el-input v-model="query.shortName" clearable placeholder="简称" style="width: 185px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<label class="el-form-item-label">店铺Id</label>
<el-input v-model="query.shopId" clearable placeholder="店铺Id" style="width: 185px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<rrOperation :crud="crud" />
</div>
<!--如果想在工具栏加入更多按钮可以使用插槽方式 slot = 'left' or 'right'-->
<crudOperation :permission="permission" />
<!--表单组件-->
<el-dialog :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="500px">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="自增id">
<el-input v-model="form.id" style="width: 370px;" />
</el-form-item>
<el-form-item label="分类名称" prop="name">
<el-input v-model="form.name" style="width: 370px;" />
</el-form-item>
<el-form-item label="简称">
<el-input v-model="form.shortName" style="width: 370px;" />
</el-form-item>
<el-form-item label="分类层级">
<el-input v-model="form.tree" style="width: 370px;" />
</el-form-item>
<el-form-item label="上级分类id-为0则表示是顶级">
<el-input v-model="form.pid" style="width: 370px;" />
</el-form-item>
<el-form-item label="图标">
<el-input v-model="form.pic" style="width: 370px;" />
</el-form-item>
<el-form-item label="商户Id">
<el-input v-model="form.merchantId" style="width: 370px;" />
</el-form-item>
<el-form-item label="店铺Id" prop="shopId">
<el-input v-model="form.shopId" style="width: 370px;" />
</el-form-item>
<el-form-item label="颜色格式标识">
<el-input v-model="form.style" style="width: 370px;" />
</el-form-item>
<el-form-item label="是否显示1显示 0不显示" prop="isShow">
<el-input v-model="form.isShow" style="width: 370px;" />
</el-form-item>
<el-form-item label="分类描述">
<el-input v-model="form.detail" style="width: 370px;" />
</el-form-item>
<el-form-item label="排序">
<el-input v-model="form.sort" style="width: 370px;" />
</el-form-item>
<el-form-item label="关键词">
<el-input v-model="form.keyWord" style="width: 370px;" />
</el-form-item>
<el-form-item label="createdAt">
<el-input v-model="form.createdAt" style="width: 370px;" />
</el-form-item>
<el-form-item label="updatedAt">
<el-input v-model="form.updatedAt" style="width: 370px;" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="crud.cancelCU">取消</el-button>
<el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确认</el-button>
</div>
</el-dialog>
<!--表格渲染-->
<el-table ref="table" v-loading="crud.loading" :data="crud.data" size="small" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="自增id" />
<el-table-column prop="name" label="分类名称" />
<el-table-column prop="shortName" label="简称" />
<el-table-column prop="tree" label="分类层级" />
<el-table-column prop="pid" label="上级分类id-为0则表示是顶级" />
<el-table-column prop="pic" label="图标" />
<el-table-column prop="merchantId" label="商户Id" />
<el-table-column prop="shopId" label="店铺Id" />
<el-table-column prop="style" label="颜色格式标识" />
<el-table-column prop="isShow" label="是否显示1显示 0不显示" />
<el-table-column prop="detail" label="分类描述" />
<el-table-column prop="sort" label="排序" />
<el-table-column prop="keyWord" label="关键词" />
<el-table-column prop="createdAt" label="createdAt" />
<el-table-column prop="updatedAt" label="updatedAt" />
<el-table-column v-if="checkPer(['admin','tbShopCategory:edit','tbShopCategory:del'])" label="操作" width="150px" align="center">
<template slot-scope="scope">
<udOperation
:data="scope.row"
:permission="permission"
/>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<pagination />
</div>
</div>
</template>
<script>
import crudTbShopCategory from '@/api/tbShopCategory'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
const defaultForm = { id: null, name: null, shortName: null, tree: null, pid: null, pic: null, merchantId: null, shopId: null, style: null, isShow: null, detail: null, sort: null, keyWord: null, createdAt: null, updatedAt: null }
export default {
name: 'TbShopCategory',
components: { pagination, crudOperation, rrOperation, udOperation },
mixins: [presenter(), header(), form(defaultForm), crud()],
cruds() {
return CRUD({ title: 'product/category', url: 'api/tbShopCategory', idField: 'id', sort: 'id,desc', crudMethod: { ...crudTbShopCategory }})
},
data() {
return {
permission: {
add: ['admin', 'tbShopCategory:add'],
edit: ['admin', 'tbShopCategory:edit'],
del: ['admin', 'tbShopCategory:del']
},
rules: {
name: [
{ required: true, message: '分类名称不能为空', trigger: 'blur' }
],
shopId: [
{ required: true, message: '店铺Id不能为空', trigger: 'blur' }
],
isShow: [
{ required: true, message: '是否显示1显示 0不显示不能为空', trigger: 'blur' }
]
},
queryTypeOptions: [
{ key: 'id', display_name: '自增id' },
{ key: 'shortName', display_name: '简称' },
{ key: 'shopId', display_name: '店铺Id' }
]
}
},
methods: {
// 钩子在获取表格数据之前执行false 则代表不获取数据
[CRUD.HOOK.beforeRefresh]() {
return true
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,27 +0,0 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'api/tbShopCategory',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'api/tbShopCategory/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'api/tbShopCategory',
method: 'put',
data
})
}
export default { add, edit, del }