在线商城

This commit is contained in:
zjf committed 2025-06-23 19:44:38 +08:00
1 parent 11b565c608
commit 3431cfa75e
16 files changed
+263 -6

No files matched your search

@@ -70,6 +70,13 @@ public interface RemoteSupermarketSpuService {
/**
* 更新库存根据货号和条码
* @param updateStockReqDTO
* @return
*/
@PostMapping("/supermarketSpu/ad/updateSpuStockByCode")
R updateSpuStockByCode(@RequestBody SupermarketSpuUpdateStockReqDTO updateStockReqDTO);
/**
@@ -0,0 +1,60 @@
package com.bsd.pjcloud.supermarket.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 商品 SKU 更新库存 Request DTO
*
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SupermarketSpuUpdateStockByCodeReqDTO {
/**
* 商品 SKU
*/
@NotNull(message = "商品 SPU 不能为空")
private List<Item> items;
@Schema(description = "下单设备类型,0默认安卓机,1移动端")
private int deviceType;
@Data
public static class Item {
// /**
// * 商品 SKU 编号
// */
@NotNull(message = "商品货号")
private String productCode ;
@NotNull(message = "商品条码")
private String barCode;
/**
* 库存变化数量
*
* 正数:增加库存
* 负数:扣减库存
*/
@NotNull(message = "库存变化数量不能为空")
private Double incrCount;
/**
* 需要扣减库存商品所属的商户部门id
*/
@NotNull(message = "部门不能为空")
private Long deptId;
}
}
@@ -10,9 +10,6 @@ import java.util.List;
/**
* 商品 SKU 更新库存 Request DTO
*
* @author LeeYan9
* @since 2022-08-26
*/
@Data
@NoArgsConstructor
@@ -113,4 +113,7 @@ public class ShopSkuEntity extends Model<ShopSkuEntity> {
*/
@Schema(description="sku属性")
private String attribute;
@Schema(description="版本号")
private Integer version;
}
@@ -57,4 +57,11 @@ public class AppShopSpuController {
vo.setSkuList(skuList.stream().map(sku -> BeanUtils.toBean(sku, ShopSkuAppVo.class)).collect(Collectors.toList()));
return R.ok(vo);
}
@PostMapping("/deductStock")
@Operation(summary = "扣减库存", description = "根据skuId和数量扣减库存")
public R<Boolean> deductStock(@RequestParam Long skuId, @RequestParam Integer num) {
boolean result = shopSkuService.deductStock(skuId, num);
return result ? R.ok(true) : R.failed("库存不足或扣减失败");
}
}
@@ -14,6 +14,7 @@ import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuAppQueryDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockByCodeReqDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
import com.bsd.pjcloud.supermarket.entity.SmErpAuxiliaryCodeEntity;
@@ -38,6 +39,7 @@ import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@@ -271,6 +273,19 @@ public class SmErpSpuController {
}
/**
* 在线商城核销扣减实际商品库存,根据货号/条码
* @param updateStockReqDTO
* @return
*/
@PostMapping("/ad/updateSpuStockByCode")
@Operation(summary = "更新库存" , description = "app和安卓公用" )
@SysLog("更新商品库存根据在线商城的编码")
public R updateSpuStockByCode(@RequestBody SupermarketSpuUpdateStockByCodeReqDTO updateStockReqDTO){
return smErpSpuService.updateSpuStockByCode(updateStockReqDTO);
}
//-------------------APP-----------------
@@ -7,4 +7,14 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ShopSkuMapper extends PjcloudBaseMapper<ShopSkuEntity> {
/**
* 修改库存(乐观锁)
* 正数:增加库存,负数:扣减库存
* @param skuId sku主键
* @param num 增减数量(正数加,负数减)
* @param version 当前版本号
* @return 影响行数
*/
int deductStock(Long skuId, Integer num, Integer version);
}
@@ -23,5 +23,12 @@ public interface SmErpUnitMapper extends PjcloudBaseMapper<SmErpUnitEntity> {
List<SmErpUnitWithSpuVo> getSupermarketUnitsWithSpu(List<Long> ids);
/**
* 根据商品编码和条码获取超市包装单位信息
* @param productCode
* @param barCode
* @param deptId
* @return
*/
SmErpUnitEntity getOneByProductCodeAndBarCode(String productCode, String barCode, Long deptId);
}
@@ -5,4 +5,12 @@ import com.bsd.pjcloud.supermarket.entity.ShopSkuEntity;
public interface ShopSkuService extends IService<ShopSkuEntity> {
/**
* 修改库存(乐观锁)
* 正数:增加库存,负数:扣减库存
* @param skuId sku主键
* @param num 增减数量(正数加,负数减)
* @return 是否成功
*/
boolean deductStock(Long skuId, Integer num);
}
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockByCodeReqDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
import com.bsd.pjcloud.supermarket.dto.cgplan.ErpCgPlanDTO;
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
@@ -41,6 +42,13 @@ public interface SmErpSpuService extends IService<SmErpSpuEntity> {
R updateSpuStock(SupermarketSpuUpdateStockReqDTO updateStockReqDTO);
/**
* 根据商品编码更新库存
* @param updateStockReqDTO
* @return
*/
R updateSpuStockByCode(SupermarketSpuUpdateStockByCodeReqDTO updateStockReqDTO);
/**
* 分页查询
* @param page
@@ -25,4 +25,13 @@ public interface SmErpUnitService extends IService<SmErpUnitEntity> {
* @return
*/
List<UnitPriceInfo> listScope(String barCode);
/**
* 根据商品编码和条形码获取商品包装单位信息
* @param productCode
* @param barCode
* @return
*/
SmErpUnitEntity getOneByProductCodeAndBarCode(String productCode, String barCode, Long deptId);
}
@@ -13,4 +13,20 @@ import org.springframework.stereotype.Service;
*/
@Service
public class ShopSkuServiceImpl extends ServiceImpl<ShopSkuMapper, ShopSkuEntity> implements ShopSkuService {
/**
* 修改库存(乐观锁)
* 正数:增加库存,负数:扣减库存
*/
@Override
public boolean deductStock(Long skuId, Integer num) {
for (int i = 0; i < 3; i++) { // 最多重试3次
ShopSkuEntity sku = this.getById(skuId);
if (sku == null) return false;
// 扣减时判断库存是否足够
if (num < 0 && sku.getStock() < -num) return false;
int updated = baseMapper.deductStock(skuId, num, sku.getVersion());
if (updated > 0) return true;
}
return false;
}
}
@@ -14,6 +14,7 @@ import com.bsd.pjcloud.common.sequence.sequence.Sequence;
import com.bsd.pjcloud.supermarket.constant.InventoryTypeEnum;
import com.bsd.pjcloud.supermarket.constant.OrderTypeEnum;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockByCodeReqDTO;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
import com.bsd.pjcloud.supermarket.dto.cgplan.ErpCgPlanDTO;
import com.bsd.pjcloud.supermarket.dto.erpspu.SmErpSpuImportDto;
@@ -390,7 +391,6 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
UpdateStockDTO updateStockDTO = new UpdateStockDTO(spuId, incrCount);
updateStockDTOS.add(updateStockDTO);
smErpStockService.updateStock(updateStockDTOS);
//生成出入库记录
SmErpInventoryRecordsItemEntity smErpInventoryRecordsItemEntity = new SmErpInventoryRecordsItemEntity();
@@ -405,6 +405,82 @@ public class SmErpSpuServiceImpl extends ServiceImpl<SmErpSpuMapper, SmErpSpuEnt
?smErpUnitEntity.getRetailPrice():smErpUnitEntity.getPromotionPrice());
smErpInventoryRecordsItemEntityList.add(smErpInventoryRecordsItemEntity);
}
smErpStockService.updateStock(updateStockDTOS);
int sum = smErpInventoryRecordsItemEntityList.stream().map(smErpInventoryRecordsItemEntity -> smErpInventoryRecordsItemEntity.getUnitPrice()).mapToInt(Integer::intValue).sum();
smErpInventoryRecordsEntity.setTotalAmount(sum);
smErpInventoryRecordsEntity.setReceiveAmount(sum);
//生成出入库记录
smErpInventoryRecordsMapper.insert(smErpInventoryRecordsEntity);
smErpInventoryRecordsItemEntityList.forEach(smErpInventoryRecordsItemEntity -> {
smErpInventoryRecordsItemEntity.setInventoryId(smErpInventoryRecordsEntity.getId());
});
smErpInventoryRecordsItemMapper.insert(smErpInventoryRecordsItemEntityList);
return R.ok();
}
@Override
@Transactional
public R updateSpuStockByCode(SupermarketSpuUpdateStockByCodeReqDTO updateStockReqDTO) {
List<UpdateStockDTO> updateStockDTOS = new ArrayList<UpdateStockDTO>();
//出库主表数据
SmErpInventoryRecordsEntity smErpInventoryRecordsEntity = new SmErpInventoryRecordsEntity();
String s = sequence.nextNo();
String result = InventoryTypeEnum.LSCK.getValue() + "-" + s;
smErpInventoryRecordsEntity.setInventoryCode(result);
smErpInventoryRecordsEntity.setInventoryDate(LocalDate.now());
smErpInventoryRecordsEntity.setInventoryType(InventoryTypeEnum.LSCK.getType());
smErpInventoryRecordsEntity.setOrderType(OrderTypeEnum.CK.getType());
smErpInventoryRecordsEntity.setDeviceType(updateStockReqDTO.getDeviceType());
List<SmErpInventoryRecordsItemEntity> smErpInventoryRecordsItemEntityList = new ArrayList<>();
for (SupermarketSpuUpdateStockByCodeReqDTO.Item v : updateStockReqDTO.getItems()) {
// LambdaQueryWrapper<SmErpUnitEntity> smErpUnitEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
// smErpUnitEntityLambdaQueryWrapper.eq(SmErpUnitEntity::getBarCode, v.getBarCode());
SmErpUnitEntity smErpUnitEntity = smErpUnitService.getOneByProductCodeAndBarCode(v.getProductCode(), v.getBarCode(),v.getDeptId());
if (null==smErpUnitEntity){
return R.failed(v.getProductCode() + "商品不存在");
}
//计算包装单位实际需要扣减的库存
Double incrCount = (smErpUnitEntity.getPackageNum()) * v.getIncrCount();
// 查询当前库存
Long spuId = smErpUnitEntity.getSpuId();
SmErpSpuEntity spu = baseMapper.selectById(spuId);
if (null==spu) {
return R.failed(spu.getProductName() + "商品不存在");
}
if (v.getIncrCount() == 0) {
return R.failed("扣减不能为0");
}
LambdaUpdateWrapper<SmErpStockEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(SmErpStockEntity::getErpSpuId, spuId);
SmErpStockEntity smErpStockEntity = smErpStockMapper.selectOne(lambdaUpdateWrapper);
// 检查库存是否足够
if (incrCount < 0 && Math.abs(incrCount) > smErpStockEntity.getCurrentStock()) {
return R.failed(spu.getProductName() + "库存不足,无法完成操作");
}
UpdateStockDTO updateStockDTO = new UpdateStockDTO(spuId, incrCount);
updateStockDTOS.add(updateStockDTO);
//生成出入库记录
SmErpInventoryRecordsItemEntity smErpInventoryRecordsItemEntity = new SmErpInventoryRecordsItemEntity();
smErpInventoryRecordsItemEntity.setInventoryId(smErpInventoryRecordsEntity.getId());
smErpInventoryRecordsItemEntity.setErpSpuId(spuId);
smErpInventoryRecordsItemEntity.setQuantity(incrCount);
smErpInventoryRecordsItemEntity.setUnitId(smErpUnitEntity.getId());
smErpInventoryRecordsItemEntity.setOrderType(OrderTypeEnum.CK.getType());
// 添加收款金额字段和会员卡号,用于记录零售业务,后续扩展使用
smErpInventoryRecordsItemEntity.setUnitPrice
(smErpUnitEntity.getPromotionPrice()==null || smErpUnitEntity.getPromotionPrice()==0
?smErpUnitEntity.getRetailPrice():smErpUnitEntity.getPromotionPrice());
smErpInventoryRecordsItemEntityList.add(smErpInventoryRecordsItemEntity);
}
smErpStockService.updateStock(updateStockDTOS);
int sum = smErpInventoryRecordsItemEntityList.stream().map(smErpInventoryRecordsItemEntity -> smErpInventoryRecordsItemEntity.getUnitPrice()).mapToInt(Integer::intValue).sum();
smErpInventoryRecordsEntity.setTotalAmount(sum);
smErpInventoryRecordsEntity.setReceiveAmount(sum);
@@ -35,4 +35,9 @@ public class SmErpUnitServiceImpl extends ServiceImpl<SmErpUnitMapper, SmErpUnit
List<UnitPriceInfo> bean = BeanUtils.toBean(smErpUnitEntities, UnitPriceInfo.class);
return bean;
}
@Override
public SmErpUnitEntity getOneByProductCodeAndBarCode(String productCode, String barCode,Long deptId) {
return baseMapper.getOneByProductCodeAndBarCode(productCode,barCode,deptId);
}
}
@@ -21,5 +21,12 @@
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
<result property="version" column="version"/>
</resultMap>
<update id="deductStock">
UPDATE shop_sku
SET stock = stock + #{num}, version = version + 1
WHERE id = #{skuId} AND stock + #{num} &gt;= 0 AND version = #{version}
</update>
</mapper>
@@ -28,7 +28,7 @@
<resultMap id="SupermarketUnitWithSpuVoMap" type="com.bsd.pjcloud.supermarket.vo.erp.SmErpUnitWithSpuVo">
<id property="id" column="id" />
<result property="productCode" column="product_code" />
<result property="barcode" column="barcode" />
<result property="barCode" column="barcode" />
<result property="picUrl" column="pic_url" />
<result property="productName" column="product_name" />
<result property="unit" column="unit" />
@@ -72,4 +72,26 @@
</if>
</where>
</select>
<select id="getOneByProductCodeAndBarCode" resultType="com.bsd.pjcloud.supermarket.entity.SmErpUnitEntity">
SELECT u.id,
u.bar_code,
u.spec,
u.unit,
u.status,
u.package_num,
u.purchase_price,
u.retail_price,
u.promotion_price,
u.spu_id,
u.cost_price,
u.is_base,
u.taste
FROM sm_erp_unit u
LEFT JOIN sm_erp_spu s
ON u.spu_id = s.id
WHERE s.del_flag = '0'
AND s.product_code = #{productCode}
AND u.bar_code = #{barCode}
AND s.dept_id = #{deptId}
</select>
</mapper>