|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
using Volo.Abp.Domain.Entities;
|
|
|
|
using Volo.Abp.Guids;
|
|
|
|
using Win_in.Sfs.Shared.Domain.Entities;
|
|
|
|
|
|
|
|
namespace Win_in.Sfs.Shared.Domain;
|
|
|
|
|
|
|
|
public abstract class SfsMasterAggregateRootBase<TDetail> : SfsAggregateRootBase
|
|
|
|
, IMasterEntity<TDetail>, IHasNumber, IHasWorker
|
|
|
|
where TDetail : SfsDetailEntityBase, IEntity<Guid>
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// 操作员
|
|
|
|
/// </summary>
|
|
|
|
[IgnoreUpdate]
|
|
|
|
public string Worker { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 单据号
|
|
|
|
/// </summary>
|
|
|
|
[IgnoreUpdate]
|
|
|
|
public string Number { get; set; }
|
|
|
|
|
|
|
|
[IgnoreUpdate]
|
|
|
|
public virtual List<TDetail> Details { get; set; } = new();
|
|
|
|
|
|
|
|
private void SetIdAndNumber(IGuidGenerator guidGenerator, string number)
|
|
|
|
{
|
|
|
|
Id = guidGenerator.Create();
|
|
|
|
Number = number;
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void SetIdAndNumberWithDetails(IGuidGenerator guidGenerator, string number)
|
|
|
|
{
|
|
|
|
SetIdAndNumber(guidGenerator, number);
|
|
|
|
SetDetailsIdAndNumber(guidGenerator);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SetDetailsIdAndNumber(IGuidGenerator guidGenerator)
|
|
|
|
{
|
|
|
|
foreach (var detail in Details)
|
|
|
|
{
|
|
|
|
detail.SetIdAndNumber(guidGenerator, Id, Number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public TDetail GetDetail(Guid id)
|
|
|
|
{
|
|
|
|
return Details.FirstOrDefault(p => p.Id == id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool AddDetail(TDetail detail)
|
|
|
|
{
|
|
|
|
//todo check
|
|
|
|
|
|
|
|
return Details.AddIfNotContains(detail);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddDetails(List<TDetail> details)
|
|
|
|
{
|
|
|
|
//todo check
|
|
|
|
|
|
|
|
Details.AddRange(details);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ReplaceDetail(Guid id,TDetail newDetail)
|
|
|
|
{
|
|
|
|
var detail = GetDetail(id);
|
|
|
|
|
|
|
|
var propertiesOfDetail = detail.GetType().GetProperties();
|
|
|
|
var propertiesOfNewDetail = newDetail.GetType().GetProperties();
|
|
|
|
foreach (var property in propertiesOfDetail)
|
|
|
|
{
|
|
|
|
if (property.Name == "Id" || property.Name == "TenantId" || !property.CanWrite)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var attributes = property.GetCustomAttributes(typeof(NotMappedAttribute), false);
|
|
|
|
if (attributes.Any())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var propertyOfNewDetail = propertiesOfNewDetail.SingleOrDefault(y => y.Name == property.Name);
|
|
|
|
if (propertyOfNewDetail == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
var oldValue = property.GetValue(detail);
|
|
|
|
var newValue = propertyOfNewDetail.GetValue(newDetail);
|
|
|
|
if (oldValue == null && newValue == null)
|
|
|
|
{
|
|
|
|
property.SetValue(detail, null);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (oldValue.Equals(newValue))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
property.SetValue(detail, newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
////todo check
|
|
|
|
//var detail = GetDetail(id);
|
|
|
|
|
|
|
|
////todo DeepClone
|
|
|
|
//detail = newDetail;
|
|
|
|
|
|
|
|
Details.ForEach(x =>
|
|
|
|
{
|
|
|
|
if (x.Id != id) return;
|
|
|
|
var propertyInfoOrigins = x.GetType().GetProperties();
|
|
|
|
foreach (var propertyInfo in propertyInfoOrigins)
|
|
|
|
{
|
|
|
|
var targetPropertyIn = propertyInfoTargets.SingleOrDefault(y => y.Name == propertyInfo.Name);
|
|
|
|
if (targetPropertyIn == null
|
|
|
|
|| propertyInfo.Name == "TenantId"
|
|
|
|
|| propertyInfo.Name == "MasterID")
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!targetPropertyIn.CanWrite)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var attributes = propertyInfo.GetCustomAttributes(typeof(NotMappedAttribute), false);
|
|
|
|
if (attributes.Any())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
propertyInfo.SetValue(x, targetPropertyIn.GetValue(newDetail));
|
|
|
|
}
|
|
|
|
});*/
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RemoveDetail(Guid id)
|
|
|
|
{
|
|
|
|
//todo check
|
|
|
|
|
|
|
|
var detail = GetDetail(id);
|
|
|
|
Details.Remove(detail);
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsInDetails(Guid id)
|
|
|
|
{
|
|
|
|
return GetDetail(id) != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsInDetails(Expression<Func<TDetail, bool>> expression)
|
|
|
|
{
|
|
|
|
return Details.Any(expression.Compile());
|
|
|
|
}
|
|
|
|
|
|
|
|
public long GetDetailCount(Expression<Func<TDetail, bool>> expression)
|
|
|
|
{
|
|
|
|
return Details.Count(expression.Compile());
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<TDetail> GetDetailList(Expression<Func<TDetail, bool>> expression)
|
|
|
|
{
|
|
|
|
return Details.Where(expression.Compile()).ToList();
|
|
|
|
}
|
|
|
|
}
|