恒合仓库 - 商品管理模块、上传照片、添加采购单、添加出库单、商品分类

news2024/11/24 17:21:39

商品管理模块

文章目录

  • 商品管理模块
  • 一、分页查询商品
    • 1.1 实体类
      • 1.1.1 Store 仓库
      • 1.1.2 Brand 品牌
      • 1.1.3 ProductType 商品分类
      • 1.1.4 Supply 供应商
      • 1.1.5 Place 产地
      • 1.1.6 Unit 单位
      • 1.1.7 Product 商品
    • 1.2 查询所有仓库
      • 1.2.1 Mapper
      • 1.2.2 Service
      • 1.2.3 Controller
      • 1.2.4 效果图
    • 1.3 查询所有品牌
      • 1.3.1 Mapper
      • 1.3.2 Service
      • 1.3.3 Controller
      • 1.3.4 效果图
    • 1.4 分页查询商品
      • 1.4.1 Mapper
      • 1.4.2 Service
      • 1.4.3 Controller
      • 1.4.4 效果图
  • 二、添加商品
    • 2.1 查询所有分类树
      • 2.1.1 Mapper
      • 2.1.2 Service
      • 2.1.3 Controller
      • 2.1.4 效果图
    • 2.2 查询所有供应商
      • 2.2.1 Mapper
      • 2.2.2 Service
      • 2.2.3 Controller
      • 2.2.4 效果图
    • 2.3 查询所有产地
      • 2.3.1 Mapper
      • 2.3.2 Service
      • 2.3.3 Controller
      • 2.3.4 效果图
    • 2.4 查询所有单位
      • 2.4.1 Mapper
      • 2.4.2 Service
      • 2.4.3 Controller
      • 2.4.4 效果图
    • 2.5 上传图片
      • 2.5.1 Mapper
      • 2.5.2 Service
      • 2.5.3 Controller
      • 2.5.4 效果图
    • 2.6 添加商品
      • 2.6.1 Mapper
      • 2.6.2 Service
      • 2.6.3 Controller
      • 2.6.4 效果图
  • 三、修改商品
    • 3.1 上下架状态
      • 3.1.1 Mapper
      • 3.1.2 Service
      • 3.1.3 Controller
    • 3.2 修改商品
      • 3.2.1 Mapper
      • 3.2.2 Service
      • 3.2.3 Controller
  • 四、删除商品
    • 4.1 Mapper
    • 4.2 Service
    • 4.3 controller
  • 五、添加采购单(核心)
    • 5.1 采购流程
    • 5.2 采购单实体类
    • 5.3 添加采购单
      • 5.3.1 Mapper
      • 5.3.2 Service
      • 5.3.3 Controller
      • 5.3.4 效果图
  • 六、添加出库单(核心)
    • 6.1 出库流程
    • 5.2 出库单实体类
    • 5.3 添加出库单
      • 5.3.1 Mapper
      • 5.3.2 Service
      • 5.3.3 Controller
      • 5.3.4 效果图
  • 七、商品分类
    • 7.1 查询商品分类树
      • 7.1.1 Controller
      • 7.1.2 效果图
    • 7.2 添加商品分类
      • 7.2.1 Mapper
      • 7.2.2 Service
      • 7.2.3 Controller
      • 7.2.4 效果图
    • 7.3 删除商品分类
      • 7.3.1 Mapper
      • 7.3.2 Service
      • 7.3.3 Controller
    • 7.4 修改商品分类
      • 7.4.1 Mapper
      • 7.4.2 Service
      • 7.4.3 Controller
      • 7.4.4 效果图

一、分页查询商品

image-20230815124434879

1.1 实体类

1.1.1 Store 仓库

/**
 * 仓库表store表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Store implements Serializable {

    private static final long serialVersionUID = 4011912702717598523L;
   
    private Integer storeId;//仓库id

    private String storeName;//仓库名称

    private String storeNum;//仓库编码

    private String storeAddress;//仓库地址

    private String concat;//仓库联系人

    private String phone;//仓库联系电话
}

image-20230815124752533

1.1.2 Brand 品牌

/**
 * 品牌表brand表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Brand implements Serializable {

    private Integer brandId;//品牌id

    private String brandName;//品牌名称

    private String brandLeter;//品牌首字母

    private String brandDesc;//品牌描述
}

image-20230815125543769

1.1.3 ProductType 商品分类

/**
 * 商品分类表product_type表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ProductType implements Serializable {

    private Integer typeId;//分类id

    private Integer parentId;//上级分类id

    private String typeCode;//分类代码

    private String typeName;//分类名称

    private String typeDesc;//分类描述

    //自定义List<ProductType>集合属性,用于存储当前分类的所有子级分类
    private List<ProductType> childProductCategory;
}

image-20230815125754166

1.1.4 Supply 供应商

/**
 * 供应商表supply表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Supply implements Serializable {

    private Integer supplyId;//供应商id

    private String supplyNum;//供应商代码

    private String supplyName;//供应商名称

    private String supplyIntroduce;//供应商介绍

    private String concat;//供应商联系人

    private String phone;//供应商联系电话

    private String address;//供应商地址

    private String isDelete;//是否删除状态,0未删除,1删除
}

image-20230815130227455

1.1.5 Place 产地

image-20230815130208570

/**
 * 产地表place表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Place implements Serializable {

    private Integer placeId;//产地id

    private String placeName;//产地名称

    private String placeNum;//产地代码

    private String introduce;//产地介绍

    private String isDelete;//是否删除状态,0未删除,1删除
}

1.1.6 Unit 单位

/**
 * 单位表unit表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Unit implements Serializable {

    private Integer unitId;//单位id

    private String unitName;//单位

    private String unitDesc;//单位描述
}

image-20230815130421129

1.1.7 Product 商品

/**
 * 商品表product表对应的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Product {

    private Integer productId;//商品id

    private Integer storeId;//商品所在仓库id
    private String storeName;//非表中字段 --商品所在仓库名称

    private Integer brandId;//商品所属品牌id
    private String brandName;//非表中字段 -- 商品所属品牌名称

    private String productName;//商品名称

    private String productNum;//商品编码

    private Integer productInvent;//商品库存

    private Integer typeId;//商品所属分类id
    private String typeName;//非表中字段 -- 商品所属分类名称

    private Integer supplyId;//商品供应商id
    private String supplyName;//非表中字段 -- 商品供应商名称

    private Integer placeId;//商品产地id
    private String placeName;//非表中字段 -- 商品产地名称

    private Integer unitId;//商品单位id
    private String unitName;//非表中字段 -- 商品单位名称

    private String introduce;//商品介绍

    private String upDownState;//商品上下架状态,1.上架,0.下架

    private Double inPrice;//商品进价

    private Double salePrice;//商品售价

    private Double memPrice;//商品会员价

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;//商品的创建时间

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;//商品的修改时间

    private Integer createBy;//创建商品的用户id

    private Integer updateBy;//修改商品的用户id

    private String imgs;//商品的图片地址

    @JsonFormat(pattern="yyyy-MM-dd")
    private Date productDate;//商品的生产日期

    @JsonFormat(pattern="yyyy-MM-dd")
    private Date suppDate;//商品的保质期

    private String isOverDate;//非表中字段 -- 商品是否过期,0未过期,1已过期
}

image-20230815134005095

1.2 查询所有仓库

为搜索商品仓库下拉框组装数据

1.2.1 Mapper

//  查询所有仓库的方法
    public List<Store> findAllStore();
<select id="findAllStore" resultType="com.pn.entity.Store">
    select *
    from store
</select>

1.2.2 Service

@CacheConfig(cacheNames = "com.pn.service.impl.StoreServiceImpl")
@Service
public class StoreServiceImpl implements StoreService {
    @Autowired
    private StoreMapper storeMapper;


    @Cacheable(key = "'all:store'")
    @Override
    public List<Store> queryAllStore() {
        return storeMapper.findAllStore();
    }
}

1.2.3 Controller

@Slf4j
@RestController
@RequestMapping("/product")
public class ProductController {

//  注入StoreService
    @Autowired
    private StoreService storeService;

    @RequestMapping("/store-list")
    public Result storeList(){
       return Result.ok(storeService.queryAllStore()) ;
    }
}

1.2.4 效果图

image-20230815132234669

1.3 查询所有品牌

1.3.1 Mapper

//  查询所有品牌的方法
    public List<Brand> findAllBrand();
<select id="findAllBrand" resultType="com.pn.entity.Brand">
    select *
    from brand
</select>

1.3.2 Service

@CacheConfig(cacheNames = "'com.pn.service.impl.BrandServiceImpl'")
@Service
public class BrandServiceImpl implements BrandService {

    @Autowired
    private BrandMapper brandMapper;


    @Cacheable(key = "'all:brand'")
    @Override
    public List<Brand> queryAllBrand() {
        return brandMapper.findAllBrand();
    }
}

1.3.3 Controller

@CacheConfig(cacheNames = "com.pn.service.impl.BrandServiceImpl")
@Service
public class BrandServiceImpl implements BrandService {

    @Autowired
    private BrandMapper brandMapper;


    @Cacheable(key = "'all:brand'")
    @Override
    public List<Brand> queryAllBrand() {
        return brandMapper.findAllBrand();
    }
}

1.3.4 效果图

image-20230815133312021

1.4 分页查询商品

根据仓库 商品名称 品牌 类型 供应商 产地 上下架状态 过期与查询商品并分页

image-20230815140448462

1.4.1 Mapper

//  查询商品行数的方法
    public Integer findProductRowCount(Product product);

//  分页查询商品的方法
    public List<Product> findProductPage(@Param("page") Page page, @Param("product") Product product);
<select id="findProductRowCount" resultType="java.lang.Integer">
    select count(*) from
    product t1, store t2, brand t3, product_type t4, supply t5,
    place t6, unit t7
    where t1.store_id = t2.store_id and t1.brand_id = t3.brand_id
    and t1.type_id = t4.type_id and t1.supply_id = t5.supply_id
    and t1.place_id = t6.place_id and t1.unit_id = t7.unit_id
    <if test="storeId != null">
        and t1.store_id = #{storeId}
    </if>
    <if test="productName != null and productName != ''">
        and t1.product_name like concat('%',#{productName},'%')
    </if>
    <if test="brandName != null and brandName != ''">
        and t3.brand_name like concat('%', #{brandName}, '%')
    </if>
    <if test="typeName != null and typeName != ''">
        and t4.type_name like concat('%', #{typeName}, '%')
    </if>
    <if test="supplyName != null and supplyName != ''">
        and t5.supply_name like concat('%', #{supplyName}, '%')
    </if>
    <if test="placeName != null and placeName != ''">
        and t6.place_name like concat('%', #{placeName}, '%')
    </if>
    <if test="upDownState != null and upDownState != ''">
        and t1.up_down_state = #{upDownState}
    </if>
    <!--
      如果方法参数Product对象的isOverDate属性值为1(查询已过期商品),则查询
      当前时间大于product表中supp_date列的时间的商品;
      反之如果方法参数Product对象的isOverDate属性值为0(查询未过期商品),则
      查询当前时间小于product表中supp_date列的时间的商品;
    -->
    <if test="isOverDate != null and isOverDate != '' and isOverDate==1">
        and date_format(now(), '%y-%m-%d') &gt; t1.supp_date
    </if>
    <if test="isOverDate != null and isOverDate != '' and isOverDate==0">
        and date_format(now(), '%y-%m-%d') &lt; t1.supp_date
    </if>
</select>

<select id="findProductPage" resultType="com.pn.entity.Product">
    select t1.*, t2.store_name, t3.brand_name, t4.type_name,
    t5.supply_name, t6.place_name, t7.unit_name from
    product t1, store t2, brand t3, product_type t4, supply t5,
    place t6, unit t7
    where t1.store_id = t2.store_id and t1.brand_id = t3.brand_id
    and t1.type_id = t4.type_id and t1.supply_id = t5.supply_id
    and t1.place_id = t6.place_id and t1.unit_id = t7.unit_id
    <if test="product.storeId != null">
        and t1.store_id = #{product.storeId}
    </if>
    <if test="product.productName != null and product.productName != ''">
        and t1.product_name like concat('%',#{product.productName},'%')
    </if>
    <if test="product.brandName != null and product.brandName != ''">
        and t3.brand_name like concat('%', #{product.brandName}, '%')
    </if>
    <if test="product.typeName != null and product.typeName != ''">
        and t4.type_name like concat('%', #{product.typeName}, '%')
    </if>
    <if test="product.supplyName != null and product.supplyName != ''">
        and t5.supply_name like concat('%', #{product.supplyName}, '%')
    </if>
    <if test="product.placeName != null and product.placeName != ''">
        and t6.place_name like concat('%', #{product.placeName}, '%')
    </if>
    <if test="product.upDownState != null and product.upDownState != ''">
        and t1.up_down_state = #{product.upDownState}
    </if>
    <if test="product.isOverDate != null and product.isOverDate != '' and product.isOverDate==1">
        and date_format(now(), '%y-%m-%d') &gt; t1.supp_date
    </if>
    <if test="product.isOverDate != null and product.isOverDate != '' and product.isOverDate==0">
        and date_format(now(), '%y-%m-%d') &lt; t1.supp_date
    </if>
    order by t1.create_time
    limit #{page.limitIndex}, #{page.pageSize}
</select>

1.4.2 Service

    @Autowired
    private ProductMapper productMapper;

    @Override
    public Page queryProductPage(Page page, Product product) {
//      查询商品行数
        Integer count = productMapper.findProductRowCount(product);
        page.setTotalNum(count);
        page.setLimitIndex(page.getLimitIndex());
        page.setPageCount(page.getPageCount());
//      分页查询商品
        List<Product> productPage = productMapper.findProductPage(page, product);

        page.setResultList(productPage);
        return page;
    }

1.4.3 Controller

    //分页查询商品的url接口
    @RequestMapping("/product-page-list")
    public Result productListPage(Page page, Product product) {
        page = productService.queryProductPage(page, product);
        return Result.ok(page);
    }

1.4.4 效果图

image-20230815145308406

二、添加商品

image-20230815153154763

2.1 查询所有分类树

2.1.1 Mapper

//  查询所有商品分类的方法
    public List<ProductType>  findAllProductType();
<select id="findAllProductType" resultType="com.pn.entity.ProductType">
    select *
    from product_type
</select>

2.1.2 Service

@CacheConfig(cacheNames = "com.pn.service.impl.ProductTypeServiceImpl")
@Service
public class ProductTypeServiceImpl implements ProductTypeService {

    @Autowired
    private ProductMapper productMapper;

    @Cacheable(key = "'all:typeTree'")
    @Override
    public List<ProductType> productTypeTree() {
//      查询出所有的商品分类
        List<ProductType> allProductType = productMapper.findAllProductType();
//      将所有商品分类转换成商品分类树
        return allTypeToTypeTree(allProductType,0);
    }

    private List<ProductType> allTypeToTypeTree(List<ProductType> typeList, Integer pid) {
//      拿到n级分类
        List<ProductType> nTypeList = new ArrayList<>();
        for (ProductType productType : typeList) {
            if (productType.getParentId().equals(pid)) {
                nTypeList.add(productType);
            }
        }

//      遍历n级分类,为其找子
        for (ProductType productType : nTypeList) {
//          找子集
            List<ProductType> productTypes = allTypeToTypeTree(typeList, productType.getTypeId());
            productType.setChildProductCategory(productTypes);
        }
        return nTypeList;
    }
}

2.1.3 Controller

@Autowired
private ProductTypeService productTypeTree;

//查询所有商品分类树的接口
@RequestMapping("/category-tree")
public Result loadTypeTree(){
    return Result.ok(productTypeTree.productTypeTree());
}

2.1.4 效果图

image-20230815223112067

2.2 查询所有供应商

2.2.1 Mapper

//  查询所有供应商的方法
    public List<Supply> findAllSupply();
<select id="findAllSupply" resultType="com.pn.entity.Supply">
    select *
    from supply
    where is_delete = 0
</select>

2.2.2 Service

@CacheConfig(cacheNames = "com.pn.service.impl.SupplyServiceImpl")
@Service
public class SupplyServiceImpl implements SupplyService {
    @Autowired
    private SupplyMapper supplyMapper;

    @Cacheable(key = "'all:supply'")
    @Override
    public List<Supply> supplyMapper() {
        return supplyMapper.findAllSupply();
    }
}

2.2.3 Controller

@Autowired
private SupplyService supplyService;

// 查询所有供应商的接口
@RequestMapping("/supply-list")
public Result supplyList(){
    return Result.ok(supplyService.supplyMapper());
}

2.2.4 效果图

image-20230815223134896

2.3 查询所有产地

2.3.1 Mapper

//查询所有产地
public List<Place> findAllPlace();
<select id="findAllPlace" resultType="com.pn.entity.Place">
    select * from place
</select>

2.3.2 Service

//指定缓存的名称即键的前缀,一般是@CacheConfig标注的类的全类名
@CacheConfig(cacheNames = "com.pn.service.impl.PlaceServiceImpl")
@Service
public class PlaceServiceImpl implements PlaceService {

    //注入PlaceMapper
    @Autowired
    private PlaceMapper placeMapper;

    /*
      查询所有产地的业务方法
     */
    //对查询到的所有产地进行缓存,缓存到redis的键为all:place
    @Cacheable(key = "'all:place'")
    @Override
    public List<Place> queryAllPlace() {
        //查询所有产地
        return placeMapper.findAllPlace();
    }
}

2.3.3 Controller

    @RequestMapping("/place-list")
    public Result placeList(){
//      执行业务
        return Result.ok(placeService.queryAllPlace());
    }

2.3.4 效果图

image-20230815223157406

2.4 查询所有单位

2.4.1 Mapper

//查询所有单位的方法
public List<Unit> findAllUnit();
<select id="findAllUnit" resultType="com.pn.entity.Unit">
    select * from unit
</select>

2.4.2 Service

//指定缓存的名称即键的前缀,一般是@CacheConfig标注的类的全类名
@CacheConfig(cacheNames = "com.pn.service.impl.UnitServiceImpl")
@Service
public class UnitServiceImpl implements UnitService {

    //注入UnitMapper
    @Autowired
    private UnitMapper unitMapper;

    /*
      查询所有单位的业务方法
     */
    //对查询到的所有单位进行缓存,缓存到redis的键为all:unit
    @Cacheable(key = "'all:unit'")
    @Override
    public List<Unit> queryAllUnit() {
        //查询所有单位
        return unitMapper.findAllUnit();
    }
}

2.4.3 Controller

    @RequestMapping("/unit-list")
    public Result unitList(){
//      执行业务
        return Result.ok(unitService.queryAllUnit());
    }

2.4.4 效果图

image-20230815223220207

2.5 上传图片

我们尝试一下上传图片,发现请求负载是一个上传的图片的二进制

image-20230818212224025

之后我们把图片上传到下图所示位置,但是这是未编译的资源

image-20230818214451024

我们真正上传到服务器上的项目是编译后的项目

image-20230818214838013

简单来说我们图片的上传位置并不是未编译之前的位置,而是编译之后且部署到服务器的classes/static/img/upload位置

所以我们在配置文件中就可以配置

#自定义属性 - 图片上传到的位置
file:
  upload-path: "classpath:static/img/upload"
  #自定义属性 - 上传的图片保存数据库的访问路径的目录路径
  access-path: "/img/upload/"

这个upload-path可以理解为未编译时,存放到上面的图2,编译后存放到上图的图3

2.5.1 Mapper

2.5.2 Service

2.5.3 Controller

 //   上传图片url接口
    //    file.transferTo(上传的文件保存到的磁盘文件的File对象)); --实现文件的上传
    @RequestMapping("/img-upload")
    @CrossOrigin//表示此接口允许被跨域请求
    public Result uploadImage(MultipartFile file) throws IOException {
        log.info("uploadAddress - "+uploadAddress);
//      实现文件的上传
//      拿到图片上传到的目录路径的file对象 - classpath:static/img/upload 图片要上传到的路径
        File uploadDirFile = ResourceUtils.getFile(uploadAddress);

//        String file1 = Objects.requireNonNull(this.getClass().getClassLoader().getResource("static/image/upload/")).getFile();
//        System.out.println(file1);

//      我们之前封装目录路径的方式如下所示
//      File f = new File(uploadAddress);
//      现在我们并不能这么封装,因为这个路径是特殊的类路径的路径,我们需要一个特定的工具类进行解析

//      拿到图片上传到的目录路径的磁盘路径
        String uploadDirPath = uploadDirFile.getAbsolutePath();
        log.info("uploadDirPath - "+uploadDirPath);

//      拿到我们上传的图片的名称
        String originalFilename = file.getOriginalFilename();
//      拿到上传的文件要保存到的磁盘文件的路径
        String uploadFilePath = uploadDirPath + "/" + originalFilename;
//      File对象表示文件保存到的那个位置
        file.transferTo(new File(uploadFilePath));


        return Result.ok("图片上传成功!");

    }

2.5.4 效果图

图片上传到下面的位置

image-20230819130929944

image-20230819130958050

2.6 添加商品

/product/product-add 真正添加商品的请求

image-20230819131404740

2.6.1 Mapper

备注:商品名可以重复,但是型号不能重复

//  添加商品的方法
    public int insertProduct(Product product);
<!--添加商品的方法-->
<insert id="insertProduct">
    insert into product
    values (null, #{storeId}, #{brandId}, #{productName}, #{productNum},
            #{productInvent}, #{typeId}, #{supplyId}, #{placeId}, #{unitId},
            #{introduce}, 0, #{inPrice}, #{salePrice}, #{memPrice}, now(),
            null, #{createBy}, null, #{imgs}, #{productDate}, #{suppDate})
</insert>
//  根据型号查询商品的方法
    public Product findProductByNum(@Param("productNum") String productNum);
<select id="findProductByNum" resultType="com.pn.entity.Product">
    select  * from product where product_num=#{productNum}
</select>

2.6.2 Service

//  添加商品的业务方法
    @Override
    public Result addProduct(Product product) {
//      先判断商品的型号是否已存在
        Product prct = productMapper.findProductByNum(product.getProductNum());

        if (prct != null){
            return Result.err(501,"商品型号已经存在");
        }

//      设定图片的访问地址(product.getImgs()前端传输过来的只有图片的名字)
        product.setImgs(imageURL+product.getImgs());
//      添加商品
        int success = productMapper.insertProduct(product);

        if(success>0){
            return Result.ok("添加商品成功");
        }

        return Result.err(501,"添加商品失败");
    }

2.6.3 Controller

    @Autowired
    private TokenUtils tokenUtils;

//   添加商品的URL接口
    @RequestMapping("/product-add")
    public Result addProduct(@RequestBody Product product, @RequestHeader("Token")String token){
//      拿到当前登录的用户id
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);
        
        product.setCreateBy(currentUser.getUserId());
        
        return productService.addProduct(product);
    }

2.6.4 效果图

image-20230819140356002

image-20230819140423667

三、修改商品

3.1 上下架状态

3.1.1 Mapper

//  根据商品id修改商品上下架状态的方法
    public int setStateByPid(@Param("productId")Integer productId,@Param("upDownState")String upDownState);
<update id="setStateByPid">
    update product set up_down_state=#{upDownState} where product_id = #{productId}
</update>

3.1.2 Service

@Override
public Result updateStateByPid(Product product) {
    int success = productMapper.setStateByPid(product.getProductId(), product.getUpDownState());
    return success>0 ? Result.ok("商品上下架状态修改成功"):Result.err(501,"商品上下架状态修改失败");
}

3.1.3 Controller

//  修改商品上下架状态
@RequestMapping("/state-change")
public Result changeProductState(@RequestBody Product product) {
    return productService.updateStateByPid(product);
}

3.2 修改商品

当我们修改商品信息的时候并没有修改图片,如下所示

图片没有被修改的时候还是完整的访问地址

image-20230819151005717

当我们修改商品的信息的时候修改了图片,如下所示

我们imgs的内容变成了图片的名称

image-20230819151207118

3.2.1 Mapper

根据商品的id修改商品信息

//  根据商品的id修改商品的信息
    public int setProductById(Product product);

3.2.2 Service

    @Value("${file.access-path}")
    private String imageURL; //   /img/upload/

    @Override
    public Result setProductById(Product product) {
//      首先看一下型号(根据型号获取product对象)
        Product prod = productMapper.findProductByNum(product.getProductNum());

//      判断型号是否改动
        if (prod != null && !prod.getProductId().equals(product.getProductId())) {
//          表示商品的型号被修改了,并且修改后的型号已经存在
            return Result.err(501, "修改后的型号已经存在");
        }

//      处理突图片,判断图片是否被修改(如果图片被修改了,则这个参数是一个图片的名称,反之是一个完整的文件路径)
        String imgs = product.getImgs();
        if (!imgs.contains(imageURL)){
//          说明图片被修改过了,product.getImgs()的值只是图片的名称
            product.setImgs(imageURL+product.getImgs());
        }

//      修改商品信息
        int success = productMapper.setProductById(product);

        return success > 0 ? Result.ok("商品修改成功") : Result.err(501, "商品修改失败");
    }

3.2.3 Controller

//   修改商品信息
    @RequestMapping("/product-update")
    public Result updateProduct(@RequestBody Product product ,@RequestHeader("Token") String token){
        //拿到当前登录的用户id
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);

        product.setCreateBy(currentUser.getUserId());

        return productService.setProductById(product);
    }

四、删除商品

4.1 Mapper

//  根据商品id删除商品的方法
    public int removeProductByIds(List<Integer> productIdList);
<delete id="removeProductByIds">
    delete from product
    where product_id in
    <foreach collection="list" open="(" close=")" separator="," item="prod">
        #{prod}
    </foreach>
</delete>

4.2 Service

@Override
public Result deleteProductByIds(List<Integer> productIdList) {
    int success = productMapper.removeProductByIds(productIdList);
    return success>0 ? Result.ok("商品删除成功"):Result.err(501,"商品删除失败");
}

4.3 controller

    //  删除单个商品
    @RequestMapping("/product-delete/{productId}")
    public Result deleteProduct(@PathVariable Integer productId) {
        return productService.deleteProductByIds(Arrays.asList(productId));
    }

    //  批量删除商品
    @RequestMapping("/product-delete")
    public Result deleteProductList(@PathVariable List<Integer> productIdList) {
        return productService.deleteProductByIds(productIdList);
    }

五、添加采购单(核心)

5.1 采购流程

类似进货

采购流程

  • 在商品列表针对具体的商品添加采购单

    image-20230819193051386

    向buy_list表中添加一条记录。添加的采购单表示预买的商品(还没有买,is_in字段的值是0)

    image-20230819185218636

  • 当商品采购到之后进行入库

    在采购单列表做入库操作,向in_store表添加记录(状态是0未入库),同时修改采购单表buy_list表由0改为1入库

image-20230819191554350

​ 下面是in_store表

image-20230819191805399

  • 商品真正的入库

    在入库单列表做确认入库操作

    image-20230819191905348

    将入库单表in_store表的入库单状态由0改为1入库

5.2 采购单实体类

/**
 * 采购单表buy_list表的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Purchase {

    private Integer buyId;//采购单id

    private Integer productId;//采购单采购的商品id

    private Integer storeId;//采购单采购的商品所在仓库id

    private Integer buyNum;//预计采购的商品数量

    private Integer factBuyNum;//实际采购的商品数量

    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date buyTime;//采购时间

    private Integer supplyId;//采购单采购的商品的供应商id

    private Integer placeId;//采购单采购的商品的产地id

    private String buyUser;//采购人

    private String phone;//采购人联系电话

    private String isIn;//是否生成入库单,1.是,0.否

    //---------------追加属性---------------------------

    private String productName;//商品名称

    private String storeName;//仓库名称

    private String startTime;//搜索起始时间

    private String endTime;//搜索结束时间
}

5.3 添加采购单

image-20230819193441082

采购单数据库表buy_list如下所示

image-20230819193636735

image-20230819194050277

5.3.1 Mapper

@Mapper
public interface PurchaseMapper {
//   添加采购单
    public int insertPurchase(Purchase purchase);
    
}
<insert id="insertPurchase">
    insert into buy_list
    values (null, #{productId}, #{storeId}, #{buyNum}, null, now(),
            #{supplyId}, #{placeId}, #{buyUser}, #{phone}, 0)
</insert>

5.3.2 Service

@Service
public class PurchaseServiceImpl implements PurchaseService {

    @Autowired
    private PurchaseMapper purchaseMapper;

    @Override
    public Result savePurchase(Purchase purchase) {
//      初始化时,实际采购数量要和预计采购数量一致
        purchase.setFactBuyNum(purchase.getBuyNum());
        int success = purchaseMapper.insertPurchase(purchase);

        return success>0 ? Result.ok("添加采购单成功") : Result.err(501,"添加采购单失败");
    }

}

5.3.3 Controller

@RestController
@RequestMapping("/purchase")
public class PurchaseController {

    @Autowired
    private PurchaseService purchaseService;

    @RequestMapping("/purchase-add")
    public Result addPurchase(@RequestBody Purchase purchase){

        return purchaseService.savePurchase(purchase);
    }

}

5.3.4 效果图

image-20230819201233500

image-20230819201346600

六、添加出库单(核心)

6.1 出库流程

  • 在商品列表针对具体的商品添加出库单

    向出库单表out_store表添加出库单(状态是0,未出库),准备出库

    image-20230819192927647

    image-20230819192954264

  • 商品真正出库之后,在出库单列表做确认出库操作

    商品真正出库之后,在出库单列表做确认出库操作

    将出库单表out_store表的出库状态由0改为1表示已出库

image-20230819193019679

5.2 出库单实体类

image-20230819205840782

image-20230819210314682

/**
 * 出库单表out_store表的实体类:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class OutStore {

    private Integer outsId;//出库单id

    private Integer productId;//出库单出库的商品id

    private Integer storeId;//出库单出库的商品所在仓库id

    private Integer tallyId;//理货员id

    private Double outPrice;//商品的出库价格

    private Integer outNum;//出库的商品数量

    private Integer createBy;//创建出库单的用户id

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;//创建出库单的时间

    private String isOut;//是否出库,0.未出库,1.已出库

    //------------------追加的属性-------------------------

    private String productName;//商品名称

    private String startTime;//起始时间

    private String endTime;//结束时间

    private String storeName;//仓库名称

    private String userCode;//创建出库单的用户的名称
}

5.3 添加出库单

需要先上架,才能进行“出库”

image-20230819205527630

5.3.1 Mapper

//添加出库单的方法
public int insertOutStore(OutStore outStore);
<insert id="insertOutStore">
    insert into out_store values(
      null, #{productId}, #{storeId}, null, null,
      #{outNum}, #{createBy}, now(), 0
    )
</insert>

5.3.2 Service

@Service
public class OutStoreServiceImpl implements OutStoreService {

  @Autowired
  private OutStoreMapper outStoreMapper;

    @Override
    public Result saveOutStore(OutStore outStore) {
//      添加
        int success = outStoreMapper.insertOutStore(outStore);

        return success>0? Result.ok("添加出货单成功") :Result.err(501,"添加出货单失败");
    }
}

5.3.3 Controller


@RequestMapping("/outstore")
@RestController
public class OutStoreController {

    //注入OutStoreService
    @Autowired
    private OutStoreService outStoreService;

    //注入TokenUtils
    @Autowired
    private TokenUtils tokenUtils;

    @RequestMapping("/outstore-add")
    public Result addOutStore(@RequestBody OutStore outStore,
                              @RequestHeader("Token") String token){

        //获取当前登录的用户
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);
        //获取当前登录的用户id,即添加出库单的用户id
        int createBy = currentUser.getUserId();
        outStore.setCreateBy(createBy);

        //响应
        return outStoreService.saveOutStore(outStore);
    }


}

5.3.4 效果图

image-20230819212314879

image-20230819212414598

七、商品分类

7.1 查询商品分类树

这个地方在2.1写过,我们重新写一个接口即可

7.1.1 Controller

//  查询商品分类树的url
    @RequestMapping("/product-category-tree")
    public Result productCategoryTree(){
//      执行业务
     return  Result.ok(productTypeService.productTypeTree())  ;
    }

7.1.2 效果图

image-20230820135443546

7.2 添加商品分类

一种是添加一级分类,直接添加即可

image-20230820135701043

一种是添加二级分类,需要先勾选一级分类

image-20230820135732834

分类编码type_code字段不能重复,这个地方的校验时当光标离开“分类编码”文本框的时候便开始校验

分类名type_name字段不能重复

image-20230820140145740

7.2.1 Mapper

校验分类编码、分类名称是否重复的Mapper方法

//  根据分类编码或者分类名称查询商品分类的方法
    public ProductType findTypeByCodeOrName(ProductType productType);
    <select id="findTypeByCodeOrName" resultType="com.pn.entity.ProductType">
        select *
        from product_type
        <where>
            <if test="typeName !=null and typeName != '' ">
                type_name = #{typeName}
            </if>
            <if test="typeCode !=null and typeCode != '' ">
               or type_code = #{typeCode}
            </if>
        </where>
    </select>

添加商品分类的Mapper方法

//  添加商品分类的方法
    public int insertProductType(ProductType productType);
<insert id="insertProductType">
    insert into product_type
    values (null, #{parentId}, #{typeCode}, #{typeName}, #{typeDesc})
</insert>

7.2.2 Service

校验分类编码、校验分类名称的业务方法分开,因为校验分类编码是否重复是在光标离开文本框的时候发送请求进行校验的,但是校验分类名称的时候是在提交表单数据的时候

校验分类编码是否重复的方法

    @Override
    public Result checkTypeCode(String typeCode) {
//      根据分类编码查询分类,并判断是否存在
        ProductType productType  = new ProductType();
        productType.setTypeCode(typeCode);
        ProductType prodType = productMapper.findTypeByCodeOrName(productType);

        return Result.ok(prodType == null);
    }

添加商品分类

    @CacheEvict(key = "'all:typeTree'")
    @Override
    public Result saveProductType(ProductType productType) {
//      首先校验一下分类名称是否存在
        ProductType prodType = new ProductType();
        prodType.setTypeName(productType.getTypeName());
        ProductType prodCategory = productMapper.findTypeByCodeOrName(prodType);
        if (prodCategory!=null){
            return Result.err(501,"分类名称已经存在");
        }

//      分类名称不存在,添加分类
        int success = productMapper.insertProductType(productType);

        return success>0 ? Result.ok("添加分类成功") : Result.err(501,"添加分类失败");
    }

7.2.3 Controller

校验分类编码是否重复的Controller

//  校验分类编码是否已经存在
    @RequestMapping("/verify-type-code")
    public Result checkTypeCode(String typeCode){
//      执行业务
       return productTypeService.checkTypeCode(typeCode);
    }

添加商品分类Controller

//  添加商品分类的url接口
    @RequestMapping("/type-add")
    public Result addProductType(@RequestBody ProductType productType){
        return productTypeService.saveProductType(productType);

7.2.4 效果图

当“分类编码”文本框失去焦点后如下所示

image-20230820143842807

添加商品分类

image-20230820150157665

image-20230820150537985

7.3 删除商品分类

删除商品分类,我们要删除哪个商品分类,就勾选哪个商品分类

如果删除父级分类的话,子级分类也要删除

根据分类id或父级分类id删除分类

7.3.1 Mapper

//  根据分类id或父级分类id删除分类的方法
    public int removeProductType(Integer typeId);
<delete id="removeProductType">
    delete
    from product_type
    where type_id = #{typeId} or parent_id = #{typeId}
</delete>

7.3.2 Service

    @CacheEvict(key = "'all:typeTree'")
    @Override
    public Result deleteProductType(Integer typeId) {
        int success = productMapper.removeProductType(typeId);

        return success>0? Result.ok("删除成功") : Result.err(501,"删除失败");
    }

7.3.3 Controller

//  删除商品分类
    @RequestMapping("/type-delete/{typeId}")
    public Result typeDelete(@PathVariable Integer typeId){
       return productTypeService.deleteProductType(typeId);
    }

7.4 修改商品分类

只能改分类名称和分类描述

image-20230820224152401

image-20230820224224072

7.4.1 Mapper

//  根据分类id修改分类的方法
    public int setProductTypeById(ProductType productType);
<update id="setProductTypeById">
    update product_type
    set type_name=#{typeName},
        type_desc=#{typeDesc}
    where type_id= #{typeId}
</update>

7.4.2 Service

    @CacheEvict(key = "'all:typeTree'")
    @Override
    public Result setProductType(ProductType productType) {
//      修改的分类名称是否已经存在
        ProductType prodType = new ProductType();
        prodType.setTypeName(productType.getTypeName());
        ProductType prodCategory = productMapper.findTypeByCodeOrName(prodType);

        if (prodCategory!=null && !prodCategory.getTypeId().equals((productType.getTypeId()))){
            return Result.err(501,"分类名称已经存在");
        }

        int success = productMapper.setProductTypeById(productType);

        return success>0? Result.ok("修改分类成功") : Result.err(501,"修改分类失败");
    }

7.4.3 Controller

//  修改商品分类的url
    @RequestMapping("/type-update")
    public Result updateProductType(@RequestBody ProductType productType){
        return productTypeService.setProductType(productType);
    }

7.4.4 效果图

image-20230820231056089

image-20230820231114015

image-20230820231129377

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1022757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于宏基因组的功能挖掘:碳水化合物活性酶(CAZymes)注释

基于宏基因组数据&#xff0c;可以通过NR数据库进行物种注释&#xff0c;还可以进行功能挖掘&#xff0c;比如通过KEGG数据库来挖掘代谢通路、根据COG注释结果对蛋白进行功能归类&#xff0c;通过CAzyme可以得到碳化合物合成、代谢、转运等酶的分类和相关信息&#xff0c;通过P…

Echarts散点图筛选新玩法dataZoom

目录 前言 一、引入Echarts5.4.3 二、新建index.html 三、绑定Echarts展示元素 四、初始数据绑定 五、option设置 六、效果展示 七、参数说明 总结 前言 如果您在日常的工作当中也会遇到如下场景&#xff0c;需要在线对已经展示出来的图表进行进一步的筛选&#xff0c…

ASL集睿致远代理商,CS5366芯片,typec转HDMI 4k60Hz带PD快充方案

CS5366是一款Type-C/DP1.4到HDMI2.0的显示协议转换芯片&#xff0c;内部集成了PD3.0及DSC decoder, 并能按客户需求配置成不同的功能组合&#xff0c; 是目前集成度与功耗最小的一颗芯片。 CS536x主要特性 1. 业界最低功耗的Type-C to HDMI2.0 4K60产品 (<300mW)。 2. 集成D…

R读写parquet文件

什么是parquet文件 Apache Parquet是一个开源的&#xff0c;列存储的数据文件格式。 https://parquet.apache.org/ 在R里面&#xff0c;我们可以通过arrow包来读写它。 我们先安装一下arrow包&#xff0c;并加载它。 install.packages("arrow") library(arrow)读写…

[CISCN2019 华东南赛区]Web11 SSTI

这道SSTI 差点给我渗透的感觉了 全是API 我还想去访问API看看 发现这里读取了我们的ip 我们抓包看看是如何做到的 没有东西 我们看看还有什么提示 欸 那我们可不可以直接修改参数呢 我们传递看看 发现成功了 是受控的 这里我就开始没有思路了 于是看了wp 说是ssti 那我们看…

buuctf-[WUSTCTF2020]朴实无华

打开环境就这么一句话 先打开index.php,但是没有什么 查看了下网络 看到gzip和php 我试了试www.zip 还有index.phps&#xff0c;也是一样的&#xff0c;都没找到文件 于是我想到用御剑扫&#xff0c;但是我好像线程太长了&#xff0c;一个没扫到&#xff0c;我就想到用dirsea…

阿里云ACE认证的含金量高吗?如何通过ACE认证考试?

在当今的社会中&#xff0c;想要获得一份好工作、得到丰厚的报酬&#xff0c;唯一的方法就是证明自己优秀&#xff0c;能给公司创造价值&#xff0c;是大多数公司想要看到的。 那么在面试过程中&#xff0c;怎么样才能让面试官一眼就记住呢&#xff1f;那一定是有一份足够优秀…

c语言基础知识+OS+数据结构

c语言&#xff1a; memory section&#xff1a; .bss .data .text C语言编译流程&#xff1a; pre-compiler: compiler: 检查语法问题 link: 将symbol转化为实际函数/变量地址&#xff0c;map file里面可以看到 预编译在做什么&#xff1a; &#xff08;#define&#x…

Unity3D C# 反射与特性的配合使用

需求分析 情况&#xff1a; 假如我们是一个动物园的管理员&#xff0c;我们需要统计园内的所有动物和动物的行为。 举例&#xff1a; 现在园区内有猫、狗和鸡。猫对应的行为是喵喵喵和卖萌&#xff0c;狗对应狗吠和干饭&#xff0c;鸡对应篮球和打鸣那么这时候我要统计这些&a…

【开发】视频监控系统/视频汇聚平台EasyCVR平台页面展示优化

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

怎么绘制骑鹅旅行记思维导图?教你这样绘制

怎么绘制骑鹅旅行记思维导图&#xff1f;骑鹅旅行记是一本经典的童话故事&#xff0c;绘制这个故事的思维导图可以帮助我们更好地理解故事情节和角色关系。那么今天就给大家介绍一种快速且简便的方法来绘制思维导图。 我们可以使用【迅捷画图】来进行制作&#xff0c;这是一种功…

深度学习笔记之优化算法(一)铺垫:梯度下降法VS最速下降法

深度学习笔记之优化算法——铺垫&#xff1a;梯度下降法VS最速下降法 引言回顾&#xff1a;条件数范数 相关描述关于梯度下降法最速下降法单位范数的描述 梯度下降法VS最速下降法梯度下降法等价于最速下降法的情况欧式范数约束产生的更新方向可能不是最优方向梯度下降法与最速下…

RayViz 一款服务于SolidWorks用于光学和机械设计的有效工具

RayViz 作为 SolidWorks 的一个扩展插件&#xff0c;不仅可以在 SolidWorks 工作环境中直接定义和保存模型光学属性&#xff0c; 而且还可以在该 CAD 工作环境中直接进行光线追迹。通过 RayViz, 把 TracePro 和 Solidworks 链接了起来&#xff0c; 一个模型可以在 TracePro 中用…

14.抽象工厂模式

UML 代码 #include <iostream> #include <list> using namespace std;class AbstractProductA { public:virtual void showa() 0; }; class ProductA1:public AbstractProductA { public:virtual void showa(){cout << "我是A1" << endl;}…

OpenHarmony Meetup常州站招募令

OpenHarmony Meetup 常州站正火热招募中&#xff01; 诚邀充满激情的开发者参与线下盛会~ 探索OpenHarmony前沿科技&#xff0c;畅谈未来前景&#xff0c; 感受OpenHarmony生态构建之路的魅力&#xff01; 线下参与&#xff0c;名额有限&#xff0c;仅限20位幸运者&#xff01…

【c++_containers】string的模拟实现

前言 在学习数据结构时&#xff0c;如何证明自己彻底掌握了一个容器的各种特性&#xff1f;最直接的办法就是自己写一个。下面我们将围绕下图展开对与string的深度了解&#xff1a; 一.string的成员变量 string是表示字符序列的对象&#xff0c;同时增加了专门用于操作单字节字…

2023Node.js零基础教程(小白友好型),nodejs新手到高手,(一)NodeJS入门

写在开始前 在无尽的代码汪洪中&#xff0c;闪耀着一抹绚丽的光芒。它叫做Web前端开发&#xff01; HTML是我们的魔法笔&#xff0c;是创造力的源泉。它将我们的思绪化为标签&#xff0c;将我们的想象变为元素。 在无尽的标签组合中&#xff0c;我们创造出独特的网页&#xff…

分享:大模型定向培养学徒来啦

模型定向培养学徒招募对象&#xff1a; 1.在读研究生学硕专硕均可 2.大数据、人工智能、统计学计算机、软件、数学等相关研究方向 3.具备Python编程基础机器学习基础 4.有深度学习自然语言处理基础优先 大模型定向培养学徒目标&#xff1a; 1.培养大模型prompt能力&#…

位图(bitmap)原理以及实现

大家好&#xff0c;我是蓝胖子&#xff0c;我一直相信编程是一门实践性的技术&#xff0c;其中算法也不例外&#xff0c;初学者可能往往对它可望而不可及&#xff0c;觉得很难&#xff0c;学了又忘&#xff0c;忘其实是由于没有真正搞懂算法的应用场景&#xff0c;所以我准备出…

Linux搭建Apache(秒懂超详细)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…