商品模块初始化

Administrator 0 2023-09-26

1.新建实体:

在WeifuwuDemo.Product.Domain中新建products文件夹并添加实体:(注意ProductInfoImage继承的类不一样)

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using Volo.Abp.Domain.Entities.Auditing;

namespace WeifuwuDemo.Product.Products
{
    public class ProductInfo:FullAuditedAggregateRoot<Guid>
    {
        public string ProductCode { set; get; }    //商品编码
        public string ProductUrl { set; get; }         // 商品主图
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductVirtualprice { set; get; } //商品虚拟价格
        public decimal ProductPrice { set; get; }       //价格
        public int ProductSort { set; get; }    //商品序号
        public int ProductSold { set; get; }        //已售件数
        public int ProductStock { set; get; }       //商品库存
        public string ProductStatus { set; get; } // 商品状态

        public virtual ICollection<ProductInfoImage> ProductImages { get; set; }


        /*public string VirturePrice { set; get; } // 虚拟价格
        public string ProductSort { set; get; } // 商品排序*/

        public ProductInfo()
        {
            ProductImages = new Collection<ProductInfoImage>();
        }

        public ProductInfo(Guid id) : base(id)
        {
            ProductImages = new Collection<ProductInfoImage>();
        }

        public ProductInfo(Guid id, Guid? tenantId) : base(id)
        {
            ProductImages = new Collection<ProductInfoImage>();
        }

        public ProductInfo(string ProductTitle)
        {
            // 业务规则:ProductTitle名称不能为空
            if (ProductTitle == null)
            {
                throw new Exception("商品名称不能为空");
            }
            ProductImages = new Collection<ProductInfoImage>();
        }

        /// <summary>
        /// 添加商品图片
        /// </summary>
        public void AddProductImage(Guid ImageId, string ImageUrl)
        {
            // 1、创建一个商品图片
            ProductInfoImage productImage = new ProductInfoImage(ImageId);
            productImage.ImageUrl = ImageUrl;

            // 2、添加到集合中
            ProductImages.Add(productImage);
        }


        /// <summary>
        /// 添加商品图片
        /// </summary>
        public void RemoveProductImage(Guid productImageId)
        {
            // 1、判断guid ,然后删除指定商品


            // 2、添加到集合中
            // ProductImages.Remove(productImage);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Entities.Auditing;

namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoImage:FullAuditedEntity<Guid>
    {
        public Guid ProductId { set; get; } // 商品编号
        public int ImageSort { set; get; } // 排序
        public string ImageStatus { set; get; } // 状态(1:启用,2:禁用)
        public string ImageUrl { set; get; } // 图片url

        public ProductInfoImage()
        {
        }
        public ProductInfoImage(Guid id) : base(id)
        {

        }
    }
}

2.表迁移:在WeifuwuDemo.Product.EntityFrameworkCore中ProductDbContextModelCreatingExtensions添加:

builder.Entity<ProductInfo>(b =>
        {
            b.ConfigureByConvention();
            b.HasMany(u => u.ProductImages).WithOne().HasForeignKey(ur => ur.ProductId).IsRequired();
        });

在ProductDbContext中添加:

namespace WeifuwuDemo.Product.EntityFrameworkCore;

[ConnectionStringName(ProductDbProperties.ConnectionStringName)]
public class ProductDbContext : AbpDbContext<ProductDbContext>, IProductDbContext
{
    /* Add DbSet for each Aggregate Root here. Example:
     * public DbSet<Question> Questions { get; set; }
     */

    public DbSet<ProductInfo> ProductInfo { get; set; }
    public ProductDbContext(DbContextOptions<ProductDbContext> options)
        : base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.ConfigureProduct();
    }
}

执行迁移命令

dotnet ef migrations add productInfo

dotnet ef database update

3.创建仓储层和实现层:

在WeifuwuDemo.Product.Domain中products文件夹创建仓储接口:

namespace WeifuwuDemo.Product.Products
{
    public interface IProductInfoAbpRepository:IRepository<ProductInfo,Guid>
    {
        ProductInfo GetProductByName(string ProductName);

        /// <summary>
        /// 查询和图片
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ProductInfo> GetProductAndImages();
    }
}

在WeifuwuDemo.Product.EntityFrameworkCore中文件夹products中创建仓储实现类:

namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoAbpRepository:EfCoreRepository<ProductDbContext,ProductInfo,Guid>,IProductInfoAbpRepository
    {
        public ProductInfoAbpRepository(IDbContextProvider<ProductDbContext> dbContextProvider):base(dbContextProvider)
        {
            
        }

        public override async Task<ProductInfo> GetAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default)
        {
            DbSet<ProductInfo> products = await GetDbSetAsync();
            return products.Include(p => p.ProductImages).Where(p => p.Id == id).FirstOrDefault();
        }

        public IEnumerable<ProductInfo> GetProductAndImages()
        {
            DbSet<ProductInfo> products = GetDbSetAsync().Result;

            return products.Include(product => product.ProductImages).ToList();
        }

        /// <summary>
        /// 根据商品名称,查询商品
        /// </summary>
        /// <param name="ProductName"></param>
        /// <returns></returns>
        public ProductInfo GetProductByName(string ProductName)
        {
            // 1、第一种实现
            //EBusinessDbContext eBusinessDbContext = GetDbContextAsync().Result;

            // 2、第二种实现,根据名称获取商品
            DbSet<ProductInfo> products = GetDbSetAsync().Result;
            return products.Where(product => product.ProductTitle == ProductName).FirstOrDefault();
        }
    }
}

在WeifuwuDemo.Product.Application.Contracts中新建products文件夹并创建service接口及dto:

namespace WeifuwuDemo.Product.Products
{
    public interface IProductInfoAbpService:ICrudAppService<ProductInfoDto,Guid,PagedAndSortedResultRequestDto,CreateProductInfoDto,UpdateProductInfoDto>
    {
    }
}

namespace WeifuwuDemo.Product.Products
{
    public class CreateProductInfoDto
    {
        public string ProductUrl { set; get; }         // 商品主图
        /*[Required]
        [StringLength(10)]*/
        //[ProductName]
        //[Range(3, 10)]
        // 规则3:商品名称长度不能大于10
        // 规则4:商品名称不能有数字
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductVirtualprice { set; get; } //商品虚拟价格
        public decimal ProductPrice { set; get; }       //价格

        public ProductInfoImageCreateDto[] ProductImages { set; get; } // 商品图片集合
    }

    public class ProductInfoImageCreateDto
    {
        public string ImageUrl { set; get; } // 图片url
        public string ImageStatus { set; get; } // 图片状态
    }
}

namespace WeifuwuDemo.Product.Products
{
    public class DeleteProductInfoDto
    {
        public string ProductUrl { set; get; }         // 商品主图
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductVirtualprice { set; get; } //商品虚拟价格
        public decimal ProductPrice { set; get; }       //价格
    }
    public class DeleteProductInfoImageDto
    {
        public Guid ProductImageId { set; get; }         // 商品图片
    }
}
namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoAttrQueryDto
    {
        public string productName { set; get; }
    }
}

namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoDto:EntityDto<Guid>
    {
        public string ProductCode { set; get; }    //商品编码
        public string ProductUrl { set; get; }         // 商品主图
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductVirtualprice { set; get; } //商品虚拟价格
        public decimal ProductPrice { set; get; }       //价格
        public int ProductSort { set; get; }    //商品序号
        public int ProductSold { set; get; }        //已售件数
        public int ProductStock { set; get; }       //商品库存
        public string ProductStatus { set; get; } // 商品状态

        public ProductInfoImageDto[] ProductImages { set; get; }// 商品图片
    }
    public class ProductInfoImageDto
    {
        public string ImageUrl { set; get; } // 图片url
    }
}
namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoNameQueryDto:PagedAndSortedResultRequestDto
    {
        public string ProductName { set; get; }
    }
}
namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoQueryDto
    {
    }
}
namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoTotaLDto
    {
    }
}}
}
namespace WeifuwuDemo.Product.Products
{
    /// <summary>
    /// 更新商品Dto
    /// </summary>
    public class UpdateProductInfoDto
    {
        public string ProductUrl { set; get; }         // 商品主图
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductVirtualprice { set; get; } //商品虚拟价格
        public decimal ProductPrice { set; get; }       //价格

        public int ProductStock { set; get; }       //商品库存
    }
}
namespace WeifuwuDemo.Product.Products
{
    /// <summary>
    /// 更新商品库存Dto
    /// </summary>
    public class UpdateProductInfoStockDto
    {
        // 商品编号
        public Guid ProductId { set; get; }
        // 商品数量
        public int ProductCount { set; get; }
    }
}

在WeifuwuDemo.Product.Application中新建文件夹并实现service接口:

namespace WeifuwuDemo.Product.Products
{
    public class ProductInfoAbpService:CrudAppService<ProductInfo,ProductInfoDto,Guid,PagedAndSortedResultRequestDto,CreateProductInfoDto,UpdateProductInfoDto>,IProductInfoAbpService
    {
        private readonly IProductInfoAbpRepository _productInfoAbpRepository;

        public ProductInfoAbpService(IProductInfoAbpRepository productInfoAbpRepository):base(productInfoAbpRepository)
        {
            _productInfoAbpRepository = productInfoAbpRepository;
        }
    }
}

在ProductApplicationAutoMapperProfile中添加dto和实体的映射:

CreateMap<ProductInfo, ProductInfoDto>();
        CreateMap<PagedAndSortedResultRequestDto, ProductInfo>();
        CreateMap<CreateProductInfoDto, ProductInfo>();
        CreateMap<UpdateProductInfoDto, ProductInfo>();
        CreateMap<ProductInfoAttrQueryDto, ProductInfo>();
        CreateMap<ProductInfoImageDto, ProductInfoImage>();
        CreateMap<ProductInfoImage, ProductInfoImageDto>();
        CreateMap<ProductInfoImageCreateDto, ProductInfoImage>();

在ProductApplicationModule中将验证实体和dto差异改为false

public class ProductApplicationModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddAutoMapperObjectMapper<ProductApplicationModule>();
        Configure<AbpAutoMapperOptions>(options =>
        {
            options.AddMaps<ProductApplicationModule>(validate: false);
        });
    }
}

在WeifuwuDemo.Product.HttpApi中新建products文件夹,并创建ProductInfoController:

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp;

namespace WeifuwuDemo.Product.Products
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class ProductInfoController:ProductController,IProductInfoAbpService
    {
        private readonly IProductInfoAbpService _productInfoAbpService;

        public ProductInfoController(IProductInfoAbpService productInfoAbpService)
        {
            _productInfoAbpService = productInfoAbpService;
        }

        /// <summary>
        /// 查询商品列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<PagedResultDto<ProductInfoDto>> GetListAsync([FromQuery] PagedAndSortedResultRequestDto input)
        {
            return await _productInfoAbpService.GetListAsync(input);
        }

        /// <summary>
        /// 查询单个商品
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<ProductInfoDto> GetAsync(Guid id)
        {
            var product = await _productInfoAbpService.GetAsync(id);
            return product;
        }

        /// <summary>
        /// 更新商品
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task<ProductInfoDto> UpdateAsync(Guid id, UpdateProductInfoDto input)
        {
            return await _productInfoAbpService.UpdateAsync(id, input);
        }

        /// <summary>
        /// 更新秒杀商品库存
        /// </summary>
        /// <param name="id"></param>
        /// <param name="product"></param>
        /// <returns></returns>
        [HttpPut("{id}/UpdateProductStock")]
        public async Task<IActionResult> PutProductStock(Guid id, UpdateProductInfoStockDto updateProductStockDto)
        {
            if (!id.Equals(updateProductStockDto.ProductId))
            {
                return BadRequest();

            }
            // 1、查询商品
            ProductInfoDto product = await _productInfoAbpService.GetAsync(updateProductStockDto.ProductId);

            // 2、判断商品库存是否完成
            if (product.ProductStock <= 0)
            {
                throw new AbpException("库存完了");
            }

            // 3、扣减商品库存
            product.ProductStock = product.ProductStock - updateProductStockDto.ProductCount;

            // 4、更新商品库存
            UpdateProductInfoDto updateProductDto = new UpdateProductInfoDto();
            updateProductDto.ProductStock = product.ProductStock;
            await _productInfoAbpService.UpdateAsync(updateProductStockDto.ProductId, updateProductDto);

            return Ok("更新库存成功");
        }

        /// <summary>
        /// 异步更新秒杀商品库存
        /// </summary>
        /// <param name="id"></param>
        /// <param name="productVo"></param>
        /// <returns></returns>
        [NonAction]
        //[CapSubscribe("product.stock")]
        public async Task<IActionResult> SetProductStock(UpdateProductInfoStockDto updateProductStockDto)
        {
            // 1、查询商品
            ProductInfoDto product = await _productInfoAbpService.GetAsync(updateProductStockDto.ProductId);

            // 2、判断商品库存是否完成
            if (product.ProductStock <= 0)
            {
                throw new AbpException("库存完了");
            }

            // 3、扣减商品库存
            product.ProductStock = product.ProductStock - updateProductStockDto.ProductCount;

            // 4、更新商品库存
            UpdateProductInfoDto updateProductDto = new UpdateProductInfoDto();
            updateProductDto.ProductStock = product.ProductStock;
            await _productInfoAbpService.UpdateAsync(updateProductStockDto.ProductId, updateProductDto);
            return Ok("更新库存成功");
        }

        /// <summary>
        /// 创建商品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ProductInfoDto> CreateAsync(CreateProductInfoDto input)
        {
            return await _productInfoAbpService.CreateAsync(input);
        }

        /// <summary>
        /// 删除商品
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task DeleteAsync(Guid id)
        {
            await _productInfoAbpService.DeleteAsync(id);
        }

    }
}