diff --git a/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs b/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs index 7d137ef..1477ba8 100644 --- a/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs +++ b/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs @@ -4,7 +4,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Church.Net.Entity; +using Church.Net.Entity.Messenger; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; namespace Church.Net.DAL.EF { @@ -17,7 +19,7 @@ namespace Church.Net.DAL.EF // public ChurchNetContext(string connString):base(connString) // { - + // } // //public DbSet PastoralDomains { get; set; } // //public DbSet FamilyMembers { get; set; } @@ -36,7 +38,10 @@ namespace Church.Net.DAL.EF public class ChurchNetContext : DbContext { private static bool _created = true; - public ChurchNetContext(DbContextOptions options) :base(options) + private readonly string connectionString; + + + public ChurchNetContext(DbContextOptions options) : base(options) { } @@ -53,23 +58,23 @@ namespace Church.Net.DAL.EF // Database.EnsureCreated(); // } //} - //public ChurchNetContext(string connectionString) - //{ - // var folder = Environment.SpecialFolder.LocalApplicationData; - // var path = Environment.GetFolderPath(folder); - // DbPath = System.IO.Path.Join(path, "ChurchNet.db"); - // DbPath = @"C:\WebSites\ChurchNetAPI\App_Data\ChurchNet.db"; - // if (!_created) - // { - // _created = true; - // Database.EnsureDeleted(); - // Database.EnsureCreated(); - // } - //} + public ChurchNetContext(string connectionString) + { + this.connectionString = connectionString; + + } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!string.IsNullOrWhiteSpace(connectionString)) + { + optionsBuilder.UseNpgsql(connectionString); + } + + } //public DbSet PastoralDomains { get; set; } //public DbSet FamilyMembers { get; set; } //public DbSet Careers { get; set; } - + protected override void OnModelCreating(ModelBuilder modelBuilder) { //modelBuilder.Conventions.Remove(); @@ -78,7 +83,7 @@ namespace Church.Net.DAL.EF modelBuilder.Entity() .HasKey(tt => new { tt.EventId, tt.MemberId }); - + modelBuilder.Entity() .HasKey(tt => new { tt.FamilyMemberId, tt.OAuthType }); @@ -91,9 +96,9 @@ namespace Church.Net.DAL.EF .HasKey(tt => new { tt.PastoralDomainCommunityAppId, tt.AutoReplyItemId }); modelBuilder.Entity() .HasOne(tt => tt.PastoralDomain) - .WithMany(t=>t.AutoReplyItemRelations) - .HasForeignKey(tt=>tt.PastoralDomainCommunityAppId) - .HasPrincipalKey(tt=>tt.CommunityAppId); + .WithMany(t => t.AutoReplyItemRelations) + .HasForeignKey(tt => tt.PastoralDomainCommunityAppId) + .HasPrincipalKey(tt => tt.CommunityAppId); //modelBuilder.Entity() // .HasOne(t => t.PastoralDomain) @@ -130,7 +135,10 @@ namespace Church.Net.DAL.EF public DbSet LogInfos { get; set; } public DbSet AutoReplyItems { get; set; } public DbSet AddressInfos { get; set; } + public DbSet LineMessageClients { get; set; } + public DbSet LineMessagingAccounts { get; set; } + #endregion diff --git a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs b/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs new file mode 100644 index 0000000..434d3ff --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs @@ -0,0 +1,210 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Transactions; +using System; +using Church.Net.DAL.EF; +using System.Linq; +using Church.Net.Utility; +using System.Threading.Tasks; +using Church.Net.Entity.Interface; +using System.ComponentModel.DataAnnotations; +using System.Reflection; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + +namespace Church.Net.DAL.EFCoreDBF +{ + public class CrudDALCBase1 : ICrudDAL where T : class, IEntity, new() + { + private readonly ChurchNetContext dbContext; + + public CrudDALCBase1(DatabaseOptions databaseOptions) + { + this.dbContext = databaseOptions.GetDbContext(); + InitKeyProperty(); + } + public IQueryable GetDbSet() + { + //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); + + return dbContext.Set().AsNoTracking(); + //return result; + } + + public virtual T First(Func filter = null) + { + return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault(); + } + + public virtual T GetById(string Id) + { + return this.GetQuery(new string[] { Id }).FirstOrDefault(); + } + + //public virtual T GetByRefndx(string refndx) + //{ + // return MapDBModelToEntity(GetFirstDBModelByRefndx(refndx, this.actionScreen)); + //} + + public virtual IEnumerable GetAll(Func filter = null) + { + //var dbObjs = GetDbSet().ToArray(); + + //IEnumerable list = GetDbSet().Where(filter ?? (s => true)).ToList(); + + return GetDbSet().AsNoTracking().Where(filter ?? (s => true)).ToList(); + } + + public virtual int Create(T entity) + { + this.CheckKeyIsEmpty(entity); + this.ConvertUTCTime(entity); + dbContext.Add(entity); + + return dbContext.SaveChanges(); + } + public virtual Task CreateAsync(T entity) + { + this.CheckKeyIsEmpty(entity); + this.ConvertUTCTime(entity); + dbContext.Add(entity); + + //CreateDone(entity, newDbObj); + return dbContext.SaveChangesAsync(); + } + + + public int CreateOrUpdate(T entity) + { + int result = 0; + this.ConvertUTCTime(entity); + if (CheckExist(entity)) + { + result = this.Update(entity); + } + else + { + result = this.Create(entity); + } + return result; + } + + public virtual int Update(T entity) + { + + //if (!this.CheckExist(entity)) + //{ + // throw new ArgumentNullException("the Id is not exist."); + //} + this.ConvertUTCTime(entity); + + dbContext.Update(entity); + + return dbContext.SaveChanges(); + + + } + public virtual void CreateDone(T entity) + { + + } + public virtual void UpdateDone(T entity) + { + + } + + public virtual int UpdateRange(IEnumerable entities) + { + dbContext.UpdateRange(entities); + + return dbContext.SaveChanges(); + } + + public virtual int Delete(T obj) + { + dbContext.Remove(obj); + return dbContext.SaveChanges(); + } + + public int Delete(Func filter) + { + var list = GetDbSet().Where(filter).ToList(); + foreach (var item in list) + { + dbContext.Remove(item); + } + return dbContext.SaveChanges(); + } + + public virtual bool CheckExist(T obj) + { + //var query = GetDbSet().AsQueryable(); + var query = GetAll(); + List props = new List(); + for (int i = 0; i < keyProps.Count; i++) + { + var prop = keyProps[i]; + props.Add(prop); + var value = prop.GetValue(obj)?.ToString(); + query = query.Where(e => prop.GetValue(e)?.ToString() == value).ToList(); + } + + return query.Any(); + } + + private void ConvertUTCTime(T entity) + { + + var props = typeof(T).GetProperties(); + foreach (var prop in props) + { + if (prop.PropertyType == typeof(DateTime)) + { + //do stuff like prop.SetValue(t, DateTime.Now, null); + DateTime utcTime = ((DateTime)prop.GetValue(entity)).ToUniversalTime(); + prop.SetValue(entity, utcTime, null); + + } + } + } + + private List keyProps; + + protected virtual void InitKeyProperty() + { + keyProps = typeof(T).GetProperties().Where( + prop => Attribute.IsDefined(prop, typeof(KeyAttribute))).OrderBy(prop => + prop.GetCustomAttribute().Order + ) + .ToList(); + + } + + protected IQueryable GetQuery(IEnumerable Ids) + { + var query = GetDbSet().AsQueryable(); + + for (int i = 0; i < keyProps.Count; i++) + { + query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i)); + } + return query; + } + protected virtual void CheckKeyIsEmpty(T entity) + { + + if (string.IsNullOrWhiteSpace(entity.Id) || entity.Id.Length <= 3) + { + entity.Id = StringHelper.Get33BaseGuid(); + } + } + + public void Dispose() + { + throw new NotImplementedException(); + } + } + + +} \ No newline at end of file diff --git a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs b/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs index a4a9835..798ea7b 100644 --- a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs +++ b/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs @@ -17,24 +17,34 @@ namespace Church.Net.DAL.EFCoreDBF { public class CombinedKeyCrudDALCBase : ICombinedKeyCrudDAL where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new() { - private readonly ChurchNetContext dbContext; + private readonly DatabaseOptions databaseOptions; - public CombinedKeyCrudDALCBase(ChurchNetContext dbContext) - { - this.dbContext = dbContext; + public CombinedKeyCrudDALCBase(DatabaseOptions databaseOptions) + { + this.databaseOptions = databaseOptions; InitKeyProperty(); } - public DbSet GetDbSet() + public IQueryable GetDbSet() { //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); - return (DbSet)dbContext.Set(); + return databaseOptions.GetDbContext().Set().AsNoTracking(); //return result; } + public ChurchNetContext GetDbContext() + { + //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); + + return databaseOptions.GetDbContext();//.Set().AsNoTracking(); + //return result; + } public virtual T First(Func filter = null) { - return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault(); + using (var dbContext = GetDbContext()) + { + return dbContext.Set().Where(filter ?? (s => true)).FirstOrDefault(); + } } public virtual T GetById(IEnumerable Ids) @@ -60,18 +70,25 @@ namespace Church.Net.DAL.EFCoreDBF { this.CheckCombinedKeyIsEmpty(entity); this.ConvertUTCTime(entity); - dbContext.Add(entity); - return dbContext.SaveChanges(); + using (var dbContext = GetDbContext()) + { + dbContext.Add(entity); + + return dbContext.SaveChanges(); + } } public virtual Task CreateAsync(T entity) { this.CheckCombinedKeyIsEmpty(entity); this.ConvertUTCTime(entity); - dbContext.Add(entity); + using (var dbContext = GetDbContext()) + { + dbContext.Add(entity); - //CreateDone(entity, newDbObj); - return dbContext.SaveChangesAsync(); + //CreateDone(entity, newDbObj); + return dbContext.SaveChangesAsync(); + } } @@ -99,9 +116,12 @@ namespace Church.Net.DAL.EFCoreDBF //} this.ConvertUTCTime(entity); - dbContext.Update(entity); + using (var dbContext = GetDbContext()) + { + dbContext.Update(entity); - return dbContext.SaveChanges(); + return dbContext.SaveChanges(); + } } @@ -116,15 +136,21 @@ namespace Church.Net.DAL.EFCoreDBF public virtual int UpdateRange(IEnumerable entities) { - dbContext.UpdateRange(entities); + using (var dbContext = GetDbContext()) + { + dbContext.UpdateRange(entities); - return dbContext.SaveChanges(); + return dbContext.SaveChanges(); + } } public virtual int Delete(T obj) { - dbContext.Remove(obj); - return dbContext.SaveChanges(); + using (var dbContext = GetDbContext()) + { + dbContext.Remove(obj); + return dbContext.SaveChanges(); + } } public virtual int Delete(IEnumerable combinedKeyIds) @@ -136,11 +162,14 @@ namespace Church.Net.DAL.EFCoreDBF public int Delete(Func filter) { var list = GetDbSet().Where(filter).ToList(); - foreach (var item in list) + using (var dbContext = GetDbContext()) { - dbContext.Remove(item); + foreach (var item in list) + { + dbContext.Remove(item); + } + return dbContext.SaveChanges(); } - return dbContext.SaveChanges(); } public virtual bool CheckExist(T obj) @@ -189,13 +218,16 @@ namespace Church.Net.DAL.EFCoreDBF private IQueryable GetQuery(IEnumerable Ids) { - var query = GetDbSet().AsQueryable(); - - for (int i = 0; i < keyProps.Count; i++) + using (var dbContext = GetDbContext()) { - query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i)); + var query = dbContext.Set().AsQueryable(); + + for (int i = 0; i < keyProps.Count; i++) + { + query = query.Where(e => keyProps[i].GetValue(e).ToString() == Ids.ElementAt(i)); + } + return query; } - return query; } private void CheckCombinedKeyIsEmpty(T entity) { diff --git a/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs b/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs index 3e6202c..11a279a 100644 --- a/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs +++ b/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs @@ -12,28 +12,37 @@ namespace Church.Net.DAL.EFCoreDBF { public class CrudDALCBase : ICrudDAL where T : class, Church.Net.Entity.Interface.IEntity, new() { - private readonly ChurchNetContext dbContext; + private readonly DatabaseOptions databaseOptions; - public CrudDALCBase(ChurchNetContext dbContext) + //private readonly ChurchNetContext dbContext; + + public CrudDALCBase(DatabaseOptions databaseOptions) { - this.dbContext = dbContext; + this.databaseOptions = databaseOptions; + //this.dbContext = databaseOptions.GetDbContext(); } - public DbSet GetDbSet() + public ChurchNetContext GetDbContext() { //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); - return (DbSet)dbContext.Set(); + return databaseOptions.GetDbContext();//.Set().AsNoTracking(); //return result; } public virtual T First(Func filter = null) { - return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault(); + using (var dbContext = GetDbContext()) + { + return dbContext.Set().Where(filter ?? (s => true)).FirstOrDefault(); + } } public virtual T GetById(string Id) { - return GetDbSet().FirstOrDefault(e => e.Id == Id); + using (var dbContext = GetDbContext()) + { + return dbContext.Set().FirstOrDefault(e => e.Id == Id); + } } //public virtual T GetByRefndx(string refndx) @@ -43,41 +52,56 @@ namespace Church.Net.DAL.EFCoreDBF public virtual IEnumerable GetAll(Func filter = null) { - //var dbObjs = GetDbSet().ToArray(); + using (var dbContext = GetDbContext()) + { + return dbContext.Set().Where(filter ?? (s => true)).ToList(); + } + //var dbObjs = GetDbContext().ToArray(); - //IEnumerable list = GetDbSet().Where(filter ?? (s => true)).ToList(); + //IEnumerable list = GetDbContext().Where(filter ?? (s => true)).ToList(); - return GetDbSet().Where(filter ?? (s => true)).ToList(); } public virtual IEnumerable GetAllById(IEnumerable Ids) { - var RowIds = Ids.Select(i => i.ToString()); + using (var dbContext = GetDbContext()) + { + var RowIds = Ids.Select(i => i.ToString()); - //return GetDbSet().Where(e => RowIds.Any(id => id == e.Id)); + //return GetDbContext().Where(e => RowIds.Any(id => id == e.Id)); - //var list = new List(); - var dbObjs = GetDbSet().Where(e => RowIds.Any(id => id == e.Id)).ToArray(); + //var list = new List(); + + return dbContext.Set().Where(e => RowIds.Any(id => id == e.Id)).ToArray(); + } + } + private bool needGenId(T entity) + { + + return string.IsNullOrWhiteSpace(entity.Id) || entity.Id.Length <= 3; - return dbObjs.ToList(); } public virtual int Create(T entity) { - if (string.IsNullOrEmpty(entity.Id)) + if (needGenId(entity)) { entity.Id = StringHelper.Get33BaseGuid(); } this.ConvertUTCTime(entity); - dbContext.Add(entity); - return dbContext.SaveChanges(); + using (var dbContext = GetDbContext()) + { + dbContext.Add(entity); + + return dbContext.SaveChanges(); + } } public virtual Task CreateAsync(T entity) { int result = 0; this.ConvertUTCTime(entity); - if (string.IsNullOrEmpty(entity.Id)) + if (needGenId(entity)) { entity.Id = StringHelper.Get33BaseGuid(); } @@ -88,10 +112,13 @@ namespace Church.Net.DAL.EFCoreDBF //newDbObj.RowId = entity.Id.ToString(); //result = Add(newDbObj) ? 1 : 0; } - dbContext.Add(entity); + using (var dbContext = GetDbContext()) + { + dbContext.Add(entity); - //CreateDone(entity, newDbObj); - return dbContext.SaveChangesAsync(); + //CreateDone(entity, newDbObj); + return dbContext.SaveChangesAsync(); + } } public virtual string CreateReturnId(T entity) { @@ -106,40 +133,45 @@ namespace Church.Net.DAL.EFCoreDBF }; } - public int CreateOrUpdate(T entity, out string id) + public int CreateOrUpdate(T entity) { - id = null; this.ConvertUTCTime(entity); - if (CheckExist(entity)) + + + using (var dbContext = GetDbContext()) { - dbContext.Update(entity); - } - else - { - if (string.IsNullOrEmpty(entity.Id)) + if (CheckExist(entity)) { - entity.Id = StringHelper.Get33BaseGuid(); + dbContext.Update(entity); } - id = entity.Id; - dbContext.Add(entity); + else + { + if (needGenId(entity)) + { + entity.Id = StringHelper.Get33BaseGuid(); + } + dbContext.Add(entity); + } + return dbContext.SaveChanges(); } - return dbContext.SaveChanges(); + } public virtual int Update(T entity) { - - var dbObj = GetDbSet().FirstOrDefault(e => e.Id == entity.Id); - if (dbObj == null) + using (var dbContext = GetDbContext()) { - throw new ArgumentNullException("the Id is not exist."); + //var dbObj = dbContext.Set().Any(e => e.Id == entity.Id); + if (!dbContext.Set().Any(e => e.Id == entity.Id)) + { + throw new ArgumentNullException("the Id is not exist."); + } + this.ConvertUTCTime(entity); + + dbContext.Update(entity); + + return dbContext.SaveChanges(); } - this.ConvertUTCTime(entity); - - dbContext.Update(dbObj); - - return dbContext.SaveChanges(); - } public virtual void CreateDone(T entity) @@ -157,31 +189,44 @@ namespace Church.Net.DAL.EFCoreDBF { this.ConvertUTCTime(entity); } - dbContext.UpdateRange(entities); + using (var dbContext = GetDbContext()) + { + dbContext.UpdateRange(entities); - return dbContext.SaveChanges(); + return dbContext.SaveChanges(); + } } public virtual int Delete(T obj) { - dbContext.Remove(GetDbSet().FirstOrDefault(e => e.Id == obj.Id.ToString())); - return dbContext.SaveChanges(); + using (var dbContext = GetDbContext()) + { + dbContext.Remove(dbContext.Set().FirstOrDefault(e => e.Id == obj.Id.ToString())); + return dbContext.SaveChanges(); + } } public int Delete(Func filter) { - var list = GetDbSet().Where(filter).ToList(); - if (list.Count > 0) + using (var dbContext = GetDbContext()) { - dbContext.RemoveRange(list); - return dbContext.SaveChanges(); + + var list = dbContext.Set().Where(filter).ToList(); + if (list.Count > 0) + { + dbContext.RemoveRange(list); + return dbContext.SaveChanges(); + } + return 0; } - return 0; } public virtual bool CheckExist(T obj) { - return GetDbSet().Any(e => e.Id == obj.Id); + using (var dbContext = GetDbContext()) + { + return dbContext.Set().Any(e => e.Id == obj.Id); + } } private void ConvertUTCTime(T entity) @@ -193,12 +238,41 @@ namespace Church.Net.DAL.EFCoreDBF if (prop.PropertyType == typeof(DateTime)) { //do stuff like prop.SetValue(t, DateTime.Now, null); - DateTime utcTime = ((DateTime)prop.GetValue(entity)).ToUniversalTime(); + DateTime localTime = ((DateTime)prop.GetValue(entity)); + if (localTime.Kind != DateTimeKind.Utc) + { + //localTime= DateTime.SpecifyKind(localTime, DateTimeKind.Local); + localTime = new DateTime(localTime.Year, localTime.Month, localTime.Day, + localTime.Hour, localTime.Minute, localTime.Second, localTime.Millisecond); + } + DateTime utcTime = localTime.ToUniversalTime(); prop.SetValue(entity, utcTime, null); } + else if (prop.PropertyType == typeof(DateTime?)) + { + DateTime? localTime = ((DateTime?)prop.GetValue(entity)); + if (localTime.HasValue) + { + if (localTime.Value.Kind != DateTimeKind.Utc) + { + //localTime = DateTime.SpecifyKind(localTime.Value, DateTimeKind.Local); + localTime = new DateTime(localTime.Value.Year, localTime.Value.Month, localTime.Value.Day, + localTime.Value.Hour, localTime.Value.Minute, localTime.Value.Second, + localTime.Value.Millisecond, DateTimeKind.Local); + } + + DateTime? utcTime = localTime.Value.ToUniversalTime(); + prop.SetValue(entity, utcTime, null); + } + } } } + + public IQueryable GetDbSet() + { + return databaseOptions.GetDbContext().Set().AsNoTracking(); + } } diff --git a/Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs b/Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs new file mode 100644 index 0000000..d52bc35 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs @@ -0,0 +1,16 @@ +using Church.Net.DAL.EF; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Church.Net.DAL.EFCoreDBF +{ + public class DatabaseOptions + { + public string ConnectionString { get; set; } + + public ChurchNetContext GetDbContext() => new ChurchNetContext(ConnectionString); + } +} diff --git a/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs b/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs index c95df21..3d46f94 100644 --- a/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs +++ b/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs @@ -9,19 +9,18 @@ using System.Threading.Tasks; namespace Church.Net.DAL.EFCoreDBF { - public interface ICrudDAL where T:class,IEntity + public interface ICrudDAL where T : class, IEntity { - DbSet GetDbSet(); + IQueryable GetDbSet(); T First(Func filter = null); T GetById(string Id); IEnumerable GetAll(Func filter = null); - IEnumerable GetAllById(IEnumerable Ids); + //IEnumerable GetAllById(IEnumerable Ids); int Create(T entity); Task CreateAsync(T entity); - string CreateReturnId(T entity); - int CreateOrUpdate(T entity, out string id); + int CreateOrUpdate(T entity); int Update(T entity); void CreateDone(T entity); void UpdateDone(T entity); @@ -35,9 +34,9 @@ namespace Church.Net.DAL.EFCoreDBF } - public interface ICombinedKeyCrudDAL where T : class, ICombinedKeyEntity + public interface ICombinedKeyCrudDAL where T : class { - DbSet GetDbSet(); + IQueryable GetDbSet(); T First(Func filter = null); T GetById(IEnumerable combinedKeyIds); diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.Designer.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.Designer.cs new file mode 100644 index 0000000..e78cb5d --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.Designer.cs @@ -0,0 +1,798 @@ +// +using System; +using Church.Net.DAL.EF; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + [DbContext(typeof(ChurchNetContext))] + [Migration("20220914151710_AddTaskToHappinessWeek")] + partial class AddTaskToHappinessWeek + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Church.Net.Entity.AddressInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Zip") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AddressInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplyItems"); + }); + + modelBuilder.Entity("Church.Net.Entity.Career", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Careers"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("CellGroupRoutineEvents"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("Id") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("JoinPotluck") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("PotluckItem") + .HasColumnType("text"); + + b.HasKey("EventId", "Id"); + + b.ToTable("CellGroupRoutineEventAttendees"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("MemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Prayer") + .HasColumnType("text"); + + b.HasKey("EventId", "MemberId"); + + b.ToTable("CellGroupRoutineEventPrayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("AvatarImage") + .HasColumnType("text"); + + b.Property("Baptized") + .HasColumnType("boolean"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("CareerId") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DateOfBaptized") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfWalkIn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Married") + .HasColumnType("boolean"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CareerId"); + + b.ToTable("FamilyMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("OAuthType") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("OAuthAccessToken") + .HasColumnType("text"); + + b.HasKey("FamilyMemberId", "OAuthType"); + + b.ToTable("FamilyMemberOAuths"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessBESTs"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BeginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HappinessGroups"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("SEQ") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessWeeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DetailMessage") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("StackTrace") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("TrackNo") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrackNo")); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LogInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("ReligionId") + .HasColumnType("integer"); + + b.Property("VisitingDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReligionId"); + + b.ToTable("NewVisitors"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CommunityAppId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Image1") + .HasColumnType("text"); + + b.Property("Image2") + .HasColumnType("text"); + + b.Property("Image3") + .HasColumnType("text"); + + b.Property("Image4") + .HasColumnType("text"); + + b.Property("Image5") + .HasColumnType("text"); + + b.Property("LeaderMemberId") + .HasColumnType("text"); + + b.Property("LogoImage") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ServiceAddressId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LeaderMemberId"); + + b.HasIndex("ServiceAddressId"); + + b.ToTable("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.Property("PastoralDomainCommunityAppId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("AutoReplyItemId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId"); + + b.HasIndex("AutoReplyItemId"); + + b.ToTable("PastoralDomainAutoReplys"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.Property("PastoralDomainId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainId", "FamilyMemberId"); + + b.HasIndex("FamilyMemberId"); + + b.ToTable("PastoralDomainMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Religion", b => + { + b.Property("ReligionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReligionId")); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("ReligionId"); + + b.ToTable("Religions"); + }); + + modelBuilder.Entity("Church.Net.Entity.Vocabulary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefinitionCh") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionEn") + .IsRequired() + .HasColumnType("text"); + + b.Property("FlashCardTimes") + .HasColumnType("integer"); + + b.Property("ImagesUrl") + .HasColumnType("text"); + + b.Property("InsertDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NounPlural") + .HasColumnType("text"); + + b.Property("PartOfSpeech") + .HasColumnType("integer"); + + b.Property("PracticeApply") + .HasColumnType("boolean"); + + b.Property("PracticeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PracticeMemorized") + .HasColumnType("boolean"); + + b.Property("PracticeReview") + .HasColumnType("boolean"); + + b.Property("PracticeSelect") + .HasColumnType("boolean"); + + b.Property("PracticeSentence") + .HasColumnType("text"); + + b.Property("PracticeStage") + .HasColumnType("integer"); + + b.Property("PracticeVisualize") + .HasColumnType("boolean"); + + b.Property("VerbParticiple") + .HasColumnType("text"); + + b.Property("VerbPast") + .HasColumnType("text"); + + b.Property("Word") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Vocabulary"); + }); + + modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer1Chs") + .HasColumnType("text"); + + b.Property("Answer1Cht") + .HasColumnType("text"); + + b.Property("Answer1En") + .HasColumnType("text"); + + b.Property("Answer2Chs") + .HasColumnType("text"); + + b.Property("Answer2Cht") + .HasColumnType("text"); + + b.Property("Answer2En") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("WhoIsSpy"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Attendees") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Prayers") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.HasOne("Church.Net.Entity.Career", "Career") + .WithMany() + .HasForeignKey("CareerId"); + + b.Navigation("Career"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", null) + .WithMany("OAuthInfos") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("BestList") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("Weeks") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.HasOne("Church.Net.Entity.Religion", "Religion") + .WithMany() + .HasForeignKey("ReligionId"); + + b.Navigation("Religion"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "Leader") + .WithMany() + .HasForeignKey("LeaderMemberId"); + + b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress") + .WithMany() + .HasForeignKey("ServiceAddressId"); + + b.Navigation("Leader"); + + b.Navigation("ServiceAddress"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("AutoReplyItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("PastoralDomainCommunityAppId") + .HasPrincipalKey("CommunityAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember") + .WithMany("PastoralDomains") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("Members") + .HasForeignKey("PastoralDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Navigation("AutoReplyItemRelations"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Navigation("Attendees"); + + b.Navigation("Prayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Navigation("OAuthInfos"); + + b.Navigation("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Navigation("BestList"); + + b.Navigation("Weeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Navigation("AutoReplyItemRelations"); + + b.Navigation("Members"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.cs new file mode 100644 index 0000000..8139cd2 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220914151710_AddTaskToHappinessWeek.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + public partial class AddTaskToHappinessWeek : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Comment", + table: "HappinessWeeks", + type: "text", + nullable: true); + + migrationBuilder.CreateTable( + name: "HappinessTask", + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + WeekId = table.Column(type: "text", nullable: true), + Type = table.Column(type: "integer", nullable: false), + Tasker = table.Column(type: "text", nullable: true), + Content = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_HappinessTask", x => x.Id); + table.ForeignKey( + name: "FK_HappinessTask_HappinessWeeks_WeekId", + column: x => x.WeekId, + principalTable: "HappinessWeeks", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_HappinessTask_WeekId", + table: "HappinessTask", + column: "WeekId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "HappinessTask"); + + migrationBuilder.DropColumn( + name: "Comment", + table: "HappinessWeeks"); + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.Designer.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.Designer.cs new file mode 100644 index 0000000..56906c3 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.Designer.cs @@ -0,0 +1,823 @@ +// +using System; +using Church.Net.DAL.EF; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + [DbContext(typeof(ChurchNetContext))] + [Migration("20220929210007_AddLienClient")] + partial class AddLienClient + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Church.Net.Entity.AddressInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Zip") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AddressInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplyItems"); + }); + + modelBuilder.Entity("Church.Net.Entity.Career", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Careers"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("CellGroupRoutineEvents"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("Id") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("JoinPotluck") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("PotluckItem") + .HasColumnType("text"); + + b.HasKey("EventId", "Id"); + + b.ToTable("CellGroupRoutineEventAttendees"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("MemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Prayer") + .HasColumnType("text"); + + b.HasKey("EventId", "MemberId"); + + b.ToTable("CellGroupRoutineEventPrayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("AvatarImage") + .HasColumnType("text"); + + b.Property("Baptized") + .HasColumnType("boolean"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("CareerId") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DateOfBaptized") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfWalkIn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Married") + .HasColumnType("boolean"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CareerId"); + + b.ToTable("FamilyMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("OAuthType") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("OAuthAccessToken") + .HasColumnType("text"); + + b.HasKey("FamilyMemberId", "OAuthType"); + + b.ToTable("FamilyMemberOAuths"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessBESTs"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BeginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("CommunityAppId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HappinessGroups"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("SEQ") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessWeeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DetailMessage") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("StackTrace") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("TrackNo") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrackNo")); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LogInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("IsGroup") + .HasColumnType("boolean"); + + b.Property("IsManager") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LineMessageClients"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("ReligionId") + .HasColumnType("integer"); + + b.Property("VisitingDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReligionId"); + + b.ToTable("NewVisitors"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CommunityAppId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Image1") + .HasColumnType("text"); + + b.Property("Image2") + .HasColumnType("text"); + + b.Property("Image3") + .HasColumnType("text"); + + b.Property("Image4") + .HasColumnType("text"); + + b.Property("Image5") + .HasColumnType("text"); + + b.Property("LeaderMemberId") + .HasColumnType("text"); + + b.Property("LogoImage") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ServiceAddressId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LeaderMemberId"); + + b.HasIndex("ServiceAddressId"); + + b.ToTable("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.Property("PastoralDomainCommunityAppId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("AutoReplyItemId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId"); + + b.HasIndex("AutoReplyItemId"); + + b.ToTable("PastoralDomainAutoReplys"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.Property("PastoralDomainId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainId", "FamilyMemberId"); + + b.HasIndex("FamilyMemberId"); + + b.ToTable("PastoralDomainMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Religion", b => + { + b.Property("ReligionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReligionId")); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("ReligionId"); + + b.ToTable("Religions"); + }); + + modelBuilder.Entity("Church.Net.Entity.Vocabulary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefinitionCh") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionEn") + .IsRequired() + .HasColumnType("text"); + + b.Property("FlashCardTimes") + .HasColumnType("integer"); + + b.Property("ImagesUrl") + .HasColumnType("text"); + + b.Property("InsertDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NounPlural") + .HasColumnType("text"); + + b.Property("PartOfSpeech") + .HasColumnType("integer"); + + b.Property("PracticeApply") + .HasColumnType("boolean"); + + b.Property("PracticeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PracticeMemorized") + .HasColumnType("boolean"); + + b.Property("PracticeReview") + .HasColumnType("boolean"); + + b.Property("PracticeSelect") + .HasColumnType("boolean"); + + b.Property("PracticeSentence") + .HasColumnType("text"); + + b.Property("PracticeStage") + .HasColumnType("integer"); + + b.Property("PracticeVisualize") + .HasColumnType("boolean"); + + b.Property("VerbParticiple") + .HasColumnType("text"); + + b.Property("VerbPast") + .HasColumnType("text"); + + b.Property("Word") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Vocabulary"); + }); + + modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer1Chs") + .HasColumnType("text"); + + b.Property("Answer1Cht") + .HasColumnType("text"); + + b.Property("Answer1En") + .HasColumnType("text"); + + b.Property("Answer2Chs") + .HasColumnType("text"); + + b.Property("Answer2Cht") + .HasColumnType("text"); + + b.Property("Answer2En") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("WhoIsSpy"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Attendees") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Prayers") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.HasOne("Church.Net.Entity.Career", "Career") + .WithMany() + .HasForeignKey("CareerId"); + + b.Navigation("Career"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", null) + .WithMany("OAuthInfos") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("BestList") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("Weeks") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.HasOne("Church.Net.Entity.Religion", "Religion") + .WithMany() + .HasForeignKey("ReligionId"); + + b.Navigation("Religion"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "Leader") + .WithMany() + .HasForeignKey("LeaderMemberId"); + + b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress") + .WithMany() + .HasForeignKey("ServiceAddressId"); + + b.Navigation("Leader"); + + b.Navigation("ServiceAddress"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("AutoReplyItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("PastoralDomainCommunityAppId") + .HasPrincipalKey("CommunityAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember") + .WithMany("PastoralDomains") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("Members") + .HasForeignKey("PastoralDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Navigation("AutoReplyItemRelations"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Navigation("Attendees"); + + b.Navigation("Prayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Navigation("OAuthInfos"); + + b.Navigation("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Navigation("BestList"); + + b.Navigation("Weeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Navigation("AutoReplyItemRelations"); + + b.Navigation("Members"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.cs new file mode 100644 index 0000000..c63289d --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220929210007_AddLienClient.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + public partial class AddLienClient : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CommunityAppId", + table: "HappinessGroups", + type: "text", + nullable: true); + + migrationBuilder.CreateTable( + name: "LineMessageClients", + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + ClientId = table.Column(type: "text", nullable: true), + IsGroup = table.Column(type: "boolean", nullable: false), + IsManager = table.Column(type: "boolean", nullable: false), + Name = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_LineMessageClients", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LineMessageClients"); + + migrationBuilder.DropColumn( + name: "CommunityAppId", + table: "HappinessGroups"); + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.Designer.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.Designer.cs new file mode 100644 index 0000000..5248581 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.Designer.cs @@ -0,0 +1,845 @@ +// +using System; +using Church.Net.DAL.EF; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + [DbContext(typeof(ChurchNetContext))] + [Migration("20220930060508_LineMessageAccount")] + partial class LineMessageAccount + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Church.Net.Entity.AddressInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Zip") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AddressInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplyItems"); + }); + + modelBuilder.Entity("Church.Net.Entity.Career", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Careers"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("CellGroupRoutineEvents"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("Id") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("JoinPotluck") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("PotluckItem") + .HasColumnType("text"); + + b.HasKey("EventId", "Id"); + + b.ToTable("CellGroupRoutineEventAttendees"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("MemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Prayer") + .HasColumnType("text"); + + b.HasKey("EventId", "MemberId"); + + b.ToTable("CellGroupRoutineEventPrayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("AvatarImage") + .HasColumnType("text"); + + b.Property("Baptized") + .HasColumnType("boolean"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("CareerId") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DateOfBaptized") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfWalkIn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Married") + .HasColumnType("boolean"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CareerId"); + + b.ToTable("FamilyMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("OAuthType") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("OAuthAccessToken") + .HasColumnType("text"); + + b.HasKey("FamilyMemberId", "OAuthType"); + + b.ToTable("FamilyMemberOAuths"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessBESTs"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BeginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("CommunityAppId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HappinessGroups"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("SEQ") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessWeeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ChatToken") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Seq") + .HasColumnType("integer"); + + b.Property("TotalUsage") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LineMessagingAccounts"); + }); + + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DetailMessage") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("StackTrace") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("TrackNo") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrackNo")); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LogInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("IsGroup") + .HasColumnType("boolean"); + + b.Property("IsManager") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LineMessageClients"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("ReligionId") + .HasColumnType("integer"); + + b.Property("VisitingDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReligionId"); + + b.ToTable("NewVisitors"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("CommunityAppId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Image1") + .HasColumnType("text"); + + b.Property("Image2") + .HasColumnType("text"); + + b.Property("Image3") + .HasColumnType("text"); + + b.Property("Image4") + .HasColumnType("text"); + + b.Property("Image5") + .HasColumnType("text"); + + b.Property("LeaderMemberId") + .HasColumnType("text"); + + b.Property("LogoImage") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ServiceAddressId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LeaderMemberId"); + + b.HasIndex("ServiceAddressId"); + + b.ToTable("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.Property("PastoralDomainCommunityAppId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("AutoReplyItemId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId"); + + b.HasIndex("AutoReplyItemId"); + + b.ToTable("PastoralDomainAutoReplys"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.Property("PastoralDomainId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainId", "FamilyMemberId"); + + b.HasIndex("FamilyMemberId"); + + b.ToTable("PastoralDomainMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Religion", b => + { + b.Property("ReligionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReligionId")); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("ReligionId"); + + b.ToTable("Religions"); + }); + + modelBuilder.Entity("Church.Net.Entity.Vocabulary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefinitionCh") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionEn") + .IsRequired() + .HasColumnType("text"); + + b.Property("FlashCardTimes") + .HasColumnType("integer"); + + b.Property("ImagesUrl") + .HasColumnType("text"); + + b.Property("InsertDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NounPlural") + .HasColumnType("text"); + + b.Property("PartOfSpeech") + .HasColumnType("integer"); + + b.Property("PracticeApply") + .HasColumnType("boolean"); + + b.Property("PracticeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PracticeMemorized") + .HasColumnType("boolean"); + + b.Property("PracticeReview") + .HasColumnType("boolean"); + + b.Property("PracticeSelect") + .HasColumnType("boolean"); + + b.Property("PracticeSentence") + .HasColumnType("text"); + + b.Property("PracticeStage") + .HasColumnType("integer"); + + b.Property("PracticeVisualize") + .HasColumnType("boolean"); + + b.Property("VerbParticiple") + .HasColumnType("text"); + + b.Property("VerbPast") + .HasColumnType("text"); + + b.Property("Word") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Vocabulary"); + }); + + modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer1Chs") + .HasColumnType("text"); + + b.Property("Answer1Cht") + .HasColumnType("text"); + + b.Property("Answer1En") + .HasColumnType("text"); + + b.Property("Answer2Chs") + .HasColumnType("text"); + + b.Property("Answer2Cht") + .HasColumnType("text"); + + b.Property("Answer2En") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("WhoIsSpy"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Attendees") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Prayers") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.HasOne("Church.Net.Entity.Career", "Career") + .WithMany() + .HasForeignKey("CareerId"); + + b.Navigation("Career"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", null) + .WithMany("OAuthInfos") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("BestList") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") + .WithMany("Weeks") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.HasOne("Church.Net.Entity.Religion", "Religion") + .WithMany() + .HasForeignKey("ReligionId"); + + b.Navigation("Religion"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "Leader") + .WithMany() + .HasForeignKey("LeaderMemberId"); + + b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress") + .WithMany() + .HasForeignKey("ServiceAddressId"); + + b.Navigation("Leader"); + + b.Navigation("ServiceAddress"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("AutoReplyItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("PastoralDomainCommunityAppId") + .HasPrincipalKey("CommunityAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember") + .WithMany("PastoralDomains") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("Members") + .HasForeignKey("PastoralDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Navigation("AutoReplyItemRelations"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Navigation("Attendees"); + + b.Navigation("Prayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Navigation("OAuthInfos"); + + b.Navigation("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b => + { + b.Navigation("BestList"); + + b.Navigation("Weeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Navigation("AutoReplyItemRelations"); + + b.Navigation("Members"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.cs new file mode 100644 index 0000000..cab82ff --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20220930060508_LineMessageAccount.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + public partial class LineMessageAccount : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "LineMessagingAccounts", + columns: table => new + { + Id = table.Column(type: "text", nullable: false), + Name = table.Column(type: "text", nullable: true), + ChatToken = table.Column(type: "text", nullable: true), + TotalUsage = table.Column(type: "integer", nullable: false), + Seq = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LineMessagingAccounts", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LineMessagingAccounts"); + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs b/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs index 13a78ec..8f34d1a 100644 --- a/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs +++ b/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs @@ -262,6 +262,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.Property("CityAndZipCode") .HasColumnType("text"); + b.Property("CommunityAppId") + .HasColumnType("text"); + b.Property("InvitationText") .HasColumnType("text"); @@ -273,6 +276,30 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.ToTable("HappinessGroups"); }); + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => { b.Property("Id") @@ -284,6 +311,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.Property("CityAndZipCode") .HasColumnType("text"); + b.Property("Comment") + .HasColumnType("text"); + b.Property("Date") .HasColumnType("timestamp with time zone"); @@ -303,6 +333,28 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.ToTable("HappinessWeeks"); }); + modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ChatToken") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Seq") + .HasColumnType("integer"); + + b.Property("TotalUsage") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LineMessagingAccounts"); + }); + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => { b.Property("Id") @@ -343,6 +395,28 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.ToTable("LogInfos"); }); + modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("IsGroup") + .HasColumnType("boolean"); + + b.Property("IsManager") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LineMessageClients"); + }); + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => { b.Property("Id") @@ -645,6 +719,15 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.Navigation("HappinessGroup"); }); + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => { b.HasOne("Church.Net.Entity.HappinessGroup", "HappinessGroup") @@ -743,6 +826,11 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.Navigation("Weeks"); }); + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Tasks"); + }); + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => { b.Navigation("AutoReplyItemRelations"); diff --git a/Church.Net.Entity2/CellGroupRoutineEvent.cs b/Church.Net.Entity2/CellGroupRoutineEvent.cs index 83cd171..cc70dca 100644 --- a/Church.Net.Entity2/CellGroupRoutineEvent.cs +++ b/Church.Net.Entity2/CellGroupRoutineEvent.cs @@ -19,6 +19,11 @@ namespace Church.Net.Entity public string Address { get; set; } public virtual ICollection Attendees { get; set; } public virtual ICollection Prayers { get; set; } + + + [ForeignKey("CellGroupInfo")] + public string PastoralDomainId { get; set; } + public PastoralDomain CellGroupInfo { get; set; } } public class CellGroupRoutineEventAttendee : ICombinedKeyEntity { diff --git a/Church.Net.Entity2/HappinessGroup.cs b/Church.Net.Entity2/HappinessGroup.cs index 9625fab..35c73e7 100644 --- a/Church.Net.Entity2/HappinessGroup.cs +++ b/Church.Net.Entity2/HappinessGroup.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Church.Net.Entity { - public class HappinessGroup : IEntity + public class HappinessGroup : IEntity, IMessengerClient { [Required, Key] public string Id { get; set; } @@ -25,5 +25,11 @@ namespace Church.Net.Entity public virtual ICollection BestList { get; set; } public virtual ICollection Weeks { get; set; } + public string CommunityAppId { get; set; } + + [ForeignKey("LineMessagingAccount")] + public string LineAccountId { get; set; } + public virtual LineMessagingAccount LineMessagingAccount { get; set; } + } } diff --git a/Church.Net.Entity2/HappinessWeek.cs b/Church.Net.Entity2/HappinessWeek.cs index 4527397..fcb73f7 100644 --- a/Church.Net.Entity2/HappinessWeek.cs +++ b/Church.Net.Entity2/HappinessWeek.cs @@ -25,5 +25,28 @@ namespace Church.Net.Entity public int SEQ { get; set; } [NotMapped] public bool UpdateRestWeekDate { get; set; } + public virtual ICollection Tasks { get; set; } + public string Comment { get; set; } + } + + public enum HappinessTaskType + { + IceBreak, + Worship, + Testimony, + Message, + Gift, + Dessert + } + public class HappinessTask : IEntity + { + [ForeignKey("HappinessWeek")] + public string WeekId { get; set; } + public HappinessWeek HappinessWeek { get; set; } + [Required, Key] + public string Id { get; set; } + public HappinessTaskType Type { get; set; } + public string Tasker { get; set; } + public string Content { get; set; } } } diff --git a/Church.Net.Entity2/Interface/IMessenger.cs b/Church.Net.Entity2/Interface/IMessenger.cs new file mode 100644 index 0000000..0e7fad3 --- /dev/null +++ b/Church.Net.Entity2/Interface/IMessenger.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Church.Net.Entity.Interface +{ + public enum MessengerType + { + Email, + Line, + Wechat, + SMS + } + public interface IMessenger + { + MessengerType Type { get; } + Task SendMessage(IMessengerClient target, string message); + Task SendMessage(IMessengerClient target, object message); + } + + public interface IMessengerClient + { + string Id { get; } + + string LineAccountId { get; set; } + + LineMessagingAccount LineMessagingAccount { get; set; } + } + + + public interface IMessageClient: IEntity + { + MessengerType Type { get; } + string ClientId { get; set; } + + } + +} diff --git a/Church.Net.Entity2/LineBotInfo.cs b/Church.Net.Entity2/LineBotInfo.cs new file mode 100644 index 0000000..5c5ebcf --- /dev/null +++ b/Church.Net.Entity2/LineBotInfo.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace Church.Net.Entity +{ + public class LineBotInfo + { + + public string Id { get; set; } + public string GroupId { get; set; } + } + + public class LineClient + { + [Required, Key] + public string Id { get; set; } + public string LineId { get; set; } + public bool IsGroup { get; set; } + public bool IsManager { get; set; } + public string Name { get; set; } + } +} diff --git a/Church.Net.Entity2/LineMessagingAccount.cs b/Church.Net.Entity2/LineMessagingAccount.cs new file mode 100644 index 0000000..c4201b8 --- /dev/null +++ b/Church.Net.Entity2/LineMessagingAccount.cs @@ -0,0 +1,16 @@ +using Church.Net.Entity.Interface; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Church.Net.Entity +{ + public class LineMessagingAccount : IEntity + { + [Required, Key] + public string Id { get; set; } + public string Name { get; set; } + public string ChatToken { get; set; } + public int TotalUsage { get; set; } + public int Seq { get; set; } + } +} diff --git a/Church.Net.Entity2/Messenger/LineMessageInfo.cs b/Church.Net.Entity2/Messenger/LineMessageInfo.cs new file mode 100644 index 0000000..94b3eda --- /dev/null +++ b/Church.Net.Entity2/Messenger/LineMessageInfo.cs @@ -0,0 +1,20 @@ +using Church.Net.Entity.Interface; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace Church.Net.Entity.Messenger +{ + public class LineMessageClient : IMessageClient + { + public MessengerType Type => MessengerType.Line; + [Required, Key] + public string Id { get; set; } + public string ClientId { get; set; } + public bool IsGroup { get; set; } + public bool IsManager { get; set; } + public string Name { get; set; } + + } +} diff --git a/Church.Net.Entity2/PastoralDomain.cs b/Church.Net.Entity2/PastoralDomain.cs index 5dd0158..c3fea77 100644 --- a/Church.Net.Entity2/PastoralDomain.cs +++ b/Church.Net.Entity2/PastoralDomain.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; namespace Church.Net.Entity { - public class PastoralDomain : IEntity + public class PastoralDomain : IEntity, IMessengerClient { public PastoralDomain() { @@ -31,8 +31,12 @@ namespace Church.Net.Entity public string Image4 { get; set; } public string Image5 { get; set; } - public string CommunityAppId { get; set; } + + [ForeignKey("LineMessagingAccount")] + public string LineAccountId { get; set; } + public virtual LineMessagingAccount LineMessagingAccount { get; set; } + [ForeignKey("Leader")] public string LeaderMemberId { get; set; } diff --git a/Church.Net.Utility/Church.Net.Utility.csproj b/Church.Net.Utility/Church.Net.Utility.csproj index 89b6631..b46ad12 100644 --- a/Church.Net.Utility/Church.Net.Utility.csproj +++ b/Church.Net.Utility/Church.Net.Utility.csproj @@ -5,6 +5,7 @@ + diff --git a/Church.Net.Utility/DateTimeHelper.cs b/Church.Net.Utility/DateTimeHelper.cs index 7c67665..0199656 100644 --- a/Church.Net.Utility/DateTimeHelper.cs +++ b/Church.Net.Utility/DateTimeHelper.cs @@ -9,7 +9,7 @@ namespace Church.Net.Utility public static class DateTimeHelper { - private static TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time"); + private static TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); public static DateTime GetNextWeekday(DateTime start, DayOfWeek day) { // The (... + 7) % 7 ensures we end up with a value in the range [0, 6] @@ -18,11 +18,11 @@ namespace Church.Net.Utility } public static DateTime Now() { - return DateTime.SpecifyKind(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone),DateTimeKind.Local); + return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, pacificZone); } public static DateTime Today() { - return TimeZoneInfo.ConvertTimeFromUtc(DateTime.Today, pacificZone); + return Now().Date; } } } diff --git a/Church.Net.Utility/Format.cs b/Church.Net.Utility/Format.cs index ff47086..955da27 100644 --- a/Church.Net.Utility/Format.cs +++ b/Church.Net.Utility/Format.cs @@ -1,4 +1,5 @@ -using System; +using SixLabors.ImageSharp.Processing; +using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; @@ -248,7 +249,7 @@ namespace Church.Net.Utility } - public static class Image + public static class ImageHelper { public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight) { @@ -369,6 +370,14 @@ namespace Church.Net.Utility return bmp.Resize(bmp.Width * percentage / 100, bmp.Height * percentage / 100); } + public static void Scalling(this SixLabors.ImageSharp.Image image, int percentage) + { + + var scale = (double)percentage/100; + var scaleWidth = (int)(image.Width * scale); + var scaleHeight = (int)(image.Height * scale); + image.Mutate(o => o.Resize(new SixLabors.ImageSharp.Size(scaleWidth, scaleHeight))); + } public static Bitmap Superimpose(Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null) diff --git a/LineMessaging/Apis/LineMessageUtils.cs b/LineMessaging/Apis/LineMessageUtils.cs new file mode 100644 index 0000000..f24edc4 --- /dev/null +++ b/LineMessaging/Apis/LineMessageUtils.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; + +namespace LineMessaging +{ + public partial class LineMessagingClient + { + private const string GroupProfileApiPath = "v2/bot/group/{0}/summary"; + private const string QuotaApiPath = "/v2/bot/message/quota/consumption"; + + public async Task GetTotalUsage() + { + return Get(QuotaApiPath).Result.TotalUsage; + } + + + + public async Task GetGroupProfile(string groupId) + { + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException($"{nameof(groupId)} is null or empty."); + } + return await Get(string.Format(GroupProfileApiPath, groupId)); + } + } +} diff --git a/LineMessaging/CommonData/LineUsage.cs b/LineMessaging/CommonData/LineUsage.cs new file mode 100644 index 0000000..1bab4ce --- /dev/null +++ b/LineMessaging/CommonData/LineUsage.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace LineMessaging +{ + public class LineUsage + { + [JsonProperty("totalUsage")] + public int TotalUsage { get; set; } + } + public class LineGroupProfile + { + [JsonProperty("groupName")] + public string GroupName { get; set; } + } + +} diff --git a/LineMessaging/LineMessagingClient.cs b/LineMessaging/LineMessagingClient.cs index f76b605..8d68f0c 100644 --- a/LineMessaging/LineMessagingClient.cs +++ b/LineMessaging/LineMessagingClient.cs @@ -11,6 +11,7 @@ namespace LineMessaging public partial class LineMessagingClient { private const string ACCESS_TOKEN = "WFAyMvMEZ86cfMJIAzE+yklUZGpeS/jFYTeL9a9O35QR83oNMmwaUJfyEe48Kegadz0BArDdBoySxs479U1pwTHtlyH+Sm4jqlz8BwukX/Hsa4D1fX03Qn4zFu7TwPFKWFXnZbWq89Yg0iNzjpfTNwdB04t89/1O/w1cDnyilFU="; + private const string ACCESS_TOKEN_SEC = "UTRu3QsV9BjVmusqgWa30j/Vs7JJb59NvIWprv9Yb4ORUOTIIco66groSy7n8TlQbxn/OsA6FsFSQZDwaRPPlyfBYoW+lvv8g7IZhA8otuK57f+ojZbLO0RvkyEyQoy09Kmd7dnr78kHlDOcBq5ATgdB04t89/1O/w1cDnyilFU="; private static readonly MediaTypeHeaderValue MediaTypeJson = MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); private static readonly MediaTypeHeaderValue MediaTypeJpeg = MediaTypeHeaderValue.Parse("image/jpeg"); private static readonly MediaTypeHeaderValue MediaTypePng = MediaTypeHeaderValue.Parse("image/png"); @@ -25,11 +26,21 @@ namespace LineMessaging Timeout = TimeSpan.FromSeconds(10) }; - private readonly AuthenticationHeaderValue accessTokenHeaderValue; + private AuthenticationHeaderValue accessTokenHeaderValue; private JsonSerializerSettings serializerSettings; public LineMessagingClient() { - string accessToken = ACCESS_TOKEN; + string accessToken = ACCESS_TOKEN_SEC;//ACCESS_TOKEN; + Initialize(accessToken); + } + public LineMessagingClient(string accessToken) + { + Initialize(accessToken); + } + + private void Initialize(string accessToken) + { + if (string.IsNullOrEmpty(accessToken)) { throw new ArgumentException($"{nameof(accessToken)} is null or empty."); @@ -38,7 +49,7 @@ namespace LineMessaging { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore, - Formatting=Formatting.Indented + Formatting = Formatting.Indented }; accessTokenHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken); } diff --git a/WebAPI/App_Data/arial.ttf b/WebAPI/App_Data/arial.ttf new file mode 100644 index 0000000..ff0815c Binary files /dev/null and b/WebAPI/App_Data/arial.ttf differ diff --git a/WebAPI/Controllers/ApiControllerBase.cs b/WebAPI/Controllers/ApiControllerBase.cs index f05b0ef..24495e0 100644 --- a/WebAPI/Controllers/ApiControllerBase.cs +++ b/WebAPI/Controllers/ApiControllerBase.cs @@ -1,5 +1,6 @@ using Church.Net.Entity; using Church.Net.Entity.Interface; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; @@ -7,6 +8,7 @@ using WebAPI.Logics.Interface; namespace WebAPI.Controllers { + [Authorize] public class ApiControllerBase : ControllerBase where T : IEntity { protected readonly ICrudLogic logic; @@ -74,6 +76,7 @@ namespace WebAPI.Controllers } } + [Authorize] public class CombinedKeyApiControllerBase : ControllerBase where T : ICombinedKeyEntity { protected readonly ICombinedKeyCrudLogic logic; diff --git a/WebAPI/Controllers/BestController.cs b/WebAPI/Controllers/BestController.cs index 3a4f215..49443d1 100644 --- a/WebAPI/Controllers/BestController.cs +++ b/WebAPI/Controllers/BestController.cs @@ -1,20 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; +using System.Collections.Generic; using System.Drawing.Imaging; using System.IO; using System.Linq; -using System.Net; -using System.Net.Http; +using System.Runtime.InteropServices; using System.Threading.Tasks; -using Church.Net.DAL.EF; using Church.Net.Entity; using Church.Net.Utility; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Primitives; using QRCoder; +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Processing; using WebAPI.Logics.Interface; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 @@ -61,13 +59,15 @@ namespace WebAPI.Controllers public async Task GetInvitationQRcode(string id) { + QRCodeGenerator gen = new QRCodeGenerator(); QRCodeGenerator qrGenerator = new QRCodeGenerator(); - QRCodeData qrCodeData = qrGenerator.CreateQrCode($"http://happiness.tours/invitation/{id}", QRCodeGenerator.ECCLevel.Q); - + QRCodeData qrCodeData = qrGenerator.CreateQrCode($"https://happiness.tours/invitation/{id}", QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); - Bitmap qrCodeImage = qrCode.GetGraphic(3); - string qrCodeImagePath = ServerUtils.MapPath("App_Data/ScaneMeQrCode.png"); - var backgroundBitmap = (Bitmap)Bitmap.FromFile(qrCodeImagePath); + var qrCodeImage = qrCode.GetGraphic(3); + string qrCodeImagePath = "/App_Data/ScaneMeQrCode.png"; + + + var backgroundBitmap = SixLabors.ImageSharp.Image.Load(qrCodeImagePath); //string qrCodeImagePath = Environment.GetEnvironmentVariable("AppData"); //HttpContext.Current.Server.MapPath("~/App_Data/"); //var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/ScaneMeQrCode.png"); @@ -81,9 +81,9 @@ namespace WebAPI.Controllers using (var memoryStream = new MemoryStream()) { //fileStream.CopyTo(memoryStream); - Bitmap image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32); - image.Scalling(75).Save(memoryStream, ImageFormat.Png); - + var image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32); + image.Scalling(75); + image.SaveAsPng(memoryStream); byte[] byteImage = memoryStream.ToArray(); return File(byteImage, "image/png"); } @@ -91,12 +91,16 @@ namespace WebAPI.Controllers return this.NotFound(); } + private Font arialFont; [NonAction] - public Bitmap Superimpose(string bestName, Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null) + public Image Superimpose(string bestName, Image largeBmp, Image smallBmp, int? x = null, int? y = null) { - Graphics g = Graphics.FromImage(largeBmp); - g.CompositingMode = CompositingMode.SourceOver; - smallBmp.MakeTransparent(); + FontCollection collection = new(); + FontFamily family = collection.Add("/App_Data/arial.ttf"); + arialFont = family.CreateFont(12, FontStyle.Italic); + //Graphics g = Graphics.FromImage(largeBmp); + //g.CompositingMode = CompositingMode.SourceOver; + //smallBmp.MakeTransparent(); int margin = 5; if (!x.HasValue) { @@ -109,9 +113,13 @@ namespace WebAPI.Controllers var scale = 0.8; var scaleWidth = (int)(smallBmp.Width * scale); var scaleHeight = (int)(smallBmp.Height * scale); - g.DrawImage(smallBmp, new Rectangle(x.Value, y.Value, scaleWidth, scaleHeight)); - g.DrawString(bestName, new Font(new FontFamily("Arial"), 12), new SolidBrush(System.Drawing.Color.Black), 10, 0); + + largeBmp.Mutate(x => x.DrawText(bestName, arialFont, Color.Black, new PointF(10, 10))); + + smallBmp.Scalling(80); + + largeBmp.Mutate(ctx => ctx.DrawImage(smallBmp, new Point(x.Value, y.Value),1f)); return largeBmp; } diff --git a/WebAPI/Controllers/LineMessageController.cs b/WebAPI/Controllers/LineMessageController.cs index dc0bad5..eb7f014 100644 --- a/WebAPI/Controllers/LineMessageController.cs +++ b/WebAPI/Controllers/LineMessageController.cs @@ -31,17 +31,15 @@ namespace WebAPI.Controllers [Route("[controller]/[action]")] public class LineMessageController : ControllerBase { - private readonly ChurchNetContext dbContext; private readonly LineAutoBotService lineAutoBotService; private readonly ILoggingService loggingService; - public LineMessageController(ChurchNetContext dbContext, + public LineMessageController( LineAutoBotService lineAutoBotService, ILoggingService loggingService ) { - this.dbContext = dbContext; this.lineAutoBotService = lineAutoBotService; this.loggingService = loggingService; } @@ -67,7 +65,9 @@ namespace WebAPI.Controllers // POST api/ [HttpPost] - public async Task PostFromLine([FromBody] object jsonData) + //[Route("[controller]/[action]")] + //[Route("[controller]/[action]/{id?}")] + public async Task PostFromLine(string id, [FromBody] object jsonData) { //string txtPath = ServerUtils.MapPath("App_Data/LinePostRawLog.txt"); @@ -76,7 +76,9 @@ namespace WebAPI.Controllers { LineWebhookContent content = JsonConvert.DeserializeObject(jsonData.ToString()); - await lineAutoBotService.AutoReply(content); + + //this.loggingService.Log("PostFromLine"); + await lineAutoBotService.AutoReply(content); } catch (Exception ex) { @@ -103,14 +105,15 @@ namespace WebAPI.Controllers } [HttpGet] - public Task PushCommandMessage(string groupToken,string command) + public Task PushCommandMessage(string groupToken, string command) { - return lineAutoBotService.PushCommandMessage(EnumHelper.GetEnumValueFromDescription(groupToken), "#"+ command); + return lineAutoBotService.PushCommandMessage(EnumHelper.GetEnumValueFromDescription(groupToken), "#" + command); } - + } - public class LineMessage{ + public class LineMessage + { public string To { get; set; } public string Message { get; set; } } diff --git a/WebAPI/Controllers/LineMessagingAccountController.cs b/WebAPI/Controllers/LineMessagingAccountController.cs new file mode 100644 index 0000000..7a8764a --- /dev/null +++ b/WebAPI/Controllers/LineMessagingAccountController.cs @@ -0,0 +1,35 @@ +using Church.Net.Entity; +using LineMessaging; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Threading.Tasks; +using WebAPI.Logics; +using WebAPI.Logics.Interface; + +namespace WebAPI.Controllers +{ + [Route("[controller]/[action]")] + [ApiController] + public class LineMessagingAccountController : ApiControllerBase + { + public LineMessagingAccountController(LineMessagingAccountLogic logic) : base(logic) + { + } + + [HttpGet] + public void RefreshAllQuota() + { + + foreach (var item in logic.GetAll()) + { + if (!string.IsNullOrWhiteSpace(item.ChatToken)) + { + var lineMessegeClient = new LineMessagingClient(item.ChatToken); + item.TotalUsage = lineMessegeClient.GetTotalUsage().Result; + logic.Update(item); + } + } + } + } +} diff --git a/WebAPI/Controllers/LogController.cs b/WebAPI/Controllers/LogController.cs index 4df82b3..6570d52 100644 --- a/WebAPI/Controllers/LogController.cs +++ b/WebAPI/Controllers/LogController.cs @@ -1,10 +1,13 @@ using Church.Net.Entity; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; using System.Threading.Tasks; using WebAPI.Logics.Interface; +using WebAPI.Services.Interfaces; namespace WebAPI.Controllers { @@ -12,13 +15,46 @@ namespace WebAPI.Controllers [ApiController] public class LogController : ApiControllerBase { - public LogController(ICrudLogic logic) : base(logic) + private readonly ILoggingService loggingService; + + public LogController( + ICrudLogic logic, + ILoggingService loggingService + ) : base(logic) { + this.loggingService = loggingService; } [HttpPost] public void PurgeBefore([FromBody] DateTime date) { logic.Delete(l => l.Time <= date.ToUniversalTime()); } + + [Route("/error-development")] + public IActionResult HandleErrorDevelopment( + [FromServices] IHostEnvironment hostEnvironment) + { + if (!hostEnvironment.IsDevelopment()) + { + return NotFound(); + } + + var exceptionHandlerFeature = + HttpContext.Features.Get()!; + this.loggingService.Error(exceptionHandlerFeature.Error, exceptionHandlerFeature.Path); + return Problem( + detail: exceptionHandlerFeature.Error.StackTrace, + title: exceptionHandlerFeature.Error.Message); + } + + [Route("/error")] + public IActionResult HandleError() + { + + var exceptionHandlerFeature = + HttpContext.Features.Get()!; + this.loggingService.Error(exceptionHandlerFeature.Error, exceptionHandlerFeature.Path); + return Problem(); + } } } diff --git a/WebAPI/Controllers/PasswordLoginController.cs b/WebAPI/Controllers/PasswordLoginController.cs index 70424f6..d949707 100644 --- a/WebAPI/Controllers/PasswordLoginController.cs +++ b/WebAPI/Controllers/PasswordLoginController.cs @@ -1,4 +1,5 @@ using Church.Net.DAL.EF; +using Church.Net.DAL.EFCoreDBF; using Church.Net.Entity; using Church.Net.Utility; using Microsoft.AspNetCore.Mvc; @@ -28,17 +29,16 @@ namespace WebAPI.Controllers // POST api/ public PasswordLoginController( - ChurchNetContext churchNetContext, ICrudLogic crudLogic, ICombinedKeyCrudLogic relationLogic, - ICrudLogic domainLogic - + ICrudLogic domainLogic, + DatabaseOptions databaseOptions ) { - this.churchNetContext = churchNetContext; this.crudLogic = crudLogic; this.relationLogic = relationLogic; this.domainLogic = domainLogic; + churchNetContext = databaseOptions.GetDbContext(); } [HttpPost] [Route("auth/login")] diff --git a/WebAPI/Controllers/PingController.cs b/WebAPI/Controllers/PingController.cs index 54c03d6..50e4ec1 100644 --- a/WebAPI/Controllers/PingController.cs +++ b/WebAPI/Controllers/PingController.cs @@ -68,14 +68,14 @@ namespace WebAPI.Controllers bool isGet = methodInfo.GetCustomAttributes(typeof(HttpGetAttribute), false).Length > 0; bool isPost = methodInfo.GetCustomAttributes(typeof(HttpPostAttribute), false).Length > 0; bool isDelete = methodInfo.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Length > 0; - if(isGet|| isPost|| isDelete) + if (isGet || isPost || isDelete) { Endpoint _endpoint = new Endpoint { Name = methodInfo.Name, Method = isGet ? "GET" : (isPost ? "POST" : (isDelete ? "DELETE" : "UNKNOWN")), - Inputs = methodInfo.GetParameters().Select(m=>new Input() { Name=m.Name}).ToArray(), + Inputs = methodInfo.GetParameters().Select(m => new Input() { Name = m.Name }).ToArray(), ReturnType = methodInfo.ReturnType, //MethodInfo = methodInfo, }; @@ -92,7 +92,7 @@ namespace WebAPI.Controllers } return _controllers; } - + [HttpGet] public async void TestMessage() { @@ -112,7 +112,7 @@ namespace WebAPI.Controllers Uri = "https://happiness.tours/CellGroup/prayer?openExternalBrowser=1", Label = "Prayer" }; - templateMessage.AltText= "代禱事項"; + templateMessage.AltText = "代禱事項"; templateMessage.Template.DefaultAction = addPrayerBtn; templateMessage.Template.ThumbnailImageUrl = "https://dailyverses.net/images/tc/cuv/matthew-21-22-3.jpg"; @@ -120,11 +120,11 @@ namespace WebAPI.Controllers templateMessage.Template.Title = "代禱事項"; templateMessage.Template.Text = "Chris" + Environment.NewLine + "Testwerewiorjowerjiowejiro, erjaiworjweiorjioawereaw"; - + templateMessage.Template.Actions = new List(); templateMessage.Template.Actions.Add(addPrayerBtn); - await test.PushMessage(EnumHelper.EnumToDescriptionString(LineGroup.Chris), textMessage); + await test.PushMessage(EnumHelper.EnumToDescriptionString(LineGroup.Chris), textMessage); } @@ -151,7 +151,7 @@ namespace WebAPI.Controllers } else { - // ReplyTextMessage(replyToken, autoReply.ReplyMessage); + // ReplyTextMessage(replyToken, autoReply.ReplyMessage); } return; @@ -162,6 +162,14 @@ namespace WebAPI.Controllers }; } + + + + [HttpGet] + public string[] GetFiles(string path) + { + return Directory.GetFiles("/App_Data/" + path); + } public class Controller { public string Name { get; set; } diff --git a/WebAPI/Controllers/WeatherForecastController.cs b/WebAPI/Controllers/WeatherForecastController.cs index 6c59f02..feedede 100644 --- a/WebAPI/Controllers/WeatherForecastController.cs +++ b/WebAPI/Controllers/WeatherForecastController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; diff --git a/WebAPI/Dockerfile b/WebAPI/Dockerfile index 41b0c45..ce0f637 100644 --- a/WebAPI/Dockerfile +++ b/WebAPI/Dockerfile @@ -9,7 +9,7 @@ FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY ["WebAPI/WebAPI.csproj", "WebAPI/"] COPY ["Church.Net.DAL.EFCoreDBF/Church.Net.DAL.EFCoreDBF.csproj", "Church.Net.DAL.EFCoreDBF/"] -COPY ["Church.Net.Entity2/Church.Net.Entity2.csproj", "Church.Net.Entity2/"] +COPY ["Church.Net.Entity2/Church.Net.Entity.csproj", "Church.Net.Entity/"] COPY ["Church.Net.Utility/Church.Net.Utility.csproj", "Church.Net.Utility/"] RUN dotnet restore "WebAPI/WebAPI.csproj" COPY . . diff --git a/WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs b/WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs new file mode 100644 index 0000000..1c1cfd8 --- /dev/null +++ b/WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs @@ -0,0 +1,43 @@ +namespace WebAPI.Handlers +{ + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Authorization.Policy; + using Microsoft.AspNetCore.Http; + using System.Linq; + using System.Threading.Tasks; + + public class BasicAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler + { + private readonly AuthorizationMiddlewareResultHandler defaultHandler = new(); + + public async Task HandleAsync( + RequestDelegate next, + HttpContext context, + AuthorizationPolicy policy, + PolicyAuthorizationResult authorizeResult) + { + // If the authorization was forbidden and the resource had a specific requirement, + // provide a custom 404 response. + if (authorizeResult.Forbidden + && authorizeResult.AuthorizationFailure!.FailedRequirements + .OfType().Any()) + { + // Return a 404 to make it appear as if the resource doesn't exist. + context.Response.StatusCode = StatusCodes.Status404NotFound; + return; + } + + if (string.IsNullOrWhiteSpace(context.Request.Headers["accessToken"])) + { + context.Response.StatusCode = StatusCodes.Status401Unauthorized; + return; + + } + // Fall back to the default implementation. + //await defaultHandler.HandleAsync(next, context, policy, authorizeResult); + await next(context); + } + } + + public class Show404Requirement : IAuthorizationRequirement { } +} diff --git a/WebAPI/Logics/CellGroupLogic.cs b/WebAPI/Logics/CellGroupLogic.cs index 4d7009a..4464e9e 100644 --- a/WebAPI/Logics/CellGroupLogic.cs +++ b/WebAPI/Logics/CellGroupLogic.cs @@ -7,21 +7,25 @@ using System; using WebAPI.Logics.Core; using WebAPI.Logics.Interface; using System.Linq; +using Microsoft.Extensions.DependencyInjection; namespace WebAPI.Logics { public class CellGroupLogic { + private readonly IServiceScopeFactory serviceScopeFactory; private readonly ICrudDAL eventCrudDAL; private readonly ICombinedKeyCrudDAL attendeeCrudDAL; private readonly ICrudDAL memberCrudDAL; public CellGroupLogic( + IServiceScopeFactory serviceScopeFactory, ICrudDAL eventCrudDAL, ICombinedKeyCrudDAL attendeeCrudDAL, ICrudDAL memberCrudDAL ) { + this.serviceScopeFactory = serviceScopeFactory; this.eventCrudDAL = eventCrudDAL; this.attendeeCrudDAL = attendeeCrudDAL; this.memberCrudDAL = memberCrudDAL; diff --git a/WebAPI/Logics/Core/LogicBase.cs b/WebAPI/Logics/Core/LogicBase.cs index 41c38fe..a75653a 100644 --- a/WebAPI/Logics/Core/LogicBase.cs +++ b/WebAPI/Logics/Core/LogicBase.cs @@ -13,8 +13,8 @@ namespace WebAPI.Logics.Core { public class LogicBase : ICrudLogic where T : class, Church.Net.Entity.Interface.IEntity, new() { - private readonly LogicService logicService; - private readonly ICrudDAL crudDAL; + protected readonly LogicService logicService; + protected readonly ICrudDAL crudDAL; public LogicBase( LogicService logicService, @@ -46,15 +46,15 @@ namespace WebAPI.Logics.Core public int CreateOrUpdate(T entity, out string id) { - var result= this.crudDAL.CreateOrUpdate(entity, out string _id); - id = _id; + var result= this.crudDAL.CreateOrUpdate(entity); + id = entity.Id; return result; } - public string CreateReturnId(T entity) - { - return this.crudDAL.CreateReturnId(entity); - } + //public string CreateReturnId(T entity) + //{ + // return this.crudDAL.CreateReturnId(entity); + //} public int Delete(T obj) { @@ -75,10 +75,10 @@ namespace WebAPI.Logics.Core return this.crudDAL.GetAll(filter); } - public IEnumerable GetAllById(IEnumerable Ids) - { - return this.crudDAL.GetAllById(Ids); - } + //public IEnumerable GetAllById(IEnumerable Ids) + //{ + // return this.crudDAL.GetAllById(Ids); + //} public T GetById(string Id) { diff --git a/WebAPI/Logics/Core/LogicService.cs b/WebAPI/Logics/Core/LogicService.cs index 06a2b5d..232a3db 100644 --- a/WebAPI/Logics/Core/LogicService.cs +++ b/WebAPI/Logics/Core/LogicService.cs @@ -1,16 +1,33 @@ using Church.Net.DAL.EF; +using Microsoft.Extensions.DependencyInjection; +using WebAPI.Services; namespace WebAPI.Logics.Core { public class LogicService { + private readonly IServiceScopeFactory serviceScopeFactory; + public LogicService( - ChurchNetContext dbContext + //ChurchNetContext dbContext + IServiceScopeFactory serviceScopeFactory ) { - DbContext = dbContext; + this.serviceScopeFactory = serviceScopeFactory; + //DbContext = dbContext; } - public ChurchNetContext DbContext { get; } + //public ChurchNetContext DbContext { get; } + public string CurrentUserId + { + get + { + using (var scope = serviceScopeFactory.CreateScope()) + { + var service = scope.ServiceProvider.GetService(); + return service.UserId; + } + } + } } } diff --git a/WebAPI/Logics/HappinessGroupLogic.cs b/WebAPI/Logics/HappinessGroupLogic.cs index 7f2a312..42a6c4c 100644 --- a/WebAPI/Logics/HappinessGroupLogic.cs +++ b/WebAPI/Logics/HappinessGroupLogic.cs @@ -37,7 +37,7 @@ namespace WebAPI.Logics { var week = GetHappinessWeek(group, i); group.Weeks.Add(week); - weekCrudDAL.CreateOrUpdate(week, out string weekId); + weekCrudDAL.CreateOrUpdate(week); } } group.Weeks = group.Weeks.OrderBy(w => w.SEQ).ToList(); @@ -66,7 +66,7 @@ namespace WebAPI.Logics } return weekCrudDAL.UpdateRange(list); } - return weekCrudDAL.CreateOrUpdate(value, out string id); + return weekCrudDAL.CreateOrUpdate(value); } diff --git a/WebAPI/Logics/Interface/ICrudLogic.cs b/WebAPI/Logics/Interface/ICrudLogic.cs index 99d483c..bbf1e91 100644 --- a/WebAPI/Logics/Interface/ICrudLogic.cs +++ b/WebAPI/Logics/Interface/ICrudLogic.cs @@ -13,10 +13,10 @@ namespace WebAPI.Logics.Interface T GetById(string Id); IEnumerable GetAll(Func filter = null); - IEnumerable GetAllById(IEnumerable Ids); + //IEnumerable GetAllById(IEnumerable Ids); int Create(T entity); Task CreateAsync(T entity); - string CreateReturnId(T entity); + //string CreateReturnId(T entity); int CreateOrUpdate(T entity, out string id); int Update(T entity); diff --git a/WebAPI/Logics/LineMessagingAccountLogic.cs b/WebAPI/Logics/LineMessagingAccountLogic.cs new file mode 100644 index 0000000..3e429e0 --- /dev/null +++ b/WebAPI/Logics/LineMessagingAccountLogic.cs @@ -0,0 +1,49 @@ +using Church.Net.DAL.EFCoreDBF; +using Church.Net.Entity; +using Church.Net.Entity.Interface; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using WebAPI.Logics.Core; +using WebAPI.Logics.Interface; + +namespace WebAPI.Logics +{ + public class LineMessagingAccountLogic : LogicBase, ICrudLogic + { + private readonly ICrudDAL happinessGroupDAL; + private readonly ICrudDAL cellGroupDAL; + + public LineMessagingAccountLogic( + LogicService logicService, + ICrudDAL crudDAL, + ICrudDAL happinessGroupDAL, + ICrudDAL cellGroupDAL + ) : base(logicService, crudDAL) + { + this.happinessGroupDAL = happinessGroupDAL; + this.cellGroupDAL = cellGroupDAL; + } + + public HappinessGroup GetHappinessGroup(string lineGroupId) + { + var group= happinessGroupDAL.First(c => c.CommunityAppId == lineGroupId); + GetLineMessagingAccount(group); + return group; + } + public PastoralDomain GetCellGroup(string lineGroupId) + { + var group = cellGroupDAL.First(c => c.CommunityAppId == lineGroupId); + GetLineMessagingAccount(group); + return group; + } + + private void GetLineMessagingAccount(IMessengerClient messengerClient) + { + if (messengerClient != null) + { + messengerClient.LineMessagingAccount = crudDAL.GetById(messengerClient.LineAccountId); + } + } + } +} diff --git a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs b/WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs index 827ff92..632bf2c 100644 --- a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs +++ b/WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs @@ -16,10 +16,9 @@ namespace WebAPI.Services.AutoReplyCommands public class ArArkCellGroupDinner : IAutoReplyCommand { - public ArArkCellGroupDinner(ChurchNetContext context, + public ArArkCellGroupDinner( CellGroupLogic logic) { - this._context = context; this.logic = logic; } private static readonly string[] COMMANDS = { "晚餐", "dinner" }; @@ -28,57 +27,12 @@ namespace WebAPI.Services.AutoReplyCommands LineGroup.Ark, LineGroup.Chris, }; - private readonly ChurchNetContext _context; private readonly CellGroupLogic logic; public string Description => "顯示方舟小組聚會晚餐"; public IEnumerable Commands => COMMANDS; public IEnumerable SupportGroups => GROUPS; - public IEnumerable ReplyMessage - { - get - { - - StringBuilder sb = new StringBuilder(); - StringBuilder comments = new StringBuilder(); - sb.AppendLine("又到了令人期待的小組日~~~"); - var _event = _context.CellGroupRoutineEvents.Where(e => e.Time >= DateTime.Today) - .Include(e => e.Attendees).FirstOrDefault(); - if (_event == null) - { - _event = new CellGroupRoutineEvent() - { - Id = Format.Get33BaseGuid(), - Time = DateTimeHelper.GetNextWeekday(DateTime.Today, DayOfWeek.Friday).AddHours(19).AddMinutes(30), - Address = "1881 Forest Dr., Azusa, CA 91702", - Attendees = new List() - }; - _context.Add(_event); - _context.SaveChanges(); - } - - - sb.AppendLine($"{_event.Time.ToString("MM/dd HH:mm tt")} 開飯~"); - - sb.AppendLine("======= 晚宴清單 ======="); - foreach (var a in _event.Attendees) - { - sb.AppendLine($"{a.Name} - {string.Join(", ", a.PotluckItem.Split('|'))}"); - - if (!string.IsNullOrWhiteSpace(a.Comment)) - { - comments.AppendLine($"{a.Name}:{a.Comment}"); - } - } - - if (comments.Length > 0) - { - sb.AppendLine("========= 備註 ========="); - sb.Append(comments.ToString()); - } - return new string[] { sb.ToString() }; - } - } + public IEnumerable ReplyMessage => null; public IEnumerable LineMessage { diff --git a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs b/WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs index 074a779..c2a7b05 100644 --- a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs +++ b/WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs @@ -231,7 +231,8 @@ namespace WebAPI.Services.AutoReplyCommands { Size = FlexObjectSize.sm, Color = "#666666", - Flex = 5 + Flex = 5, + Wrap = true }); comments.Add(commentLineBox); } diff --git a/WebAPI/Services/DbLoggingService.cs b/WebAPI/Services/DbLoggingService.cs index 15af8d5..7ab9ba0 100644 --- a/WebAPI/Services/DbLoggingService.cs +++ b/WebAPI/Services/DbLoggingService.cs @@ -127,12 +127,12 @@ namespace WebAPI.Services EventLog.WriteEntry("BeyondAPI", $"Can Not Append Error Log:{ex.Message}", EventLogEntryType.Error); } - public void Log(string message, object detail) + public void Log(string message, object detail = null) { LogInfo log = new LogInfo(LogLevel.Info) { Message = message, - DetailMessage = JsonConvert.SerializeObject(detail,Formatting.Indented) , + DetailMessage = JsonConvert.SerializeObject(detail, Formatting.Indented), //Source = exception.Source, //StackTrace = exception.StackTrace }; diff --git a/WebAPI/Services/IdentityService.cs b/WebAPI/Services/IdentityService.cs new file mode 100644 index 0000000..2ab5802 --- /dev/null +++ b/WebAPI/Services/IdentityService.cs @@ -0,0 +1,26 @@ +using Church.Net.Entity; +using Church.Net.Utility; +using Microsoft.AspNetCore.SignalR; + +namespace WebAPI.Services +{ + public class IdentityService + { + public string UserAccessToken { get; set; } + public string UserId { get; set; } + + public PastoralDomain CellGroup + { + get { + + TokenHelper.GetUserIdFromToken + return null; } + } + + + + + + + } +} diff --git a/WebAPI/Services/Interfaces/ILoggingService.cs b/WebAPI/Services/Interfaces/ILoggingService.cs index 382c1b3..dd3aa10 100644 --- a/WebAPI/Services/Interfaces/ILoggingService.cs +++ b/WebAPI/Services/Interfaces/ILoggingService.cs @@ -7,7 +7,7 @@ namespace WebAPI.Services.Interfaces { public interface ILoggingService { - void Log(string message, object detail); + void Log(string message, object detail=null); void Warning(string message, object detail); int Error(Exception exception); int Error(Exception exception, string from); diff --git a/WebAPI/Services/Interfaces/IScheduledTask.cs b/WebAPI/Services/Interfaces/IScheduledTask.cs new file mode 100644 index 0000000..8b98a7a --- /dev/null +++ b/WebAPI/Services/Interfaces/IScheduledTask.cs @@ -0,0 +1,15 @@ +using LineMessaging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebAPI.Services.Interfaces +{ + public interface IScheduledTask + { + string Description { get; } + bool CheckTime(DateTime time); + Task RunTask(); + } +} diff --git a/WebAPI/Services/LineAutoBotService.cs b/WebAPI/Services/LineAutoBotService.cs index ec1e309..b140077 100644 --- a/WebAPI/Services/LineAutoBotService.cs +++ b/WebAPI/Services/LineAutoBotService.cs @@ -1,4 +1,5 @@ -using Church.Net.Utility; +using Church.Net.Entity.Messenger; +using Church.Net.Utility; using LineMessaging; using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; @@ -8,6 +9,7 @@ using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using WebAPI.Logics.Interface; using WebAPI.Services.Interfaces; using static System.Net.Mime.MediaTypeNames; @@ -27,14 +29,17 @@ namespace WebAPI.Services { private readonly IEnumerable autoReplyCommands; private readonly ILoggingService loggingService; + private readonly ICrudLogic clientLogic; public LineAutoBotService( IEnumerable autoReplyCommands, - ILoggingService loggingService + ILoggingService loggingService, + ICrudLogic clientLogic ) { this.autoReplyCommands = autoReplyCommands; this.loggingService = loggingService; + this.clientLogic = clientLogic; } public void SendTextMessage(string text, LineGroup target) { @@ -72,7 +77,12 @@ namespace WebAPI.Services } catch (Exception ex) { - this.loggingService.Error(ex, "ReplyTextMessage:68", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); + this.loggingService.Error(ex, "ReplyTextMessage:75", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); + + if (ex.Message == "You have reached your monthly limit.") + { + this.SendTextMessage("Line Bot Exist Monthly Limit!!!", LineGroup.Chris); + } return false; } } @@ -92,7 +102,11 @@ namespace WebAPI.Services } catch (Exception ex) { - this.loggingService.Error(ex, "ReplyLineMessage:84", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); + this.loggingService.Error(ex, "ReplyLineMessage:95", JsonConvert.SerializeObject(replyMessage, Formatting.Indented)); + if (ex.Message == "You have reached your monthly limit.") + { + this.SendTextMessage("Line Bot Exist Monthly Limit!!!", LineGroup.Chris); + } return false; } @@ -112,10 +126,13 @@ namespace WebAPI.Services string replyToken = e.ReplyToken; string text = e.Message.Text; string target = ""; + bool isGroup = true; + var client = new LineMessagingClient(); switch (e.Source.Type) { case WebhookRequestSourceType.User: target = e.Source.UserId; + isGroup = false; break; case WebhookRequestSourceType.Group: target = e.Source.GroupId; @@ -127,6 +144,33 @@ namespace WebAPI.Services default: break; } + if (isGroup) + { + if (clientLogic.First(c => c.ClientId == e.Source.GroupId) == null) + { + clientLogic.CreateOrUpdate(new LineMessageClient() + { + ClientId = target, + Name = client.GetGroupProfile(e.Source.GroupId).Result.GroupName, + IsGroup = true + }, out string id); + } + //TODO:Get user by user id under group + } + else + { + if (clientLogic.First(c => c.ClientId == e.Source.UserId) == null) + { + + clientLogic.CreateOrUpdate(new LineMessageClient() + { + ClientId = target, + Name = client.GetProfile(e.Source.UserId).Result.DisplayName, + IsGroup = false + }, out string id); + } + } + if (!String.IsNullOrWhiteSpace(replyToken) && text.IndexOf("#") == 0) { @@ -166,8 +210,12 @@ namespace WebAPI.Services } + else if (e.Message.Type == MessageType.Sticker && e.Source.GroupId == LineGroup.Ark.EnumToDescriptionString() && e.Message.PackageId == "1011092" && e.Message.StickerId == "510712") + { + + await ReplyLineMessage(e.Source.GroupId, autoReplyCommands.Where(ar => ar.Commands.Contains("pray")).FirstOrDefault().LineMessage); + } - this.LogLineMessage(e); } } catch (Exception ex) @@ -224,7 +272,7 @@ namespace WebAPI.Services } catch (Exception ex) { - loggingService.Error(ex, "AutoReply:188",command); + loggingService.Error(ex, "AutoReply:188", command); return false; } @@ -232,64 +280,5 @@ namespace WebAPI.Services return true; } - private void LogLineMessage(LineWebhookContent.Event e) - { - return; - try - { - - //var lineHookRequest = new LineMessaging.LineWebhookRequest("d23edf453427256a759d218ec8b6779f", request); - //var content = await lineHookRequest.GetContent(); - string txtPath = ServerUtils.MapPath("App_Data/LinePostLog.txt"); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine($"==================={DateTime.Now.ToString("MM/dd/yyyy HH:mm")}========================="); - - stringBuilder.AppendLine($"Message Type:{e.Type.ToString()}"); - - switch (e.Source.Type) - { - case WebhookRequestSourceType.User: - stringBuilder.AppendLine($"UserId:{e.Source.UserId}"); - break; - case WebhookRequestSourceType.Group: - stringBuilder.AppendLine($"GroupId:{e.Source.GroupId}"); - - break; - case WebhookRequestSourceType.Room: - stringBuilder.AppendLine($"RoomId:{e.Source.RoomId}"); - break; - default: - break; - } - stringBuilder.AppendLine($"Reply Token:{e.ReplyToken}"); - - stringBuilder.AppendLine($"Message Type:{e.Message.Type.ToString()}"); - switch (e.Message.Type) - { - case MessageType.Text: - stringBuilder.AppendLine($"Message:{e.Message.Text}"); - break; - case MessageType.Image: - case MessageType.Video: - case MessageType.Audio: - case MessageType.File: - case MessageType.Location: - case MessageType.Sticker: - case MessageType.Imagemap: - case MessageType.Template: - default: - - stringBuilder.AppendLine($"Message:{JsonConvert.SerializeObject(e.Message, Formatting.Indented)}"); - break; - } - - - System.IO.File.AppendAllText(txtPath, stringBuilder.ToString()); - } - catch (Exception ex) - { - } - - } } } diff --git a/WebAPI/Services/ScheduledTask/MorningPrayer.cs b/WebAPI/Services/ScheduledTask/MorningPrayer.cs new file mode 100644 index 0000000..849d648 --- /dev/null +++ b/WebAPI/Services/ScheduledTask/MorningPrayer.cs @@ -0,0 +1,46 @@ +using Church.Net.Utility; +using System; +using System.Threading.Tasks; +using WebAPI.Services.Interfaces; + +namespace WebAPI.Services.ScheduledTask +{ + public class MorningPrayer : IScheduledTask + { + private readonly LineAutoBotService lineAutoBotService; + private readonly ILoggingService loggingService; + private DateTime? nextRunningTime = null; + public MorningPrayer( + LineAutoBotService lineAutoBotService, + ILoggingService loggingService + ) + { + this.lineAutoBotService = lineAutoBotService; + this.loggingService = loggingService; + this.SetNextRunningTime(); + } + public string Description => "Sent out Ark Morning Prayer"; + + public bool CheckTime(DateTime time) + { + if(nextRunningTime == null) + { + this.SetNextRunningTime(); + return true; + } + + return time >= nextRunningTime.Value; + } + + public Task RunTask() + { + SetNextRunningTime(); + return lineAutoBotService.PushCommandMessage(LineGroup.Ark, "#pray"); + } + private void SetNextRunningTime() + { + nextRunningTime = DateTimeHelper.Today().AddDays(1).AddHours(8); + loggingService.Log($"Scheduled Task {this.Description}", nextRunningTime.Value); + } + } +} diff --git a/WebAPI/Services/WorkerService.cs b/WebAPI/Services/WorkerService.cs new file mode 100644 index 0000000..0333550 --- /dev/null +++ b/WebAPI/Services/WorkerService.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Hosting; +using System.Threading.Tasks; +using System.Threading; +using System; +using WebAPI.Services.Interfaces; +using System.Collections.Generic; +using System.Linq; +using Church.Net.Utility; +using Microsoft.AspNetCore.Hosting; + +namespace WebAPI.Services +{ + public class WorkerService : BackgroundService + { + private IEnumerable scheduledTasks; + private ILoggingService loggingService; + private readonly IWebHostEnvironment env; + private static bool initialized = false; + + public WorkerService( + IEnumerable scheduledTasks, + ILoggingService loggingService + ) + { + this.scheduledTasks = scheduledTasks; + this.loggingService = loggingService; + } + private const int generalDelay = 5 * 60 * 1000; // 10 seconds + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + + //await DoBackupAsync(); + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(generalDelay, stoppingToken); + await DoBackupAsync(); + } + } + + private async Task DoBackupAsync() + { + // here i can write logic for taking backup at midnight + //if (IsMidnight()) + //{ + // Console.WriteLine("Executing background task"); + // TakeBackup(); + //} + + var now = DateTimeHelper.Now(); + foreach (var worker in scheduledTasks) + { + try + { + if (worker.CheckTime(now)) + { + loggingService.Log($"Running {worker.Description}"); + await worker.RunTask(); + } + } + catch (Exception ex) + { + loggingService.Error(ex, worker.Description); + } + } + + return "Done"; + } + } +} diff --git a/WebAPI/Startup.cs b/WebAPI/Startup.cs index 64123b6..9801a21 100644 --- a/WebAPI/Startup.cs +++ b/WebAPI/Startup.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Church.Net.DAL.EF; using Church.Net.DAL.EFCoreDBF; using Church.Net.Entity; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Hosting; @@ -18,6 +19,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Serialization; +using WebAPI.Handlers; using WebAPI.Hubs; using WebAPI.Logics; using WebAPI.Logics.Core; @@ -25,6 +27,7 @@ using WebAPI.Logics.Interface; using WebAPI.Services; using WebAPI.Services.AutoReplyCommands; using WebAPI.Services.Interfaces; +using WebAPI.Services.ScheduledTask; using static System.Net.Mime.MediaTypeNames; namespace WebAPI @@ -51,7 +54,7 @@ namespace WebAPI NamingStrategy = new CamelCaseNamingStrategy(), }; - options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified; + //options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified; options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }); @@ -60,6 +63,7 @@ namespace WebAPI services.AddSignalR(); services.AddSingleton(); + services.AddSingleton(_ => new DatabaseOptions { ConnectionString = "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" }); //services.AddSingleton(new ChurchNetContext()); services.AddDbContext(options => options.UseNpgsql( @@ -67,30 +71,37 @@ namespace WebAPI "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" )); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(); + services.AddSingleton(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(typeof(ICrudLogic<>), typeof(LogicBase<>)); - services.AddScoped(typeof(ICrudDAL<>), typeof(CrudDALCBase<>)); - services.AddScoped(typeof(ICombinedKeyCrudLogic<>), typeof(CombinedKeyLogicBase<>)); - services.AddScoped(typeof(ICombinedKeyCrudDAL<>), typeof(CombinedKeyCrudDALCBase<>)); - services.AddScoped(); - services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(typeof(ICrudLogic<>), typeof(LogicBase<>)); + services.AddSingleton(typeof(ICrudDAL<>), typeof(CrudDALCBase<>)); + services.AddSingleton(typeof(ICombinedKeyCrudLogic<>), typeof(CombinedKeyLogicBase<>)); + services.AddSingleton(typeof(ICombinedKeyCrudDAL<>), typeof(CombinedKeyCrudDALCBase<>)); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddScoped(); + + services.AddHostedService(); //services.AddMvc(o=>o.Filters.Add(typeof(HandleExceptionFilter))); //services.AddMvc(o => o.Filters.Add(new HandleExceptionFilter(services.BuildServiceProvider().GetService()))); //services.BuildServiceProvider().GetService(); - + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ChurchNetContext dbContext) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DatabaseOptions databaseOptions) { //Reference:https://stackoverflow.com/questions/69961449/net6-and-datetime-problem-cannot-write-datetime-with-kind-utc-to-postgresql-ty @@ -101,7 +112,12 @@ namespace WebAPI AppDomain.CurrentDomain.SetData("WebRootPath", env.WebRootPath); if (env.IsDevelopment()) { - app.UseDeveloperExceptionPage(); + //app.UseDeveloperExceptionPage(); + app.UseExceptionHandler("/error-development"); + } + else + { + app.UseExceptionHandler("/error"); } // global cors policy @@ -113,18 +129,16 @@ namespace WebAPI .AllowCredentials() ); // allow credentials - //app.UseCors(builder => - //{ - // builder.WithOrigins("http://localhost:4200") - // .AllowAnyHeader() - // .WithMethods("GET", "POST") - // .AllowCredentials(); - //}); + //app.UseHttpsRedirection(); //app.UsePathBase(new PathString("/api")); app.UsePathBase(new PathString("/")); app.UseRouting(); + + //app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => { //endpoints.MapControllerRoute( @@ -135,50 +149,19 @@ namespace WebAPI endpoints.MapHub("/BaseHub"); endpoints.MapControllers(); - + //endpoints.MapControllerRoute( // name: "default", // pattern: "{controller}/{action=Index}/{id?}"); }); - //app.UseExceptionHandler(exceptionHandlerApp => - //{ - // exceptionHandlerApp.Run(async context => - // { - // context.Response.StatusCode = StatusCodes.Status500InternalServerError; - - // // using static System.Net.Mime.MediaTypeNames; - // context.Response.ContentType = Text.Plain; - - // await context.Response.WriteAsync("An exception was thrown."); - - // var exceptionHandlerPathFeature = - // context.Features.Get(); - - // if (exceptionHandlerPathFeature?.Error is FileNotFoundException) - // { - // await context.Response.WriteAsync(" The file was not found."); - // } - - // if (exceptionHandlerPathFeature?.Path == "/") - // { - // await context.Response.WriteAsync(" Page: Home."); - // } - // }); - //}); - //app.UseAuthorization(); - - //app.UseEndpoints(endpoints => - //{ - // endpoints.MapControllers(); - // endpoints.MapHub("/WhoIsSpyHub"); - //}); if (env.IsDevelopment()) { + databaseOptions.GetDbContext().Database.Migrate(); + //new ChurchNetContext(databaseOptions.ConnectionString).Database.Migrate(); //dbContext.Database.EnsureCreated(); - dbContext.Database.Migrate(); + //dbContext.Database.Migrate(); } - } } } diff --git a/WebAPI/WebAPI.csproj b/WebAPI/WebAPI.csproj index cd5d138..0a08b40 100644 --- a/WebAPI/WebAPI.csproj +++ b/WebAPI/WebAPI.csproj @@ -17,6 +17,7 @@ + @@ -38,8 +39,10 @@ - + + +