Update API

This commit is contained in:
Chris Chen 2022-09-30 09:40:42 -07:00
parent 184db15773
commit b33c0d8286
55 changed files with 3877 additions and 360 deletions

View File

@ -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
{
@ -36,6 +38,9 @@ namespace Church.Net.DAL.EF
public class ChurchNetContext : DbContext
{
private static bool _created = true;
private readonly string connectionString;
public ChurchNetContext(DbContextOptions<ChurchNetContext> options) : base(options)
{
@ -53,19 +58,19 @@ 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<PastoralDomain> PastoralDomains { get; set; }
//public DbSet<FamilyMember> FamilyMembers { get; set; }
//public DbSet<Career> Careers { get; set; }
@ -130,6 +135,9 @@ namespace Church.Net.DAL.EF
public DbSet<LogInfo> LogInfos { get; set; }
public DbSet<AutoReplyItem> AutoReplyItems { get; set; }
public DbSet<AddressInfo> AddressInfos { get; set; }
public DbSet<LineMessageClient> LineMessageClients { get; set; }
public DbSet<LineMessagingAccount> LineMessagingAccounts { get; set; }
#endregion

View File

@ -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<T> : ICrudDAL<T> where T : class, IEntity, new()
{
private readonly ChurchNetContext dbContext;
public CrudDALCBase1(DatabaseOptions databaseOptions)
{
this.dbContext = databaseOptions.GetDbContext();
InitKeyProperty();
}
public IQueryable<T> GetDbSet()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return dbContext.Set<T>().AsNoTracking();
//return result;
}
public virtual T First(Func<T, bool> 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<ST>(refndx, this.actionScreen));
//}
public virtual IEnumerable<T> GetAll(Func<T, bool> filter = null)
{
//var dbObjs = GetDbSet().ToArray();
//IEnumerable<T> 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<int> 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<T> entities)
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges();
}
public virtual int Delete(T obj)
{
dbContext.Remove(obj);
return dbContext.SaveChanges();
}
public int Delete(Func<T, bool> 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<PropertyInfo> props = new List<PropertyInfo>();
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<PropertyInfo> keyProps;
protected virtual void InitKeyProperty()
{
keyProps = typeof(T).GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(KeyAttribute))).OrderBy(prop =>
prop.GetCustomAttribute<ColumnAttribute>().Order
)
.ToList();
}
protected IQueryable<T> GetQuery(IEnumerable<string> 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();
}
}
}

View File

@ -17,24 +17,34 @@ namespace Church.Net.DAL.EFCoreDBF
{
public class CombinedKeyCrudDALCBase<T> : ICombinedKeyCrudDAL<T> where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new()
{
private readonly ChurchNetContext dbContext;
private readonly DatabaseOptions databaseOptions;
public CombinedKeyCrudDALCBase(ChurchNetContext dbContext)
public CombinedKeyCrudDALCBase(DatabaseOptions databaseOptions)
{
this.dbContext = dbContext;
this.databaseOptions = databaseOptions;
InitKeyProperty();
}
public DbSet<T> GetDbSet()
public IQueryable<T> GetDbSet()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return (DbSet<T>)dbContext.Set<T>();
return databaseOptions.GetDbContext().Set<T>().AsNoTracking();
//return result;
}
public ChurchNetContext GetDbContext()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return databaseOptions.GetDbContext();//.Set<T>().AsNoTracking();
//return result;
}
public virtual T First(Func<T, bool> filter = null)
{
return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault();
using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Where(filter ?? (s => true)).FirstOrDefault();
}
}
public virtual T GetById(IEnumerable<string> Ids)
@ -60,19 +70,26 @@ namespace Church.Net.DAL.EFCoreDBF
{
this.CheckCombinedKeyIsEmpty(entity);
this.ConvertUTCTime(entity);
using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
return dbContext.SaveChanges();
}
}
public virtual Task<int> CreateAsync(T entity)
{
this.CheckCombinedKeyIsEmpty(entity);
this.ConvertUTCTime(entity);
using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
//CreateDone(entity, newDbObj);
return dbContext.SaveChangesAsync();
}
}
public int CreateOrUpdate(T entity)
@ -99,9 +116,12 @@ namespace Church.Net.DAL.EFCoreDBF
//}
this.ConvertUTCTime(entity);
using (var dbContext = GetDbContext())
{
dbContext.Update(entity);
return dbContext.SaveChanges();
}
}
@ -115,17 +135,23 @@ namespace Church.Net.DAL.EFCoreDBF
}
public virtual int UpdateRange(IEnumerable<T> entities)
{
using (var dbContext = GetDbContext())
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges();
}
}
public virtual int Delete(T obj)
{
using (var dbContext = GetDbContext())
{
dbContext.Remove(obj);
return dbContext.SaveChanges();
}
}
public virtual int Delete(IEnumerable<string> combinedKeyIds)
{
@ -136,12 +162,15 @@ namespace Church.Net.DAL.EFCoreDBF
public int Delete(Func<T, bool> filter)
{
var list = GetDbSet().Where(filter).ToList();
using (var dbContext = GetDbContext())
{
foreach (var item in list)
{
dbContext.Remove(item);
}
return dbContext.SaveChanges();
}
}
public virtual bool CheckExist(T obj)
{
@ -189,7 +218,9 @@ namespace Church.Net.DAL.EFCoreDBF
private IQueryable<T> GetQuery(IEnumerable<string> Ids)
{
var query = GetDbSet().AsQueryable();
using (var dbContext = GetDbContext())
{
var query = dbContext.Set<T>().AsQueryable();
for (int i = 0; i < keyProps.Count; i++)
{
@ -197,6 +228,7 @@ namespace Church.Net.DAL.EFCoreDBF
}
return query;
}
}
private void CheckCombinedKeyIsEmpty(T entity)
{
for (int i = 0; i < keyProps.Count; i++)

View File

@ -12,28 +12,37 @@ namespace Church.Net.DAL.EFCoreDBF
{
public class CrudDALCBase<T> : ICrudDAL<T> 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<T> GetDbSet()
public ChurchNetContext GetDbContext()
{
//var result = (DbSet<T>)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null);
return (DbSet<T>)dbContext.Set<T>();
return databaseOptions.GetDbContext();//.Set<T>().AsNoTracking();
//return result;
}
public virtual T First(Func<T, bool> filter = null)
{
return GetDbSet().Where(filter ?? (s => true)).FirstOrDefault();
using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().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<T>().FirstOrDefault(e => e.Id == Id);
}
}
//public virtual T GetByRefndx(string refndx)
@ -43,41 +52,56 @@ namespace Church.Net.DAL.EFCoreDBF
public virtual IEnumerable<T> GetAll(Func<T, bool> filter = null)
{
//var dbObjs = GetDbSet().ToArray();
using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Where(filter ?? (s => true)).ToList();
}
//var dbObjs = GetDbContext().ToArray();
//IEnumerable<T> list = GetDbSet().Where(filter ?? (s => true)).ToList();
//IEnumerable<T> list = GetDbContext().Where(filter ?? (s => true)).ToList();
return GetDbSet().Where(filter ?? (s => true)).ToList();
}
public virtual IEnumerable<T> GetAllById(IEnumerable<string> Ids)
{
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<T>();
var dbObjs = GetDbSet().Where(e => RowIds.Any(id => id == e.Id)).ToArray();
return dbObjs.ToList();
return dbContext.Set<T>().Where(e => RowIds.Any(id => id == e.Id)).ToArray();
}
}
private bool needGenId(T entity)
{
return string.IsNullOrWhiteSpace(entity.Id) || entity.Id.Length <= 3;
}
public virtual int Create(T entity)
{
if (string.IsNullOrEmpty(entity.Id))
if (needGenId(entity))
{
entity.Id = StringHelper.Get33BaseGuid();
}
this.ConvertUTCTime(entity);
using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
return dbContext.SaveChanges();
}
}
public virtual Task<int> CreateAsync(T entity)
{
int result = 0;
this.ConvertUTCTime(entity);
if (string.IsNullOrEmpty(entity.Id))
if (needGenId(entity))
{
entity.Id = StringHelper.Get33BaseGuid();
}
@ -88,11 +112,14 @@ namespace Church.Net.DAL.EFCoreDBF
//newDbObj.RowId = entity.Id.ToString();
//result = Add(newDbObj) ? 1 : 0;
}
using (var dbContext = GetDbContext())
{
dbContext.Add(entity);
//CreateDone(entity, newDbObj);
return dbContext.SaveChangesAsync();
}
}
public virtual string CreateReturnId(T entity)
{
this.ConvertUTCTime(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);
using (var dbContext = GetDbContext())
{
if (CheckExist(entity))
{
dbContext.Update(entity);
}
else
{
if (string.IsNullOrEmpty(entity.Id))
if (needGenId(entity))
{
entity.Id = StringHelper.Get33BaseGuid();
}
id = entity.Id;
dbContext.Add(entity);
}
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())
{
//var dbObj = dbContext.Set<T>().Any(e => e.Id == entity.Id);
if (!dbContext.Set<T>().Any(e => e.Id == entity.Id))
{
throw new ArgumentNullException("the Id is not exist.");
}
this.ConvertUTCTime(entity);
dbContext.Update(dbObj);
dbContext.Update(entity);
return dbContext.SaveChanges();
}
}
public virtual void CreateDone(T entity)
@ -157,20 +189,29 @@ namespace Church.Net.DAL.EFCoreDBF
{
this.ConvertUTCTime(entity);
}
using (var dbContext = GetDbContext())
{
dbContext.UpdateRange(entities);
return dbContext.SaveChanges();
}
}
public virtual int Delete(T obj)
{
dbContext.Remove(GetDbSet().FirstOrDefault(e => e.Id == obj.Id.ToString()));
using (var dbContext = GetDbContext())
{
dbContext.Remove(dbContext.Set<T>().FirstOrDefault(e => e.Id == obj.Id.ToString()));
return dbContext.SaveChanges();
}
}
public int Delete(Func<T, bool> filter)
{
var list = GetDbSet().Where(filter).ToList();
using (var dbContext = GetDbContext())
{
var list = dbContext.Set<T>().Where(filter).ToList();
if (list.Count > 0)
{
dbContext.RemoveRange(list);
@ -178,10 +219,14 @@ namespace Church.Net.DAL.EFCoreDBF
}
return 0;
}
}
public virtual bool CheckExist(T obj)
{
return GetDbSet().Any(e => e.Id == obj.Id);
using (var dbContext = GetDbContext())
{
return dbContext.Set<T>().Any(e => e.Id == obj.Id);
}
}
private void ConvertUTCTime(T entity)
@ -193,11 +238,40 @@ 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<T> GetDbSet()
{
return databaseOptions.GetDbContext().Set<T>().AsNoTracking();
}
}

View File

@ -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);
}
}

View File

@ -11,17 +11,16 @@ namespace Church.Net.DAL.EFCoreDBF
{
public interface ICrudDAL<T> where T : class, IEntity
{
DbSet<T> GetDbSet();
IQueryable<T> GetDbSet();
T First(Func<T, bool> filter = null);
T GetById(string Id);
IEnumerable<T> GetAll(Func<T, bool> filter = null);
IEnumerable<T> GetAllById(IEnumerable<string> Ids);
//IEnumerable<T> GetAllById(IEnumerable<string> Ids);
int Create(T entity);
Task<int> 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<T> where T : class, ICombinedKeyEntity
public interface ICombinedKeyCrudDAL<T> where T : class
{
DbSet<T> GetDbSet();
IQueryable<T> GetDbSet();
T First(Func<T, bool> filter = null);
T GetById(IEnumerable<string> combinedKeyIds);

View File

@ -0,0 +1,798 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("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
}
}
}

View File

@ -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<string>(
name: "Comment",
table: "HappinessWeeks",
type: "text",
nullable: true);
migrationBuilder.CreateTable(
name: "HappinessTask",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
WeekId = table.Column<string>(type: "text", nullable: true),
Type = table.Column<int>(type: "integer", nullable: false),
Tasker = table.Column<string>(type: "text", nullable: true),
Content = table.Column<string>(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");
}
}
}

View File

@ -0,0 +1,823 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("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
}
}
}

View File

@ -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<string>(
name: "CommunityAppId",
table: "HappinessGroups",
type: "text",
nullable: true);
migrationBuilder.CreateTable(
name: "LineMessageClients",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ClientId = table.Column<string>(type: "text", nullable: true),
IsGroup = table.Column<bool>(type: "boolean", nullable: false),
IsManager = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(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");
}
}
}

View File

@ -0,0 +1,845 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("City")
.HasColumnType("text");
b.Property<string>("State")
.HasColumnType("text");
b.Property<string>("Zip")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AddressInfos");
});
modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Command")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("AutoReplyItems");
});
modelBuilder.Entity("Church.Net.Entity.Career", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Careers");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("CellGroupRoutineEvents");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<bool>("JoinPotluck")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("PotluckItem")
.HasColumnType("text");
b.HasKey("EventId", "Id");
b.ToTable("CellGroupRoutineEventAttendees");
});
modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b =>
{
b.Property<string>("EventId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("MemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("Prayer")
.HasColumnType("text");
b.HasKey("EventId", "MemberId");
b.ToTable("CellGroupRoutineEventPrayers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMember", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("AvatarImage")
.HasColumnType("text");
b.Property<bool>("Baptized")
.HasColumnType("boolean");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<string>("CareerId")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("DateOfBaptized")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfWalkIn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("Married")
.HasColumnType("boolean");
b.Property<string>("Password")
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CareerId");
b.ToTable("FamilyMembers");
});
modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b =>
{
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("OAuthType")
.HasColumnType("text")
.HasColumnOrder(1);
b.Property<string>("OAuthAccessToken")
.HasColumnType("text");
b.HasKey("FamilyMemberId", "OAuthType");
b.ToTable("FamilyMemberOAuths");
});
modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessBESTs");
});
modelBuilder.Entity("Church.Net.Entity.HappinessGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<DateTime>("BeginTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("HappinessGroups");
});
modelBuilder.Entity("Church.Net.Entity.HappinessTask", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<string>("GroupId")
.HasColumnType("text");
b.Property<string>("InvitationText")
.HasColumnType("text");
b.Property<int>("SEQ")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("HappinessWeeks");
});
modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ChatToken")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<int>("Seq")
.HasColumnType("integer");
b.Property<int>("TotalUsage")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("LineMessagingAccounts");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DetailMessage")
.HasColumnType("text");
b.Property<int>("Level")
.HasColumnType("integer");
b.Property<string>("Message")
.HasColumnType("text");
b.Property<string>("Source")
.HasColumnType("text");
b.Property<string>("StackTrace")
.HasColumnType("text");
b.Property<DateTime>("Time")
.HasColumnType("timestamp with time zone");
b.Property<int>("TrackNo")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TrackNo"));
b.Property<string>("Url")
.HasColumnType("text");
b.Property<string>("UserId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Address")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ComunityAppId")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Note")
.HasColumnType("text");
b.Property<string>("Phone")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<int?>("ReligionId")
.HasColumnType("integer");
b.Property<DateTime>("VisitingDate")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ReligionId");
b.ToTable("NewVisitors");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Image1")
.HasColumnType("text");
b.Property<string>("Image2")
.HasColumnType("text");
b.Property<string>("Image3")
.HasColumnType("text");
b.Property<string>("Image4")
.HasColumnType("text");
b.Property<string>("Image5")
.HasColumnType("text");
b.Property<string>("LeaderMemberId")
.HasColumnType("text");
b.Property<string>("LogoImage")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("ServiceAddressId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("LeaderMemberId");
b.HasIndex("ServiceAddressId");
b.ToTable("PastoralDomains");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b =>
{
b.Property<string>("PastoralDomainCommunityAppId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("AutoReplyItemId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId");
b.HasIndex("AutoReplyItemId");
b.ToTable("PastoralDomainAutoReplys");
});
modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b =>
{
b.Property<string>("PastoralDomainId")
.HasColumnType("text")
.HasColumnOrder(0);
b.Property<string>("FamilyMemberId")
.HasColumnType("text")
.HasColumnOrder(1);
b.HasKey("PastoralDomainId", "FamilyMemberId");
b.HasIndex("FamilyMemberId");
b.ToTable("PastoralDomainMembers");
});
modelBuilder.Entity("Church.Net.Entity.Religion", b =>
{
b.Property<int>("ReligionId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ReligionId"));
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("ReligionId");
b.ToTable("Religions");
});
modelBuilder.Entity("Church.Net.Entity.Vocabulary", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("DefinitionCh")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DefinitionEn")
.IsRequired()
.HasColumnType("text");
b.Property<int>("FlashCardTimes")
.HasColumnType("integer");
b.Property<string>("ImagesUrl")
.HasColumnType("text");
b.Property<DateTime>("InsertDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("NounPlural")
.HasColumnType("text");
b.Property<int>("PartOfSpeech")
.HasColumnType("integer");
b.Property<bool>("PracticeApply")
.HasColumnType("boolean");
b.Property<DateTime>("PracticeDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("PracticeMemorized")
.HasColumnType("boolean");
b.Property<bool>("PracticeReview")
.HasColumnType("boolean");
b.Property<bool>("PracticeSelect")
.HasColumnType("boolean");
b.Property<string>("PracticeSentence")
.HasColumnType("text");
b.Property<int>("PracticeStage")
.HasColumnType("integer");
b.Property<bool>("PracticeVisualize")
.HasColumnType("boolean");
b.Property<string>("VerbParticiple")
.HasColumnType("text");
b.Property<string>("VerbPast")
.HasColumnType("text");
b.Property<string>("Word")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Vocabulary");
});
modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Answer1Chs")
.HasColumnType("text");
b.Property<string>("Answer1Cht")
.HasColumnType("text");
b.Property<string>("Answer1En")
.HasColumnType("text");
b.Property<string>("Answer2Chs")
.HasColumnType("text");
b.Property<string>("Answer2Cht")
.HasColumnType("text");
b.Property<string>("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
}
}
}

View File

@ -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<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: true),
ChatToken = table.Column<string>(type: "text", nullable: true),
TotalUsage = table.Column<int>(type: "integer", nullable: false),
Seq = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_LineMessagingAccounts", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "LineMessagingAccounts");
}
}
}

View File

@ -262,6 +262,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("CommunityAppId")
.HasColumnType("text");
b.Property<string>("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<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Tasker")
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<string>("WeekId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("WeekId");
b.ToTable("HappinessTask");
});
modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b =>
{
b.Property<string>("Id")
@ -284,6 +311,9 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.Property<string>("CityAndZipCode")
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("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<string>("Id")
.HasColumnType("text");
b.Property<string>("ChatToken")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<int>("Seq")
.HasColumnType("integer");
b.Property<int>("TotalUsage")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("LineMessagingAccounts");
});
modelBuilder.Entity("Church.Net.Entity.LogInfo", b =>
{
b.Property<string>("Id")
@ -343,6 +395,28 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations
b.ToTable("LogInfos");
});
modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.HasColumnType("text");
b.Property<bool>("IsGroup")
.HasColumnType("boolean");
b.Property<bool>("IsManager")
.HasColumnType("boolean");
b.Property<string>("Name")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("LineMessageClients");
});
modelBuilder.Entity("Church.Net.Entity.NewVisitor", b =>
{
b.Property<string>("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");

View File

@ -19,6 +19,11 @@ namespace Church.Net.Entity
public string Address { get; set; }
public virtual ICollection<CellGroupRoutineEventAttendee> Attendees { get; set; }
public virtual ICollection<CellGroupRoutineEventPrayer> Prayers { get; set; }
[ForeignKey("CellGroupInfo")]
public string PastoralDomainId { get; set; }
public PastoralDomain CellGroupInfo { get; set; }
}
public class CellGroupRoutineEventAttendee : ICombinedKeyEntity
{

View File

@ -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<HappinessBEST> BestList { get; set; }
public virtual ICollection<HappinessWeek> Weeks { get; set; }
public string CommunityAppId { get; set; }
[ForeignKey("LineMessagingAccount")]
public string LineAccountId { get; set; }
public virtual LineMessagingAccount LineMessagingAccount { get; set; }
}
}

View File

@ -25,5 +25,28 @@ namespace Church.Net.Entity
public int SEQ { get; set; }
[NotMapped]
public bool UpdateRestWeekDate { get; set; }
public virtual ICollection<HappinessTask> 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; }
}
}

View File

@ -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<bool> SendMessage(IMessengerClient target, string message);
Task<bool> 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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }

View File

@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
</ItemGroup>

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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<int> GetTotalUsage()
{
return Get<LineUsage>(QuotaApiPath).Result.TotalUsage;
}
public async Task<LineGroupProfile> GetGroupProfile(string groupId)
{
if (string.IsNullOrEmpty(groupId))
{
throw new ArgumentException($"{nameof(groupId)} is null or empty.");
}
return await Get<LineGroupProfile>(string.Format(GroupProfileApiPath, groupId));
}
}
}

View File

@ -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; }
}
}

View File

@ -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.");

BIN
WebAPI/App_Data/arial.ttf Normal file

Binary file not shown.

View File

@ -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<T> : ControllerBase where T : IEntity
{
protected readonly ICrudLogic<T> logic;
@ -74,6 +76,7 @@ namespace WebAPI.Controllers
}
}
[Authorize]
public class CombinedKeyApiControllerBase<T> : ControllerBase where T : ICombinedKeyEntity
{
protected readonly ICombinedKeyCrudLogic<T> logic;

View File

@ -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<IActionResult> 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;
}

View File

@ -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/<BestController>
[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,6 +76,8 @@ namespace WebAPI.Controllers
{
LineWebhookContent content = JsonConvert.DeserializeObject<LineWebhookContent>(jsonData.ToString());
//this.loggingService.Log("PostFromLine");
await lineAutoBotService.AutoReply(content);
}
catch (Exception ex)
@ -110,7 +112,8 @@ namespace WebAPI.Controllers
}
public class LineMessage{
public class LineMessage
{
public string To { get; set; }
public string Message { get; set; }
}

View File

@ -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<LineMessagingAccount>
{
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);
}
}
}
}
}

View File

@ -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<LogInfo>
{
public LogController(ICrudLogic<LogInfo> logic) : base(logic)
private readonly ILoggingService loggingService;
public LogController(
ICrudLogic<LogInfo> 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<IExceptionHandlerFeature>()!;
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<IExceptionHandlerFeature>()!;
this.loggingService.Error(exceptionHandlerFeature.Error, exceptionHandlerFeature.Path);
return Problem();
}
}
}

View File

@ -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/<PasswordLoginController>
public PasswordLoginController(
ChurchNetContext churchNetContext,
ICrudLogic<FamilyMember> crudLogic,
ICombinedKeyCrudLogic<PastoralDomainMembers> relationLogic,
ICrudLogic<PastoralDomain> domainLogic
ICrudLogic<PastoralDomain> domainLogic,
DatabaseOptions databaseOptions
)
{
this.churchNetContext = churchNetContext;
this.crudLogic = crudLogic;
this.relationLogic = relationLogic;
this.domainLogic = domainLogic;
churchNetContext = databaseOptions.GetDbContext();
}
[HttpPost]
[Route("auth/login")]

View File

@ -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; }

View File

@ -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;

View File

@ -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 . .

View File

@ -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<Show404Requirement>().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 { }
}

View File

@ -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<CellGroupRoutineEvent> eventCrudDAL;
private readonly ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL;
private readonly ICrudDAL<FamilyMember> memberCrudDAL;
public CellGroupLogic(
IServiceScopeFactory serviceScopeFactory,
ICrudDAL<CellGroupRoutineEvent> eventCrudDAL,
ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL,
ICrudDAL<FamilyMember> memberCrudDAL
)
{
this.serviceScopeFactory = serviceScopeFactory;
this.eventCrudDAL = eventCrudDAL;
this.attendeeCrudDAL = attendeeCrudDAL;
this.memberCrudDAL = memberCrudDAL;

View File

@ -13,8 +13,8 @@ namespace WebAPI.Logics.Core
{
public class LogicBase<T> : ICrudLogic<T> where T : class, Church.Net.Entity.Interface.IEntity, new()
{
private readonly LogicService logicService;
private readonly ICrudDAL<T> crudDAL;
protected readonly LogicService logicService;
protected readonly ICrudDAL<T> 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<T> GetAllById(IEnumerable<string> Ids)
{
return this.crudDAL.GetAllById(Ids);
}
//public IEnumerable<T> GetAllById(IEnumerable<string> Ids)
//{
// return this.crudDAL.GetAllById(Ids);
//}
public T GetById(string Id)
{

View File

@ -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<IdentityService>();
return service.UserId;
}
}
}
}
}

View File

@ -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);
}

View File

@ -13,10 +13,10 @@ namespace WebAPI.Logics.Interface
T GetById(string Id);
IEnumerable<T> GetAll(Func<T, bool> filter = null);
IEnumerable<T> GetAllById(IEnumerable<string> Ids);
//IEnumerable<T> GetAllById(IEnumerable<string> Ids);
int Create(T entity);
Task<int> CreateAsync(T entity);
string CreateReturnId(T entity);
//string CreateReturnId(T entity);
int CreateOrUpdate(T entity, out string id);
int Update(T entity);

View File

@ -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<LineMessagingAccount>, ICrudLogic<LineMessagingAccount>
{
private readonly ICrudDAL<HappinessGroup> happinessGroupDAL;
private readonly ICrudDAL<PastoralDomain> cellGroupDAL;
public LineMessagingAccountLogic(
LogicService logicService,
ICrudDAL<LineMessagingAccount> crudDAL,
ICrudDAL<HappinessGroup> happinessGroupDAL,
ICrudDAL<PastoralDomain> 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);
}
}
}
}

View File

@ -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<string> Commands => COMMANDS;
public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<string> 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<CellGroupRoutineEventAttendee>()
};
_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<string> ReplyMessage => null;
public IEnumerable<ILineMessage> LineMessage
{

View File

@ -231,7 +231,8 @@ namespace WebAPI.Services.AutoReplyCommands
{
Size = FlexObjectSize.sm,
Color = "#666666",
Flex = 5
Flex = 5,
Wrap = true
});
comments.Add(commentLineBox);
}

View File

@ -127,7 +127,7 @@ 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)
{

View File

@ -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; }
}
}
}

View File

@ -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);

View File

@ -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<bool> RunTask();
}
}

View File

@ -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<IAutoReplyCommand> autoReplyCommands;
private readonly ILoggingService loggingService;
private readonly ICrudLogic<LineMessageClient> clientLogic;
public LineAutoBotService(
IEnumerable<IAutoReplyCommand> autoReplyCommands,
ILoggingService loggingService
ILoggingService loggingService,
ICrudLogic<LineMessageClient> 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)
@ -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)
{
}
}
}
}

View File

@ -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<bool> 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);
}
}
}

View File

@ -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<IScheduledTask> scheduledTasks;
private ILoggingService loggingService;
private readonly IWebHostEnvironment env;
private static bool initialized = false;
public WorkerService(
IEnumerable<IScheduledTask> 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<string> 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";
}
}
}

View File

@ -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<GameRoomLogic>();
services.AddSingleton(_ => new DatabaseOptions { ConnectionString = "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" });
//services.AddSingleton<ChurchNetContext>(new ChurchNetContext());
services.AddDbContext<ChurchNetContext>(options =>
options.UseNpgsql(
@ -67,30 +71,37 @@ namespace WebAPI
"Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124"
));
services.AddTransient<LineAutoBotService>();
services.AddTransient<IAutoReplyCommand, ArChurchInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupDinner>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupPrayer>();
services.AddSingleton<LineAutoBotService>();
services.AddSingleton<IAutoReplyCommand, ArChurchInfo>();
services.AddSingleton<IAutoReplyCommand, ArArkCellGroupInfo>();
services.AddSingleton<IAutoReplyCommand, ArArkCellGroupDinner>();
services.AddSingleton<IAutoReplyCommand, ArArkCellGroupPrayer>();
services.AddSingleton<IScheduledTask, MorningPrayer>();
services.AddSingleton<VideoDownloadLogic>();
services.AddScoped<LogicService>();
services.AddScoped<CellGroupLogic>();
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<HappinessGroupLogic>();
services.AddTransient<ILoggingService, DbLoggingService>();
services.AddSingleton<LogicService>();
services.AddSingleton<CellGroupLogic>();
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<HappinessGroupLogic>();
services.AddSingleton<LineMessagingAccountLogic>();
services.AddSingleton<ILoggingService, DbLoggingService>();
services.AddScoped<IdentityService>();
services.AddHostedService<WorkerService>();
//services.AddMvc(o=>o.Filters.Add(typeof(HandleExceptionFilter)));
//services.AddMvc(o => o.Filters.Add(new HandleExceptionFilter(services.BuildServiceProvider().GetService<ILoggingService>())));
//services.BuildServiceProvider().GetService<ILoggingService>();
services.AddSingleton<IAuthorizationMiddlewareResultHandler, BasicAuthorizationMiddlewareResultHandler>();
}
// 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(
@ -141,44 +155,13 @@ namespace WebAPI
// 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<IExceptionHandlerPathFeature>();
// 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>("/WhoIsSpyHub");
//});
if (env.IsDevelopment())
{
databaseOptions.GetDbContext().Database.Migrate();
//new ChurchNetContext(databaseOptions.ConnectionString).Database.Migrate();
//dbContext.Database.EnsureCreated();
dbContext.Database.Migrate();
}
//dbContext.Database.Migrate();
}
}
}
}

View File

@ -17,6 +17,7 @@
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Controllers\PasswordLogin\" />
<Folder Include="Filters\" />
</ItemGroup>
<ItemGroup>
@ -38,8 +39,10 @@
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="QRCoder" Version="1.4.1" />
<PackageReference Include="QRCoder-ImageSharp" Version="0.9.0" />
<PackageReference Include="SharpGrabber.YouTube" Version="1.4.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
</ItemGroup>
<ItemGroup>