using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.Serialization; using System.Web; using System.Web.Http; using tyme.solar; namespace Model { // 為對應資料表MODEL宣告額外參數類別(Metadata) // [JsonIgnore] 避免WEBAPI自動抓關聯資料 [MetadataType(typeof(followerMetadata))] public partial class follower { private class followerMetadata { [JsonIgnore] public virtual ICollection followers1 { get; set; } [JsonIgnore] public virtual follower follower1 { get; set; } [JsonIgnore] public virtual ICollection activity_check { get; set; } [JsonIgnore] public virtual country country1 { get; set; } [JsonIgnore] public virtual ICollection members { get; set; } [JsonIgnore] public virtual ICollection pro_order_detail { get; set; } [JsonIgnore] public virtual ICollection pro_order_detail1 { get; set; } [JsonIgnore] public virtual ICollection pro_order { get; set; } [JsonIgnore] public virtual ICollection pro_order1 { get; set; } [JsonIgnore] public virtual ICollection followers_tablet { get; set; } [JsonIgnore] public virtual appellation appellation { get; set; } } public enum type : int { [Description("出家眾")] Monk = 1,// 4, [Description("個人")] Personal = 2, //1, [Description("法人")] Legal = 3, //2, [Description("往生菩薩")] Bodhisattva = 4, //3, [Description("蓮友")] Seeker = 10, } public static IEnumerable allFaollowers = new Model.ezEntities().followers.AsEnumerable(); //public static string identity_type_list() #region 農曆生日&生肖 public enum chinese { 鼠 = 1, 牛 = 2, 虎 = 3, 兔 = 4, 龍 = 5, 蛇 = 6, 馬 = 7, 羊 = 8, 猴 = 9, 雞 = 10, 狗 = 11, 豬 = 12 } public enum heavenlyStems { 甲 = 1, 乙, 丙, 丁, 戊, 己, 庚, 辛, 壬, 癸 } public enum earthlyBranches { 子 = 1, 丑, 寅, 卯, 辰, 巳, 午, 未, 申, 酉, 戌, 亥 } public static string chagenSign(DateTime? date) { //可改公用 //生肖 if (date == null) return null; DateTime d = date.Value; // 使用 tyme4net 方法 try { var solarDay = SolarDay.FromYmd(d.Year, d.Month, d.Day); var lunarDay = solarDay.GetLunarDay(); // 使用正確的 tyme4net API var lunarYear = tyme.lunar.LunarYear.FromYear(lunarDay.Year); return lunarYear.SixtyCycle.EarthBranch.GetZodiac().GetName(); } catch (Exception ex) { return $"生肖計算錯誤: {ex.Message}"; } } public static string sexagenary(DateTime? date) { try { if (date != null) { DateTime d = date ?? DateTime.Now; //依農曆年計算,故同一年的1月跟6月會得不同結果 //ChineseLunisolarCalendar chineseDate = new ChineseLunisolarCalendar(); //int y = chineseDate.GetYear(d);// 農曆年分 //int a = chineseDate.GetSexagenaryYear(d); // 獲取干支纪年值 //heavenlyStems tg = (heavenlyStems)chineseDate.GetCelestialStem(a); //earthlyBranches dz = (earthlyBranches)chineseDate.GetTerrestrialBranch(a); //return $"{tg}{dz}"; int year = d.Year; if (year > 3) { int tgIndex = (year - 4) % 10; int dzIndex = (year - 4) % 12; return $"{(heavenlyStems)(tgIndex + 1)}{(earthlyBranches)(dzIndex + 1)}"; } //throw new ArgumentOutOfRangeException("無效的年份!"); return null; } } catch { //return null; } return null; } public static string ChkNewFollower(Model.follower newFollower) { Model.ezEntities _db = new Model.ezEntities(); if (string.IsNullOrWhiteSpace(newFollower.u_name)) { return "姓名不應為空白"; } MyWeb.encrypt encrypt = new MyWeb.encrypt(); // 解密並只保留數字 string decryptedNewPhone = !string.IsNullOrWhiteSpace(newFollower.phone) ? new string(encrypt.DecryptAutoKey(newFollower.phone).Where(char.IsDigit).ToArray()) : ""; string decryptedNewCellphone = !string.IsNullOrWhiteSpace(newFollower.cellphone) ? new string(encrypt.DecryptAutoKey(newFollower.cellphone).Where(char.IsDigit).ToArray()) : ""; var existingFollowers = _db.followers.Where(f => f.u_name == newFollower.u_name).ToList(); if (!existingFollowers.Any()) { return ""; } foreach (var follower in existingFollowers) { string decryptedPhone = !string.IsNullOrWhiteSpace(follower.phone) ? new string(encrypt.DecryptAutoKey(follower.phone).Where(char.IsDigit).ToArray()) : ""; string decryptedCellphone = !string.IsNullOrWhiteSpace(follower.cellphone) ? new string(encrypt.DecryptAutoKey(follower.cellphone).Where(char.IsDigit).ToArray()) : ""; if ((!string.IsNullOrWhiteSpace(decryptedNewPhone) && decryptedNewPhone == decryptedPhone) || (!string.IsNullOrWhiteSpace(decryptedNewCellphone) && decryptedNewCellphone == decryptedCellphone)) { return "姓名重複 + 電話或手機重複"; } } return ""; } #endregion public static string generate_f_number(string sex = "男眾") { string selectedSex = sex; var datePart = DateTime.Now.ToString("yyyyMMdd"); // 使用重試機制確保不重號 int maxRetries = 5; for (int retry = 0; retry < maxRetries; retry++) { try { using (var _db = new Model.ezEntities()) using (var transaction = _db.Database.BeginTransaction()) { // 在交易中查詢最大序號 int nextSerial = GetNextSerialFromDatabase(_db, datePart, selectedSex); string f_number = GenerateFNumber(selectedSex, datePart, nextSerial); // 立即檢查是否重複(在交易中) if (!_db.followers.Any(f => f.f_number == f_number)) { transaction.Commit(); return f_number; } // 如果重複,回滾交易並重試 transaction.Rollback(); // 短暫延遲後重試 if (retry < maxRetries - 1) { System.Threading.Thread.Sleep(10 + retry * 5); // 10ms, 15ms, 20ms, 25ms } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"生成編號失敗 (重試 {retry + 1}): {ex.Message}"); if (retry == maxRetries - 1) { // 最後一次重試失敗,使用時間戳記確保唯一性 return GenerateFNumberWithTimestamp(selectedSex, datePart); } } } // 如果所有重試都失敗,使用時間戳記 return GenerateFNumberWithTimestamp(selectedSex, datePart); } private static int GetNextSerialFromDatabase(Model.ezEntities _db, string datePart, string sex) { var prefix = sex == "男眾" ? "M" : "F"; var searchPattern = prefix + datePart; var maxFNumber = _db.followers .Where(m => m.f_number.Length == 14 && m.f_number.StartsWith(searchPattern)) .OrderByDescending(m => m.f_number) .Select(m => m.f_number) .FirstOrDefault(); if (!string.IsNullOrEmpty(maxFNumber)) { var serialPart = maxFNumber.Substring(9, 5); return int.Parse(serialPart) + 1; } return 1; } private static string GenerateFNumber(string sex, string datePart, int serial) { string prefix = sex == "男眾" ? "M" : "F"; return prefix + datePart + serial.ToString("D5"); } private static string GenerateFNumberWithTimestamp(string sex, string datePart) { // 使用時間戳記確保唯一性(最後手段) string prefix = sex == "男眾" ? "M" : "F"; var timestamp = DateTime.Now.ToString("HHmmss"); return prefix + datePart + timestamp; } } }