采购订单添加物料功能

This commit is contained in:
陈淳
2023-01-05 19:21:48 +08:00
parent 7d578ce363
commit efbf799218
49 changed files with 518 additions and 191 deletions

View File

@@ -953,5 +953,11 @@
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.CurrentUserTest">
<summary>
获取当前用户信息测试
</summary>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Yi.Framework.Common.Abstract;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Common.Models;
using Yi.Framework.DtoModel.ERP.Purchase;
using Yi.Framework.Interface.ERP;

View File

@@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common.Abstract;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Common.Const;
using Yi.Framework.Common.Models;
@@ -45,6 +46,9 @@ namespace Yi.Framework.ApiMicroservice.Controllers
private CacheInvoker _cacheDb;
private ILogger<TestController> _logger;
ISugarUnitOfWork<UnitOfWork> _unitOfWork;
[Autowired]
private ICurrentUser _currentUser { get; set; }
[Autowired]
public CacheInvoker CacheInvoker { get; set; }
//你可以依赖注入服务层各各接口,也可以注入其他仓储层,怎么爽怎么来!
@@ -403,5 +407,17 @@ namespace Yi.Framework.ApiMicroservice.Controllers
{
return Result.Success().SetStatus(CacheInvoker is not null);
}
/// <summary>
/// 获取当前用户信息测试
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize]
public Result CurrentUserTest()
{
var per = _currentUser.Permission;
return Result.Success().SetData(per);
}
}
}

View File

@@ -159,6 +159,10 @@ builder.Services.AddHttpContextAccessor();
#endregion
builder.Services.AddSingleton<ThumbnailSharpInvoer>();
#region
//<2F><><EFBFBD>ӵ<EFBFBD>ǰ<EFBFBD>û<EFBFBD><C3BB><EFBFBD>Ϣʹ<CFA2><CAB9>
#endregion
builder.Services.AddCurrentUserServer();
#region
//ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>ʼ<EFBFBD><CABC>ֵ
@@ -222,6 +226,10 @@ app.UseAuthentication();
#endregion
app.UseAuthorization();
#region
//<2F><><EFBFBD>ӵ<EFBFBD>ǰ<EFBFBD>û<EFBFBD><C3BB><EFBFBD>Ϣʹ<CFA2><CAB9>
#endregion
app.UseCurrentUserServer();
#region
//Consul<75><6C><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
#endregion
app.UseConsulService();

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Common.Abstract
{
public interface ICurrentUser
{
public bool IsAuthenticated { get; set; }
public long Id { get; set; }
public string UserName { get; set; }
public Guid? TenantId { get; set; }
public string Email { get; set; }
public bool EmailVerified { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberVerified { get; set; }
public string[] Roles { get; set; }
public string[] Permission { get; set; }
}
}

View File

@@ -12,5 +12,8 @@ namespace Yi.Framework.Common.Const
public const string AdminRolesCode = "admin";
public const string AdminPermissionCode = "*:*:*";
public const string PermissionClaim = "permission";
public const string UserName = "userName";
public const string DeptId = "deptId";
public const string TenantId = "tenantId";
}
}

View File

@@ -43,8 +43,8 @@ namespace Yi.Framework.Core
claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"));
claims.Add(new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMinutes(minutes)).ToUnixTimeSeconds()}"));
claims.Add(new Claim(JwtRegisteredClaimNames.Sid, user.Id.ToString()));
claims.Add(new Claim("userName", user.UserName));
claims.Add(new Claim("deptId", user.DeptId.ToString()));
claims.Add(new Claim(SystemConst.UserName, user.UserName));
claims.Add(new Claim(SystemConst.DeptId, user.DeptId.ToString()));
//-----------------------------以下从user的权限表中添加权限-----------------------例如:
foreach (var m in menus)

View File

@@ -10,9 +10,9 @@ namespace Yi.Framework.DtoModel.ERP.Material
{
public class MaterialCreateUpdateInput : EntityDto<long>
{
public string Code { get; set; }
public string Name { get; set; }
public string UnitName { get; set; }
public string Remarks { get; set; }
public string? Code { get; set; }
public string? Name { get; set; }
public string? UnitName { get; set; }
public string? Remarks { get; set; }
}
}

View File

@@ -10,10 +10,12 @@ namespace Yi.Framework.DtoModel.ERP.PurchaseDetails
{
public class PurchaseDetailsCreateUpdateInput : EntityDto<long>
{
public string MaterialUnit { get; set; }
public string? MaterialUnit { get; set; }
public string? MaterialName { get; set; }
public float UnitPrice { get; set; }
public long TotalNumber { get; set; }
public long CompleteNumber { get; set; }
public string Remarks { get; set; }
public long? CompleteNumber { get; set; }
public string? Remarks { get; set; }
}
}

View File

@@ -9,6 +9,7 @@ namespace Yi.Framework.DtoModel.ERP.PurchaseDetails
{
public class PurchaseDetailsGetListOutput: EntityDto<long>
{
public string MaterialName { get; set; }
public string MaterialUnit { get; set; }
public float UnitPrice { get; set; }
public long TotalNumber { get; set; }

View File

@@ -10,8 +10,8 @@ namespace Yi.Framework.DtoModel.ERP.Unit
{
public class UnitCreateUpdateInput : EntityDto<long>
{
public string Code { get; set; }
public string Name { get; set; }
public string Remarks { get; set; }
public string? Code { get; set; }
public string? Name { get; set; }
public string? Remarks { get; set; }
}
}

View File

@@ -11,9 +11,9 @@ namespace Yi.Framework.DtoModel.ERP.Warehouse
{
public class WarehouseCreateUpdateInput : EntityDto<long>
{
public string Code { get; set; }
public string Name { get; set; }
public string Remarks { get; set; }
public StateEnum State { get; set; }
public string? Code { get; set; }
public string? Name { get; set; }
public string? Remarks { get; set; }
public StateEnum? State { get; set; }
}
}

View File

@@ -13,29 +13,29 @@ namespace Yi.Framework.DtoModel.ERP.Supplier
/// <summary>
/// 供应商编码
/// </summary>
public string Code { get; set; }
public string? Code { get; set; }
/// <summary>
/// 供应商名称
/// </summary>
public string Name { get; set; }
public string? Name { get; set; }
/// <summary>
/// 供应商地址
/// </summary>
public string Address { get; set; }
public string? Address { get; set; }
/// <summary>
/// 电话
/// </summary>
public long Phone { get; set; }
public long? Phone { get; set; }
/// <summary>
/// 传真
/// </summary>
public string Fax { get; set; }
public string? Fax { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
public string? Email { get; set; }
}
}

View File

@@ -6,15 +6,13 @@ using System.Threading.Tasks;
namespace Yi.Framework.Interface.Base.Crud
{
public interface ICreateAppService<TEntityDto>
: ICreateAppService<TEntityDto, TEntityDto>
public interface ICreateAppService<TEntityDto>: ICreateAppService<TEntityDto, TEntityDto>
{
}
public interface ICreateAppService<TCreateResultOutputDto
, in TCreateInputDto> : IApplicationService
public interface ICreateAppService<TCreateResultOutputDto , in TCreateInputDto> : IApplicationService
{
Task<TCreateResultOutputDto> CreateAsync(TCreateInputDto dto);

View File

@@ -12,21 +12,21 @@ namespace Yi.Framework.Interface.Base.Crud
}
public interface ICrudAppService<TEntityDto, in TKey, in TCreateInput>
: ICrudAppService<TEntityDto, TKey, TCreateInput, TCreateInput>
public interface ICrudAppService<TEntityDto, in TKey, in TCreateInputDto>
: ICrudAppService<TEntityDto, TKey, TCreateInputDto, TCreateInputDto>
{
}
public interface ICrudAppService<TEntityDto, in TKey, in TCreateInput, in TUpdateInput>
: ICrudAppService<TEntityDto, TEntityDto, TKey, TCreateInput, TUpdateInput>
public interface ICrudAppService<TEntityDto, in TKey, in TCreateInputDto, in TUpdateInputDto>
: ICrudAppService<TEntityDto, TEntityDto, TKey, TCreateInputDto, TUpdateInputDto>
{
}
public interface ICrudAppService<TGetOutputDto, TGetListOutputDto, in TKey, in TCreateInput, in TUpdateInput>
: IReadOnlyAppService<TGetOutputDto, TGetListOutputDto, TKey>,
ICreateUpdateAppService<TGetOutputDto, TKey, TCreateInput, TUpdateInput>,
public interface ICrudAppService<TGetOutputDto, TListOutputDto, in TKey, in TCreateInputDto, in TUpdateInputDto>
: IReadOnlyAppService<TGetOutputDto, TListOutputDto, TKey>,
ICreateUpdateAppService<TGetOutputDto, TKey, TCreateInputDto, TUpdateInputDto>,
IDeleteAppService<TKey>
{

View File

@@ -37,6 +37,12 @@ namespace Yi.Framework.Model.ERP.Entitys
/// </summary>
public long MaterialId { get; set; }
/// <summary>
/// 物料名称
/// </summary>
public string MaterialName { get; set; }
/// <summary>
/// 物料单位
/// </summary>

View File

@@ -14,28 +14,18 @@ namespace Yi.Framework.Service.Base.Crud
: AbstractKeyCrudAppService<TEntity, TEntityDto, TKey, TEntityDto, TEntityDto>
where TEntity : class, IEntity, new()
{
protected AbstractKeyCrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
}
public abstract class AbstractKeyCrudAppService<TEntity, TEntityDto, TKey, TCreateUpdateInput>
: AbstractKeyCrudAppService<TEntity, TEntityDto, TKey, TCreateUpdateInput, TCreateUpdateInput>
where TEntity : class, IEntity, new()
{
protected AbstractKeyCrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
}
public abstract class AbstractKeyCrudAppService<TEntity, TEntityDto, TKey, TCreateInput, TUpdateInput>
: AbstractKeyCrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TCreateInput, TUpdateInput>
public abstract class AbstractKeyCrudAppService<TEntity, TEntityDto, TKey, TCreateInputDto, TUpdateInputDto>
: AbstractKeyCrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TCreateInputDto, TUpdateInputDto>
where TEntity : class, IEntity, new()
{
protected AbstractKeyCrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
protected override Task<TEntityDto> MapToGetListOutputDtoAsync(TEntity entity)
{
return MapToGetOutputDtoAsync(entity);
@@ -47,23 +37,20 @@ namespace Yi.Framework.Service.Base.Crud
}
}
public abstract class AbstractKeyCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TCreateInput, TUpdateInput>
: AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey>,
ICrudAppService<TGetOutputDto, TGetListOutputDto, TKey, TCreateInput, TUpdateInput>
public abstract class AbstractKeyCrudAppService<TEntity, TGetOutputDto, TListOutputDto, TKey, TCreateInputDto, TUpdateInputDto>
: AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TListOutputDto, TKey>,
ICrudAppService<TGetOutputDto, TListOutputDto, TKey, TCreateInputDto, TUpdateInputDto>
where TEntity : class, IEntity, new()
{
protected AbstractKeyCrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
/// <summary>
/// 创建
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public virtual async Task<TGetOutputDto> CreateAsync(TCreateInput input)
public virtual async Task<TGetOutputDto> CreateAsync(TCreateInputDto input)
{
var entity = await MapToEntityAsync(input);
TryToSetTenantId(entity);
@@ -76,7 +63,7 @@ namespace Yi.Framework.Service.Base.Crud
}
public async virtual Task CreateAsync(IEnumerable<TCreateInput> dtos)
public async virtual Task CreateAsync(IEnumerable<TCreateInputDto> dtos)
{
var entity = await MapToEntitysAsync(dtos);
@@ -105,7 +92,7 @@ namespace Yi.Framework.Service.Base.Crud
/// <param name="id"></param>
/// <param name="dto"></param>
/// <returns></returns>
public virtual async Task<TGetOutputDto> UpdateAsync(TKey id, TUpdateInput input)
public virtual async Task<TGetOutputDto> UpdateAsync(TKey id, TUpdateInputDto input)
{
var entity = await GetEntityByIdAsync(id);
@@ -123,31 +110,30 @@ namespace Yi.Framework.Service.Base.Crud
/// <param name="idEntity"></param>
/// <param name="dto"></param>
/// <returns></returns>
protected virtual Task UpdateValidAsync(TEntity idEntity, TUpdateInput dto)
protected virtual Task UpdateValidAsync(TEntity idEntity, TUpdateInputDto dto)
{
return Task.CompletedTask;
}
/// <summary>
/// 将 更新输入dto转化为实体的异步
/// 批量更新输入dto转化为实体的同步方法
/// </summary>
/// <param name="updateInput"></param>
/// <param name="entity"></param>
protected virtual Task MapToEntityAsync(TUpdateInput updateInput, TEntity entity)
/// <returns></returns>
protected virtual List<TEntity> MapToEntity(IEnumerable<TCreateInputDto> updateInput)
{
MapToEntity(updateInput, entity);
return Task.CompletedTask;
return ObjectMapper.Map<List<TEntity>>(updateInput);
}
/// <summary>
/// 将 批量更新输入dto转化为实体的异步
/// </summary>
/// <param name="updateInput"></param>
/// <param name="entity"></param>
protected virtual async Task<List<TEntity>> MapToEntitysAsync(IEnumerable<TCreateInput> updateInput)
protected virtual async Task<List<TEntity>> MapToEntitysAsync(IEnumerable<TCreateInputDto> updateInput)
{
List<TEntity> entitys = MapToEntitys(updateInput);
List<TEntity> entitys = MapToEntity(updateInput);
return await Task.FromResult(entitys);
}
@@ -156,28 +142,28 @@ namespace Yi.Framework.Service.Base.Crud
/// </summary>
/// <param name="updateInput"></param>
/// <param name="entity"></param>
protected virtual void MapToEntity(TUpdateInput updateInput, TEntity entity)
protected virtual void MapToEntity(TUpdateInputDto updateInput, TEntity entity)
{
ObjectMapper.Map(updateInput, entity);
}
/// <summary>
/// 批量更新输入dto转化为实体的同步方法
/// 将 更新输入dto转化为实体的异步
/// </summary>
/// <param name="updateInput"></param>
/// <returns></returns>
protected virtual List<TEntity> MapToEntitys(IEnumerable<TCreateInput> updateInput)
/// <param name="entity"></param>
protected virtual Task MapToEntityAsync(TUpdateInputDto updateInput, TEntity entity)
{
return ObjectMapper.Map<List<TEntity>>(updateInput);
MapToEntity(updateInput, entity);
return Task.CompletedTask;
}
/// <summary>
/// 创建dto 给 实体的转换的异步方法
/// </summary>
/// <param name="createInput"></param>
/// <returns></returns>
protected virtual Task<TEntity> MapToEntityAsync(TCreateInput createInput)
protected virtual Task<TEntity> MapToEntityAsync(TCreateInputDto createInput)
{
return Task.FromResult(MapToEntity(createInput));
}
@@ -187,9 +173,9 @@ namespace Yi.Framework.Service.Base.Crud
/// </summary>
/// <param name="createInput"></param>
/// <returns></returns>
protected virtual TEntity MapToEntity(TCreateInput createInput)
protected virtual TEntity MapToEntity(TCreateInputDto createInput)
{
var entity = ObjectMapper.Map<TCreateInput, TEntity>(createInput);
var entity = ObjectMapper.Map<TCreateInputDto, TEntity>(createInput);
SetIdForGuids(entity);
return entity;
}

View File

@@ -7,6 +7,9 @@ using System.Linq.Expressions;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Common.Enum;
using Yi.Framework.Common.Exceptions;
using Yi.Framework.Interface.Base.Crud;
using Yi.Framework.Model.Base;
using Yi.Framework.Repository;
@@ -17,9 +20,6 @@ namespace Yi.Framework.Service.Base.Crud
: AbstractKeyReadOnlyAppService<TEntity, TEntityDto, TEntityDto, TKey>
where TEntity : class, IEntity, new()
{
protected AbstractKeyReadOnlyAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
}
@@ -27,13 +27,8 @@ namespace Yi.Framework.Service.Base.Crud
IReadOnlyAppService<TGetOutputDto, TGetListOutputDto, TKey>
where TEntity : class, IEntity, new()
{
public AbstractKeyReadOnlyAppService(IRepository<TEntity> repository, IMapper mapper) : base(mapper)
{
Repository = repository;
}
protected IRepository<TEntity> Repository { get; set; }
[Autowired]
public IRepository<TEntity> Repository { get; set; }
public async Task<List<TGetListOutputDto>> GetListAsync()
@@ -46,6 +41,10 @@ namespace Yi.Framework.Service.Base.Crud
public async Task<TGetOutputDto> GetByIdAsync(TKey id)
{
var entity = await GetEntityByIdAsync(id);
if (entity is null)
{
throw new UserFriendlyException($"主键:{id} 数据不存在",ResultCodeEnum.NotSuccess);
}
var entityDto = await MapToGetOutputDtoAsync(entity);
return entityDto;
@@ -92,6 +91,24 @@ namespace Yi.Framework.Service.Base.Crud
return dtos;
}
/// <summary>
/// 多个实体列表映射GetList输出dto列表的同步方法
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
protected virtual async Task<List<TGetListOutputDto>> MapToGetListOutputDtos(IEnumerable<TEntity> entities)
{
var dtos = new List<TGetListOutputDto>();
foreach (var entity in entities)
{
dtos.Add(await MapToGetListOutputDtoAsync(entity));
}
return dtos;
}
/// <summary>
/// 实体列表映射GetList输出dto的异步方法
/// </summary>

View File

@@ -1,16 +1,16 @@
using AutoMapper;
using AutoMapper.Internal.Mappers;
using Microsoft.Extensions.DependencyInjection;
using System;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Interface.Base.Crud;
namespace Yi.Framework.Service.Base.Crud
{
public class ApplicationService : IApplicationService
{
public ApplicationService(IMapper mapper)
{
ObjectMapper = mapper;
}
protected IMapper ObjectMapper { get; set; }
[Autowired]
public IServiceProvider ServiceProvider { get; set; }
protected IMapper ObjectMapper => ServiceProvider.GetRequiredService<IMapper>();
}
}

View File

@@ -14,28 +14,17 @@ namespace Yi.Framework.Service.Base.Crud
: CrudAppService<TEntity, TEntityDto, TKey, TEntityDto>
where TEntity : class, IEntity<TKey>, new()
{
protected CrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
}
public abstract class CrudAppService<TEntity, TEntityDto, TKey, TCreateInput>
: CrudAppService<TEntity, TEntityDto, TKey, TCreateInput, TCreateInput>
public abstract class CrudAppService<TEntity, TEntityDto, TKey, TCreateInputDto>
: CrudAppService<TEntity, TEntityDto, TKey, TCreateInputDto, TCreateInputDto>
where TEntity : class, IEntity<TKey>, new()
{
protected CrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
}
public abstract class CrudAppService<TEntity, TEntityDto, TKey, TCreateInput, TUpdateInput>
: CrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TCreateInput, TUpdateInput>
public abstract class CrudAppService<TEntity, TEntityDto, TKey, TCreateInputDto, TUpdateInputDto>: CrudAppService<TEntity, TEntityDto, TEntityDto, TKey, TCreateInputDto, TUpdateInputDto>
where TEntity : class, IEntity<TKey>, new()
{
protected CrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
protected override Task<TEntityDto> MapToGetListOutputDtoAsync(TEntity entity)
{
return MapToGetOutputDtoAsync(entity);
@@ -47,14 +36,10 @@ namespace Yi.Framework.Service.Base.Crud
}
}
public abstract class CrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TCreateInput, TUpdateInput>
: AbstractKeyCrudAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey, TCreateInput, TUpdateInput>
public abstract class CrudAppService<TEntity, TGetOutputDto, TListOutputDto, TKey, TCreateInputDto, TUpdateInputDto>
: AbstractKeyCrudAppService<TEntity, TGetOutputDto, TListOutputDto, TKey, TCreateInputDto, TUpdateInputDto>
where TEntity : class, IEntity<TKey>, new()
{
protected CrudAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
protected override async Task DeleteByIdAsync(TKey id)
{
await DeleteAsync(new List<TKey> { id });
@@ -65,7 +50,7 @@ namespace Yi.Framework.Service.Base.Crud
return await Repository.GetByIdAsync(id);
}
protected override void MapToEntity(TUpdateInput updateInput, TEntity entity)
protected override void MapToEntity(TUpdateInputDto updateInput, TEntity entity)
{
if (updateInput is IEntityDto<TKey> entityDto)
{

View File

@@ -14,10 +14,6 @@ namespace Yi.Framework.Service.Base.Crud
: AbstractKeyReadOnlyAppService<TEntity, TGetOutputDto, TGetListOutputDto, TKey>
where TEntity : class, IEntity<TKey>, new()
{
protected ReadOnlyAppService(IRepository<TEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
protected override async Task<TEntity> GetEntityByIdAsync(TKey id)
{
return await Repository.GetByIdAsync(id);

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.ERP
{
public class MaterialService : CrudAppService<MaterialEntity, MaterialGetListOutput, long, MaterialCreateUpdateInput>, IMaterialService
{
public MaterialService(IRepository<MaterialEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<MaterialGetListOutput>>> PageListAsync(MaterialCreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.ERP
{
public class PurchaseDetailsService : CrudAppService<PurchaseDetailsEntity, PurchaseDetailsGetListOutput, long, PurchaseDetailsCreateUpdateInput>, IPurchaseDetailsService
{
public PurchaseDetailsService(IRepository<PurchaseDetailsEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<PurchaseDetailsGetListOutput>>> PageListAsync(PurchaseDetailsCreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -5,9 +5,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Common.Models;
using Yi.Framework.DtoModel.ERP.Purchase;
using Yi.Framework.Interface.ERP;
using Yi.Framework.Model.Base;
using Yi.Framework.Model.ERP.Entitys;
using Yi.Framework.Repository;
using Yi.Framework.Service.Base.Crud;
@@ -16,10 +18,10 @@ namespace Yi.Framework.Service.ERP
{
public class PurchaseService : CrudAppService<PurchaseEntity, PurchaseGetListOutput, long, PurchaseCreateInput, PurchaseUpdateInput>, IPurchaseService
{
private readonly ISugarUnitOfWork<UnitOfWork> _unitOfWork;
private ISugarUnitOfWork<UnitOfWork> _unitOfWork;
private readonly IPurchaseDetailsService _purchaseDetailsService;
public PurchaseService(IRepository<PurchaseEntity> repository, IMapper mapper, ISugarUnitOfWork<UnitOfWork> unitOfWork,
IPurchaseDetailsService purchaseDetailsService) : base(repository, mapper)
public PurchaseService(ISugarUnitOfWork<UnitOfWork> unitOfWork,
IPurchaseDetailsService purchaseDetailsService)
{
_unitOfWork = unitOfWork;
_purchaseDetailsService = purchaseDetailsService;
@@ -36,20 +38,20 @@ namespace Yi.Framework.Service.ERP
public override async Task<PurchaseGetListOutput> CreateAsync(PurchaseCreateInput input)
{
PurchaseEntity entity = null;
using (var uow = _unitOfWork.CreateContext())
{
var entity = await MapToEntityAsync(input);
entity = await MapToEntityAsync(input);
entity.PaidMoney = 0;
entity.TotalMoney = input.PurchaseDetails.Sum(u => u.UnitPrice * u.TotalNumber);
entity.PurchaseState = PurchaseStateEnum.Build;
TryToSetTenantId(entity);
var purchaseId = await Repository.InsertReturnSnowflakeIdAsync(entity);
entity.Id = purchaseId;
await _purchaseDetailsService.CreateAsync(input.PurchaseDetails);
uow.Commit();
}
return null;
return await MapToGetListOutputDtoAsync(entity); ;
}
}
}

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.ERP
{
public class SupplierService : CrudAppService<SupplierEntity, SupplierGetListOutput, long, SupplierCreateUpdateInput>, ISupplierService
{
public SupplierService(IRepository<SupplierEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<SupplierGetListOutput>>> PageListAsync(SupplierCreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.ERP
{
public class UnitService : CrudAppService<UnitEntity, UnitGetListOutput, long, UnitCreateUpdateInput>, IUnitService
{
public UnitService(IRepository<UnitEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<UnitGetListOutput>>> PageListAsync(UnitCreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.ERP
{
public class WarehouseService : CrudAppService<WarehouseEntity, WarehouseGetListOutput, long, WarehouseCreateUpdateInput>, IWarehouseService
{
public WarehouseService(IRepository<WarehouseEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<WarehouseGetListOutput>>> PageListAsync(WarehouseCreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -14,10 +14,6 @@ namespace Yi.Framework.Service.RABC
{
public class StudentService : CrudAppService<StudentEntity, StudentGetOutput, StudentListOutput, Guid, StudentCreateInput, StudentUpdateInput>, IStudentService
{
public StudentService(IRepository<StudentEntity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<List<StudentListOutput>> GetListAsync()
{
return await MapToGetListOutputDtosAsync(await Repository.GetListAsync());

View File

@@ -17,6 +17,7 @@ foreach (var entityName in entityNames)
option.Add(new IServceTemplateProvider(modelName, entityName));
option.Add(new CreateUpdateInputTemplateProvider(modelName, entityName));
option.Add(new GetListOutputTemplateProvider(modelName, entityName));
option.Add(new GetListInputTemplateProvider(modelName, entityName));
option.Add(new ConstTemplateProvider(modelName, entityName));
option.Add(new ProfileTemplateProvider(modelName, entityName));
option.Add(new ControllerTemplateProvider(modelName, entityName));

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Template.Abstract;
using Yi.Framework.Template.Const;
namespace Yi.Framework.Template.Provider.Server
{
public class GetListInputTemplateProvider : ModelTemplateProvider
{
public GetListInputTemplateProvider(string modelName, string entityName) : base(modelName, entityName)
{
BuildPath = $@"..\..\..\..\Yi.Framework.DtoModel\{TemplateConst.ModelName}\{TemplateConst.EntityName}\{TemplateConst.EntityName}GetListInput.cs";
TemplatePath = $@"..\..\..\Template\Server\GetListInputTemplate.txt";
EntityPath = $@"..\..\..\..\Yi.Framework.Model\{TemplateConst.ModelName}\Entitys\{TemplateConst.EntityName}Entity.cs";
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Model.Base;
namespace Yi.Framework.DtoModel.#ModelName#.#EntityName#
{
public class #EntityName#GetListInput
{
#EntityField#
}
}

View File

@@ -16,9 +16,6 @@ namespace Yi.Framework.Service.#ModelName#
{
public class #EntityName#Service : CrudAppService<#EntityName#Entity, #EntityName#GetListOutput, long, #EntityName#CreateUpdateInput>, I#EntityName#Service
{
public #EntityName#Service(IRepository<#EntityName#Entity> repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<PageModel<List<#EntityName#GetListOutput>>> PageListAsync(#EntityName#CreateUpdateInput input, PageParModel page)
{
RefAsync<int> totalNumber = 0;

View File

@@ -20,6 +20,9 @@
<None Update="Template\Server\ControllerTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Template\Server\GetListInputTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Template\Server\ProfileTemplate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@@ -11,11 +11,13 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Yi.Framework.Common.Abstract;
using Yi.Framework.Interface;
using Yi.Framework.Job;
using Yi.Framework.Repository;
using Yi.Framework.Service;
using Yi.Framework.WebCore.AutoFacExtend;
using Yi.Framework.WebCore.Impl;
using Module = Autofac.Module;
namespace Yi.Framework.WebCore.AutoFacExtend
@@ -31,7 +33,7 @@ namespace Yi.Framework.WebCore.AutoFacExtend
var msg = "service.dll 丢失,请编译后重新生成。";
throw new Exception(msg);
}
return Assembly.LoadFrom(servicesDllFile); ;
return Assembly.LoadFrom(servicesDllFile); ;
}
protected override void Load(ContainerBuilder containerBuilder)
@@ -39,18 +41,18 @@ namespace Yi.Framework.WebCore.AutoFacExtend
//containerBuilder.RegisterType<DbContextFactory>().As<IDbContextFactory>().InstancePerDependency().EnableInterfaceInterceptors();
containerBuilder.RegisterType< HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
//containerBuilder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
//containerBuilder.RegisterGeneric(typeof(BaseService<>)).As(typeof(IBaseService<>)).InstancePerLifetimeScope();
///反射注入服务层及接口层
var assemblysServices = GetDll( "Yi.Framework.Service.dll");
containerBuilder.RegisterAssemblyTypes(assemblysServices)
var assemblysServices = GetDll("Yi.Framework.Service.dll");
containerBuilder.RegisterAssemblyTypes(assemblysServices).PropertiesAutowired(new AutowiredPropertySelector())
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors();
//开启工作单元拦截
//.InterceptedBy(typeof(UnitOfWorkInterceptor));
//开启工作单元拦截
//.InterceptedBy(typeof(UnitOfWorkInterceptor));
///反射注册任务调度层
var assemblysJob = GetDll("Yi.Framework.Job.dll");
@@ -61,10 +63,6 @@ namespace Yi.Framework.WebCore.AutoFacExtend
containerBuilder.Register(c => new CustomAutofacAop());//AOP注册
//containerBuilder.RegisterType<A>().As<IA>().EnableInterfaceInterceptors();开启Aop
//将数据库对象注入
@@ -73,7 +71,6 @@ namespace Yi.Framework.WebCore.AutoFacExtend
//containerBuilder.RegisterGeneric(typeof(BaseService<>)).As(typeof(IBaseService<>)).InstancePerDependency().EnableInterfaceInterceptors();
}
}

View File

@@ -14,9 +14,11 @@ using System.Reflection;
using System.Threading.Tasks;
using Yi.Framework.Common.Attribute;
using Yi.Framework.Interface;
using Yi.Framework.Interface.Base.Crud;
using Yi.Framework.Job;
using Yi.Framework.Repository;
using Yi.Framework.Service;
using Yi.Framework.Service.Base.Crud;
using Module = Autofac.Module;
namespace Yi.Framework.WebCore.AutoFacExtend

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Abstract;
namespace Yi.Framework.WebCore.Impl
{
public class CurrentUser : ICurrentUser
{
public bool IsAuthenticated { get; set; }
public long Id { get; set; }
public string UserName { get; set; } = string.Empty;
public Guid? TenantId { get; set; }
public string Email { get; set; }=string.Empty;
public bool EmailVerified { get; set; }
public string PhoneNumber { get; set; } = string.Empty;
public bool PhoneNumberVerified { get; set; }
public string[]? Roles { get; set; }
public string[]? Permission { get; set; }
}
}

View File

@@ -0,0 +1,80 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Yi.Framework.Common.Abstract;
using Yi.Framework.Common.Const;
using Yi.Framework.WebCore.Impl;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
public static class CurrentUserExrension
{
public static IServiceCollection AddCurrentUserServer(this IServiceCollection services)
{
return services.AddScoped<ICurrentUser, CurrentUser>();
}
public static IApplicationBuilder UseCurrentUserServer(this IApplicationBuilder app)
{
return app.UseMiddleware<CurrentUserMiddleware>();
}
}
public class CurrentUserMiddleware
{
private readonly RequestDelegate _next;
private ILogger<CurrentUserMiddleware> _logger;
public CurrentUserMiddleware(RequestDelegate next, ILogger<CurrentUserMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context, ICurrentUser _currentUser)
{
var authenticateContext = await context.AuthenticateAsync();
if (authenticateContext.Principal is null)
{
_currentUser.IsAuthenticated = false;
await _next(context);
return;
}
var claims = authenticateContext.Principal.Claims;
//通过鉴权之后,开始赋值
_currentUser.IsAuthenticated = true;
_currentUser.Id = claims.GetClaim(JwtRegisteredClaimNames.Sid) is null ? 0 : Convert.ToInt64(claims.GetClaim(JwtRegisteredClaimNames.Sid));
_currentUser.UserName = claims.GetClaim(SystemConst.UserName);
_currentUser.Permission = claims.GetClaims(SystemConst.PermissionClaim);
_currentUser.TenantId = claims.GetClaim(SystemConst.TenantId) is null ? null : Guid.Parse(claims.GetClaim(SystemConst.TenantId)!);
await _next(context);
}
}
public static class ClaimExtension
{
public static string? GetClaim(this IEnumerable<Claim> claims, string type)
{
return claims.Where(c => c.Type == type).Select(c => c.Value).FirstOrDefault();
}
public static string[]? GetClaims(this IEnumerable<Claim> claims, string type)
{
return claims.Where(c => c.Type == type).Select(c => c.Value).ToArray();
}
}
}

View File

@@ -142,14 +142,19 @@
</el-col>
<el-col :span="8">
<el-form-item label="需求时间" prop="name">
<el-input v-model="form.name" placeholder="请输入采购单员" />
<el-form-item label="需求时间" prop="needTime">
<el-date-picker
v-model="form.needTime"
type="date"
placeholder="选择一个日期"
size="default"
/>
</el-form-item>
</el-col>
<el-col :offset="8" :span="8">
<el-form-item label="总金额" prop="name">
999{{ form.name }}
<el-form-item label="总金额">
{{showTotalMoney}}
</el-form-item>
</el-col>
@@ -158,7 +163,7 @@
<el-row>
<el-col :span="24">
<el-form-item label="物料信息">
<el-table :data="tableData" border style="width: 100%">
<el-table :data="form.purchaseDetails" border style="width: 100%">
<el-table-column width="90">
<template #default>
@@ -166,11 +171,30 @@
</template>
</el-table-column>
<el-table-column prop="date" label="物料" width="180" />
<el-table-column prop="name" label="单" width="180" />
<el-table-column prop="address" label="采购数量" width="180" />
<el-table-column prop="address" label="备注" />
<el-table-column prop="materialName" label="物料" width="180" />
<el-table-column prop="materialUnit" label="单" width="180" />
<el-table-column prop="unitPrice" label="单价" width="180" >
<template #default="scope">
<el-input
v-model="scope.row.unitPrice"/>
</template>
</el-table-column>
<el-table-column prop="totalNumber" label="采购数量" width="180" >
<template #default="scope">
<el-input v-model="scope.row.totalNumber"/>
</template>
</el-table-column>
<el-table-column prop="remarks" label="备注" >
<template #default="scope">
<el-input
v-model="scope.row.remarks"/>
</template>
</el-table-column>
</el-table>
<el-button class="form-add-btn" type="primary" icon="CirclePlus" plain @click="materialHandleAdd">添加物料</el-button>
</el-form-item>
</el-col>
</el-row>
@@ -185,6 +209,44 @@
</div>
</template>
</el-dialog>
<!-- ---------------------这里是新增物料的对话框--------------------- -->
<el-dialog title="添加物料" v-model="openMaterial" width="800px" append-to-body>
<el-form :model="queryMaterialParams" ref="queryMaterialRef" :inline="true" label-width="70px">
<el-form-item label="物料名称" prop="name">
<el-input v-model="queryMaterialParams.name" placeholder="请输入物料名称" clearable style="width: 150px"
@keyup.enter="handleMaterialQuery" prop="name" />
</el-form-item>
<el-form-item label="物料编码" prop="code">
<el-input v-model="queryMaterialParams.code" placeholder="请输入物料编码" clearable style="width: 150px"
@keyup.enter="handleMaterialQuery" prop="code" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleMaterialQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetMaterialQuery">重置</el-button>
</el-form-item>
<!-- 物料表单 -->
<el-table
style="width: 100%"
:data="materialList"
@selection-change="materialHandleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column property="code" label="物料编码" />
<el-table-column property="name" label="物料信息" />
<el-table-column property="unitName" label="物料单位" />
</el-table>
<pagination v-show="materialTotal > 0" :total="materialTotal" v-model:page="queryMaterialParams.pageNum"
v-model:limit="queryMaterialParams.pageSize" @pagination="getMaterialList" />
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitMaterialForm"> </el-button>
<el-button @click="materialCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@@ -196,33 +258,21 @@ import {
addData,
updateData,
} from "@/api/erp/purchaseApi";
import { ref } from "@vue/reactivity";
import {
listData as materialListData
} from "@/api/erp/materialApi";
import { ref } from "@vue/reactivity";
import { computed } from "@vue/runtime-core";
const { proxy } = getCurrentInstance();
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
//添加物料对话框
const openMaterial=ref(false);
const materialList= ref([]);
const materialTotal = ref(0);
const materialMultipleSelection=ref([]);
const dataList = ref([]);
@@ -236,7 +286,10 @@ const total = ref(0);
const title = ref("");
const dateRange = ref([]);
const data = reactive({
form: {},
form: {
totalMoney:0,
purchaseDetails:[]
},
queryParams: {
pageNum: 1,
pageSize: 10,
@@ -244,14 +297,19 @@ const data = reactive({
code: undefined,
buyer: undefined,
},
queryMaterialParams:{
pageNum: 1,
pageSize: 10,
name: undefined,
code: undefined,
},
rules: {
code: [{ required: true, message: "采购单编号不能为空", trigger: "blur" }],
name: [{ required: true, message: "采购单名称不能为空", trigger: "blur" }],
},
});
const { queryParams, form, rules } = toRefs(data);
const { queryParams, form, queryMaterialParams,rules } = toRefs(data);
/** 查询列表 */
function getList() {
loading.value = true;
@@ -263,6 +321,7 @@ function getList() {
}
);
}
/** 取消按钮 */
function cancel() {
open.value = false;
@@ -343,5 +402,87 @@ function handleDelete(row) {
/** 导出按钮操作 */
function handleExport() { }
//-------------这里开始是物料对话框的数据-----------
/** 物料查询列表 */
function getMaterialList() {
materialListData(proxy.addDateRange(queryMaterialParams.value, dateRange.value)).then(
(response) => {
materialList.value = response.data.data;
materialTotal.value = response.data.total;
}
);
}
/** 表单改变选择 */
function materialHandleSelectionChange(select)
{
materialMultipleSelection.value=select
}
/** 打开对话框 */
function materialHandleAdd()
{
getMaterialList();
openMaterial.value=true;
}
/** 搜索 */
function handleMaterialQuery()
{
getMaterialList();
}
/**重置表单 */
function resetMaterialQuery()
{
proxy.resetForm("queryMaterialRef");
handleMaterialQuery();
}
/** 提交物料表单 */
function submitMaterialForm()
{
if(materialMultipleSelection.value.length>0)
{
const purchaseDetailsList= materialMultipleSelection.value.map(u=>{
return {materialName:u.name,materialUnit:u.unitName}
})
form.value.purchaseDetails.push(...purchaseDetailsList)
materialCancel()
}
else
{
proxy.$modal.msgError("请选择至少一个物料");
}
}
/** 取消对话框 */
function materialCancel()
{
openMaterial.value=false
}
// watch(data.form, (newValue, oldValue) => {
// console.log(newValue.purchaseDetails,999)
// }
// , { immdiate: true })
/** 计算属性:实时计算展示的价格 */
const showTotalMoney =computed(()=>{
let res=0;
form.value.purchaseDetails.forEach(details => {
if(details.unitPrice!=undefined && details.totalNumber!=undefined)
{res+= details.unitPrice*details.totalNumber}
});
return res;
})
getList();
</script>
</script>
<style scoped>
.form-add-btn{
width: 100%;
margin-top: 10px;
}
</style>