Ver código fonte

Merge remote-tracking branch 'origin/dunt'

hieubt 2 semanas atrás
pai
commit
988f4234c0
32 arquivos alterados com 4489 adições e 1064 exclusões
  1. 5 0
      EsimLao/Common/Common.csproj
  2. 16 7
      EsimLao/Common/CommonLogic.cs
  3. 5 0
      EsimLao/Common/Constant/CommonConstant.cs
  4. 31 0
      EsimLao/Common/Http/ArticleDetailReq.cs
  5. 0 5
      EsimLao/Common/Http/ArticleRequest.cs
  6. 19 1
      EsimLao/Common/Http/AuthRequest.cs
  7. 8 0
      EsimLao/Common/Http/ContentRequest.cs
  8. 4 2
      EsimLao/Database/Database/Config.cs
  9. 6 0
      EsimLao/Database/Database/FaqCategory.cs
  10. 24 0
      EsimLao/Database/Database/ModelContext.cs
  11. 1678 0
      EsimLao/Database/database_bk12012026.sql
  12. 130 81
      EsimLao/Esim.Apis/Business/Article/ArticleBusinessImpl.cs
  13. 1 0
      EsimLao/Esim.Apis/Business/Article/IArticleBusiness.cs
  14. 80 70
      EsimLao/Esim.Apis/Business/Content/ContentBusinessImpl.cs
  15. 3 0
      EsimLao/Esim.Apis/Business/User/IUserBusiness.cs
  16. 556 41
      EsimLao/Esim.Apis/Business/User/UserBusinessImpl.cs
  17. 13 2
      EsimLao/Esim.Apis/Controllers/ArticleController.cs
  18. 22 6
      EsimLao/Esim.Apis/Controllers/ContentController.cs
  19. 41 2
      EsimLao/Esim.Apis/Controllers/UserController.cs
  20. 23 5
      EsimLao/Esim.Apis/Program.cs
  21. 20 7
      EsimLao/Esim.Apis/Singleton/ConfigManager.cs
  22. 14 1
      EsimLao/Esim.Apis/appsettings.json
  23. 30 28
      EsimLao/Esim.Apis/log4net.config
  24. 1 0
      EsimLao/Esim.SendMail/Esim.SendMail.csproj
  25. 176 0
      EsimLao/Esim.SendMail/ExpiredMessageCleanupWorker.cs
  26. 77 0
      EsimLao/Esim.SendMail/Logging/Log4NetProvider.cs
  27. 45 23
      EsimLao/Esim.SendMail/MessageQueueWorker.cs
  28. 9 1
      EsimLao/Esim.SendMail/Program.cs
  29. 8 4
      EsimLao/Esim.SendMail/appsettings.json
  30. 0 778
      EsimLao/docs/api_auth_otp.txt
  31. 1444 0
      EsimLao/docs/api_auth_otp_Esim.txt
  32. BIN
      EsimLao/lib/DotnetLib.dll

+ 5 - 0
EsimLao/Common/Common.csproj

@@ -26,4 +26,9 @@
 	<ItemGroup>
 		<ProjectReference Include="..\Database\Database.csproj" />
 	</ItemGroup>
+	<ItemGroup>
+	  <Reference Include="DotnetLib">
+	    <HintPath>..\lib\DotnetLib.dll</HintPath>
+	  </Reference>
+	</ItemGroup>
 </Project>

+ 16 - 7
EsimLao/Common/CommonLogic.cs

@@ -18,7 +18,7 @@ public class CommonLogic
 {
     private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CommonLogic));
 
-    public static String GenToken(IConfiguration configuration, String msisdn, String accountId)
+    public static String GenToken(IConfiguration configuration, String Email, String accountId)
     {
         var issuer = configuration["Jwt:Issuer"];
         var audience = configuration["Jwt:Audience"];
@@ -29,7 +29,7 @@ public class CommonLogic
                 new[]
                 {
                     new Claim("Id", Guid.NewGuid().ToString()),
-                    new Claim("Msisdn", msisdn),
+                    new Claim("Msisdn", Email),
                     new Claim("AccountId", accountId),
                     new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                 }
@@ -155,19 +155,28 @@ public class CommonLogic
 
     /// <summary>
     /// Get language from request header or body
-    /// Priority: header Accept-Language > body lang > default "lo"
+    /// Priority: header Lang > header Accept-Language > body lang > default "lo"
     /// </summary>
     /// <param name="httpRequest">HTTP request</param>
     /// <param name="bodyLang">Language from request body (optional)</param>
     /// <returns>Language code: "lo" or "en"</returns>
     public static string GetLanguage(HttpRequest httpRequest, string? bodyLang = null)
     {
-        // Check header first
-        var headerLang = httpRequest.Headers["Accept-Language"].FirstOrDefault();
-        if (!string.IsNullOrEmpty(headerLang))
+        // Check custom Lang header first (highest priority)
+        var langHeader = httpRequest.Headers["Lang"].FirstOrDefault();
+        if (!string.IsNullOrEmpty(langHeader))
+        {
+            var lang = langHeader.ToLower();
+            if (lang == "en" || lang == "lo")
+                return lang;
+        }
+
+        // Check Accept-Language header
+        var acceptLangHeader = httpRequest.Headers["Accept-Language"].FirstOrDefault();
+        if (!string.IsNullOrEmpty(acceptLangHeader))
         {
             // Accept-Language can be "en", "lo", "en-US,en;q=0.9", etc.
-            var lang = headerLang.Split(',')[0].Split('-')[0].ToLower();
+            var lang = acceptLangHeader.Split(',')[0].Split('-')[0].ToLower();
             if (lang == "en" || lang == "lo")
                 return lang;
         }

+ 5 - 0
EsimLao/Common/Constant/CommonConstant.cs

@@ -159,10 +159,14 @@ public static class ApiUrlConstant
     // Auth URLs
     public const String RequestOtpUrl = "/apis/auth/request-otp";
     public const String VerifyOtpUrl = "/apis/auth/verify-otp";
+    public const String ResendOtpUrl = "/apis/auth/resend-otp";
+    public const String GoogleLoginUrl = "/apis/auth/google-login";
+    public const String GoogleCallbackUrl = "/apis/auth/google-callback";
 
     // Article URLs
     public const String ArticleCategoryUrl = "/apis/article/category";
     public const String ArticleLoadUrl = "/apis/article/load";
+    public const String ArticleDetailUrl = "/apis/article/detail";
 
     // Content URLs
     public const String BannerLoadUrl = "/apis/content/banner";
@@ -226,6 +230,7 @@ public static class CommonErrorCode
     public const string OtpSendFailed = "-205";
     public const string OtpTooManyRequests = "-206";
     public const string OtpNotFound = "-207";
+    public const string OtpNotRequested = "-208"; // User hasn't requested OTP yet (for resend scenario)
 
     // ============================================
     // USER/CUSTOMER ERRORS (-300 to -399)

+ 31 - 0
EsimLao/Common/Http/ArticleDetailReq.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Common.Http
+{
+    /// <summary>
+    /// Request to get article detail by ID or slug
+    /// </summary>
+    public class ArticleDetailReq
+    {
+        /// <summary>
+        /// Language code for response: "lo" (Lao), "en" (English)
+        /// Default: "lo"
+        /// </summary>
+        public string? lang { get; set; } = "lo";
+
+        /// <summary>
+        /// Article ID (primary way to get detail)
+        /// </summary>
+        public int? id { get; set; }
+
+        /// <summary>
+        /// Article slug (alternative to ID for SEO-friendly URLs)
+        /// </summary>
+        public string? slug { get; set; }
+    }
+}

+ 0 - 5
EsimLao/Common/Http/ArticleRequest.cs

@@ -68,10 +68,5 @@ namespace Common.Http
         /// Filter by featured articles only
         /// </summary>
         public bool? isFeatured { get; set; }
-
-        /// <summary>
-        /// Article slug for getting single article detail
-        /// </summary>
-        public string? slug { get; set; }
     }
 }

+ 19 - 1
EsimLao/Common/Http/AuthRequest.cs

@@ -35,5 +35,23 @@ namespace Common.Http
         /// </summary>
         public string? lang { get; set; } = "lo";
     }
-}
 
+    public class GoogleCallbackReq
+    {
+        [Required(ErrorMessage = "Authorization code is required")]
+        public string code { get; set; }
+        
+        public string? redirectUri { get; set; } // Optional: if frontend handles redirect, it might need to pass this
+
+        public string? lang { get; set; } = "lo";
+    }
+
+    public class GoogleLoginReq
+    {
+        /// <summary>
+        /// Language code for response messages: "lo" (Lao), "en" (English)
+        /// Default: "lo"
+        /// </summary>
+        public string? lang { get; set; } = "lo";
+    }
+}

+ 8 - 0
EsimLao/Common/Http/ContentRequest.cs

@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 
 namespace Common.Http
 {
@@ -25,8 +26,13 @@ namespace Common.Http
     public class CustomerReviewCreateReq
     {
         public string? lang { get; set; } = "lo";
+        
+        [Required(ErrorMessage = "Customer name is required")]
         public string customerName { get; set; } = null!;
+        
+        [Required(ErrorMessage = "Review content is required")]
         public string reviewContent { get; set; } = null!;
+        
         public string? destination { get; set; }
         public int rating { get; set; }
     }
@@ -37,6 +43,8 @@ namespace Common.Http
         public string? lang { get; set; } = "lo";
         public int pageNumber { get; set; } = 0;
         public int pageSize { get; set; } = 10;
+        /// <summary>Parent category ID (null = get root categories)</summary>
+        public int? parentId { get; set; }
     }
 
     public class FaqLoadReq

+ 4 - 2
EsimLao/Database/Database/Config.cs

@@ -9,9 +9,11 @@ public partial class Config
 
     public string Name { get; set; } = null!;
 
-    public string ValueLocal { get; set; } = null!;
+    public string? ValueLocal { get; set; }  // Lao (lo)
 
-    public string ValueGlobal { get; set; } = null!;
+    public string? ValueGlobal { get; set; } // English (en)
+
+    public string? Value { get; set; }       // Vietnamese (vi)
 
     public string Type { get; set; } = null!;
 }

+ 6 - 0
EsimLao/Database/Database/FaqCategory.cs

@@ -15,6 +15,8 @@ public partial class FaqCategory
 
     public string? IconUrl { get; set; }
 
+    public int? ParentId { get; set; }
+
     public short? DisplayOrder { get; set; }
 
     public bool? Status { get; set; }
@@ -33,5 +35,9 @@ public partial class FaqCategory
 
     public string? DescriptionEn { get; set; }
 
+    public virtual FaqCategory? ParentCategory { get; set; }
+
+    public virtual ICollection<FaqCategory> ChildCategories { get; set; } = new List<FaqCategory>();
+
     public virtual ICollection<Faq> Faqs { get; set; } = new List<Faq>();
 }

+ 24 - 0
EsimLao/Database/Database/ModelContext.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 
 namespace Database.Database;
 
@@ -67,12 +68,23 @@ public partial class ModelContext : DbContext
 
     public virtual DbSet<WsUser> WsUsers { get; set; }
 
+    // Oracle doesn't have boolean type - configure global conversion from bool to NUMBER(1)
+    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
+    {
+        configurationBuilder.Properties<bool>()
+            .HaveConversion<BoolToZeroOneConverter<int>>();
+        
+        configurationBuilder.Properties<bool?>()
+            .HaveConversion<BoolToZeroOneConverter<int?>>();
+    }
+
     protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
         modelBuilder
             .HasDefaultSchema("LAOS_ESIM")
             .UseCollation("USING_NLS_COMP");
 
+
         modelBuilder.Entity<AdminUser>(entity =>
         {
             entity.HasKey(e => e.Id).HasName("ADMIN_USER_PK");
@@ -523,6 +535,10 @@ public partial class ModelContext : DbContext
                 .HasMaxLength(1000)
                 .IsUnicode(false)
                 .HasColumnName("VALUE_LOCAL");
+            entity.Property(e => e.Value)
+                .HasMaxLength(1000)
+                .IsUnicode(false)
+                .HasColumnName("VALUE");
         });
 
         modelBuilder.Entity<ContactForm>(entity =>
@@ -932,10 +948,18 @@ public partial class ModelContext : DbContext
             entity.Property(e => e.LastUpdate)
                 .HasColumnType("DATE")
                 .HasColumnName("LAST_UPDATE");
+            entity.Property(e => e.ParentId)
+                .HasPrecision(10)
+                .HasColumnName("PARENT_ID");
             entity.Property(e => e.Status)
                 .HasPrecision(1)
                 .HasDefaultValueSql("1")
                 .HasColumnName("STATUS");
+
+            entity.HasOne(d => d.ParentCategory)
+                .WithMany(p => p.ChildCategories)
+                .HasForeignKey(d => d.ParentId)
+                .HasConstraintName("FAQ_CATEGORY_PARENT_FK");
         });
 
         modelBuilder.Entity<MessageQueue>(entity =>

+ 1678 - 0
EsimLao/Database/database_bk12012026.sql

@@ -0,0 +1,1678 @@
+--------------------------------------------------------
+--  File created - Monday-January-12-2026   
+--------------------------------------------------------
+--------------------------------------------------------
+--  DDL for Table ARTICLE
+--------------------------------------------------------
+
+  CREATE TABLE "ARTICLE" 
+   (	"ID" NUMBER(10,0), 
+	"CATEGORY_ID" NUMBER(10,0), 
+	"TITLE" NVARCHAR2(500), 
+	"SLUG" VARCHAR2(500 BYTE), 
+	"SUMMARY" NVARCHAR2(2000), 
+	"CONTENT" CLOB, 
+	"THUMBNAIL_URL" VARCHAR2(1000 BYTE), 
+	"COVER_IMAGE_URL" VARCHAR2(1000 BYTE), 
+	"META_DESCRIPTION" NVARCHAR2(500), 
+	"META_KEYWORDS" NVARCHAR2(500), 
+	"AUTHOR_ID" NUMBER(10,0), 
+	"VIEW_COUNT" NUMBER(10,0) DEFAULT 0, 
+	"IS_FEATURED" NUMBER(1,0) DEFAULT 0, 
+	"IS_PINNED" NUMBER(1,0) DEFAULT 0, 
+	"STATUS" NUMBER(1,0) DEFAULT 0, 
+	"PUBLISHED_DATE" DATE, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'vi', 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"UPDATED_BY" NUMBER(10,0), 
+	"TITLE_LO" NVARCHAR2(500), 
+	"TITLE_EN" NVARCHAR2(500), 
+	"SUMMARY_LO" NVARCHAR2(2000), 
+	"SUMMARY_EN" NVARCHAR2(2000), 
+	"CONTENT_LO" CLOB, 
+	"CONTENT_EN" CLOB, 
+	"META_DESCRIPTION_LO" NVARCHAR2(500), 
+	"META_DESCRIPTION_EN" NVARCHAR2(500)
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("CONTENT") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_LO") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_EN") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "ARTICLE"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "ARTICLE"."CATEGORY_ID" IS 'ID danh muc bai viet';
+   COMMENT ON COLUMN "ARTICLE"."TITLE" IS 'Tieu de bai viet';
+   COMMENT ON COLUMN "ARTICLE"."SLUG" IS 'URL-friendly slug';
+   COMMENT ON COLUMN "ARTICLE"."SUMMARY" IS 'Tom tat noi dung';
+   COMMENT ON COLUMN "ARTICLE"."CONTENT" IS 'Noi dung HTML day du';
+   COMMENT ON COLUMN "ARTICLE"."THUMBNAIL_URL" IS 'Anh thu nho';
+   COMMENT ON COLUMN "ARTICLE"."COVER_IMAGE_URL" IS 'Anh bia bai viet';
+   COMMENT ON COLUMN "ARTICLE"."META_DESCRIPTION" IS 'Mo ta SEO';
+   COMMENT ON COLUMN "ARTICLE"."META_KEYWORDS" IS 'Tu khoa SEO';
+   COMMENT ON COLUMN "ARTICLE"."AUTHOR_ID" IS 'ID tac gia';
+   COMMENT ON COLUMN "ARTICLE"."VIEW_COUNT" IS 'So luot xem';
+   COMMENT ON COLUMN "ARTICLE"."IS_FEATURED" IS 'Bai viet noi bat: 0=Khong, 1=Co';
+   COMMENT ON COLUMN "ARTICLE"."IS_PINNED" IS 'Ghim len dau: 0=Khong, 1=Co';
+   COMMENT ON COLUMN "ARTICLE"."STATUS" IS 'Trang thai: 0=Nhap, 1=Xuat ban, 2=An';
+   COMMENT ON COLUMN "ARTICLE"."PUBLISHED_DATE" IS 'Ngay xuat ban';
+   COMMENT ON COLUMN "ARTICLE"."LANGUAGE" IS 'Ngon ngu: vi, en, lo';
+   COMMENT ON COLUMN "ARTICLE"."CREATED_BY" IS 'ID nguoi tao';
+   COMMENT ON COLUMN "ARTICLE"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "ARTICLE"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "ARTICLE"."UPDATED_BY" IS 'ID nguoi cap nhat';
+   COMMENT ON COLUMN "ARTICLE"."TITLE_LO" IS 'Tieu de bai viet tieng Lao';
+   COMMENT ON COLUMN "ARTICLE"."TITLE_EN" IS 'Tieu de bai viet tieng Anh';
+   COMMENT ON COLUMN "ARTICLE"."SUMMARY_LO" IS 'Tom tat tieng Lao';
+   COMMENT ON COLUMN "ARTICLE"."SUMMARY_EN" IS 'Tom tat tieng Anh';
+   COMMENT ON COLUMN "ARTICLE"."CONTENT_LO" IS 'Noi dung bai viet tieng Lao';
+   COMMENT ON COLUMN "ARTICLE"."CONTENT_EN" IS 'Noi dung bai viet tieng Anh';
+   COMMENT ON COLUMN "ARTICLE"."META_DESCRIPTION_LO" IS 'Mo ta SEO tieng Lao';
+   COMMENT ON COLUMN "ARTICLE"."META_DESCRIPTION_EN" IS 'Mo ta SEO tieng Anh';
+   COMMENT ON TABLE "ARTICLE"  IS 'Bang bai viet (Cam nang du lich, Huong dan)';
+--------------------------------------------------------
+--  DDL for Table ARTICLE_CATEGORY
+--------------------------------------------------------
+
+  CREATE TABLE "ARTICLE_CATEGORY" 
+   (	"ID" NUMBER(10,0), 
+	"CATEGORY_NAME" NVARCHAR2(200), 
+	"CATEGORY_SLUG" VARCHAR2(200 BYTE), 
+	"DESCRIPTION" NVARCHAR2(1000), 
+	"ICON_URL" VARCHAR2(500 BYTE), 
+	"PARENT_ID" NUMBER(10,0), 
+	"DISPLAY_ORDER" NUMBER(5,0) DEFAULT 1, 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"CATEGORY_NAME_LO" NVARCHAR2(200), 
+	"CATEGORY_NAME_EN" NVARCHAR2(200), 
+	"DESCRIPTION_LO" NVARCHAR2(1000), 
+	"DESCRIPTION_EN" NVARCHAR2(1000), 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."CATEGORY_NAME" IS 'Ten danh muc';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."CATEGORY_SLUG" IS 'URL slug cua danh muc';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."DESCRIPTION" IS 'Mo ta danh muc';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."ICON_URL" IS 'Duong dan icon';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."PARENT_ID" IS 'ID danh muc cha (null = goc)';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."DISPLAY_ORDER" IS 'Thu tu hien thi';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."CATEGORY_NAME_LO" IS 'Ten danh muc tieng Lao';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."CATEGORY_NAME_EN" IS 'Ten danh muc tieng Anh';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."DESCRIPTION_LO" IS 'Mo ta danh muc tieng Lao';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."DESCRIPTION_EN" IS 'Mo ta danh muc tieng Anh';
+   COMMENT ON COLUMN "ARTICLE_CATEGORY"."LANGUAGE" IS 'Ngon ngu mac dinh: lo, en';
+   COMMENT ON TABLE "ARTICLE_CATEGORY"  IS 'Bang danh muc bai viet (Cam nang, Huong dan)';
+--------------------------------------------------------
+--  DDL for Table BANNER
+--------------------------------------------------------
+
+  CREATE TABLE "BANNER" 
+   (	"ID" NUMBER(10,0), 
+	"TITLE" NVARCHAR2(500), 
+	"SUBTITLE" NVARCHAR2(1000), 
+	"IMAGE_URL" VARCHAR2(1000 BYTE), 
+	"IMAGE_MOBILE_URL" VARCHAR2(1000 BYTE), 
+	"LINK_URL" VARCHAR2(1000 BYTE), 
+	"LINK_TARGET" VARCHAR2(20 BYTE) DEFAULT '_self', 
+	"POSITION" VARCHAR2(50 BYTE) DEFAULT 'HOME', 
+	"DISPLAY_ORDER" NUMBER(5,0) DEFAULT 1, 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"START_DATE" DATE, 
+	"END_DATE" DATE, 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"TITLE_LO" NVARCHAR2(500), 
+	"TITLE_EN" NVARCHAR2(500), 
+	"SUBTITLE_LO" NVARCHAR2(1000), 
+	"SUBTITLE_EN" NVARCHAR2(1000), 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'  -- Ngôn ng? m?c ??nh
+
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "BANNER"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "BANNER"."TITLE" IS 'Tieu de banner';
+   COMMENT ON COLUMN "BANNER"."SUBTITLE" IS 'Mo ta ngan';
+   COMMENT ON COLUMN "BANNER"."IMAGE_URL" IS 'Duong dan anh banner (desktop)';
+   COMMENT ON COLUMN "BANNER"."IMAGE_MOBILE_URL" IS 'Duong dan anh banner (mobile)';
+   COMMENT ON COLUMN "BANNER"."LINK_URL" IS 'URL khi click vao banner';
+   COMMENT ON COLUMN "BANNER"."LINK_TARGET" IS 'Mo tab: _self hoac _blank';
+   COMMENT ON COLUMN "BANNER"."POSITION" IS 'Vi tri: HOME, PRODUCT, SUPPORT, etc.';
+   COMMENT ON COLUMN "BANNER"."DISPLAY_ORDER" IS 'Thu tu hien thi';
+   COMMENT ON COLUMN "BANNER"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "BANNER"."START_DATE" IS 'Ngay bat dau hien thi';
+   COMMENT ON COLUMN "BANNER"."END_DATE" IS 'Ngay ket thuc hien thi';
+   COMMENT ON COLUMN "BANNER"."CREATED_BY" IS 'ID nguoi tao';
+   COMMENT ON COLUMN "BANNER"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "BANNER"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "BANNER"."TITLE_LO" IS 'Tieu de banner tieng Lao';
+   COMMENT ON COLUMN "BANNER"."TITLE_EN" IS 'Tieu de banner tieng Anh';
+   COMMENT ON COLUMN "BANNER"."SUBTITLE_LO" IS 'Mo ta ngan tieng Lao';
+   COMMENT ON COLUMN "BANNER"."SUBTITLE_EN" IS 'Mo ta ngan tieng Anh';
+   COMMENT ON COLUMN "BANNER"."LANGUAGE" IS 'Ngon ngu mac dinh: lo, en';
+   COMMENT ON TABLE "BANNER"  IS 'Bang quan ly banner/slider trang web';
+--------------------------------------------------------
+--  DDL for Table CMS_CONTENT
+--------------------------------------------------------
+
+  CREATE TABLE "CMS_CONTENT" 
+   (	"ID" NUMBER(10,0), 
+	"PAGE_CODE" VARCHAR2(100 BYTE), 
+	"PAGE_TITLE" NVARCHAR2(500), 
+	"PAGE_SLUG" VARCHAR2(200 BYTE), 
+	"META_DESCRIPTION" NVARCHAR2(500), 
+	"META_KEYWORDS" NVARCHAR2(500), 
+	"CONTENT" CLOB, 
+	"PAGE_TYPE" VARCHAR2(50 BYTE) DEFAULT 'STATIC', 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'vi', 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"UPDATED_BY" NUMBER(10,0), 
+	"PAGE_TITLE_LO" NVARCHAR2(500), 
+	"PAGE_TITLE_EN" NVARCHAR2(500), 
+	"META_DESCRIPTION_LO" NVARCHAR2(500), 
+	"META_DESCRIPTION_EN" NVARCHAR2(500), 
+	"CONTENT_LO" CLOB, 
+	"CONTENT_EN" CLOB
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("CONTENT") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_LO") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_EN") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "CMS_CONTENT"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_CODE" IS 'Ma trang (VD: ABOUT_US, TERMS, PRIVACY)';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_TITLE" IS 'Tieu de trang';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_SLUG" IS 'URL-friendly slug';
+   COMMENT ON COLUMN "CMS_CONTENT"."META_DESCRIPTION" IS 'Mo ta SEO';
+   COMMENT ON COLUMN "CMS_CONTENT"."META_KEYWORDS" IS 'Tu khoa SEO';
+   COMMENT ON COLUMN "CMS_CONTENT"."CONTENT" IS 'Noi dung HTML';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_TYPE" IS 'Loai trang: STATIC, POLICY, GUIDE';
+   COMMENT ON COLUMN "CMS_CONTENT"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "CMS_CONTENT"."LANGUAGE" IS 'Ngon ngu: vi, en, lo';
+   COMMENT ON COLUMN "CMS_CONTENT"."CREATED_BY" IS 'ID nguoi tao';
+   COMMENT ON COLUMN "CMS_CONTENT"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "CMS_CONTENT"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "CMS_CONTENT"."UPDATED_BY" IS 'ID nguoi cap nhat';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_TITLE_LO" IS 'Tieu de trang tieng Lao';
+   COMMENT ON COLUMN "CMS_CONTENT"."PAGE_TITLE_EN" IS 'Tieu de trang tieng Anh';
+   COMMENT ON COLUMN "CMS_CONTENT"."META_DESCRIPTION_LO" IS 'Mo ta SEO tieng Lao';
+   COMMENT ON COLUMN "CMS_CONTENT"."META_DESCRIPTION_EN" IS 'Mo ta SEO tieng Anh';
+   COMMENT ON COLUMN "CMS_CONTENT"."CONTENT_LO" IS 'Noi dung trang tieng Lao';
+   COMMENT ON COLUMN "CMS_CONTENT"."CONTENT_EN" IS 'Noi dung trang tieng Anh';
+   COMMENT ON TABLE "CMS_CONTENT"  IS 'Bang noi dung cac trang tinh (Gioi thieu, Chinh sach...)';
+--------------------------------------------------------
+--  DDL for Table CONFIG
+--------------------------------------------------------
+
+  CREATE TABLE "CONFIG" 
+   (	"ID" NUMBER(38,0), 
+	"NAME" VARCHAR2(100 BYTE), 
+	"VALUE_LOCAL" VARCHAR2(1000 BYTE), 
+	"VALUE_GLOBAL" VARCHAR2(1000 BYTE), 
+	"TYPE" VARCHAR2(20 BYTE) DEFAULT 'WEB', 
+	"VALUE" VARCHAR2(1000 BYTE)
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Table CONTACT_FORM
+--------------------------------------------------------
+
+  CREATE TABLE "CONTACT_FORM" 
+   (	"ID" NUMBER(10,0), 
+	"FULL_NAME" NVARCHAR2(200), 
+	"EMAIL" VARCHAR2(200 BYTE), 
+	"PHONE_NUMBER" VARCHAR2(20 BYTE), 
+	"SUBJECT" NVARCHAR2(500), 
+	"MESSAGE" CLOB, 
+	"STATUS" NUMBER(2,0) DEFAULT 0, 
+	"ASSIGNED_TO" NUMBER(10,0), 
+	"ADMIN_NOTES" NVARCHAR2(2000), 
+	"REPLIED_AT" DATE, 
+	"IP_ADDRESS" VARCHAR2(50 BYTE), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE
+   ) SEGMENT CREATION DEFERRED 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+ LOB ("MESSAGE") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES ) ;
+
+   COMMENT ON COLUMN "CONTACT_FORM"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "CONTACT_FORM"."FULL_NAME" IS 'Ho ten khach hang';
+   COMMENT ON COLUMN "CONTACT_FORM"."EMAIL" IS 'Email lien he';
+   COMMENT ON COLUMN "CONTACT_FORM"."PHONE_NUMBER" IS 'So dien thoai';
+   COMMENT ON COLUMN "CONTACT_FORM"."SUBJECT" IS 'Chu de lien he';
+   COMMENT ON COLUMN "CONTACT_FORM"."MESSAGE" IS 'Noi dung tin nhan';
+   COMMENT ON COLUMN "CONTACT_FORM"."STATUS" IS 'Trang thai: 0=Moi, 1=Dang xu ly, 2=Da tra loi, 3=Dong';
+   COMMENT ON COLUMN "CONTACT_FORM"."ASSIGNED_TO" IS 'ID nhan vien xu ly';
+   COMMENT ON COLUMN "CONTACT_FORM"."ADMIN_NOTES" IS 'Ghi chu cua admin';
+   COMMENT ON COLUMN "CONTACT_FORM"."REPLIED_AT" IS 'Thoi gian tra loi';
+   COMMENT ON COLUMN "CONTACT_FORM"."IP_ADDRESS" IS 'Dia chi IP gui form';
+   COMMENT ON COLUMN "CONTACT_FORM"."CREATED_DATE" IS 'Ngay gui';
+   COMMENT ON TABLE "CONTACT_FORM"  IS 'Bang luu form lien he tu khach hang';
+--------------------------------------------------------
+--  DDL for Table CUSTOMER_INFO
+--------------------------------------------------------
+
+  CREATE TABLE "CUSTOMER_INFO" 
+   (	"ID" NUMBER(10,0), 
+	"SUR_NAME" VARCHAR2(500 BYTE), 
+	"LAST_NAME" VARCHAR2(500 BYTE), 
+	"EMAIL" VARCHAR2(200 BYTE), 
+	"PHONE_NUMBER" VARCHAR2(20 BYTE), 
+	"CREATED_DATE" DATE, 
+	"LAST_UPDATE" DATE, 
+	"GOOGLE_ID" VARCHAR2(200 BYTE), 
+	"AVATAR_URL" VARCHAR2(1000 BYTE), 
+	"PASSWORD_HASH" VARCHAR2(500 BYTE), 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"IS_VERIFIED" NUMBER(1,0) DEFAULT 0, 
+	"LAST_LOGIN_DATE" DATE
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "CUSTOMER_INFO"."ID" IS 'ID tu dong tang cua khach hang';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."SUR_NAME" IS 'Ho cua khach hang';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."LAST_NAME" IS 'Ten cua khach hang';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."EMAIL" IS 'Dia chi email (dung de dang nhap)';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."PHONE_NUMBER" IS 'So dien thoai lien he';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."CREATED_DATE" IS 'Ngay tao tai khoan';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."LAST_UPDATE" IS 'Ngay cap nhat gan nhat';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."GOOGLE_ID" IS 'ID tu Google OAuth khi dang nhap bang Gmail';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."AVATAR_URL" IS 'Duong dan anh dai dien tu Google';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."PASSWORD_HASH" IS 'Mat khau ma hoa (neu dang nhap bang password)';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."STATUS" IS 'Trang thai tai khoan: 0=Khoa, 1=Hoat dong';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."IS_VERIFIED" IS 'Da xac thuc email: 0=Chua, 1=Da xac thuc';
+   COMMENT ON COLUMN "CUSTOMER_INFO"."LAST_LOGIN_DATE" IS 'Thoi gian dang nhap gan nhat';
+   COMMENT ON TABLE "CUSTOMER_INFO"  IS 'Bang thong tin khach hang va tai khoan dang nhap';
+--------------------------------------------------------
+--  DDL for Table CUSTOMER_REVIEW
+--------------------------------------------------------
+
+  CREATE TABLE "CUSTOMER_REVIEW" 
+   (	"ID" NUMBER(10,0), 
+	"CUSTOMER_NAME" NVARCHAR2(200), 
+	"AVATAR_URL" VARCHAR2(500 BYTE), 
+	"RATING" NUMBER(1,0) DEFAULT 5, 
+	"REVIEW_CONTENT" NVARCHAR2(2000), 
+	"DESTINATION" NVARCHAR2(200), 
+	"DISPLAY_ORDER" NUMBER(5,0) DEFAULT 1, 
+	"IS_FEATURED" NUMBER(1,0) DEFAULT 0, 
+	"STATUS" NUMBER(1,0) DEFAULT 0, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"APPROVED_DATE" DATE, 
+	"APPROVED_BY" NUMBER(10,0), 
+	"REVIEW_CONTENT_LO" NVARCHAR2(2000), 
+	"REVIEW_CONTENT_EN" NVARCHAR2(2000), 
+	"DESTINATION_LO" NVARCHAR2(200), 
+	"DESTINATION_EN" NVARCHAR2(200), 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."CUSTOMER_NAME" IS 'Ten khach hang';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."AVATAR_URL" IS 'Anh dai dien khach hang';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."RATING" IS 'Diem danh gia 1-5 sao';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."REVIEW_CONTENT" IS 'Noi dung danh gia';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."DESTINATION" IS 'Diem den du lich (VD: Thai Lan, Han Quoc)';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."DISPLAY_ORDER" IS 'Thu tu hien thi';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."IS_FEATURED" IS 'Hien thi trang chu: 0=Khong, 1=Co';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."STATUS" IS 'Trang thai: 0=Cho duyet, 1=Da duyet, 2=Tu choi';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."APPROVED_DATE" IS 'Ngay duyet';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."APPROVED_BY" IS 'ID nguoi duyet';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."REVIEW_CONTENT_LO" IS 'Noi dung danh gia tieng Lao';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."REVIEW_CONTENT_EN" IS 'Noi dung danh gia tieng Anh';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."DESTINATION_LO" IS 'Diem den tieng Lao';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."DESTINATION_EN" IS 'Diem den tieng Anh';
+   COMMENT ON COLUMN "CUSTOMER_REVIEW"."LANGUAGE" IS 'Ngon ngu mac dinh: lo, en';
+   COMMENT ON TABLE "CUSTOMER_REVIEW"  IS 'Bang danh gia cua khach hang (Testimonials)';
+--------------------------------------------------------
+--  DDL for Table DEVICE_ESIM_COMPATIBILITY
+--------------------------------------------------------
+
+  CREATE TABLE "DEVICE_ESIM_COMPATIBILITY" 
+   (	"ID" NUMBER, 
+	"BRAND" VARCHAR2(100 BYTE), 
+	"MODEL_NAME" VARCHAR2(200 BYTE), 
+	"MODEL_NAME_EN" VARCHAR2(200 BYTE), 
+	"MODEL_NAME_LO" VARCHAR2(200 BYTE), 
+	"SUPPORTS_ESIM" NUMBER(1,0) DEFAULT 1, 
+	"CATEGORY" VARCHAR2(50 BYTE) DEFAULT 'Phone', 
+	"NOTES" VARCHAR2(1000 BYTE), 
+	"NOTES_EN" VARCHAR2(1000 BYTE), 
+	"NOTES_LO" VARCHAR2(1000 BYTE), 
+	"IS_POPULAR" NUMBER(1,0) DEFAULT 0, 
+	"DISPLAY_ORDER" NUMBER DEFAULT 999, 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"UPDATED_DATE" DATE
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "DEVICE_ESIM_COMPATIBILITY"."BRAND" IS 'Hãng s?n xu?t';
+   COMMENT ON COLUMN "DEVICE_ESIM_COMPATIBILITY"."MODEL_NAME" IS 'Tên model thi?t b?';
+   COMMENT ON COLUMN "DEVICE_ESIM_COMPATIBILITY"."SUPPORTS_ESIM" IS '1=H? tr? eSIM, 0=Không h? tr?';
+   COMMENT ON COLUMN "DEVICE_ESIM_COMPATIBILITY"."IS_POPULAR" IS '1=Thi?t b? ph? bi?n (hi?n th? trong quick lookup)';
+   COMMENT ON TABLE "DEVICE_ESIM_COMPATIBILITY"  IS 'Danh sách thi?t b? h? tr? eSIM';
+--------------------------------------------------------
+--  DDL for Table FAQ
+--------------------------------------------------------
+
+  CREATE TABLE "FAQ" 
+   (	"ID" NUMBER(10,0), 
+	"CATEGORY_ID" NUMBER(10,0), 
+	"QUESTION" NVARCHAR2(1000), 
+	"ANSWER" CLOB, 
+	"DISPLAY_ORDER" NUMBER(5,0) DEFAULT 1, 
+	"VIEW_COUNT" NUMBER(10,0) DEFAULT 0, 
+	"IS_FEATURED" NUMBER(1,0) DEFAULT 0, 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'vi', 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"QUESTION_LO" NVARCHAR2(1000), 
+	"QUESTION_EN" NVARCHAR2(1000), 
+	"ANSWER_LO" CLOB, 
+	"ANSWER_EN" CLOB
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("ANSWER") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("ANSWER_LO") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("ANSWER_EN") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "FAQ"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "FAQ"."CATEGORY_ID" IS 'ID danh muc FAQ';
+   COMMENT ON COLUMN "FAQ"."QUESTION" IS 'Cau hoi';
+   COMMENT ON COLUMN "FAQ"."ANSWER" IS 'Cau tra loi (HTML)';
+   COMMENT ON COLUMN "FAQ"."DISPLAY_ORDER" IS 'Thu tu hien thi';
+   COMMENT ON COLUMN "FAQ"."VIEW_COUNT" IS 'So luot xem';
+   COMMENT ON COLUMN "FAQ"."IS_FEATURED" IS 'Noi bat trang chu: 0=Khong, 1=Co';
+   COMMENT ON COLUMN "FAQ"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "FAQ"."LANGUAGE" IS 'Ngon ngu: vi, en, lo';
+   COMMENT ON COLUMN "FAQ"."CREATED_BY" IS 'ID nguoi tao';
+   COMMENT ON COLUMN "FAQ"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "FAQ"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "FAQ"."QUESTION_LO" IS 'Cau hoi tieng Lao';
+   COMMENT ON COLUMN "FAQ"."QUESTION_EN" IS 'Cau hoi tieng Anh';
+   COMMENT ON COLUMN "FAQ"."ANSWER_LO" IS 'Cau tra loi tieng Lao';
+   COMMENT ON COLUMN "FAQ"."ANSWER_EN" IS 'Cau tra loi tieng Anh';
+   COMMENT ON TABLE "FAQ"  IS 'Bang cau hoi thuong gap';
+--------------------------------------------------------
+--  DDL for Table FAQ_CATEGORY
+--------------------------------------------------------
+
+  CREATE TABLE "FAQ_CATEGORY" 
+   (	"ID" NUMBER(10,0), 
+	"CATEGORY_NAME" NVARCHAR2(200), 
+	"CATEGORY_SLUG" VARCHAR2(200 BYTE), 
+	"DESCRIPTION" NVARCHAR2(1000), 
+	"ICON_URL" VARCHAR2(500 BYTE), 
+	"DISPLAY_ORDER" NUMBER(5,0) DEFAULT 1, 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'vi', 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"CATEGORY_NAME_LO" NVARCHAR2(200), 
+	"CATEGORY_NAME_EN" NVARCHAR2(200), 
+	"DESCRIPTION_LO" NVARCHAR2(1000), 
+	"DESCRIPTION_EN" NVARCHAR2(1000), 
+	"PARENT_ID" NUMBER(10,0)
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "FAQ_CATEGORY"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."CATEGORY_NAME" IS 'Ten danh muc (VD: Gioi thieu co ban, Cai dat  hoat)';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."CATEGORY_SLUG" IS 'URL slug cua danh muc';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."DESCRIPTION" IS 'Mo ta danh muc';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."ICON_URL" IS 'Duong dan icon danh muc';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."DISPLAY_ORDER" IS 'Thu tu hien thi';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."LANGUAGE" IS 'Ngon ngu: vi, en, lo';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."CATEGORY_NAME_LO" IS 'Ten danh muc tieng Lao';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."CATEGORY_NAME_EN" IS 'Ten danh muc tieng Anh';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."DESCRIPTION_LO" IS 'Mo ta danh muc tieng Lao';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."DESCRIPTION_EN" IS 'Mo ta danh muc tieng Anh';
+   COMMENT ON COLUMN "FAQ_CATEGORY"."PARENT_ID" IS 'ID danh muc cha (null = danh muc goc)';
+   COMMENT ON TABLE "FAQ_CATEGORY"  IS 'Bang danh muc FAQ (Gioi thieu, Cai dat, Su dung, Su co)';
+--------------------------------------------------------
+--  DDL for Table MESSAGE_QUEUE
+--------------------------------------------------------
+
+  CREATE TABLE "MESSAGE_QUEUE" 
+   (	"ID" NUMBER(10,0), 
+	"MESSAGE_TYPE" NUMBER(2,0) DEFAULT 1, 
+	"RECIPIENT" VARCHAR2(200 BYTE), 
+	"SUBJECT" NVARCHAR2(500), 
+	"CONTENT" CLOB, 
+	"TEMPLATE_CODE" VARCHAR2(50 BYTE), 
+	"TEMPLATE_DATA" CLOB, 
+	"PRIORITY" NUMBER(1,0) DEFAULT 5, 
+	"STATUS" NUMBER(2,0) DEFAULT 0, 
+	"SCHEDULED_AT" DATE, 
+	"PROCESSED_AT" DATE, 
+	"RETRY_COUNT" NUMBER(2,0) DEFAULT 0, 
+	"MAX_RETRY" NUMBER(2,0) DEFAULT 3, 
+	"ERROR_MESSAGE" VARCHAR2(2000 BYTE), 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("CONTENT") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("TEMPLATE_DATA") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."MESSAGE_TYPE" IS 'Loai tin nhan: 1=Email, 2=SMS, 3=Push Notification';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."RECIPIENT" IS 'Dia chi nhan (email/so dien thoai)';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."SUBJECT" IS 'Tieu de tin nhan/email';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."CONTENT" IS 'Noi dung tin nhan';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."TEMPLATE_CODE" IS 'Ma mau tin nhan';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."TEMPLATE_DATA" IS 'Du lieu thay the vao mau (JSON)';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."PRIORITY" IS 'Do uu tien: 1=Cao nhat, 10=Thap nhat';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."STATUS" IS 'Trang thai: 0=Cho xu ly, 1=Dang xu ly, 2=Thanh cong, 3=That bai';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."SCHEDULED_AT" IS 'Thoi gian dat lich gui';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."PROCESSED_AT" IS 'Thoi gian da xu ly';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."RETRY_COUNT" IS 'So lan thu lai';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."MAX_RETRY" IS 'So lan thu lai toi da';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."ERROR_MESSAGE" IS 'Thong bao loi khi gui that bai';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."CREATED_BY" IS 'ID nguoi tao';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "MESSAGE_QUEUE"."LANGUAGE" IS 'Ngon ngu tin nhan: lo (Lao), en (English)';
+   COMMENT ON TABLE "MESSAGE_QUEUE"  IS 'Bang luu tin nhan cho xu ly gui (email/SMS)';
+--------------------------------------------------------
+--  DDL for Table MESSAGE_QUEUE_HIS
+--------------------------------------------------------
+
+  CREATE TABLE "MESSAGE_QUEUE_HIS" 
+   (	"ID" NUMBER(10,0), 
+	"MESSAGE_TYPE" NUMBER(1,0) DEFAULT 1, 
+	"RECIPIENT" VARCHAR2(500 BYTE), 
+	"SUBJECT" NVARCHAR2(500), 
+	"CONTENT" NCLOB, 
+	"TEMPLATE_CODE" VARCHAR2(100 BYTE), 
+	"TEMPLATE_DATA" CLOB, 
+	"PRIORITY" NUMBER(1,0) DEFAULT 0, 
+	"STATUS" NUMBER(1,0) DEFAULT 0, 
+	"SCHEDULED_AT" TIMESTAMP (6), 
+	"PROCESSED_AT" TIMESTAMP (6), 
+	"RETRY_COUNT" NUMBER(3,0) DEFAULT 0, 
+	"MAX_RETRY" NUMBER(3,0) DEFAULT 3, 
+	"ERROR_MESSAGE" VARCHAR2(2000 BYTE), 
+	"CREATED_BY" NUMBER(10,0), 
+	"CREATED_DATE" TIMESTAMP (6) DEFAULT SYSTIMESTAMP, 
+	"MOVED_DATE" TIMESTAMP (6) DEFAULT SYSTIMESTAMP, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("CONTENT") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("TEMPLATE_DATA") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."ID" IS 'Original ID from MESSAGE_QUEUE';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."MESSAGE_TYPE" IS 'Message type: 1=Email, 2=SMS, 3=Push';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."RECIPIENT" IS 'Recipient address (email/phone)';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."SUBJECT" IS 'Email subject';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."CONTENT" IS 'Message content';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."TEMPLATE_CODE" IS 'Template code reference';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."TEMPLATE_DATA" IS 'Template parameters (JSON)';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."PRIORITY" IS 'Priority: 1=High, 0=Normal';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."STATUS" IS 'Final status: 2=Success, 3=Failed';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."SCHEDULED_AT" IS 'Scheduled send time';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."PROCESSED_AT" IS 'Actual processing time';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."RETRY_COUNT" IS 'Number of retries attempted';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."MAX_RETRY" IS 'Maximum retries allowed';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."ERROR_MESSAGE" IS 'Error message if failed';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."CREATED_BY" IS 'User who created the message';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."CREATED_DATE" IS 'Original creation date';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."MOVED_DATE" IS 'Date moved to history';
+   COMMENT ON COLUMN "MESSAGE_QUEUE_HIS"."LANGUAGE" IS 'Ngon ngu tin nhan: lo (Lao), en (English)';
+   COMMENT ON TABLE "MESSAGE_QUEUE_HIS"  IS 'History table for processed messages (success/failed)';
+--------------------------------------------------------
+--  DDL for Table MESSAGE_TEMPLATE
+--------------------------------------------------------
+
+  CREATE TABLE "MESSAGE_TEMPLATE" 
+   (	"ID" NUMBER(10,0), 
+	"TEMPLATE_CODE" VARCHAR2(50 BYTE), 
+	"TEMPLATE_NAME" NVARCHAR2(200), 
+	"MESSAGE_TYPE" NUMBER(2,0) DEFAULT 1, 
+	"SUBJECT" NVARCHAR2(500), 
+	"CONTENT" CLOB, 
+	"VARIABLES" VARCHAR2(1000 BYTE), 
+	"STATUS" NUMBER(1,0) DEFAULT 1, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_UPDATE" DATE, 
+	"TEMPLATE_NAME_LO" NVARCHAR2(200), 
+	"TEMPLATE_NAME_EN" NVARCHAR2(200), 
+	"SUBJECT_LO" NVARCHAR2(500), 
+	"SUBJECT_EN" NVARCHAR2(500), 
+	"CONTENT_LO" CLOB, 
+	"CONTENT_EN" CLOB, 
+	"LANGUAGE" VARCHAR2(10 BYTE) DEFAULT 'lo'  -- Ngôn ng? m?c ??nh
+
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
+ LOB ("CONTENT") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_LO") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) 
+ LOB ("CONTENT_EN") STORE AS SECUREFILE (ENABLE STORAGE IN ROW CHUNK 8192
+  NOCACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES 
+  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;
+
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."TEMPLATE_CODE" IS 'Ma mau tin nhan (unique)';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."TEMPLATE_NAME" IS 'Ten mau tin nhan';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."MESSAGE_TYPE" IS 'Loai: 1=Email, 2=SMS';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."SUBJECT" IS 'Tieu de email';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."CONTENT" IS 'Noi dung mau';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."VARIABLES" IS 'Danh sach bien (VD: {{name}},{{email}})';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."STATUS" IS 'Trang thai: 0=An, 1=Hien';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."CREATED_DATE" IS 'Ngay tao';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."LAST_UPDATE" IS 'Ngay cap nhat';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."TEMPLATE_NAME_LO" IS 'Ten mau email tieng Lao';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."TEMPLATE_NAME_EN" IS 'Ten mau email tieng Anh';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."SUBJECT_LO" IS 'Tieu de email tieng Lao';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."SUBJECT_EN" IS 'Tieu de email tieng Anh';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."CONTENT_LO" IS 'Noi dung email tieng Lao';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."CONTENT_EN" IS 'Noi dung email tieng Anh';
+   COMMENT ON COLUMN "MESSAGE_TEMPLATE"."LANGUAGE" IS 'Ngon ngu mac dinh: lo, en';
+   COMMENT ON TABLE "MESSAGE_TEMPLATE"  IS 'Bang mau tin nhan email/SMS';
+--------------------------------------------------------
+--  DDL for Table OTP_VERIFICATION
+--------------------------------------------------------
+
+  CREATE TABLE "OTP_VERIFICATION" 
+   (	"ID" NUMBER(10,0), 
+	"CUSTOMER_ID" NUMBER(10,0), 
+	"USER_EMAIL" VARCHAR2(200 BYTE), 
+	"OTP_CODE" VARCHAR2(10 BYTE), 
+	"OTP_TYPE" NUMBER(2,0) DEFAULT 1, 
+	"EXPIRED_AT" DATE, 
+	"IS_USED" NUMBER(1,0) DEFAULT 0, 
+	"ATTEMPT_COUNT" NUMBER(2,0) DEFAULT 0, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "OTP_VERIFICATION"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."CUSTOMER_ID" IS 'ID khach hang (CUSTOMER_INFO.ID)';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."USER_EMAIL" IS 'Email can xac thuc';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."OTP_CODE" IS 'Ma OTP 6 so';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."OTP_TYPE" IS 'Loai OTP: 1=Dang nhap, 2=Dat lai mat khau, 3=Xac thuc email';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."EXPIRED_AT" IS 'Thoi gian het han OTP';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."IS_USED" IS 'Da su dung: 0=Chua, 1=Da dung';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."ATTEMPT_COUNT" IS 'So lan thu sai';
+   COMMENT ON COLUMN "OTP_VERIFICATION"."CREATED_DATE" IS 'Ngay tao OTP';
+   COMMENT ON TABLE "OTP_VERIFICATION"  IS 'Bang luu ma OTP xac thuc dang nhap';
+--------------------------------------------------------
+--  DDL for Table USER_TOKEN
+--------------------------------------------------------
+
+  CREATE TABLE "USER_TOKEN" 
+   (	"ID" NUMBER(10,0), 
+	"CUSTOMER_ID" NUMBER(10,0), 
+	"ACCESS_TOKEN" VARCHAR2(500 BYTE), 
+	"REFRESH_TOKEN" VARCHAR2(500 BYTE), 
+	"TOKEN_TYPE" VARCHAR2(50 BYTE) DEFAULT 'Bearer', 
+	"DEVICE_INFO" VARCHAR2(500 BYTE), 
+	"IP_ADDRESS" VARCHAR2(50 BYTE), 
+	"EXPIRED_AT" DATE, 
+	"REFRESH_EXPIRED_AT" DATE, 
+	"IS_REVOKED" NUMBER(1,0) DEFAULT 0, 
+	"CREATED_DATE" DATE DEFAULT SYSDATE, 
+	"LAST_USED" DATE
+   ) SEGMENT CREATION IMMEDIATE 
+  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
+ NOCOMPRESS LOGGING
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+
+   COMMENT ON COLUMN "USER_TOKEN"."ID" IS 'ID tu dong tang';
+   COMMENT ON COLUMN "USER_TOKEN"."CUSTOMER_ID" IS 'ID khach hang (CUSTOMER_INFO.ID)';
+   COMMENT ON COLUMN "USER_TOKEN"."ACCESS_TOKEN" IS 'Access token JWT';
+   COMMENT ON COLUMN "USER_TOKEN"."REFRESH_TOKEN" IS 'Refresh token de lam moi access token';
+   COMMENT ON COLUMN "USER_TOKEN"."TOKEN_TYPE" IS 'Loai token (Bearer)';
+   COMMENT ON COLUMN "USER_TOKEN"."DEVICE_INFO" IS 'Thong tin thiet bi dang nhap';
+   COMMENT ON COLUMN "USER_TOKEN"."IP_ADDRESS" IS 'Dia chi IP khi dang nhap';
+   COMMENT ON COLUMN "USER_TOKEN"."EXPIRED_AT" IS 'Thoi gian het han access token';
+   COMMENT ON COLUMN "USER_TOKEN"."REFRESH_EXPIRED_AT" IS 'Thoi gian het han refresh token';
+   COMMENT ON COLUMN "USER_TOKEN"."IS_REVOKED" IS 'Token bi thu hoi: 0=Khong, 1=Da thu hoi';
+   COMMENT ON COLUMN "USER_TOKEN"."CREATED_DATE" IS 'Ngay tao token';
+   COMMENT ON COLUMN "USER_TOKEN"."LAST_USED" IS 'Thoi gian su dung gan nhat';
+   COMMENT ON TABLE "USER_TOKEN"  IS 'Bang quan ly token xac thuc API';
+REM INSERTING into ARTICLE
+SET DEFINE OFF;
+Insert into ARTICLE (ID,CATEGORY_ID,TITLE,SLUG,SUMMARY,THUMBNAIL_URL,COVER_IMAGE_URL,META_DESCRIPTION,META_KEYWORDS,AUTHOR_ID,VIEW_COUNT,IS_FEATURED,IS_PINNED,STATUS,PUBLISHED_DATE,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,TITLE_LO,TITLE_EN,SUMMARY_LO,SUMMARY_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (3,3,'? KHUY?N MÃI HOT: Gi?m 30% eSIM Châu Âu','khuyen-mai-giam-30-esim-chau-au','Ch??ng trình khuy?n mãi l?n nh?t n?m! Gi?m ngay 30% t?t c? gói eSIM Châu Âu. Áp d?ng t? 01/01 - 31/01/2026.','https://images.pexels.com/photos/2035891/pexels-photo-2035891.jpeg','https://images.pexels.com/photos/2035891/pexels-photo-2035891.jpeg','Khuy?n mãi l?n! Gi?m 30% eSIM Châu Âu. Áp d?ng ??n 31/01/2026.',null,null,545,1,1,1,to_date('04-JAN-26','DD-MON-RR'),'vi',null,to_date('04-JAN-26','DD-MON-RR'),null,null,'? ????????: ???? 30% eSIM ??????','? HOT DEAL: 30% OFF Europe eSIM',null,'Biggest promotion of the year! Get 30% OFF all Europe eSIM packages. Valid from 01/01 - 31/01/2026.',null,null);
+Insert into ARTICLE (ID,CATEGORY_ID,TITLE,SLUG,SUMMARY,THUMBNAIL_URL,COVER_IMAGE_URL,META_DESCRIPTION,META_KEYWORDS,AUTHOR_ID,VIEW_COUNT,IS_FEATURED,IS_PINNED,STATUS,PUBLISHED_DATE,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,TITLE_LO,TITLE_EN,SUMMARY_LO,SUMMARY_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (1,null,'H??ng d?n cài ??t eSIM trên iPhone chi ti?t nh?t 2024','huong-dan-cai-dat-esim-tren-iphone','H??ng d?n t?ng b??c cài ??t eSIM trên iPhone m?t cách chi ti?t và d? hi?u nh?t. Ch? m?t 2 phút là b?n ?ã có th? s? d?ng eSIM.','https://images.pexels.com/photos/30091776/pexels-photo-30091776.jpeg','https://images.pexels.com/photos/30091776/pexels-photo-30091776.jpeg','H??ng d?n chi ti?t cách cài ??t eSIM trên iPhone. Ch? 2 phút là xong!','esim, iphone, cài ??t esim, h??ng d?n esim, esim iphone',null,363,1,1,1,to_date('31-DEC-25','DD-MON-RR'),'vi',null,to_date('31-DEC-25','DD-MON-RR'),null,null,'??????????????? eSIM ?? iPhone 2024','Complete Guide to Install eSIM on iPhone 2024','???????????????????? eSIM ?? iPhone. ??? 2 ???? ???????????? eSIM ???.','Step-by-step guide to install eSIM on iPhone in the most detailed and easy way. Only 2 minutes and you can use eSIM.','???????????????????????? eSIM ?? iPhone','Detailed guide on how to install eSIM on iPhone. Done in just 2 minutes!');
+Insert into ARTICLE (ID,CATEGORY_ID,TITLE,SLUG,SUMMARY,THUMBNAIL_URL,COVER_IMAGE_URL,META_DESCRIPTION,META_KEYWORDS,AUTHOR_ID,VIEW_COUNT,IS_FEATURED,IS_PINNED,STATUS,PUBLISHED_DATE,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,TITLE_LO,TITLE_EN,SUMMARY_LO,SUMMARY_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (2,2,'Top 5 ?i?m ??n du l?ch ?ông Nam Á nên dùng eSIM','top-5-diem-den-du-lich-dong-nam-a-nen-dung-esim','Khám phá 5 ?i?m ??n h?p d?n nh?t ?ông Nam Á và lý do t?i sao b?n nên s? d?ng eSIM khi du l?ch ??n nh?ng n?i này.','https://images.pexels.com/photos/2035891/pexels-photo-2035891.jpeg','https://images.pexels.com/photos/2035891/pexels-photo-2035891.jpeg',null,null,null,286,1,0,1,to_date('02-JAN-26','DD-MON-RR'),'VN',null,to_date('02-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,null,null,null,null);
+REM INSERTING into ARTICLE_CATEGORY
+SET DEFINE OFF;
+Insert into ARTICLE_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,PARENT_ID,DISPLAY_ORDER,STATUS,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,LANGUAGE) values (1,'Handbook','handbook','handbook',null,null,1,1,to_date('30-DEC-25','DD-MON-RR'),null,'handbook','handbook','handbook','handbook','lo');
+Insert into ARTICLE_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,PARENT_ID,DISPLAY_ORDER,STATUS,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,LANGUAGE) values (2,'Kinh nghi?m du l?ch','kinh-nghiem-du-lich','Chia s? kinh nghi?m du l?ch và tips h?u ích','/icons/travel.svg',null,2,1,to_date('05-JAN-26','DD-MON-RR'),null,'???????????????????','Travel Tips','??????????????????????? ??? ????????????????????','Share travel experience and useful tips','lo');
+Insert into ARTICLE_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,PARENT_ID,DISPLAY_ORDER,STATUS,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,LANGUAGE) values (3,'Tin t?c  mãi','tin-tuc-khuyen-mai','Tin t?c m?i nh?t và ch??ng trình khuy?n mãi h?p d?n','/icons/news.svg',null,3,1,to_date('05-JAN-26','DD-MON-RR'),null,'??????? ??? ????????','News ','?????????????? ??? ???????????????????','Latest news and attractive promotions','lo');
+REM INSERTING into BANNER
+SET DEFINE OFF;
+Insert into BANNER (ID,TITLE,SUBTITLE,IMAGE_URL,IMAGE_MOBILE_URL,LINK_URL,LINK_TARGET,POSITION,DISPLAY_ORDER,STATUS,START_DATE,END_DATE,CREATED_BY,CREATED_DATE,LAST_UPDATE,TITLE_LO,TITLE_EN,SUBTITLE_LO,SUBTITLE_EN,LANGUAGE) values (1,'K?t n?i muôn n?i, mua SIM giá h?i','Mua SIM d? dàng, s?n sàng vi vu','https://wallpaperaccess.com/full/706916.jpg','https://wallpaperaccess.com/full/706916.jpg','/mua-esim','_self','home',1,1,to_date('05-JAN-26','DD-MON-RR'),to_date('05-JUL-26','DD-MON-RR'),null,to_date('05-JAN-26','DD-MON-RR'),null,'????????????????????, ??? SIM ??????','Connect Everywhere, Buy SIM at Great Prices','??? SIM ?????, ???????????','Buy SIM Easily, Ready to Travel','lo');
+Insert into BANNER (ID,TITLE,SUBTITLE,IMAGE_URL,IMAGE_MOBILE_URL,LINK_URL,LINK_TARGET,POSITION,DISPLAY_ORDER,STATUS,START_DATE,END_DATE,CREATED_BY,CREATED_DATE,LAST_UPDATE,TITLE_LO,TITLE_EN,SUBTITLE_LO,SUBTITLE_EN,LANGUAGE) values (2,'eSIM Qu?c T? - Ti?t ki?m 80%',null,'https://image.yachtcharterfleet.com/w1920/h619/qh/ca/ow-1/k26856a87/areaguide/photo/2014375/saudi-arabia-guide.jpg','https://image.yachtcharterfleet.com/w1920/h619/qh/ca/ow-1/k26856a87/areaguide/photo/2014375/saudi-arabia-guide.jpg','/esim-sale','_self','home',2,1,null,null,null,to_date('05-JAN-26','DD-MON-RR'),null,'eSIM ????? - ?????? 80%','International eSIM - Save 80%',null,null,'lo');
+REM INSERTING into CMS_CONTENT
+SET DEFINE OFF;
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (1,'ABOUT_US','V? chúng tôi','about-us','Thông tin v? EsimLao',null,'STATIC',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'V? chúng tôi',null,'Thông tin v? EsimLao',null);
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (2,'TERMS_OF_SERVICE','?i?u kho?n d?ch v?','terms-and-services','?i?u kho?n s? d?ng d?ch v?',null,'POLICY',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'?i?u kho?n d?ch v?',null,'?i?u kho?n s? d?ng d?ch v?',null);
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (3,'PRIVACY_POLICY','Chính sách b?o m?t','privacy-policy','Chính sách b?o m?t thông tin',null,'POLICY',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'Chính sách b?o m?t',null,'Chính sách b?o m?t thông tin',null);
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (4,'PAYMENT_POLICY','Chính sách thanh toán','payment-policy','Chính sách thanh toán',null,'POLICY',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'Chính sách thanh toán',null,'Chính sách thanh toán',null);
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (5,'DELIVERY_POLICY','Chính sách giao hàng','delivery-policy','Chính sách giao hàng',null,'POLICY',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'Chính sách giao hàng',null,'Chính sách giao hàng',null);
+Insert into CMS_CONTENT (ID,PAGE_CODE,PAGE_TITLE,PAGE_SLUG,META_DESCRIPTION,META_KEYWORDS,PAGE_TYPE,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,UPDATED_BY,PAGE_TITLE_LO,PAGE_TITLE_EN,META_DESCRIPTION_LO,META_DESCRIPTION_EN) values (6,'REFUND_POLICY','Chính sách ??i tr? và hoàn ti?n','refund-policy','Chính sách ??i tr? và hoàn ti?n',null,'POLICY',1,'vi',null,to_date('29-DEC-25','DD-MON-RR'),null,null,'Chính sách ??i tr? và hoàn ti?n',null,'Chính sách ??i tr? và hoàn ti?n',null);
+REM INSERTING into CONFIG
+SET DEFINE OFF;
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (13,'EMAIL_REQUIRED','??????????????','Email is required','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (15,'OTP_SENT_SUCCESS','????????? OTP ??????','OTP sent successfully','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (16,'OTP_INVALID','????? OTP ??????????','Invalid OTP','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (17,'OTP_EXPIRED','????? OTP ???????????','OTP has expired','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (18,'OTP_ALREADY_USED','????? OTP ???????????????','OTP has already been used','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (19,'OTP_RESENT_SUCCESS','????????? OTP ?????????','OTP resent successfully','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (20,'OTP_NOT_REQUESTED','????????????? OTP ????','Please request OTP first','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (21,'USER_NOT_FOUND','????????????','User not found','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (22,'LOGIN_SUCCESS','???????????????????','Login successful','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (1,'SYSTEM_FAILURE','System error occurred Local','System error occurred','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (4,'EMAIL_OTP_REQUIRED','Email and OTP are required Local','Email and OTP are required','WEB',null);
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (23,'SUCCESS','??????','Success','WEB','Thành công');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (24,'GOOGLE_CONFIG_MISSING','?????????? Google ?????????????','Google Auth configuration missing','WEB','C?u hình Google ch?a ???c thi?t l?p');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (37,'GOOGLE_CODE_REQUIRED','??????????????? Google ??????','Authorization code is required','WEB','Mã xác th?c t? Google là b?t bu?c');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (38,'GOOGLE_TOKEN_EXCHANGE_FAILED','??????????????? token ??? Google','Failed to exchange token with Google','WEB','Không th? xác th?c v?i Google');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (39,'GOOGLE_NO_ACCESS_TOKEN','????????? access token ??? Google','No access token received from Google','WEB','Không nh?n ???c token t? Google');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (40,'GOOGLE_USERINFO_FAILED','??????????????????????????? Google','Failed to get user info from Google','WEB','Không th? l?y thông tin ng??i dùng t? Google');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (41,'GOOGLE_NO_EMAIL','????????? email ??? Google','No email received from Google','WEB','Không nh?n ???c email t? Google');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (42,'GOOGLE_LOGIN_SUCCESS','????????????? Google ??????','Google login successful','WEB','??ng nh?p Google thành công');
+Insert into CONFIG (ID,NAME,VALUE_LOCAL,VALUE_GLOBAL,TYPE,VALUE) values (10,'LOAD_SUCCESS','LOAD_SUCCESS_Local','LOAD_SUCCESS','WEB',null);
+REM INSERTING into CONTACT_FORM
+SET DEFINE OFF;
+REM INSERTING into CUSTOMER_INFO
+SET DEFINE OFF;
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (1,'Viettech','Asia','sale.admin@viettech.asia',null,to_date('17-DEC-25','DD-MON-RR'),to_date('17-DEC-25','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (240,'Tùng','Nguy?n','nvta8hp0@gmail.com','+84393004441',to_date('18-DEC-25','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('09-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (364,'oi','oi','oi@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (304,'user','user','user@example.com',null,to_date('30-DEC-25','DD-MON-RR'),to_date('30-DEC-25','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (362,'thanhhuong','thanhhuong','thanhhuong@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (370,'tru2','tru2','tru2@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (421,'A Thao','A Thao','nvt315@gmail.com','0972978396',to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('10-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (441,'trongduc02','trongduc02','trongduc02@gmail.com',null,to_date('12-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (282,null,null,'dsadas@example.com',null,to_date('29-DEC-25','DD-MON-RR'),to_date('29-DEC-25','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (320,'abc','abc','abc@gmail.com',null,to_date('01-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('12-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (363,'thanhhuongoo','thanhhuongoo','thanhhuongoo@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (372,'trunghieu.95.h12p','trunghieu.95.h12p','trunghieu.95.h12p@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (400,'Thanh h??ng','Thanh H??ng','huongvtt@viettech.asia','0972978396',to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('10-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (340,'Hi?u','Bùi','trunghieu.95.hp@gmail.com','+84965974369',to_date('05-JAN-26','DD-MON-RR'),to_date('05-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (361,'alo_mitnghe_1710_pr0','alo_mitnghe_1710_pr0','alo_mitnghe_1710_pr0@yahoo.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (420,'Tinh','An','giadinhthanyeuk13@gmail.com','0912345983',to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('10-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (440,'use1r','use1r','use1r@gmail.com',null,to_date('12-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (305,'Thanh h??ng','Thanh H??ng','thanhhuong1710@gmail.com','0972978396',to_date('30-DEC-25','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('09-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (365,'TEST','DUONGTT','duongtt@onepay.vn','+84848484848',to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (366,'klinhnguyen.viettech','klinhnguyen.viettech','klinhnguyen.viettech@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('08-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (241,'Linh','Nguy?n','klinhnguyen.1206@gmail.com','0336548007',to_date('18-DEC-25','DD-MON-RR'),to_date('18-DEC-25','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (260,'Thanh Huong','Vu','linhbell120672000@gmail.com','0972978396',to_date('19-DEC-25','DD-MON-RR'),to_date('19-DEC-25','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (360,'janevuglobal','janevuglobal','janevuglobal@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'),null,null,null,1,1,to_date('09-JAN-26','DD-MON-RR'));
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (367,'Van Quang','Phan','phanquang84@gmail.com','0912345983',to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (368,'abc1','abc1','abc1@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (369,'tru','tru','tru@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (371,'trunghieu.95.h1p','trunghieu.95.h1p','trunghieu.95.h1p@gmail.com',null,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+Insert into CUSTOMER_INFO (ID,SUR_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,CREATED_DATE,LAST_UPDATE,GOOGLE_ID,AVATAR_URL,PASSWORD_HASH,STATUS,IS_VERIFIED,LAST_LOGIN_DATE) values (380,'han','nguyen','abc',null,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'),null,null,null,1,0,null);
+REM INSERTING into CUSTOMER_REVIEW
+SET DEFINE OFF;
+Insert into CUSTOMER_REVIEW (ID,CUSTOMER_NAME,AVATAR_URL,RATING,REVIEW_CONTENT,DESTINATION,DISPLAY_ORDER,IS_FEATURED,STATUS,CREATED_DATE,APPROVED_DATE,APPROVED_BY,REVIEW_CONTENT_LO,REVIEW_CONTENT_EN,DESTINATION_LO,DESTINATION_EN,LANGUAGE) values (1,'Phan H?ng','https://res.cloudinary.com/prod/image/upload/e_background_removal/me/bgr-people-1.png',5,'C? gia ?ình tôi ?ã có m?t k? ngh? d??ng tuy?t v?i ? Phuket, Thái Lan nh? eSIM infiGate. K?t n?i m?nh ?n ??nh, t?c ?? trung bình kho?ng 25Mbps, ?? ?? c? nhà xem phim, l??t web, s? d?ng m?ng xã h?i m?t cách tho?i mái.','Hà N?i',1,1,1,to_date('05-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),1,'????????????????????????????????????? Phuket, ??????? ???? eSIM infiGate. ??????????????????????????????????, ????????????????? 25Mbps.','My family had a wonderful vacation in Phuket, Thailand thanks to infiGate eSIM. Strong and stable connection, average speed around 25Mbps, enough for the whole family to watch movies, surf the web, use social media comfortably.','???????','Hanoi','lo');
+Insert into CUSTOMER_REVIEW (ID,CUSTOMER_NAME,AVATAR_URL,RATING,REVIEW_CONTENT,DESTINATION,DISPLAY_ORDER,IS_FEATURED,STATUS,CREATED_DATE,APPROVED_DATE,APPROVED_BY,REVIEW_CONTENT_LO,REVIEW_CONTENT_EN,DESTINATION_LO,DESTINATION_EN,LANGUAGE) values (2,'Quang Huy','https://res.cloudinary.com/prod/image/upload/e_background_removal/me/bgr-automotive-1.png',5,'Trong su?t hành trình ?i ph??t bên M?, tôi dò ???ng b?ng Google Map phát tr?c ti?p t? sim data t?c ?? cao mua s?n ? Vi?t Nam t?i shop web infiGate. R?t d? dàng, không ph?i m?t th?i gian ?? ?i tìm mua sim ? M?.','Ngh? An',2,1,1,to_date('05-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),1,'??????????????????????????, ??????? Google Maps ???? SIM ???????????????????????? infiGate. ????????.','Throughout my backpacking trip in the US, I navigated with Google Maps using high-speed data SIM purchased in Vietnam from infiGate. Very easy, no need to waste time looking for SIM in the US.','???????','Nghe An','lo');
+Insert into CUSTOMER_REVIEW (ID,CUSTOMER_NAME,AVATAR_URL,RATING,REVIEW_CONTENT,DESTINATION,DISPLAY_ORDER,IS_FEATURED,STATUS,CREATED_DATE,APPROVED_DATE,APPROVED_BY,REVIEW_CONTENT_LO,REVIEW_CONTENT_EN,DESTINATION_LO,DESTINATION_EN,LANGUAGE) values (3,'H?ng Mây','https://res.cloudinary.com/prod/image/upload/e_background_removal/me/bgr-people-2.png',5,'Dùng thích nên l?n nào ?i công tác mình c?ng mua ? ch?t l??ng dùng m?ng bên TQ nhanh, v??t ???c h?t t??ng l?a ?? truy c?p zalo, fb tho?i mái, giá r?.','H? Chí Minh',3,1,1,to_date('05-JAN-26','DD-MON-RR'),null,null,'??????? ?????????????????????? ? ???????????????, ????? Zalo, FB ????????, ???????.','Love it so much that I buy it every business trip ? Network quality in China is fast, bypasses firewall to access Zalo, FB comfortably, cheap price.','????????????','Ho Chi Minh City','lo');
+Insert into CUSTOMER_REVIEW (ID,CUSTOMER_NAME,AVATAR_URL,RATING,REVIEW_CONTENT,DESTINATION,DISPLAY_ORDER,IS_FEATURED,STATUS,CREATED_DATE,APPROVED_DATE,APPROVED_BY,REVIEW_CONTENT_LO,REVIEW_CONTENT_EN,DESTINATION_LO,DESTINATION_EN,LANGUAGE) values (4,'David','https://res.cloudinary.com/prod/image/upload/e_background_removal/me/bgr-people-3.png',5,'The easiest way to stay connected in Vietnam. As a traveler from the U.S., I was worried about staying online during my trip. This SIM card solved everything. Fast 4G everywhere I went—from Hanoi to Hoi An. Highly recommended!','Hoa K?',4,1,1,to_date('05-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),1,'?????????????????????????????????????. SIM ???????????????. 4G ?????????????.','The easiest way to stay connected in Vietnam. As a traveler from the U.S., I was worried about staying online during my trip. This SIM card solved everything. Fast 4G everywhere I went—from Hanoi to Hoi An. Highly recommended!','???????????????','United States','lo');
+Insert into CUSTOMER_REVIEW (ID,CUSTOMER_NAME,AVATAR_URL,RATING,REVIEW_CONTENT,DESTINATION,DISPLAY_ORDER,IS_FEATURED,STATUS,CREATED_DATE,APPROVED_DATE,APPROVED_BY,REVIEW_CONTENT_LO,REVIEW_CONTENT_EN,DESTINATION_LO,DESTINATION_EN,LANGUAGE) values (5,'Min-jun','https://res.cloudinary.com/prod/image/upload/e_background_removal/me/bgr-people-4.png',5,'?? SIM ???? ??? ??? ???? ??? ?? ???. ??? ???? ??? ??! ????, ???, ??? ? ???? ?? ????.','Hàn Qu?c',5,1,1,to_date('05-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'),1,null,'Local SIM card with unlimited data plan is so good. Affordable price and fast speed! Using KakaoTalk, Instagram, YouTube without any problems.','??????????','South Korea','lo');
+REM INSERTING into DEVICE_ESIM_COMPATIBILITY
+SET DEFINE OFF;
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (1,'Apple','iPhone XS','iPhone XS','iPhone XS',1,'Phone','T?t c? các phiên b?n tr? iPhone t? Trung Qu?c ??i l?c, Hong Kong và Macau','All versions except iPhone from mainland China, Hong Kong and Macau','????????????????? iPhone ??? ??????????????, ??????? ??? ??????',1,1,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (2,'Apple','iPhone XS Max','iPhone XS Max','iPhone XS Max',1,'Phone','T?t c? các phiên b?n tr? iPhone t? Trung Qu?c ??i l?c, Hong Kong và Macau','All versions except iPhone from mainland China, Hong Kong and Macau','????????????????? iPhone ??? ??????????????, ??????? ??? ??????',1,2,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (3,'Apple','iPhone XR','iPhone XR','iPhone XR',1,'Phone','T?t c? các phiên b?n tr? iPhone t? Trung Qu?c ??i l?c, Hong Kong và Macau','All versions except iPhone from mainland China, Hong Kong and Macau','????????????????? iPhone ??? ??????????????, ??????? ??? ??????',1,3,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (4,'Apple','iPhone 11','iPhone 11','iPhone 11',1,'Phone','T?t c? các phiên b?n tr? iPhone t? Trung Qu?c ??i l?c, Hong Kong và Macau','All versions except iPhone from mainland China, Hong Kong and Macau',null,1,4,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (5,'Apple','iPhone 11 Pro','iPhone 11 Pro','iPhone 11 Pro',1,'Phone',null,null,null,1,5,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (6,'Apple','iPhone 11 Pro Max','iPhone 11 Pro Max','iPhone 11 Pro Max',1,'Phone',null,null,null,1,6,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (7,'Apple','iPhone SE (2020)','iPhone SE (2020)','iPhone SE (2020)',1,'Phone',null,null,null,1,7,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (8,'Apple','iPhone 12','iPhone 12','iPhone 12',1,'Phone',null,null,null,1,8,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (9,'Apple','iPhone 12 mini','iPhone 12 mini','iPhone 12 mini',1,'Phone',null,null,null,1,9,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (10,'Apple','iPhone 12 Pro','iPhone 12 Pro','iPhone 12 Pro',1,'Phone',null,null,null,1,10,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (11,'Apple','iPhone 12 Pro Max','iPhone 12 Pro Max','iPhone 12 Pro Max',1,'Phone',null,null,null,1,11,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (12,'Apple','iPhone 13','iPhone 13','iPhone 13',1,'Phone',null,null,null,1,12,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (13,'Apple','iPhone 13 mini','iPhone 13 mini','iPhone 13 mini',1,'Phone',null,null,null,1,13,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (14,'Apple','iPhone 13 Pro','iPhone 13 Pro','iPhone 13 Pro',1,'Phone',null,null,null,1,14,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (15,'Apple','iPhone 13 Pro Max','iPhone 13 Pro Max','iPhone 13 Pro Max',1,'Phone',null,null,null,1,15,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (16,'Apple','iPhone SE (2022)','iPhone SE (2022)','iPhone SE (2022)',1,'Phone',null,null,null,1,16,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (17,'Apple','iPhone 14','iPhone 14','iPhone 14',1,'Phone',null,null,null,1,17,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (18,'Apple','iPhone 14 Plus','iPhone 14 Plus','iPhone 14 Plus',1,'Phone',null,null,null,1,18,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (19,'Apple','iPhone 14 Pro','iPhone 14 Pro','iPhone 14 Pro',1,'Phone',null,null,null,1,19,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (20,'Apple','iPhone 14 Pro Max','iPhone 14 Pro Max','iPhone 14 Pro Max',1,'Phone',null,null,null,1,20,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (21,'Apple','iPhone 15','iPhone 15','iPhone 15',1,'Phone',null,null,null,1,21,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (22,'Apple','iPhone 15 Plus','iPhone 15 Plus','iPhone 15 Plus',1,'Phone',null,null,null,1,22,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (23,'Apple','iPhone 15 Pro','iPhone 15 Pro','iPhone 15 Pro',1,'Phone',null,null,null,1,23,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (24,'Apple','iPhone 15 Pro Max','iPhone 15 Pro Max','iPhone 15 Pro Max',1,'Phone',null,null,null,1,24,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (25,'Samsung','Galaxy S20','Galaxy S20','Galaxy S20',1,'Phone',null,null,null,1,30,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (26,'Samsung','Galaxy S20+','Galaxy S20+','Galaxy S20+',1,'Phone',null,null,null,1,31,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (27,'Samsung','Galaxy S20 Ultra','Galaxy S20 Ultra','Galaxy S20 Ultra',1,'Phone',null,null,null,1,32,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (28,'Samsung','Galaxy S21','Galaxy S21','Galaxy S21',1,'Phone',null,null,null,1,33,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (29,'Samsung','Galaxy S21+','Galaxy S21+','Galaxy S21+',1,'Phone',null,null,null,1,34,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (30,'Samsung','Galaxy S21 Ultra','Galaxy S21 Ultra','Galaxy S21 Ultra',1,'Phone',null,null,null,1,35,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (31,'Samsung','Galaxy S22','Galaxy S22','Galaxy S22',1,'Phone',null,null,null,1,36,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (32,'Samsung','Galaxy S22+','Galaxy S22+','Galaxy S22+',1,'Phone',null,null,null,1,37,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (33,'Samsung','Galaxy S22 Ultra','Galaxy S22 Ultra','Galaxy S22 Ultra',1,'Phone',null,null,null,1,38,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (34,'Samsung','Galaxy S23','Galaxy S23','Galaxy S23',1,'Phone',null,null,null,1,39,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (35,'Samsung','Galaxy S23+','Galaxy S23+','Galaxy S23+',1,'Phone',null,null,null,1,40,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (36,'Samsung','Galaxy S23 Ultra','Galaxy S23 Ultra','Galaxy S23 Ultra',1,'Phone',null,null,null,1,41,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (37,'Samsung','Galaxy Z Flip','Galaxy Z Flip','Galaxy Z Flip',1,'Phone',null,null,null,1,42,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (38,'Samsung','Galaxy Z Flip 3','Galaxy Z Flip 3','Galaxy Z Flip 3',1,'Phone',null,null,null,1,43,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (39,'Samsung','Galaxy Z Flip 4','Galaxy Z Flip 4','Galaxy Z Flip 4',1,'Phone',null,null,null,1,44,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (40,'Samsung','Galaxy Z Fold','Galaxy Z Fold','Galaxy Z Fold',1,'Phone',null,null,null,1,45,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (41,'Samsung','Galaxy Z Fold 2','Galaxy Z Fold 2','Galaxy Z Fold 2',1,'Phone',null,null,null,1,46,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (42,'Samsung','Galaxy Z Fold 3','Galaxy Z Fold 3','Galaxy Z Fold 3',1,'Phone',null,null,null,1,47,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (43,'Samsung','Galaxy Z Fold 4','Galaxy Z Fold 4','Galaxy Z Fold 4',1,'Phone',null,null,null,1,48,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (44,'Google','Pixel 3','Pixel 3','Pixel 3',1,'Phone',null,null,null,1,50,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (45,'Google','Pixel 3 XL','Pixel 3 XL','Pixel 3 XL',1,'Phone',null,null,null,1,51,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (46,'Google','Pixel 3a','Pixel 3a','Pixel 3a',1,'Phone',null,null,null,1,52,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (47,'Google','Pixel 4','Pixel 4','Pixel 4',1,'Phone',null,null,null,1,53,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (48,'Google','Pixel 4a','Pixel 4a','Pixel 4a',1,'Phone',null,null,null,1,54,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (49,'Google','Pixel 5','Pixel 5','Pixel 5',1,'Phone',null,null,null,1,55,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (50,'Google','Pixel 6','Pixel 6','Pixel 6',1,'Phone',null,null,null,1,56,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (51,'Google','Pixel 6 Pro','Pixel 6 Pro','Pixel 6 Pro',1,'Phone',null,null,null,1,57,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (52,'Google','Pixel 7','Pixel 7','Pixel 7',1,'Phone',null,null,null,1,58,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (53,'Google','Pixel 7 Pro','Pixel 7 Pro','Pixel 7 Pro',1,'Phone',null,null,null,1,59,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (54,'Huawei','P40','P40','P40',1,'Phone',null,null,null,0,100,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (55,'Huawei','P40 Pro','P40 Pro','P40 Pro',1,'Phone',null,null,null,0,101,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (56,'Motorola','Razr 2019','Razr 2019','Razr 2019',1,'Phone',null,null,null,0,102,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (57,'Oppo','Find X3 Pro','Find X3 Pro','Find X3 Pro',1,'Phone',null,null,null,0,103,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (58,'Apple','iPad Pro 11-inch (3rd generation)','iPad Pro 11-inch (3rd generation)','iPad Pro 11-inch (3rd generation)',1,'Tablet',null,null,null,0,200,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (59,'Apple','iPad Pro 12.9-inch (5th generation)','iPad Pro 12.9-inch (5th generation)','iPad Pro 12.9-inch (5th generation)',1,'Tablet',null,null,null,0,201,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (60,'Apple','iPad Air (4th generation)','iPad Air (4th generation)','iPad Air (4th generation)',1,'Tablet',null,null,null,0,202,1,to_date('05-JAN-26','DD-MON-RR'),null);
+Insert into DEVICE_ESIM_COMPATIBILITY (ID,BRAND,MODEL_NAME,MODEL_NAME_EN,MODEL_NAME_LO,SUPPORTS_ESIM,CATEGORY,NOTES,NOTES_EN,NOTES_LO,IS_POPULAR,DISPLAY_ORDER,STATUS,CREATED_DATE,UPDATED_DATE) values (61,'Apple','iPad Mini (6th generation)','iPad Mini (6th generation)','iPad Mini (6th generation)',1,'Tablet',null,null,null,0,203,1,to_date('05-JAN-26','DD-MON-RR'),null);
+REM INSERTING into FAQ
+SET DEFINE OFF;
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (7,12,'Cài ??t eSIM trên iPhone nh? th? nào?',1,0,0,0,'VN',null,to_date('05-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),'??????? eSIM ?? iPhone ??????','Cài ??t eSIM trên iPhone nh? th? nào?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (8,10,'Tôi có th? thanh toán b?ng cách nào?',1,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'??????????????????????????','What payment methods are available?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (9,10,'Chính sách hoàn ti?n nh? th? nào?',2,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'???????????????????????????','What is the refund policy?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (10,15,'eSIM không k?t n?i ???c m?ng, ph?i làm sao?',1,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'eSIM ?????????????????????????, ??????????','eSIM cannot connect to network, what to do?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (11,16,'Không quét ???c mã QR, làm sao?',1,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'?????????????????? QR, ??????????','Cannot scan QR code, what to do?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (12,8,'Tôi có th? s? d?ng cùng lúc SIM v?t lý và eSIM không?',3,0,0,0,'EN',null,to_date('05-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),'???????????? SIM ??? ??? eSIM ?????????????','Tôi có th? s? d?ng cùng lúc SIM v?t lý và eSIM không?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (13,9,'Khi nào tôi nên kích ho?t eSIM?',2,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'????????????????? eSIM ????????','When should I activate eSIM?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (5,8,'Thi?t b? nào h? tr? eSIM?',2,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'?????????????????? eSIM?','Which devices support eSIM?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (6,9,'Làm sao ?? cài ??t eSIM?',1,0,1,1,'vi',null,to_date('05-JAN-26','DD-MON-RR'),null,'??????? eSIM ??????','How to install eSIM?');
+Insert into FAQ (ID,CATEGORY_ID,QUESTION,DISPLAY_ORDER,VIEW_COUNT,IS_FEATURED,STATUS,LANGUAGE,CREATED_BY,CREATED_DATE,LAST_UPDATE,QUESTION_LO,QUESTION_EN) values (4,8,'eSIM là gì?',1,0,0,0,'VN',null,to_date('05-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'),'eSIM ?????????','eSIM là gì?');
+REM INSERTING into FAQ_CATEGORY
+SET DEFINE OFF;
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (8,'eSIM/ SIM du l?ch là gì?','about-esim','Tìm hi?u v? công ngh? eSIM và l?i ích c?a nó','/icons/info-circle.svg',1,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'eSIM/SIM ?????????????????','What is eSIM/ Travel SIM?','??????????????????????? eSIM ??????????????????','Learn about eSIM technology and its benefits',null);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (9,'Cài ??t  ho?t eSIM','installation-activation','H??ng d?n cài ??t và kích ho?t eSIM trên thi?t b?','/icons/settings.svg',2,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'?????????? ??? ?????????????','Installation ','??????????????? ??? ????????????? eSIM ????????????????','Guide to installing and activating eSIM on your device',null);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (10,'Thanh toán  ti?n','payment-refund','Thông tin v? thanh toán và chính sách hoàn ti?n','/icons/credit-card.svg',3,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'??????????? ??? ??????????','Payment ','???????????????????????? ??? ?????????????????','Information about payment and refund policy',null);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (11,'S? c? k? thu?t','technical-issues','X? lý các s? c? th??ng g?p khi s? d?ng eSIM','/icons/alert-triangle.svg',4,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'????????????????','Technical Issues','???????????????????????? eSIM','Troubleshooting common issues when using eSIM',null);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (12,'H??ng d?n cho iPhone','iphone-setup','Cài ??t eSIM trên các thi?t b? iPhone','/icons/apple.svg',1,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'?????????? iPhone','Guide for iPhone','??????? eSIM ????????? iPhone','Installing eSIM on iPhone devices',9);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (13,'H??ng d?n cho Android','android-setup','Cài ??t eSIM trên các thi?t b? Android','/icons/android.svg',2,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'?????????? Android','Guide for Android','??????? eSIM ????????? Android','Installing eSIM on Android devices',9);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (14,'H??ng d?n cho Samsung','samsung-setup','Cài ??t eSIM trên các thi?t b? Samsung','/icons/smartphone.svg',3,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'?????????? Samsung','Guide for Samsung','??????? eSIM ????????? Samsung','Installing eSIM on Samsung devices',9);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (15,'Không k?t n?i ???c m?ng','network-connection-issues','X? lý các v?n ?? v? k?t n?i m?ng','/icons/wifi-off.svg',1,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'????????????????????????????','Cannot Connect to Network','??????????????????????????????','Troubleshooting network connection issues',11);
+Insert into FAQ_CATEGORY (ID,CATEGORY_NAME,CATEGORY_SLUG,DESCRIPTION,ICON_URL,DISPLAY_ORDER,STATUS,LANGUAGE,CREATED_DATE,LAST_UPDATE,CATEGORY_NAME_LO,CATEGORY_NAME_EN,DESCRIPTION_LO,DESCRIPTION_EN,PARENT_ID) values (16,'Không quét ???c QR Code','qr-code-scanning-issues','Gi?i quy?t v?n ?? không quét ???c QR Code','/icons/qrcode.svg',2,1,'vi',to_date('05-JAN-26','DD-MON-RR'),null,'????????????? QR Code ???','Cannot Scan QR Code','?????????????????? QR Code','Solving QR code scanning problems',11);
+REM INSERTING into MESSAGE_QUEUE
+SET DEFINE OFF;
+REM INSERTING into MESSAGE_QUEUE_HIS
+SET DEFINE OFF;
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (1,1,'user@example.com','????? OTP ???????',null,1,2,to_timestamp('30-DEC-25 05.21.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('30-DEC-25 05.21.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,304,to_timestamp('30-DEC-25 05.21.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('30-DEC-25 05.21.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (2,1,'thanhhuong1710@gmail.com','????? OTP ???????',null,1,2,to_timestamp('30-DEC-25 05.22.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('30-DEC-25 05.22.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('30-DEC-25 05.22.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('30-DEC-25 05.22.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (6,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.12.45.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.12.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.12.45.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.12.50.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (7,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.17.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.17.37.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.17.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.17.37.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (8,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.18.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.18.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.18.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.18.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (9,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.18.16.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.18.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.18.16.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.18.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (10,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.19.52.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.19.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.19.52.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.19.55.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (11,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.19.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.20.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.19.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.20.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (12,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.21.26.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.21.26.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (13,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.21.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.21.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (14,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.21.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.21.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.21.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (15,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.23.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.23.26.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.23.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.23.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (16,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 11.23.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.23.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 11.23.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 11.23.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (19,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.28.16.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.29.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.28.16.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.29.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (20,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.31.15.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.31.18.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.31.15.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.31.19.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (21,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.31.32.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.31.40.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.31.32.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.31.41.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (22,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.31.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.32.02.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.31.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.32.03.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (33,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 04.31.45.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.31.53.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,340,to_timestamp('07-JAN-26 04.31.33.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.31.54.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (34,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('07-JAN-26 04.32.48.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.32.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('07-JAN-26 04.32.48.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.32.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (35,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 04.34.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.34.49.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('07-JAN-26 04.34.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.34.49.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (36,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 04.37.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.37.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('07-JAN-26 04.37.34.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.37.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (37,1,'thanhhuong1710@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 04.44.10.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.44.12.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('07-JAN-26 04.44.10.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.44.12.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (38,1,'thanhhuong1710@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 04.45.43.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.45.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('07-JAN-26 04.45.43.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 04.45.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (39,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 05.41.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.41.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,305,to_timestamp('08-JAN-26 05.41.05.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.41.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (40,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 05.45.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.46.04.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 05.45.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.46.05.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (41,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.01.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.01.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,360,to_timestamp('08-JAN-26 06.00.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.01.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (42,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.05.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.05.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 06.05.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.05.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (43,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.08.17.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.08.28.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,360,to_timestamp('08-JAN-26 06.08.17.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.08.28.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (44,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.10.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.11.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 06.10.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.11.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (45,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.13.25.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.13.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 06.13.25.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.13.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (46,1,'alo_mitnghe_1710_pr0@yahoo.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.17.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.17.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,361,to_timestamp('08-JAN-26 06.17.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.17.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (25,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,3,to_timestamp('07-JAN-26 09.37.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.08.48.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-07 09:37:36',340,to_timestamp('07-JAN-26 09.37.36.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.08.48.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (53,1,'duongtt@onepay.vn','Transaction success!',null,1,2,to_timestamp('08-JAN-26 10.58.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.58.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,365,to_timestamp('08-JAN-26 10.58.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.58.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (54,1,'klinhnguyen.viettech@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 11.21.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.21.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,366,to_timestamp('08-JAN-26 11.21.08.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.21.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (55,1,'klinhnguyen.viettech@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 11.23.32.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.23.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,366,to_timestamp('08-JAN-26 11.23.32.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.23.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (56,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('08-JAN-26 11.44.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.44.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,340,to_timestamp('08-JAN-26 11.44.26.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 11.44.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (57,1,'phanquang84@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 02.55.50.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 02.55.58.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,367,to_timestamp('08-JAN-26 02.55.43.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 02.55.58.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (59,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.12.21.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.12.28.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.12.21.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.12.28.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (60,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.13.21.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.13.30.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.13.21.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.13.31.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (62,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.19.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.19.08.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.19.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.19.09.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (65,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.22.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.22.46.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.22.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.22.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (66,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.23.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.23.59.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.23.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.23.59.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (68,1,'abc1@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.26.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.27.05.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,368,to_timestamp('08-JAN-26 03.26.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.27.05.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (69,1,'abc1@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.27.57.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.28.07.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,368,to_timestamp('08-JAN-26 03.27.57.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.28.07.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (73,1,'trunghieu.95.h1p@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.31.35.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.31.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,371,to_timestamp('08-JAN-26 03.31.35.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.31.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (47,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.18.08.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.18.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 06.18.08.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.18.12.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (48,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.20.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.20.14.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,360,to_timestamp('08-JAN-26 06.20.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.20.15.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (49,1,'thanhhuong@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.21.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.21.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,362,to_timestamp('08-JAN-26 06.21.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.21.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (50,1,'thanhhuongoo@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.21.56.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.21.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,363,to_timestamp('08-JAN-26 06.21.56.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.21.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (51,1,'oi@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 06.22.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.22.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,364,to_timestamp('08-JAN-26 06.22.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 06.22.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (52,1,'duongtt@onepay.vn','Transaction success!',null,1,2,to_timestamp('08-JAN-26 10.44.46.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.44.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,365,to_timestamp('08-JAN-26 10.44.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 10.44.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (58,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.11.28.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.11.36.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,340,to_timestamp('08-JAN-26 03.11.18.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.11.36.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (61,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.14.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.14.33.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.14.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.14.33.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (63,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.20.03.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.20.11.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.20.03.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.20.11.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (64,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.21.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.21.14.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.21.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.21.14.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (67,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.25.13.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.25.22.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('08-JAN-26 03.25.13.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.25.22.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (70,1,'abc1@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.28.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.28.59.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,368,to_timestamp('08-JAN-26 03.28.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.29.00.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (71,1,'tru@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.30.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.30.53.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,369,to_timestamp('08-JAN-26 03.30.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.30.53.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (72,1,'tru2@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.30.53.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.31.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,370,to_timestamp('08-JAN-26 03.30.53.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.31.05.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (74,1,'trunghieu.95.h1p@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.34.03.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.34.10.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,371,to_timestamp('08-JAN-26 03.34.03.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.34.10.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (75,1,'trunghieu.95.h12p@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.49.08.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.49.16.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,372,to_timestamp('08-JAN-26 03.48.58.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.49.16.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (0,1,'dsadas@example.com',null,'OTP_LOGIN_EN',1,2,to_timestamp('29-DEC-25 02.01.07.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('29-DEC-25 04.33.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,282,to_timestamp('29-DEC-25 02.01.07.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('29-DEC-25 04.33.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (23,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.38.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.38.57.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.38.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.38.57.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (24,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('05-JAN-26 01.39.17.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.39.18.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('05-JAN-26 01.39.17.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-26 01.39.19.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (3,1,'abc@gmail.com','????? OTP ???????',null,1,3,to_timestamp('01-JAN-26 03.40.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-01 15:40:36',320,to_timestamp('01-JAN-26 03.40.36.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (4,1,'abc@gmail.com','????? OTP ???????',null,1,3,to_timestamp('05-JAN-26 10.29.46.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-05 10:29:39',320,to_timestamp('05-JAN-26 10.29.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (5,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,3,to_timestamp('05-JAN-26 11.09.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-05 11:09:17',340,to_timestamp('05-JAN-26 11.09.17.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (18,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,3,to_timestamp('05-JAN-26 01.27.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-05 13:27:08',340,to_timestamp('05-JAN-26 01.27.08.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (17,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,3,to_timestamp('05-JAN-26 11.48.44.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,'EXPIRED: Message older than 1 day(s) - Auto-deleted to prevent spam and table bloat. Created: 2026-01-05 11:48:38',340,to_timestamp('05-JAN-26 11.48.38.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 11.08.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (28,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 02.41.46.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 02.41.54.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,340,to_timestamp('07-JAN-26 02.41.36.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 02.41.54.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (29,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 03.16.57.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.17.05.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,340,to_timestamp('07-JAN-26 03.16.42.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.17.05.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (30,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 03.18.00.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.18.08.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('07-JAN-26 03.18.00.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.18.08.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (31,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 03.20.28.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.20.31.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('07-JAN-26 03.20.28.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.20.31.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (32,1,'trunghieu.95.hp@gmail.com','Transaction success!',null,1,2,to_timestamp('07-JAN-26 03.29.45.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.29.50.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('07-JAN-26 03.29.45.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('07-JAN-26 03.29.50.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (82,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 06.52.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.52.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,360,to_timestamp('09-JAN-26 06.52.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.52.21.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (85,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 09.11.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.11.18.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,305,to_timestamp('09-JAN-26 09.11.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.11.18.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (86,1,'trunghieu.95.hp@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 09.17.12.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.17.18.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,340,to_timestamp('09-JAN-26 09.17.12.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.17.19.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (87,1,'thanhhuong1710@gmail.com','Transaction success!',null,1,2,to_timestamp('09-JAN-26 09.40.03.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.40.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,305,to_timestamp('09-JAN-26 09.39.10.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.40.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (88,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 446',null,1,2,to_timestamp('09-JAN-26 09.40.40.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.41.14.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 09.40.40.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.41.14.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (89,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 446',null,1,2,to_timestamp('09-JAN-26 09.41.31.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.41.57.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 09.41.31.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.41.57.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (90,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 446',null,1,3,to_timestamp('09-JAN-26 09.55.06.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.55.10.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 09.54.40.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 09.55.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (92,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.03.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.03.48.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.02.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.03.48.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (93,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.40.16.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.40.32.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.39.47.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.40.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (94,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.40.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.40.55.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.39.51.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.41.02.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (95,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.40.45.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.40.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.39.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.41.02.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (96,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.40.48.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.41.00.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.39.56.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.41.02.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (97,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 445',null,1,3,to_timestamp('09-JAN-26 10.42.51.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.42.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.42.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.42.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (98,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,3,to_timestamp('09-JAN-26 10.50.07.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.50.12.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 10.49.39.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.50.13.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (99,1,'janevuglobal@gmail.com','Your OTP Code',null,1,3,to_timestamp('09-JAN-26 10.54.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.54.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,360,to_timestamp('09-JAN-26 10.53.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.54.29.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (118,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 520',null,1,2,to_timestamp('12-JAN-26 06.10.42.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.53.31.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('12-JAN-26 06.10.42.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.53.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (119,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('12-JAN-26 06.11.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.53.31.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('12-JAN-26 06.11.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.53.30.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (120,1,'use1r@gmail.com','Your OTP Code',null,1,2,to_timestamp('12-JAN-26 08.54.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.54.42.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,440,to_timestamp('12-JAN-26 08.54.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.54.41.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (121,1,'trongduc02@gmail.com','Your OTP Code',null,1,2,to_timestamp('12-JAN-26 08.58.08.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.58.14.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,441,to_timestamp('12-JAN-26 08.57.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 08.58.13.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (122,1,'trongduc02@gmail.com','Your OTP Code',null,1,2,to_timestamp('12-JAN-26 09.00.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 09.00.26.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,441,to_timestamp('12-JAN-26 09.00.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('12-JAN-26 09.00.24.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (77,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.55.19.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.55.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('08-JAN-26 03.55.19.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.55.24.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (78,1,'trunghieu.95.h1p@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.56.29.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.56.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,371,to_timestamp('08-JAN-26 03.56.29.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.56.37.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (101,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 11.03.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.03.54.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 11.03.43.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.03.55.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (102,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 11.04.47.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.04.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 11.04.47.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.04.59.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (103,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 11.07.42.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.07.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 11.07.42.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.07.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (104,1,'nvta8hp0@gmail.com','Xác nh?n ??n hàng eSim GetGo - 467',null,1,2,to_timestamp('09-JAN-26 02.12.15.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.12.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,240,to_timestamp('09-JAN-26 02.12.01.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.12.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (105,1,'nvta8hp0@gmail.com','Xác nh?n ??n hàng eSim GetGo - 467',null,1,2,to_timestamp('09-JAN-26 02.12.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.12.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,240,to_timestamp('09-JAN-26 02.12.47.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.12.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (106,1,'nvta8hp0@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 02.26.35.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.26.43.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,240,to_timestamp('09-JAN-26 02.26.23.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.26.43.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (107,1,'nvta8hp0@gmail.com','Xác nh?n ??n hàng eSim GetGo - 469',null,1,2,to_timestamp('09-JAN-26 02.33.20.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.33.26.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,240,to_timestamp('09-JAN-26 02.33.20.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 02.33.26.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (109,1,'abc','Xác nh?n ??n hàng eSim GetGo - 471',null,1,3,to_timestamp('09-JAN-26 10.32.27.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.32.31.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,380,to_timestamp('09-JAN-26 10.31.56.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 10.32.32.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (110,1,'alo_mitnghe_1710_pr0@yahoo.com','Your OTP Code',null,1,2,to_timestamp('10-JAN-26 06.46.03.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.46.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,361,to_timestamp('10-JAN-26 06.45.56.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.46.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (112,1,'huongvtt@viettech.asia','Xác nh?n ??n hàng eSim GetGo - 480',null,1,2,to_timestamp('10-JAN-26 06.51.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.51.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,400,to_timestamp('10-JAN-26 06.51.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.51.20.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (117,1,'nvt315@gmail.com','Your OTP Code',null,1,2,to_timestamp('10-JAN-26 09.25.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.25.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,421,to_timestamp('10-JAN-26 09.25.49.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.25.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (81,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 06.52.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.52.32.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,360,to_timestamp('09-JAN-26 06.52.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.52.32.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (79,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 05.36.44.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.36.52.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,305,to_timestamp('08-JAN-26 05.36.32.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.36.52.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (84,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 06.58.04.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.58.14.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 06.58.04.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.58.15.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (100,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,3,to_timestamp('09-JAN-26 11.00.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.01.04.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),3,3,null,305,to_timestamp('09-JAN-26 11.00.25.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 11.01.04.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (113,1,'phanquang84@gmail.com','Your OTP Code',null,1,2,to_timestamp('10-JAN-26 09.02.09.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.02.17.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,367,to_timestamp('10-JAN-26 09.01.56.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.02.17.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (114,1,'giadinhthanyeuk13@gmail.com','Xác nh?n ??n hàng eSim GetGo - 501',null,1,2,to_timestamp('10-JAN-26 09.05.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.06.05.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,420,to_timestamp('10-JAN-26 09.05.58.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.06.05.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (116,1,'nvt315@gmail.com','Xác nh?n ??n hàng eSim GetGo - 502',null,1,2,to_timestamp('10-JAN-26 09.24.53.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.25.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,421,to_timestamp('10-JAN-26 09.24.46.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.25.01.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (115,1,'giadinhthanyeuk13@gmail.com','Your OTP Code',null,1,2,to_timestamp('10-JAN-26 09.06.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.06.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,420,to_timestamp('10-JAN-26 09.06.23.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 09.06.27.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (76,1,'trunghieu.95.h1p@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 03.52.27.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.52.30.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,371,to_timestamp('08-JAN-26 03.52.27.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 03.52.30.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (80,1,'janevuglobal@gmail.com','Your OTP Code',null,1,2,to_timestamp('08-JAN-26 05.36.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.37.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,360,to_timestamp('08-JAN-26 05.36.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('08-JAN-26 05.37.04.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (83,1,'thanhhuong1710@gmail.com','Your OTP Code',null,1,2,to_timestamp('09-JAN-26 06.53.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.53.19.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,305,to_timestamp('09-JAN-26 06.53.11.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 06.53.19.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (108,1,'thanhhuong1710@gmail.com','Xác nh?n ??n hàng eSim GetGo - 470',null,1,2,to_timestamp('09-JAN-26 08.26.42.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 08.26.50.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),1,3,null,305,to_timestamp('09-JAN-26 08.26.31.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('09-JAN-26 08.26.51.000000000 PM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+Insert into MESSAGE_QUEUE_HIS (ID,MESSAGE_TYPE,RECIPIENT,SUBJECT,TEMPLATE_CODE,PRIORITY,STATUS,SCHEDULED_AT,PROCESSED_AT,RETRY_COUNT,MAX_RETRY,ERROR_MESSAGE,CREATED_BY,CREATED_DATE,MOVED_DATE,LANGUAGE) values (111,1,'huongvtt@viettech.asia','Your OTP Code',null,1,2,to_timestamp('10-JAN-26 06.48.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.48.45.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),0,3,null,400,to_timestamp('10-JAN-26 06.48.35.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('10-JAN-26 06.48.46.000000000 AM','DD-MON-RR HH.MI.SSXFF AM'),'lo');
+REM INSERTING into MESSAGE_TEMPLATE
+SET DEFINE OFF;
+Insert into MESSAGE_TEMPLATE (ID,TEMPLATE_CODE,TEMPLATE_NAME,MESSAGE_TYPE,SUBJECT,VARIABLES,STATUS,CREATED_DATE,LAST_UPDATE,TEMPLATE_NAME_LO,TEMPLATE_NAME_EN,SUBJECT_LO,SUBJECT_EN,LANGUAGE) values (1,'BUY_SUCCESS','Buy Esim success',1,'Xác nh?n ??n hàng eSim GetGo - {{ORDER_ID}}','CUSTOMER_NAME,EMAIL,MSISDN,SIM_INFO',1,to_date('30-DEC-25','DD-MON-RR'),null,null,null,'Xác nh?n ??n hàng eSim GetGo - {{ORDER_ID}}','Xác nh?n ??n hàng eSim GetGo - {{ORDER_ID}}','lo');
+Insert into MESSAGE_TEMPLATE (ID,TEMPLATE_CODE,TEMPLATE_NAME,MESSAGE_TYPE,SUBJECT,VARIABLES,STATUS,CREATED_DATE,LAST_UPDATE,TEMPLATE_NAME_LO,TEMPLATE_NAME_EN,SUBJECT_LO,SUBJECT_EN,LANGUAGE) values (4,'OTP_LOGIN','OTP Login Template',1,'Your OTP Code','OTP_CODE,EXPIRE_MINUTES',1,to_date('30-DEC-25','DD-MON-RR'),null,null,null,'????? OTP ???????','Your OTP Code','lo');
+Insert into MESSAGE_TEMPLATE (ID,TEMPLATE_CODE,TEMPLATE_NAME,MESSAGE_TYPE,SUBJECT,VARIABLES,STATUS,CREATED_DATE,LAST_UPDATE,TEMPLATE_NAME_LO,TEMPLATE_NAME_EN,SUBJECT_LO,SUBJECT_EN,LANGUAGE) values (2,'SIM_INFO','SimInfo',1,'SimInfo',null,1,to_date('30-DEC-25','DD-MON-RR'),null,null,null,null,null,'lo');
+REM INSERTING into OTP_VERIFICATION
+SET DEFINE OFF;
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (1,304,'user@example.com','020913',1,to_date('30-DEC-25','DD-MON-RR'),1,0,to_date('30-DEC-25','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (23,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (25,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (31,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (32,320,'abc@gmail.com','111111',1,to_date('12-JAN-26','DD-MON-RR'),1,0,to_date('12-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (35,362,'thanhhuong@gmail.com','253069',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (37,364,'oi@gmail.com','098730',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (42,370,'tru2@gmail.com','582643',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (47,420,'giadinhthanyeuk13@gmail.com','821608',1,to_date('10-JAN-26','DD-MON-RR'),1,0,to_date('10-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (50,441,'trongduc02@gmail.com','455307',1,to_date('12-JAN-26','DD-MON-RR'),0,0,to_date('12-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (0,282,'dsadas@example.com','339902',1,to_date('29-DEC-25','DD-MON-RR'),0,0,to_date('29-DEC-25','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (36,363,'thanhhuongoo@gmail.com','816035',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (44,372,'trunghieu.95.h12p@gmail.com','244025',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (21,320,'abc@gmail.com','111111',1,to_date('06-JAN-26','DD-MON-RR'),1,0,to_date('06-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (46,400,'huongvtt@viettech.asia','191015',1,to_date('10-JAN-26','DD-MON-RR'),1,0,to_date('10-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (29,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (30,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (27,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (34,361,'alo_mitnghe_1710_pr0@yahoo.com','753116',1,to_date('10-JAN-26','DD-MON-RR'),0,0,to_date('10-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (45,240,'nvta8hp0@gmail.com','664454',1,to_date('09-JAN-26','DD-MON-RR'),1,0,to_date('09-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (49,440,'use1r@gmail.com','716298',1,to_date('12-JAN-26','DD-MON-RR'),0,0,to_date('12-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (3,304,'user@example.com','211856',1,to_date('30-DEC-25','DD-MON-RR'),0,0,to_date('30-DEC-25','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (4,305,'thanhhuong1710@gmail.com','687764',1,to_date('12-JAN-26','DD-MON-RR'),0,0,to_date('12-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (22,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (26,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (38,366,'klinhnguyen.viettech@gmail.com','318539',1,to_date('08-JAN-26','DD-MON-RR'),1,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (24,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (28,320,'abc@gmail.com','111111',1,to_date('07-JAN-26','DD-MON-RR'),1,0,to_date('07-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (33,360,'janevuglobal@gmail.com','872919',1,to_date('09-JAN-26','DD-MON-RR'),0,0,to_date('09-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (39,367,'phanquang84@gmail.com','828151',1,to_date('10-JAN-26','DD-MON-RR'),0,0,to_date('10-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (40,368,'abc1@gmail.com','892989',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (41,369,'tru@gmail.com','972550',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (43,371,'trunghieu.95.h1p@gmail.com','675263',1,to_date('08-JAN-26','DD-MON-RR'),0,0,to_date('08-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (48,421,'nvt315@gmail.com','613894',1,to_date('10-JAN-26','DD-MON-RR'),1,0,to_date('10-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (19,340,'trunghieu.95.hp@gmail.com','531609',1,to_date('09-JAN-26','DD-MON-RR'),0,0,to_date('09-JAN-26','DD-MON-RR'));
+Insert into OTP_VERIFICATION (ID,CUSTOMER_ID,USER_EMAIL,OTP_CODE,OTP_TYPE,EXPIRED_AT,IS_USED,ATTEMPT_COUNT,CREATED_DATE) values (20,320,'abc@gmail.com','111111',1,to_date('05-JAN-26','DD-MON-RR'),1,0,to_date('05-JAN-26','DD-MON-RR'));
+REM INSERTING into USER_TOKEN
+SET DEFINE OFF;
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (8,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjFhNGQxZDlkLTY0ZGEtNDhiYi04OWExLTFmYzAyNzdiMjEzOCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIzMjE4Y2I0Mi1lZGEwLTQ3NWUtOTE2Zi1jNjhlMWUwYzliMTAiLCJuYmYiOjE3Njc3NTQyNDIsImV4cCI6MTc2NzgwODI0MiwiaWF0IjoxNzY3NzU0MjQyLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.bD9He_YT-4tzmriUisKHa1uOZWSrfpZYXNQXJ4F5KsY4DyHO3GDVvNHRbDUoNwlBRl5fnd9DoMC6Pk-oRu9QMA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImRkZDg3YWIxLWU5N2UtNGFhYS04Njc5LTA4ODVhZjMyZTg2OSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI4ZWFhNjFkYi1mMWJhLTQ2YzgtODgyMS1kZjIzYTdkMjc1YjgiLCJuYmYiOjE3Njc3NTQyNDIsImV4cCI6MTc2NzgwODI0MiwiaWF0IjoxNzY3NzU0MjQyLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.YysPfUwNLEAqWSZvqAuQfxigr4yzuho95mI22HdzKsVTw2eZ-ppffupAyLKNMRGUr9oQLCfwjSAEA5uOoqgAOA','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (9,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImI4OTM2ZGI1LWZkMWItNGQ1Mi1iMzgzLTJlYmU2ZmQwYmFlYyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI4NWE0NTdiOS1kNjkzLTQ5NmYtODBhYi02YmY4MzVjNTFjMTAiLCJuYmYiOjE3Njc3NTQzMDMsImV4cCI6MTc2NzgwODMwMywiaWF0IjoxNzY3NzU0MzAzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.JjquXCBPgb73PzVERdQ39p3j6Wd9qBNfqmtau2JWwCIVQJ1wZ-UkVBw9_YrfTUd4_Luzg5oApjQCn0vAjNKQjw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjYwMGZhMDU3LTVhZjAtNDY4ZS04MGIzLTZiMTMzMWRiMTFjMSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIyNmJkYTYxOC04MDgyLTQ3ODQtYTMzOC0wYWI2N2NjNzQzMTIiLCJuYmYiOjE3Njc3NTQzMDMsImV4cCI6MTc2NzgwODMwMywiaWF0IjoxNzY3NzU0MzAzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.KIcSeb2JdLYMAMcqR0t9YF1_7VhSvsY7-DBYKtRKNofAQmfBk887qa0Wk2QtEKgMbUQFJ4AG8ZFlCXuHFm8_sQ','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (10,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjlhODQ5M2RkLTE2YzktNGJmNC1hZmI1LTYwODE3ODhhMzVlYiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJiYjRiZjAxMS1iMzY2LTQ5NmUtYjU5MS1jNWE5OGY0Y2M1MmIiLCJuYmYiOjE3Njc3NTQ0ODYsImV4cCI6MTc2NzgwODQ4NiwiaWF0IjoxNzY3NzU0NDg2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.eu322_CUU0uKhomaLaHRi6DdrFQcO7m76OtoPavVjc5afH-7D2_OaRtg7KaSpj1ujmF95I19-BOLQNJR9D6NvQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjQ5OTFmNmZiLTkyMDEtNDcxYy04YjZmLTgxN2YwZGJjZDE4YiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJmNDAwMzU2ZS02ZGNkLTRiNWItODkzMC1iZDcwOTkyMGVmZGYiLCJuYmYiOjE3Njc3NTQ0ODYsImV4cCI6MTc2NzgwODQ4NiwiaWF0IjoxNzY3NzU0NDg2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.1Yhscyos3Da70K2SAoYTKfRM7HlWLNrUH0dsLkg-CvH5AdOu5DtYO5K5hbZF3yQvmTqNljAYf7daQLGqj8g04g','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (11,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQ5ODMyZDFmLTU3ZmMtNDdiYy1iZjA3LTBkNWFkOWQwZGRmYyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJkNTM3MmNiNS1lYmU4LTQyYTAtODJlNS0zOTJiOTQ1NjY0ZGYiLCJuYmYiOjE3Njc3NTQ2MDUsImV4cCI6MTc2NzgwODYwNSwiaWF0IjoxNzY3NzU0NjA1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.1KuYAJ8wwqXnYikp1SXim_NEzzsk2JDGNbK9qKsEaHGgcDQOXss-LjnclZZi_ZiGG2He0It2lqP9sBdGJXBStQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjQ1ZTYzN2YxLTc4OTUtNDE1Ny05YTFlLThhYTNlOTExNTAwNCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIyMzY4N2Q3Ny0zNDMwLTQ5NmEtOWYyYS1iMzE2MTEzZDQwMjAiLCJuYmYiOjE3Njc3NTQ2MDUsImV4cCI6MTc2NzgwODYwNSwiaWF0IjoxNzY3NzU0NjA1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.epxKA-WhrfJy3DLBQ7IR7JkxtKN7KhepKMEZIQrU8zaBlIyDNYE24bSbTgzdZc_c9PHCq67vhTCbToap6kjj-Q','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (12,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImIxYWYxODBlLTlkZGItNDQ4My1iODk0LTk5YjU0MDhmZDc2MyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIxZDMzMzU4NC01YTdiLTQ0NjItYTA4Yi0xZTJmNTQ0ZDkxNDMiLCJuYmYiOjE3Njc3NTQ4MTgsImV4cCI6MTc2NzgwODgxOCwiaWF0IjoxNzY3NzU0ODE4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.bDfuyyliZS1lFGJGOyvJQ-BZl_8rTVF6QIi3yPrlICo1sFQEd7nZi6ChFqpXhri5-OU_KuNLV0GltoudFFoDrg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjRmOTFmNzFjLTY2MGItNDI2My05MTRmLTUzMTcyODEzZjliYSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIwN2I1NmE2Ni02NWI5LTQ2YjktOWVkMC0zNTM5NmE3MDRkNDYiLCJuYmYiOjE3Njc3NTQ4MTgsImV4cCI6MTc2NzgwODgxOCwiaWF0IjoxNzY3NzU0ODE4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.6KBPG-VRDpfLD5YV1OwgtE6L5Kt94djIHz9RgSXrsrQTToM4pDNQQmYD2ijtpAUfNYPvF6rw4IhHYlEFgC1ySQ','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (28,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImYxMmMzNDVjLTg2YmQtNDQ0Yy1hODI4LWI4Y2ZlYWQ2NTBjOSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJkNDYyMTBiMC0yMjhmLTRhNWQtYTI1YS01ZWRhZDAxMzY3OGMiLCJuYmYiOjE3Njc4NTYxNTUsImV4cCI6MTc2NzkxMDE1NSwiaWF0IjoxNzY3ODU2MTU1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.BN70TfjNQAu8exL_dg9EVFhzYxhRHjYf-bunzsd0aeaQFaDPdBwIJxijpklYTKx8B49IK1My6gW3IcOHKiVCYw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImM0NGJjNzM2LTFiNjAtNDg3ZC04MTljLWU5YTIxOWQ0Yzk5OCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJmMWU5NzU5OC00MjUyLTQzNjUtOWY0MS0xNjIwNTNjZWUzNmEiLCJuYmYiOjE3Njc4NTYxNTUsImV4cCI6MTc2NzkxMDE1NSwiaWF0IjoxNzY3ODU2MTU1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.RqsSc_5mzfrZk1IMpGQMefjlnj0M5qlu1Irw-yN0vRmUtxSdHbEBWqaRQoRTYnQbvu_cr5ob7XOLt57Fi9_4sw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (32,360,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjdiMDZhMDQ3LTFhOTktNDQyMi1iY2FkLTU2OTM2YTc4ZDg3ZCIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzNjAiLCJqdGkiOiJmNmRmMjE3NC1mY2YxLTRmMjItODJjYi0yMWM2YTEyN2Y5ZmEiLCJuYmYiOjE3Njc4Njg2NTgsImV4cCI6MTc2NzkyMjY1OCwiaWF0IjoxNzY3ODY4NjU4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.N5oTgFMSBwW_JrirYfKdqkOqG1i7oRBTjrMMQ3WW0Sstj7cO_oFSP7MZtVDxe_F0ioal8qYtvXvLd9hVC4QQlA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQ1NTJiYWE4LTgxMWQtNGRjYy1iNTQ0LWZhNDlhMDZiYjg4ZCIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJqdGkiOiJmMjE0NGM0Yy01NDUwLTQ4ODgtODQ2Ny03MjNkMmRjMzVmMGMiLCJuYmYiOjE3Njc4Njg2NTgsImV4cCI6MTc2NzkyMjY1OCwiaWF0IjoxNzY3ODY4NjU4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.0ybWSKn31tU6IIGw6_-S9R1fpB4aqmnbdAjFaws51KHvRC-KYrxPUhXOzJEmvuEHSC0EogWoH3rLRiiYUEpeFw','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (2,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjhjODQ1ZjkyLTJkY2QtNDA2ZC1hMjVhLWExNmJmNDJhNzZhYSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJjOTM3ODQ4My1iMDEzLTRlNDQtYTJkMy03YWUwZjEwMGI5MDgiLCJuYmYiOjE3Njc2ODgxOTcsImV4cCI6MTc2Nzc0MjE5NywiaWF0IjoxNzY3Njg4MTk3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.jR0L-3YvdjLsZT3ROVWxu6ucUnAen8RKQ5SStHn3motEqsVY8hsgo2StlmJ_YFtLf3M8rAEoyifoiO6bBPvNgA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImUwNTlkZjRiLTI1NzEtNGE5ZS1hZDk2LWI3OWFhOThiYWE2MSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJiYTJmMTVhNC1iNTY1LTRlZDktYjE2MC05MzU1ZmRmODc2ODgiLCJuYmYiOjE3Njc2ODgxOTcsImV4cCI6MTc2Nzc0MjE5NywiaWF0IjoxNzY3Njg4MTk3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.jWjzj1ubijVHNrOZUPMYRtb_rzcxHQBU7K0SI4iI-AWSeiXVSlS1FwbmAvF2zVuzJAybbMw-ADTvi4syZAPFCw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','127.0.0.1',to_date('07-JAN-26','DD-MON-RR'),to_date('05-FEB-26','DD-MON-RR'),1,to_date('06-JAN-26','DD-MON-RR'),to_date('06-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (14,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImZjOTYyODQ0LTQxZGYtNGVkYi05OTg1LWQwMmJlZjFhNTcxMCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIyNTczZmU4NC04ZDU3LTQ2Y2EtYjQ2Zi1hZmRkNTdjNWQ4MDciLCJuYmYiOjE3Njc3NzAyMDgsImV4cCI6MTc2NzgyNDIwOCwiaWF0IjoxNzY3NzcwMjA4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.yihz7tCLDhvQfXalPiISAW5LYBPru6iqu2axWsjafJoA_KNEjI1T-TTG0GsHr_KTuCOBZf6bP7UsLAXhaQQAjA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjNiYmM0Y2VhLWQ0MmYtNGRhMy05NzRkLTk0Yjk0NTQ4Yzc0ZSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIxM2YwN2IzMy00M2I2LTQ0NTctYWExZS1jMjFiMjY4ZGE0MzciLCJuYmYiOjE3Njc3NzAyMDgsImV4cCI6MTc2NzgyNDIwOCwiaWF0IjoxNzY3NzcwMjA4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.g6uaGrMQSQklPWbK8ZRqHe8ktL5eDw96brpvYudyytW6nM263C0z02hvqYUorz6nepL6dFoZfK18uDdyndWu4A','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (15,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjM4ODgzNmIxLWJlZjAtNDA5NS04ZmM5LTA3ZmZiM2JmZTBlNCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIyZDMzOThmOC1jZDhmLTRlZDItYjYxZC03OWQzNjc2OGQ5YWMiLCJuYmYiOjE3Njc3NzM4MjUsImV4cCI6MTc2NzgyNzgyNSwiaWF0IjoxNzY3NzczODI1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.j1JF3CrCmTwIPsNi58tWyC6AiWuOZDOJthkrn1hzDOAUH6GHHIV2pYoraSKguwuX3zOGUq_1laQCi7WSUOCP_A','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImU4MjNhNDhhLTNjNjItNGRhMS1hMWEwLWFmZjNlZjRjYWNmZCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJiMzdmM2ZmOC1hZjAzLTRiZmMtYmI5Ni05MmMwNjViZTdmMTciLCJuYmYiOjE3Njc3NzM4MjUsImV4cCI6MTc2NzgyNzgyNSwiaWF0IjoxNzY3NzczODI1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.9TjeBeX3CCkDnE54paloNoy_ZMcBlsAGBJtMxVP9fOUJAsOJpayE2rpD1M_x6EVAsaxJaLPh82gaxtJOzRSHIw','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (26,366,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQzOTE5OGQzLWQyMzktNDkwOC1iMGNlLWFkOTg4NGNjMzM5MiIsIk1zaXNkbiI6ImtsaW5obmd1eWVuLnZpZXR0ZWNoQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjM2NiIsImp0aSI6IjgyZGFkZGU3LTUwN2QtNDk5NC05MDVkLTFhZWNjYWYyOWE3OSIsIm5iZiI6MTc2Nzg0NjEyNiwiZXhwIjoxNzY3OTAwMTI2LCJpYXQiOjE3Njc4NDYxMjYsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.FYuJpBarMtL97TO1vbP7-aOEAj7FjObr9a0-MKcSxn2stsOLZfULhA_hl4cw2h3dbDOwd1U5LtTuXGSNXE2cdA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImIyMTI0NmVjLWQ0NTktNDE4OS1iMDlhLTFjZGE0ZGU2ZTQ3NSIsIk1zaXNkbiI6ImtsaW5obmd1eWVuLnZpZXR0ZWNoQGdtYWlsLmNvbSIsImp0aSI6ImExMzUxNWViLTc2MmQtNDQzOC1iZGY2LTUyZDk0YmQzMjlhZiIsIm5iZiI6MTc2Nzg0NjEyNiwiZXhwIjoxNzY3OTAwMTI2LCJpYXQiOjE3Njc4NDYxMjYsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.zS11qB4nRdjJ8qkPy7mpupHHK1FmfefgDriATIpRmp_CgTgGcHDlQEH9dmc4ex0djG2gKDgjuNCYGQGbXHNNxw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (33,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImZjMzZiMzFhLTRmN2QtNDhhNS04NTlkLTUxOWI1ZmQwZjQyNiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI3NTUyMmRhZS02MDc3LTRjZDctYTZjNC05N2Q0MjkwOGYzOGEiLCJuYmYiOjE3Njc5MTYxNzUsImV4cCI6MTc2Nzk3MDE3NSwiaWF0IjoxNzY3OTE2MTc1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.6J9EIVbO7By3EtHMzGqQM09eneZFrstHznTd_Sqi577jsd5h3P13ztNIYgkn_-pihBdqY3pctedRQglpYYeA5Q','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjVhNGY5OWE4LTA3MGMtNDM3ZS05NWNjLTZlMjNjZmE3Y2NlZSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIyNmI5MzM0Mi1iOTIxLTQ5NTUtOWJhZC1jOWViMDY0Y2MzNGMiLCJuYmYiOjE3Njc5MTYxNzUsImV4cCI6MTc2Nzk3MDE3NSwiaWF0IjoxNzY3OTE2MTc1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.jmz5sSBEgNdpDpx9FWPv_DtIMlPIP5AqgtUfHV7zxo8Aa0s07inw4Y0OAteA2YYpxkB7U5sSbZRXBY8_QY314Q','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (34,360,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjBjMTU1MzNiLTU4YmItNDI1Ni1iM2RjLTA2ZDE1MzZkYTMxZiIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzNjAiLCJqdGkiOiIxY2MzODk2My0zNjdmLTRmZmUtYmEwOC04MGVjY2YzZGE4N2MiLCJuYmYiOjE3Njc5MTYzNzAsImV4cCI6MTc2Nzk3MDM3MCwiaWF0IjoxNzY3OTE2MzcwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.Aj8yL4mW5WdbY2zG4X2fqii16Nqdnbbm93GBh2mTqClOduRuIuj8SkFMP1CQrTaT7sOS55oclNw0uMdM7K1a2g','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImU0YWFlM2VkLTIzY2UtNDY3MS1iY2MyLWRkYTEwNDE3MWYwYSIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJqdGkiOiJlZDc5YTcxOC02YzljLTRmYzUtOWQ1OS1mOTE3M2YwMTJkYmQiLCJuYmYiOjE3Njc5MTYzNzAsImV4cCI6MTc2Nzk3MDM3MCwiaWF0IjoxNzY3OTE2MzcwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.Jh0PUGacoz7hqSAjzTsEXeqrtf48TkWsvE29kY_UQ9bMbw1C5goGWgTmvjQn_tf6Pr_0lscRnjHExd7UL9uIYg','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),0,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (35,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjIyYzYwNzAyLTJlM2MtNDMzNC05ZGE1LThiMzU0MzNjYmQyNiIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6Ijc5OTQ2OGM4LTllZTYtNGU3YS1hZWFmLTY1Yjc0ZTE2MDdkZCIsIm5iZiI6MTc2NzkxNjQyMiwiZXhwIjoxNzY3OTcwNDIyLCJpYXQiOjE3Njc5MTY0MjIsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.JhmIOUCRa4gspicFah-iQSmaUDYQ1DxDcPGgluDn9fTYRlz58kr6uV9aHs4BRd46yRoNAUXfRRwhZEaBkeD54w','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQyM2I5ZWRhLWE3MWEtNDllNi1iMmFlLTg3NTk4MWU4Y2IxMSIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjRhZmJmMTc2LWRlODctNGEzMC04ZWI1LWE1MTFlYjVlNmU4ZiIsIm5iZiI6MTc2NzkxNjQyMiwiZXhwIjoxNzY3OTcwNDIyLCJpYXQiOjE3Njc5MTY0MjIsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.I-1158iKzrfLlIQFYs7riLiWTN-g3rH5RClMz3ZRezSbqVGmK2Emc6-9uUXCHRVk7HwMfuOS4w-sPuef1uAqPw','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (1,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImIzOGQ5MjE3LWQ5NTMtNGNkYS05NzM0LTYxODBkYzExMzhkZiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJjZDRiZjI5ZC0wZjYzLTQwMWItODc1Ny01NjMzMzg2OWMzNTIiLCJuYmYiOjE3Njc1OTUxNzAsImV4cCI6MTc2NzY0OTE3MCwiaWF0IjoxNzY3NTk1MTcwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.MNTf2TzRTsFbk0XusMfz-Ojv_5gEhJU51Od45-7NQ6Hpe-BRo8qCVW4YjXoVVRJN4jA54Om_yzU8GH1dCX22ww','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjY3OTc3NTkzLTY0MDUtNGJkMy04MWZmLWQ2NGU1NTdkOTM2YyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI0OWUzOGYwYS05Y2U2LTQxNjUtODFjZC1hZGQ4Zjc0OWNiODAiLCJuYmYiOjE3Njc1OTUxNzAsImV4cCI6MTc2NzY0OTE3MCwiaWF0IjoxNzY3NTk1MTcwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.XpBRrBKMdVhCCL3gMKl2bp3uPW8jrMIUf1vGIwZ0ahYvGHWA870eAnw61UtX_25rj-c_38ct5vauvKGpuBVuOg','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('06-JAN-26','DD-MON-RR'),to_date('04-FEB-26','DD-MON-RR'),1,to_date('05-JAN-26','DD-MON-RR'),to_date('05-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (4,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjM1YmNkYTgzLTE3ZGUtNGIyMS1hNDI3LThhODRlMjNjOWQwMyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJkMTIzZGQwNS02YWVmLTQxNTEtODk3Zi0wOTc1NWE4NjAyNWEiLCJuYmYiOjE3Njc3NTM4OTgsImV4cCI6MTc2NzgwNzg5OCwiaWF0IjoxNzY3NzUzODk4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.eSOyl9U8z9Z59UhKb6OkMbSGfPK6KcoRu0FxOtxtMwJIbY2jyCtOUGaDysao0Aw4BMxt9BQV1gX8veYN50dU4Q','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjIyOWI5MDA5LTIyYWUtNGVhMS1hZjI5LTRlZmYzMjMzYmU2NSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJmYTVkNGUyNi0zMWI5LTQ1NWQtOGY2Yy04NzcxMzA5MmM0ZmIiLCJuYmYiOjE3Njc3NTM4OTgsImV4cCI6MTc2NzgwNzg5OCwiaWF0IjoxNzY3NzUzODk4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.LOS4Nu4LUf1x5MHh50qNjYQhTysDAISE_Np9dDZvMX6JvHb7Aq3jY1GFqHyQ9gI66jehS3TjYqXXRyw3pAGtjA','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (17,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjM1ZmMwN2JkLTE5YWUtNGM3ZS05MzZhLTg5NjdiOGZkOWU0YyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIxYjNlZGU5Zi03YjY5LTQ5MWEtODUxNC04NjBlMTYxZDEyOTgiLCJuYmYiOjE3Njc3Nzk5ODMsImV4cCI6MTc2NzgzMzk4MywiaWF0IjoxNzY3Nzc5OTgzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.xTKaRt18BIujPNNqK9uRB7BEuKQn4MstahphmTdwWF80TgCeJD-fsUdhrx1bTgQEhU-GFCKRWd3rTP499XZ4fA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImI1MzNmZDY1LThiM2ItNDg3Yy1iMmIwLTQyM2QyZDU2MjFlNSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJlYWNmZGRhNy04YzcyLTQ4N2ItYWM3Mi0yNjlkNDk5NjE0NTkiLCJuYmYiOjE3Njc3Nzk5ODMsImV4cCI6MTc2NzgzMzk4MywiaWF0IjoxNzY3Nzc5OTgzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.ZuR_6BZ8AJR7-GbRX41t_tMXyXSgjHoKRh84yrY-6SB34v8g-SL8Zw9-bEPxiSRsuUkj1XFaWoSRdi3Is5fJHA','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (20,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImI2MTQzNWQ3LTNlOGEtNGIyNS04OTIyLTNkYWIyNDMxMDViNSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJlMDVkNzkwZi03MjU1LTQwZmEtYmM2NS1lYTZlOTBiNzQ0YzIiLCJuYmYiOjE3Njc3OTk0MTksImV4cCI6MTc2Nzg1MzQxOSwiaWF0IjoxNzY3Nzk5NDE5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.7gUcfv1DC-W6phZ2nDX55sE072HOc6E6LOyBhXWeydoRNBc8vedYDwEzKQlc8O3KQ1tmQzuyJepYQ-OhqmP6mw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY5ZjUwN2NiLWI2YzktNDM2OS1hMWJkLTdhZGI4NmZiNTczNyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIzMzk4YTA4OC03NzdiLTQ2M2QtYTkxMC1jOTk2OGRkNDhhNTYiLCJuYmYiOjE3Njc3OTk0MTksImV4cCI6MTc2Nzg1MzQxOSwiaWF0IjoxNzY3Nzk5NDE5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.FiG8an2cz3G0Yt_V7I2y2YNAmSGluJvPDS7G7QoJFtGQe3IzBSwKSEX8_NL54k7nIvg-59tzWfE7HbIv-qP1_g','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.232.210.120',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (21,360,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjgyMTdmODBlLWY2YjUtNDU0NC05MDEwLWRmZWU3N2E4NWY3NyIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzNjAiLCJqdGkiOiI3NWZmZDkxMS04MmFiLTQwOGYtYjc4YS1lNTAxZDdjNjI1NzQiLCJuYmYiOjE3Njc4MjY4OTQsImV4cCI6MTc2Nzg4MDg5NCwiaWF0IjoxNzY3ODI2ODk0LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.efF8FCfXKVTMnxCEL-P8gz8tUgyiaHbVi7QKoOmnWBtZF4cR0aICFgi5SWlRIgRcRvs9GTCc3bpq4QQUxqXE3w','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjY1M2ZjNGYxLWEzNGUtNDRjZS1hZWIzLTYwMTQzZTljMTgyYiIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJqdGkiOiJjZmU2ZDY0Mi1jMGRhLTQ4ZDMtODI1Mi1kMTZhMjNmODA5ODQiLCJuYmYiOjE3Njc4MjY4OTQsImV4cCI6MTc2Nzg4MDg5NCwiaWF0IjoxNzY3ODI2ODk0LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.hbBCIhiSO2O8zh5oc1rN-4VmBFoVzH24yKpiiqa5M6QSJb0FB-O5NTQ86P5Tx4pwbvX6MUMq8JJtdIjgE-lkCw','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_7_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/143.0.7499.151 Mobile/15E148 Safari/604.1','27.73.116.176',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (22,360,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImJlZTNjMjM2LWFiODUtNDc0OC05NjQ5LWQ2MWQwYjA2YjUwYiIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzNjAiLCJqdGkiOiIyYTNjZmM2Yy01YzA1LTQ4M2YtYTJiMi1iNTUxNDBkMTk3OTkiLCJuYmYiOjE3Njc4MjczMjUsImV4cCI6MTc2Nzg4MTMyNSwiaWF0IjoxNzY3ODI3MzI1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.dVC0D-1GqKqtLBBWPtEIpwgFwxc9tEx5de01LAxqo7CUTWVoH_x9xqO85es72lXgboC1c61hm8zu4rCL0XoJgw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjlmNzhlMmM5LWY2NDYtNDM4Ny1iOTJkLWI3YmQ4NTE1MmVjYyIsIk1zaXNkbiI6ImphbmV2dWdsb2JhbEBnbWFpbC5jb20iLCJqdGkiOiJhNzQzOGU3OS03NTk5LTQxYzctOTcwNC05ODAwOTk5NThjMjMiLCJuYmYiOjE3Njc4MjczMjUsImV4cCI6MTc2Nzg4MTMyNSwiaWF0IjoxNzY3ODI3MzI1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.VvNpJ9UrzscbD5b-BI6aVOMS5-j7ZHMW-Xv3zjt52e2j96midpZoMarLKCqKqHVBWb83-PWbvTdNhjG0YY0oSA','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_7_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/143.0.7499.151 Mobile/15E148 Safari/604.1','27.73.116.176',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (23,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImMwMTk1ZDRhLWUzNDUtNGJhOC04MTBlLThjMzRiZDQ1ZTkxNCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6IjkwMmY3OTA2LTljY2EtNDUxOC05ZTdmLWU3YWUxYmY1MjgzYSIsIm5iZiI6MTc2NzgyNzYzMSwiZXhwIjoxNzY3ODgxNjMxLCJpYXQiOjE3Njc4Mjc2MzEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.AQOPflJ9D3f7mxv-HoJtfdMIdFIe1rDBxxRDgdE2kmu5h6FnW0LG122yfmeYJ6kkNmxZXI_TJd8DUJmXZ96ypw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6Ijk4MDI1MGVhLTBiYTYtNGQ5Ni04NTNjLWVjY2JhNTc1NmNhNCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjExNWFlZjEzLTFiMjYtNDMyMi04YzQzLTExNWQyZmEyNWEzYiIsIm5iZiI6MTc2NzgyNzYzMSwiZXhwIjoxNzY3ODgxNjMxLCJpYXQiOjE3Njc4Mjc2MzEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.-QamTykrcW9JkyUwDnUxrPgn6n03u-Y_5UEH4EiBYYIGZIMomco9qsutJJTJI9dxEbPR7GwCHGGQip4od2p1QQ','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_7_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/143.0.7499.151 Mobile/15E148 Safari/604.1','27.73.116.176',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (3,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjI4ZTViYWVkLWM5ODMtNGVmNC1iN2M1LTM2OWE5NmI3MDBhNSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIxMDIwN2FjNi00NGEwLTQzZjItODFhOS03MTYwOTdhNTJmMmUiLCJuYmYiOjE3Njc3NTM3ODksImV4cCI6MTc2NzgwNzc4OSwiaWF0IjoxNzY3NzUzNzg5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.9u1LqXX2HyHrAP2V01fxzbk6bUXqs0XJeM6vXLR2DqRrNU4WWl-0Cbd5sc8JLlWqYWTBH-SefJ3pn7gdsKcrBg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjY0NGNmYTZhLWJhNDQtNDJhOC1hY2JhLTQwMDI5OTViM2I2NCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI2NzQ2YzRlOS00ZTFkLTQzNjctYjc3My02NDBhYzI3NmQwNzMiLCJuYmYiOjE3Njc3NTM3ODksImV4cCI6MTc2NzgwNzc4OSwiaWF0IjoxNzY3NzUzNzg5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.IVVArlNNs1AFH_aYk39UqBqGQzgaAdnLO_NThc632CEAf6rQmYypNrFcKOIaBLLTZ1miWFrQGy8tIoXW5eUK2Q','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (5,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjJlOTk2YzliLWIyNzMtNDgyYi05ZDNlLTIzMjQxYmNkOTUwYiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJkYzZmODVlOS1jNjZiLTRhNTgtYjQ5Ny0wMmMzODQ2YTM5MWMiLCJuYmYiOjE3Njc3NTQwMDgsImV4cCI6MTc2NzgwODAwOCwiaWF0IjoxNzY3NzU0MDA4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.zz1jT6vbRwgETVWx1QIRFHJ4Q0j7OENEdv7GTx_3f_fnWEeLhE18JKuH2xNa_GITdZGEc0EcDIzOyVahk8Qqiw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjBiZjYzYjQyLTE2ODItNDRjNy05NzQ2LThmNDMxNjIzNjViNCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJlYmZiMmNjMC01OWM0LTQ4OTMtOGIxNS0xNzUxZDAzNjc0ZmQiLCJuYmYiOjE3Njc3NTQwMDgsImV4cCI6MTc2NzgwODAwOCwiaWF0IjoxNzY3NzU0MDA4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.5kbidrqtJwuvKm-6jKABCaotigDJg9fafx-MA1FVAt2IX9SYVe14ZJ5-lAXsBAPn_CLI9-yuTRL5M6BuEi9c1w','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (7,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjJlNDc5MmRiLTE4ZmYtNDBkYy1hZjJkLWEyNzU5MWQ1NGM5OCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI0Y2EyMzNjNy0xODVjLTQ0YTUtYTY5YS1iYWI2MWU3M2Q1YWMiLCJuYmYiOjE3Njc3NTQxNjMsImV4cCI6MTc2NzgwODE2MywiaWF0IjoxNzY3NzU0MTYzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.Kjke-Fqsr4hU1BtjUL67PuIYNudplz6WIw_ydfzvSVaQhcNoaXdvUgPc9ryo3jCwsp--BpTflM_KJI88PUt-YQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjBkOWZhMmRiLTkzMzctNGFhMy1hMDE0LWUzYWI2ODRhY2EwOCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJmZWJmYzFlNi0zNjA3LTQwYTItOTRiMS02NjgyYzA4MDAyMGQiLCJuYmYiOjE3Njc3NTQxNjMsImV4cCI6MTc2NzgwODE2MywiaWF0IjoxNzY3NzU0MTYzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.VhFebjBPyxgexA7hRdzAGxtCjhzd4jRabH3LvOv9mgdr05uiQSn7IxjHKOB2nsHTkEEkDnxCkOxMCQQqoC3DOw','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (13,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjlhOTRkZDZiLWI0OTctNDU5My1hOWVkLWFkZTFlODAzZGU5MSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJhNjZhNmRiYS05YmNkLTQ3OTktYTlkNS1mMDU4YjczYTc3NTYiLCJuYmYiOjE3Njc3NTc4ODAsImV4cCI6MTc2NzgxMTg4MCwiaWF0IjoxNzY3NzU3ODgwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.FUHyKbzwJIPXGjLpiS8E6rCP1-A292Cz0OqAHC3cqf3AUo1768IQOYKEPAwOet5Bzo__4iKL7LAFCncbxLHT0Q','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjA1YzUxYWE2LWM2NTItNGMwYy1iNzcwLWJmODBkYWI1MzhkYSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI3NzE4NjI5Zi0yZTg5LTQyZWUtYTVlYy02MWZlYTk1NTcyNTYiLCJuYmYiOjE3Njc3NTc4ODAsImV4cCI6MTc2NzgxMTg4MCwiaWF0IjoxNzY3NzU3ODgwLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.hy84VVznNmLxvm7EfKR_ykOQ3GATAnL3w9yswowba0mtJtbRxZCVQFeIqR9k-CabsuWZeSeacBvF9IPTTGxJrA','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (16,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImZlNTg0M2M1LThlOGItNDM5MC05YzE5LTg0NWU1NWE3Yjc3YSIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6ImJkMTJmYzRmLTM0OWQtNDMyMC1iYmI3LTk2YjMwMDgzM2VhOSIsIm5iZiI6MTc2Nzc3ODQwNywiZXhwIjoxNzY3ODMyNDA3LCJpYXQiOjE3Njc3Nzg0MDcsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.n0it2Bze1MOKdhtg6akPxHIg0x9arsdSp13BV8FW7tQwiSt0oBeV7TEV706SOR7Sp3Yrdgrgf1WaTa99UnXbyQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImUzZWNmZWVmLTYzZWUtNDY1MC05YmExLTkyMDI4MjMyZjVmOCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6ImNjNDk5MGZkLWZjMzAtNDE1Ny1hYjkyLWIzNmIwZTZmNDI0MCIsIm5iZiI6MTc2Nzc3ODQwNywiZXhwIjoxNzY3ODMyNDA3LCJpYXQiOjE3Njc3Nzg0MDcsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.p6Yjs7U0WLiSGut9mxXMUvYeNzGCqih_ceN2T-ZKvKxB11FZFxXkrDYkEGKgd8h4w9fb6uJRPBSH8alDbVKDMg','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (19,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjFjN2M4MTIzLTUyM2ItNDMyMy1iOTZmLWQxNWIzMjk5NzQwNiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI1OWFjYzAzMy00MWQwLTQ4N2MtOWU5ZC03ZjRlZGYxYzM1NzciLCJuYmYiOjE3Njc3OTEzOTcsImV4cCI6MTc2Nzg0NTM5NywiaWF0IjoxNzY3NzkxMzk3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.04gpFHYszT9u1HjFfHwRYZg2JH-cM4j9OOgoAjdXDj_87J7t7_8ZIV0GPvl1F42Nyn1CirvuGv1r5HUFi8V6Tg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjU1ZGY2OGRjLTE4ZTktNGJiOC05OWRjLWI2NWI1YzE3YjBhMCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJhZWMzMTIyMy03YzRjLTQyNzctOTk2Mi1lMGE1NjE3ZmJjN2YiLCJuYmYiOjE3Njc3OTEzOTcsImV4cCI6MTc2Nzg0NTM5NywiaWF0IjoxNzY3NzkxMzk3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.5FqTVcWRrtchr1FcBzEDm28iyARbcLEaxhAnKlvQTCjnvC6kygMO1DL-xhFzrFQ---asXbjiaaAlqrMq6E285w','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Mobile/15E148 Safari/604.1','104.28.71.150',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (24,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjVmYTk5YjM1LTFmNjAtNDY3Mi1iM2Q0LWZiMTM3OGQ2YTNhNCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI1YzgzOTY4MC1hMTQ0LTRhNmItODg0My01MDcxZTQ1ODZhODEiLCJuYmYiOjE3Njc4MzcwNDEsImV4cCI6MTc2Nzg5MTA0MSwiaWF0IjoxNzY3ODM3MDQxLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.U2Hp0GSJENE9WQzS8_IhD-lTe8RvOpUwr3eZraqnjCahQhkx42XFYkTvu_jzrrexe-Juk83uvVmPchUQ658ksg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImYxMDgzMjU2LTUzNGEtNGFmYi1iMWE3LTk4Y2NkNThlZWYxYyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI2YTlmM2NjYi04ODgwLTRmZDQtYWFjMi1mYWRkNjUwNzA1ZDQiLCJuYmYiOjE3Njc4MzcwNDEsImV4cCI6MTc2Nzg5MTA0MSwiaWF0IjoxNzY3ODM3MDQxLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.gGDHAM646P1Xnl5P9bKJ-euiGuWoUb4byuPszxUBhFcbcjYDVy5czclVnDV2T_bNNENkjk8rHGhd1fSOn8THFw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (6,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY2MmQzYTY2LWM5NjAtNDdjMy04MTA4LTczODI4NjQzZTBlOSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJkYjRlM2FkMy03NmUzLTRmZjgtOTdhNS1iODMwMGJkYTFkOTYiLCJuYmYiOjE3Njc3NTQwODUsImV4cCI6MTc2NzgwODA4NSwiaWF0IjoxNzY3NzU0MDg1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.JZUDt5lKgHKOxLgGfWhwDAZ5rjDMWOZJksFF4ge5QB0K1b7irn5hg4LdYVAXd3Vj4tNyoQTvotCcILvp54Z1cA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY1ODg0NmEzLTcxZTgtNDgxZS05YjM3LTA3NGU4MmMzMDkzMyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI3ZjVmZDc1Mi1iMWY4LTQ1YTEtOWFlMi04YWRjNjllMDU4MzciLCJuYmYiOjE3Njc3NTQwODUsImV4cCI6MTc2NzgwODA4NSwiaWF0IjoxNzY3NzU0MDg1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.4IRggxqt8wVGqzTSK1L6bcPx6jan-TD-Hj5MVHL9tGkLC7ltpirfYtgjIZz5_VPUnsRObMCkSwcjHh7XpOR9ow','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (18,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjU0YTg5MGJhLTQ5NzEtNDU2MS1hOTY2LTJiZmZjODliOTVkNiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJhODFhOGMyMi0yZDk0LTQxM2ItOTFmNC1jMGRkZGU0ZGZkN2IiLCJuYmYiOjE3Njc3ODAyMTksImV4cCI6MTc2NzgzNDIxOSwiaWF0IjoxNzY3NzgwMjE5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.9_xioUMwKRXhafpEcxZEXhDs5egSk8TogDiR5FCTPL6SP5OVKdie527UhhA5fItTgEOOpuimwoHLtc5siKhDRg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjAyMzBiYzUyLTdiNjktNDVkZi05ZGZkLTEzNjhhNmUzMmIwZSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJmZDgxZmMwZS0wMTA1LTRmZWItYTU1ZC0xM2ZjYzY1N2NhZDIiLCJuYmYiOjE3Njc3ODAyMTksImV4cCI6MTc2NzgzNDIxOSwiaWF0IjoxNzY3NzgwMjE5LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.G8QyuegzdfIrVOwZn9QnNTj_HhjNvlDEi6ZXxFVGcWRp2dytQjXz69jIcWRquECoQFVKGxjGmUwo57Gfs5tUbg','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('08-JAN-26','DD-MON-RR'),to_date('06-FEB-26','DD-MON-RR'),1,to_date('07-JAN-26','DD-MON-RR'),to_date('07-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (25,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjFlM2E0Yzg1LThhOGUtNDAyZi04MTQ2LWE3ZTJkYmRmMTZkYyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI4ODQ5ZjViNy01MmI3LTQ5NDEtYTNjOS03MTgzNDE0ZWVlMTAiLCJuYmYiOjE3Njc4Mzc3NjQsImV4cCI6MTc2Nzg5MTc2NCwiaWF0IjoxNzY3ODM3NzY0LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.wtgKWPJplvhDPBRcRCBRUqfuvDARAkMHnkoqT4r6fIYGFZx5WgmSQQs5LRdV-YLnQlaZTh3a3_qAwozZ1cWLwg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjhjOWMyNTA4LTk0NDQtNDNlZS1iZjkzLTEwNjMwZDMwMTM5YiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI3MDZjZTNmNC1mOTIyLTQ4NzYtOGU0MS00YjZmZDY1N2MzYWQiLCJuYmYiOjE3Njc4Mzc3NjQsImV4cCI6MTc2Nzg5MTc2NCwiaWF0IjoxNzY3ODM3NzY0LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.bvfFaoihe-GbBFKyx-X6fj5FqYiMCPMcxp8Bz5IBGCRlJwlnjvoYtoWL6hzWzXdyIL43LKb5j7evlibSZjMXKg','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (27,366,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6Ijc3YmNkYmQ4LTY0ODMtNGE0MC04OGY4LTY5NzRmYjgwNTc1MyIsIk1zaXNkbiI6ImtsaW5obmd1eWVuLnZpZXR0ZWNoQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjM2NiIsImp0aSI6IjA5OTcwNmU4LTAyZmUtNGUyOC05ZmEyLWFjNjlhM2Y4YjZhNCIsIm5iZiI6MTc2Nzg0NjIzNSwiZXhwIjoxNzY3OTAwMjM1LCJpYXQiOjE3Njc4NDYyMzUsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.nUOo3vH9WK8BKrTdEN9KDqzGeM0_QAXUJ-zlrEqSVEadw4cFA7NCyXVpzNUiHzn9KvaolXf0utEtxY4jYHqawg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjU2ZWRlZDI2LWE5NzctNGMyOC1iMjg0LWZiMGJmYWMwMjc1NCIsIk1zaXNkbiI6ImtsaW5obmd1eWVuLnZpZXR0ZWNoQGdtYWlsLmNvbSIsImp0aSI6IjBlYjMzZmUxLWE3ZmUtNGU0NC04ZTNiLTg0NTAxYjEwYzE3ZCIsIm5iZiI6MTc2Nzg0NjIzNSwiZXhwIjoxNzY3OTAwMjM1LCJpYXQiOjE3Njc4NDYyMzUsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.D20ZRRumCJe7klIApyos280JZ2SA2PVHycZIIFsQuWrnYmCpyyr-I9eREUGhPCm7fWoRRiJsRURzM1S-LJJ_xA','Bearer','Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),0,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (29,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjZmYTJkNGQxLTZmMmMtNDM3ZS1iNzhiLWI2MzA2MjkxMzUxZSIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6ImExZjViYzVhLWYyOTgtNDc1ZC04ODdmLTQ1ZGE5MGQ5NGI1NyIsIm5iZiI6MTc2Nzg2MjU0MywiZXhwIjoxNzY3OTE2NTQzLCJpYXQiOjE3Njc4NjI1NDMsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.L72Jb2kTB0qKHCkEyohd-5ojnopM1L3KinZWAEI79i0pbggmuMY4yHzmiRKCArpK6RSGf7A6e_qqAkkS8i8hDQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY5MDk1OWM3LWJjYWUtNDcyYy04MTQ2LWQ5NmNkZDc4Y2E5MSIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjAwMDZlOTk1LTMxYWEtNDUxZC1hZDlhLWRmNDA3NjZmNWQyNyIsIm5iZiI6MTc2Nzg2MjU0MywiZXhwIjoxNzY3OTE2NTQzLCJpYXQiOjE3Njc4NjI1NDMsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.hfg7_tqEqK6F3XS2UT5WQ3NoBki_OozYVcZ2PIuvqqDZ4wDn56xiNwOu2prB5uZFCqjPRx-2vtExzCjS-yu8zw','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (30,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQ1NDZlY2M4LTk5ZTYtNGNlYy1hNzEwLTA0MTYwOTNkNWQyZSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJmYjFjNTI3NC02Y2JlLTQwODctOTcwZS04NTFkZWU0MzBkMWQiLCJuYmYiOjE3Njc4NjMxMTMsImV4cCI6MTc2NzkxNzExMywiaWF0IjoxNzY3ODYzMTEzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.X9oSFB1NpSqT_UFa94_y_KX0JNG7140fZXgGNySGauzjFEDYcBMiw0hp8_5d_1i8tUfKDZ7PN99NdQ6Ieq2dow','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY4ZmI3MGNjLWQ1YzQtNDQwZS1hZGM0LTdjY2Q2MTJhYTA3NiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI1Mzk2N2QwZi02ZGFkLTQ2NDktOGI3NS1mNjBlZGJkYjc4YWEiLCJuYmYiOjE3Njc4NjMxMTMsImV4cCI6MTc2NzkxNzExMywiaWF0IjoxNzY3ODYzMTEzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.4crQjvkOmFdz61UtjVi3dpHaCPRVwI8I-DKCdQmmgiMVLmTJxfOPkKB-qzUhPubuOZSGqPv19I3EdOJxxZ8LAw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (31,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImEyZjg0YzQzLWVhNzItNDNhYy1iMzkxLWM1Y2NiNjk2MjZlMyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI2Mzc3ZjgzMS1iOWVkLTQzMzktOWVkYS1lNGVlY2JiZGFlNzYiLCJuYmYiOjE3Njc4NjMyMDcsImV4cCI6MTc2NzkxNzIwNywiaWF0IjoxNzY3ODYzMjA3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.0so6bCtD1hp7IZofGhrQylGUsYKPJAUlPiUhmM-rSIEz0rCvcuWTGK0-XmP4UlV48aDGlhVR6yu8DkAhznXOeg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImIzZDk0ZDE2LTE4YjktNDU2MC04NDI2LWFmMmExYmM2ODZmMiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIwNjY5N2NlYi03MWMwLTQwNjgtYWYyNC00OTYxZGU2N2Q1MzYiLCJuYmYiOjE3Njc4NjMyMDcsImV4cCI6MTc2NzkxNzIwNywiaWF0IjoxNzY3ODYzMjA3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.pQC3zaUVL604C9rNH3neaFUP91EjxjF7v49ArnDFtb5vuyjp2yKW2EggnGHUIBmuFElIB5vKDRDNsucdMJL41Q','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1','14.231.235.195',to_date('09-JAN-26','DD-MON-RR'),to_date('07-FEB-26','DD-MON-RR'),1,to_date('08-JAN-26','DD-MON-RR'),to_date('08-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (38,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjFjNGU0ZjMxLTQ5YjEtNGNhOC1hNmZiLWEyN2I1Mjg0YTAzNyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJjZjBkMjE4My04NGMyLTRiNzctYTc5Ni0yODI1YzZiMTVlNDciLCJuYmYiOjE3Njc5MjUxMDcsImV4cCI6MTc2Nzk3OTEwNywiaWF0IjoxNzY3OTI1MTA3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.EHD1EAL6GFSg-1kVqw8zunR230OCVN6QTYbNYv6AQ-Gk7QYspALV26lUtlbCurlZ5-Fa_HXET1icIsN2MnrNNQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImVlYmExMjRmLTcwMjQtNGIyNC04NjcxLTAwN2ZkMTU5ZGI5MyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI2ODVkNDZhMC1lMGJiLTRmYjktYWU3ZS03ZjY5MjkzMDliMDEiLCJuYmYiOjE3Njc5MjUxMDcsImV4cCI6MTc2Nzk3OTEwNywiaWF0IjoxNzY3OTI1MTA3LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.P0h_ZttZaC7rtI7MnxN6BhXZd5Ii_ooKXcxY_Ou_UEr59HwktKPaO8BbnDsuaSIjxC9UKmZbV4LqHf0mYiH8gg','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (46,400,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQ2YjIwMDE4LThlYjYtNGVhNi04ODk3LThkMGRlNjJjNjJlMyIsIk1zaXNkbiI6Imh1b25ndnR0QHZpZXR0ZWNoLmFzaWEiLCJBY2NvdW50SWQiOiI0MDAiLCJqdGkiOiJkOWZjZmZjOC1kNGVmLTQ4OTAtYjhhMS1lYzBjNGIxZmNlYjUiLCJuYmYiOjE3NjgwMDI1OTUsImV4cCI6MTc2ODA1NjU5NSwiaWF0IjoxNzY4MDAyNTk1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.RI_P3eS4vgSTR861jUcG2v0kkwo_HZswjuwszGDbuvgNN66U9H6GO5rdD5Zk-_R3Wj0-IGthrt-42atljXpfLQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImM5OTUzMGU3LWE3ODAtNGIwYS1iNzhkLTUwMjlmNzM2ZWM5OSIsIk1zaXNkbiI6Imh1b25ndnR0QHZpZXR0ZWNoLmFzaWEiLCJqdGkiOiJhNDM3YzQzYi0zNDNkLTQ5N2MtYmQzNi0xN2MyMGViZTQxMzQiLCJuYmYiOjE3NjgwMDI1OTUsImV4cCI6MTc2ODA1NjU5NSwiaWF0IjoxNzY4MDAyNTk1LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.6hPtXgX153EFD1xFWkev5mjyncjaqxHTKU1Z2iUfD5-BAYk5a38QGri-GPYjbufh7hkWputYTdZi_1evBnYlOA','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('11-JAN-26','DD-MON-RR'),to_date('09-FEB-26','DD-MON-RR'),0,to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (40,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjFkZjE1MjVlLTA5YzQtNGZmMS05ODIzLTBhYmI2MTRmZjIwNiIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6IjEzM2MwZTM1LTEwODItNDhhMS1hN2E2LTViODJjNDYyN2IyYSIsIm5iZiI6MTc2NzkzMTQ0NywiZXhwIjoxNzY3OTg1NDQ3LCJpYXQiOjE3Njc5MzE0NDcsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.4g5YvJvNlZZZE4toc2Uvx_ohN0BBt7eo6neCxym9kdw_-NBo9lWPdC5CdEfsvJ68hobA2qJS-9KXP-RCWoN9AQ','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjBmMTA2MDMyLWQyODUtNGIxNC05NTAxLWM0OWYzOTVhYWRmMCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjdiNDhmY2UzLTViYWItNDBlYy04MmEyLTFkNmYyNTFjODZiOCIsIm5iZiI6MTc2NzkzMTQ0NywiZXhwIjoxNzY3OTg1NDQ3LCJpYXQiOjE3Njc5MzE0NDcsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.MFl1fmv_54jvpp19O7csN1A184A_q8JMXY2ScxLbs2VW-otamDxSJYtrYos2KXU8FFrg7QfPWtXHZc_6obcwXg','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (41,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjkwYTdjYjRmLTVhOTktNDc5MC1iODA0LTBlZjJjNDI2MjQ0YiIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6IjY1ZTA2ZDVjLWZmMDktNDhmYi1hNGExLTBjOTYwNzU4MWY0NiIsIm5iZiI6MTc2NzkzMTUxMSwiZXhwIjoxNzY3OTg1NTExLCJpYXQiOjE3Njc5MzE1MTEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.Ax54JDrrs8syiweaCvmQSrqpZwncNvh7ZmoaNKASLJt2oAlY_EZckztqCNehAyPasNFVB2x22LOo1mUGehm3EA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImVkYmRjMWIwLWQ4ZWMtNGM5My1iYWMzLTU5YWJmZDEwNzNiYiIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjhkMTQ0YzI0LWNiZDAtNDIxNy1iNGVkLTU5MTg4ZWJjZTJhZCIsIm5iZiI6MTc2NzkzMTUxMSwiZXhwIjoxNzY3OTg1NTExLCJpYXQiOjE3Njc5MzE1MTEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.V69t9sGqqs4BNu3xgWY7ND7VNYu60SQgImRdA3nHMY-IvGf_4he3uCfdDIhyYXbbgMX5s-ib6GsFpzJcF38pcQ','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (42,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImUyYTljMTk3LWNiNDYtNDYzZi04YzQxLTUyOTQyMDAzMTYzYyIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6IjBjM2YxOTA1LTg2ODktNGY2OC05MzcwLWUzNDQxYTBiMWVlOSIsIm5iZiI6MTc2NzkzMTUzMCwiZXhwIjoxNzY3OTg1NTMwLCJpYXQiOjE3Njc5MzE1MzAsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.gFCgSaozHJ_TWsaODPf8gOBdgsW65P1nOYOmJRPDoSPqkkG_y5g7XMw_n7XlWvi9lIUjR7ym9GXfTpfAo6eEjA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjVjYjc5MTFiLWY4MjEtNGUyYS04N2FmLTI0YTgyODUwMjFiNSIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjZiYzg3MDA2LTI2NzgtNDQ0YS04OGE5LTZiYTgxNGQzZjA5MCIsIm5iZiI6MTc2NzkzMTUzMCwiZXhwIjoxNzY3OTg1NTMwLCJpYXQiOjE3Njc5MzE1MzAsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.RHHXOnzcxpSe2wTjVC627iCHV4cKSe3CFV1SKS627ujHORm5-mgtwo2Y75JJX8UqCi4sgONsa9E5F_IaCwcM5g','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (43,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjljMzk2YTc3LTE0ODUtNDM3NS1hZDE1LTA1MmI2ZDdmYzZjMyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiI2OTI5NTE3YS1hOWZkLTRjNTAtOTdjNC1mYzhhOWVkNWZkMDAiLCJuYmYiOjE3Njc5MzE2NDMsImV4cCI6MTc2Nzk4NTY0MywiaWF0IjoxNzY3OTMxNjQzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.abW4Z4l_1VpoGxi0UEybudwRrjdBkOb6Qma_OH2jlcl7_YcmoQ-AfIpFhIV8IDj6sN1jlJN4o2aiziUGyM-pXA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY3NGFjZjc3LWQ4ZTQtNGQyZS05NTdiLTRjN2U0NTc2MmRlMCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI5YTBlZjNiOS02MzA5LTQzMDYtYjNjMS0yZGUzMDMxODU5MWEiLCJuYmYiOjE3Njc5MzE2NDMsImV4cCI6MTc2Nzk4NTY0MywiaWF0IjoxNzY3OTMxNjQzLCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.9xkZ2TIgUsGdCDI2cs6MgU0cOlyAiijaghXhPCeuR96BkqBUaJKfLi0v0gzVjoZ5z5vRIJSv0VFGube1-eQu5w','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (44,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjY3NzRlMzRmLWNmYzctNGNiOS1hMTUxLTRmNjgwZmMzNThjNCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6ImE5NTFhODc4LTRhN2MtNDY0Yy1iM2I5LTVlY2M3NGZkN2Q1NCIsIm5iZiI6MTc2NzkzMTY4MSwiZXhwIjoxNzY3OTg1NjgxLCJpYXQiOjE3Njc5MzE2ODEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0._bcKFq5sqv25HBJ4LBIm_TxD52ynlC5w1ZnBIyIKLg7hoo07XNCgqmyMJGQLsnrbDNBEHlpOwV_dXtvH0RBkzg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImFlYzRjMjMzLTU3ODYtNDU5Ni04ZGY1LWU3OWQwMjYzNjZkNyIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6IjA1YzMxMGM2LWUwNDctNDlhMS05YTJiLTk3MmViZmM2YzBiNCIsIm5iZiI6MTc2NzkzMTY4MSwiZXhwIjoxNzY3OTg1NjgxLCJpYXQiOjE3Njc5MzE2ODEsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.6-D3xXTpHA-_rVYCZCYbUPRAeGfGD9Mxp4tW1tt9c2JrgwXdwViHuzNDt11C07h87gK4qYOv45qwrbkHgekxAA','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),0,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (36,305,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImU0YzM5NTU0LTVjMzYtNDUzMC1iOGYzLTc3OWRlNmZlMWI0MCIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjMwNSIsImp0aSI6ImIyYjM3YzUwLWY5YWItNDA0My05ZjNiLWVmYjNjY2MxZDljOCIsIm5iZiI6MTc2NzkxNjcwOCwiZXhwIjoxNzY3OTcwNzA4LCJpYXQiOjE3Njc5MTY3MDgsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.82sMQWk1uemm4EBIqH87N01yF4ODa6vm6YsRELfznExxThB6B0m6QOulVeFitgu67antVz_8VPEgZWySjolzOA','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjQ0ZjNlZmRmLTkyMjktNDAxYi04YjBjLWFjMTJlYWE3NDM2YiIsIk1zaXNkbiI6InRoYW5oaHVvbmcxNzEwQGdtYWlsLmNvbSIsImp0aSI6ImZhODdiODNiLWNhOGItNDU1Ny1iN2RkLWVmOTllZGFjNWMwMCIsIm5iZiI6MTc2NzkxNjcwOCwiZXhwIjoxNzY3OTcwNzA4LCJpYXQiOjE3Njc5MTY3MDgsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.99v6oTdbrJpT_FnVJirzgKYZwgX71r-X81Ot6eYUd4qipP0VQL9LiFdeUrihlI_DPueaIgQwOtGDcZQ99F0pUw','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (47,420,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjMxNjdjZTkzLWJiZWItNDY2Ni1iZTI0LTRhMmUwNzE1NGZiZSIsIk1zaXNkbiI6ImdpYWRpbmh0aGFueWV1azEzQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjQyMCIsImp0aSI6IjI0NTJmOTI5LTgzMTMtNGUzOS1hMjA4LTJiODRhOGU4Yjc3MiIsIm5iZiI6MTc2ODAxMDgwMCwiZXhwIjoxNzY4MDY0ODAwLCJpYXQiOjE3NjgwMTA4MDAsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.6Qjl5xXIDGpKAzY8WtqAIBzKlR5Sy00JWWAnaI1mycxxXxGlK89IlICIVOrvwZXmUs9KcG3qd8BQcfwoabIlQg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImRhZmZjYzM4LTI5NGUtNGYxOC1hMTUwLThjMzZiYTBmZjNjNCIsIk1zaXNkbiI6ImdpYWRpbmh0aGFueWV1azEzQGdtYWlsLmNvbSIsImp0aSI6IjQ3NmU0OTZiLTdhZTAtNDQxOS04NTczLWZhNTdmNjgxMDNiNSIsIm5iZiI6MTc2ODAxMDgwMCwiZXhwIjoxNzY4MDY0ODAwLCJpYXQiOjE3NjgwMTA4MDAsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.bfcbW9NffQ2Swv1sTN2M8FRuotriJlPPn9qql2hd9QFBqYW5J0IReeXoIKTE6D04r4eyGjLU2VERvbstMpejoA','Bearer','Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1 Mobile/15E148 Safari/604.1','104.28.68.156',to_date('11-JAN-26','DD-MON-RR'),to_date('09-FEB-26','DD-MON-RR'),0,to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (49,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjIzY2M5OGY4LWVkODMtNDIyYS04M2Q1LTc0YWQ3OWFhYTRhOSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiIyMDQxYmFkYi1iM2ZlLTRlNzctYWQ3NS0xY2EzOWEyOWM2MTkiLCJuYmYiOjE3NjgxNzMxNDYsImV4cCI6MTc2ODIyNzE0NiwiaWF0IjoxNzY4MTczMTQ2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.__rA6XZqN67SWVveBEazDIp2s7FibzyKusfEMX6La6ZRiCvuOpzHrV2S1YbAkGGOMG-7iAjjJ8r2Y2D5o_b67Q','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImNjNDY5YzAyLTc0M2EtNGNmYi04OGQyLTEyODc0MDZlN2Y2NiIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiI5NmUzOGM2YS05ODg5LTRjMjMtYjY3YS0xMDJkNGNiOWY4ODkiLCJuYmYiOjE3NjgxNzMxNDYsImV4cCI6MTc2ODIyNzE0NiwiaWF0IjoxNzY4MTczMTQ2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.miuFCCNh6jwg9v8KCzlFY2bJQkhUu1Xj9xzc33IJ9SF8nUOyqOKIOC9y9wgqQ1C0_JU4qp4g7grdsdCbgtRUYg','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','27.73.116.176',to_date('13-JAN-26','DD-MON-RR'),to_date('11-FEB-26','DD-MON-RR'),0,to_date('12-JAN-26','DD-MON-RR'),to_date('12-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (48,421,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY0OGVmNTE3LTAyYzgtNDU0Mi04NjIzLWJiMjQxMTg3NzZiZiIsIk1zaXNkbiI6Im52dDMxNUBnbWFpbC5jb20iLCJBY2NvdW50SWQiOiI0MjEiLCJqdGkiOiI2NTA4YjZlMC1hOWQyLTRjNzYtOGU2YS1lYTI1MGNkOWZmN2MiLCJuYmYiOjE3NjgwMTE5NzgsImV4cCI6MTc2ODA2NTk3OCwiaWF0IjoxNzY4MDExOTc4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.jWVbrjzsbEQtU0VCAlCZ0F9IIl5BG4AAovYn5aYxqDL-REigZ3R4oEKa9dA9do9DP0JjAQ_HaAL2Ao_f1scP2A','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjM4MjE4NTRkLWNlMWYtNDVkYi1iM2U2LTUxMjM0M2EwOGE3MyIsIk1zaXNkbiI6Im52dDMxNUBnbWFpbC5jb20iLCJqdGkiOiJlMjIxZDc5MS1lOTYxLTQ1YzItYTJkNi1mYzdmODY4ZDYzNjMiLCJuYmYiOjE3NjgwMTE5NzgsImV4cCI6MTc2ODA2NTk3OCwiaWF0IjoxNzY4MDExOTc4LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.U8evBDESX2nqC-aGdcp_fqrOc2ub6R3D7N05MT9iC8wzoRmURlYKi5Z5_HohRmiztyxd-Byj7WX5VDgsnuQu_Q','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('11-JAN-26','DD-MON-RR'),to_date('09-FEB-26','DD-MON-RR'),0,to_date('10-JAN-26','DD-MON-RR'),to_date('10-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (37,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImQ5NjU5MmZkLWEyZjUtNGQwNC1hNDdlLTNiYjc2NmNjMWE3YSIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJiMzVlMGRkNS1hYThlLTRmZTYtOTFlMS02NTEyNjQyMDMwMDAiLCJuYmYiOjE3Njc5MjUwNDYsImV4cCI6MTc2Nzk3OTA0NiwiaWF0IjoxNzY3OTI1MDQ2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.cTbToi2mSv2hj4xnyLwS6PileW-mU0PpOYtPEfUkbwMfQJH2MfxczVZDqb7TFG23Bj5DFI7BRvHd6C9RZ1EOAg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjZlZjg3MGNkLWE5MzItNDU5ZC05ODNmLTRhN2Y1MGY3ZTU1ZCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiIxODM1MmQ4NS0yYTdlLTRjNjAtYjdiNC01ZDJjYWM5ZjBkNjYiLCJuYmYiOjE3Njc5MjUwNDYsImV4cCI6MTc2Nzk3OTA0NiwiaWF0IjoxNzY3OTI1MDQ2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.-NlR58Uv6ZLNDzUTRYDK8ILVQKuPDS22R5ZkoKli3znLP2xeKz9pf8WWVHmfCRjQ2rBn5Sd8KuS2W8kaVlsVjg','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (39,320,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6ImY2ZTM1Njg4LTVkNzktNDgxNC1iNDAyLTQ3ZGUyOTEyNTA3MyIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJBY2NvdW50SWQiOiIzMjAiLCJqdGkiOiJjNDliM2E1NS0zNWZjLTQyNTktOGQ4OS1lYzMyNTI4ZTJmODciLCJuYmYiOjE3Njc5MjUzMTYsImV4cCI6MTc2Nzk3OTMxNiwiaWF0IjoxNzY3OTI1MzE2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.JdCLellgJBt6EF0jGjCi5Xa7IZ3X9tf2Ychfy8RKw9g5klBTzTJsA5gDhJuA2nueSpmzLJza79F1VcRCLjARRw','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjZlNWRhYWI2LTUyZGEtNGIxNS05YjUwLWRhNjIwYzFlMTk4MCIsIk1zaXNkbiI6ImFiY0BnbWFpbC5jb20iLCJqdGkiOiJlOGVmNDM4ZS1hMmJhLTQzZDktOGY5Ny1iMjA0YmVhMWVlYWMiLCJuYmYiOjE3Njc5MjUzMTYsImV4cCI6MTc2Nzk3OTMxNiwiaWF0IjoxNzY3OTI1MzE2LCJpc3MiOiJFc2ltTGFvIiwiYXVkIjoiRXNpbUxhb0NsaWVudCJ9.BWXw1AohT24eNdmeBS8Pkg0OhVFVYr_YqnM5dfSG1hBoOtDBXrdCz1KL7t10QfE8MXrK9FPqzZHvNjorjtAZeg','Bearer','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),1,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+Insert into USER_TOKEN (ID,CUSTOMER_ID,ACCESS_TOKEN,REFRESH_TOKEN,TOKEN_TYPE,DEVICE_INFO,IP_ADDRESS,EXPIRED_AT,REFRESH_EXPIRED_AT,IS_REVOKED,CREATED_DATE,LAST_USED) values (45,240,'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjBmZTY1ZTFlLTU5NzAtNDhmZi1iODY3LWUzYzlmNjg0OTcxMyIsIk1zaXNkbiI6Im52dGE4aHAwQGdtYWlsLmNvbSIsIkFjY291bnRJZCI6IjI0MCIsImp0aSI6IjZmMmQwMTc0LTVjYmQtNDU3Ny04MjMwLWQyNGVhZDFhYzFhZSIsIm5iZiI6MTc2Nzk0MzYyNiwiZXhwIjoxNzY3OTk3NjI2LCJpYXQiOjE3Njc5NDM2MjYsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.NwLBnfpEsT40RoBvO1wXG3ItRIxtFKidarz8OGeF49eMQB6okc9kV1bO1nes0IlCHfp7Av-5zEdn5xdH47ffdg','eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjdiYmE0ZjRhLTU4ODAtNDEwZS1hMjdhLWYyOTYwMDMyOWVmNCIsIk1zaXNkbiI6Im52dGE4aHAwQGdtYWlsLmNvbSIsImp0aSI6IjM2ZWIzYWY0LTg3ZDktNGViNi05MDFhLTY5YzExMzMwNDU2ZSIsIm5iZiI6MTc2Nzk0MzYyNiwiZXhwIjoxNzY3OTk3NjI2LCJpYXQiOjE3Njc5NDM2MjYsImlzcyI6IkVzaW1MYW8iLCJhdWQiOiJFc2ltTGFvQ2xpZW50In0.COIF-_L6Gqb_JonpeYCNf2N9jbxSJSQDaDAHQyvpRqcSJVyXWmVeZiyrc7wa_08nS91dIu_VJYLbcB5UC1QXIw','Bearer','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36','14.231.235.195',to_date('10-JAN-26','DD-MON-RR'),to_date('08-FEB-26','DD-MON-RR'),0,to_date('09-JAN-26','DD-MON-RR'),to_date('09-JAN-26','DD-MON-RR'));
+--------------------------------------------------------
+--  DDL for Index ARTICLE_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "ARTICLE_PK" ON "ARTICLE" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index ARTICLE_SLUG_LANG_UQ
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "ARTICLE_SLUG_LANG_UQ" ON "ARTICLE" ("SLUG", "LANGUAGE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index ARTICLE_CATEGORY_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "ARTICLE_CATEGORY_IDX" ON "ARTICLE" ("CATEGORY_ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index ARTICLE_STATUS_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "ARTICLE_STATUS_IDX" ON "ARTICLE" ("STATUS", "PUBLISHED_DATE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index ARTICLE_CATEGORY_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "ARTICLE_CATEGORY_PK" ON "ARTICLE_CATEGORY" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index BANNER_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "BANNER_PK" ON "BANNER" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CMS_CONTENT_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CMS_CONTENT_PK" ON "CMS_CONTENT" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CMS_CONTENT_CODE_LANG_UQ
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CMS_CONTENT_CODE_LANG_UQ" ON "CMS_CONTENT" ("PAGE_CODE", "LANGUAGE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CMS_CONTENT_SLUG_UQ
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CMS_CONTENT_SLUG_UQ" ON "CMS_CONTENT" ("PAGE_SLUG", "LANGUAGE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CONFIG_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CONFIG_PK" ON "CONFIG" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CONTACT_FORM_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CONTACT_FORM_PK" ON "CONTACT_FORM" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS ;
+--------------------------------------------------------
+--  DDL for Index CUSTOMER_INFO_EMAIL_UQ
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CUSTOMER_INFO_EMAIL_UQ" ON "CUSTOMER_INFO" ("EMAIL") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index CUSTOMER_REVIEW_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "CUSTOMER_REVIEW_PK" ON "CUSTOMER_REVIEW" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index SYS_C00174194
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "SYS_C00174194" ON "DEVICE_ESIM_COMPATIBILITY" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index IDX_DEVICE_BRAND
+--------------------------------------------------------
+
+  CREATE INDEX "IDX_DEVICE_BRAND" ON "DEVICE_ESIM_COMPATIBILITY" ("BRAND") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index IDX_DEVICE_MODEL
+--------------------------------------------------------
+
+  CREATE INDEX "IDX_DEVICE_MODEL" ON "DEVICE_ESIM_COMPATIBILITY" ("MODEL_NAME") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index IDX_DEVICE_POPULAR
+--------------------------------------------------------
+
+  CREATE INDEX "IDX_DEVICE_POPULAR" ON "DEVICE_ESIM_COMPATIBILITY" ("IS_POPULAR", "STATUS") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index IDX_DEVICE_CATEGORY
+--------------------------------------------------------
+
+  CREATE INDEX "IDX_DEVICE_CATEGORY" ON "DEVICE_ESIM_COMPATIBILITY" ("CATEGORY", "STATUS") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index FAQ_CATEGORY_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "FAQ_CATEGORY_IDX" ON "FAQ" ("CATEGORY_ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index FAQ_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "FAQ_PK" ON "FAQ" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index FAQ_CATEGORY_PARENT_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "FAQ_CATEGORY_PARENT_IDX" ON "FAQ_CATEGORY" ("PARENT_ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index FAQ_CATEGORY_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "FAQ_CATEGORY_PK" ON "FAQ_CATEGORY" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "MESSAGE_QUEUE_PK" ON "MESSAGE_QUEUE" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_STATUS_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "MESSAGE_QUEUE_STATUS_IDX" ON "MESSAGE_QUEUE" ("STATUS", "PRIORITY", "SCHEDULED_AT") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_HIS_STATUS_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "MESSAGE_QUEUE_HIS_STATUS_IDX" ON "MESSAGE_QUEUE_HIS" ("STATUS", "MOVED_DATE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_HIS_RECIPIENT_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "MESSAGE_QUEUE_HIS_RECIPIENT_IDX" ON "MESSAGE_QUEUE_HIS" ("RECIPIENT", "MOVED_DATE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_HIS_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "MESSAGE_QUEUE_HIS_PK" ON "MESSAGE_QUEUE_HIS" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_QUEUE_HIS_DATE_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "MESSAGE_QUEUE_HIS_DATE_IDX" ON "MESSAGE_QUEUE_HIS" ("MOVED_DATE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_TEMPLATE_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "MESSAGE_TEMPLATE_PK" ON "MESSAGE_TEMPLATE" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index MESSAGE_TEMPLATE_CODE_UQ
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "MESSAGE_TEMPLATE_CODE_UQ" ON "MESSAGE_TEMPLATE" ("TEMPLATE_CODE") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index OTP_VERIFICATION_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "OTP_VERIFICATION_PK" ON "OTP_VERIFICATION" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index OTP_EMAIL_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "OTP_EMAIL_IDX" ON "OTP_VERIFICATION" ("USER_EMAIL", "IS_USED") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index USER_TOKEN_PK
+--------------------------------------------------------
+
+  CREATE UNIQUE INDEX "USER_TOKEN_PK" ON "USER_TOKEN" ("ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index USER_TOKEN_CUSTOMER_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "USER_TOKEN_CUSTOMER_IDX" ON "USER_TOKEN" ("CUSTOMER_ID") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  DDL for Index USER_TOKEN_ACCESS_IDX
+--------------------------------------------------------
+
+  CREATE INDEX "USER_TOKEN_ACCESS_IDX" ON "USER_TOKEN" ("ACCESS_TOKEN") 
+  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
+--------------------------------------------------------
+--  Constraints for Table ARTICLE
+--------------------------------------------------------
+
+  ALTER TABLE "ARTICLE" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE" MODIFY ("TITLE" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE" MODIFY ("SLUG" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE" ADD CONSTRAINT "ARTICLE_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table ARTICLE_CATEGORY
+--------------------------------------------------------
+
+  ALTER TABLE "ARTICLE_CATEGORY" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE_CATEGORY" MODIFY ("CATEGORY_NAME" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE_CATEGORY" MODIFY ("CATEGORY_SLUG" NOT NULL ENABLE);
+  ALTER TABLE "ARTICLE_CATEGORY" ADD CONSTRAINT "ARTICLE_CATEGORY_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table BANNER
+--------------------------------------------------------
+
+  ALTER TABLE "BANNER" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "BANNER" MODIFY ("IMAGE_URL" NOT NULL ENABLE);
+  ALTER TABLE "BANNER" ADD CONSTRAINT "BANNER_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table CMS_CONTENT
+--------------------------------------------------------
+
+  ALTER TABLE "CMS_CONTENT" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "CMS_CONTENT" MODIFY ("PAGE_CODE" NOT NULL ENABLE);
+  ALTER TABLE "CMS_CONTENT" MODIFY ("PAGE_TITLE" NOT NULL ENABLE);
+  ALTER TABLE "CMS_CONTENT" MODIFY ("PAGE_SLUG" NOT NULL ENABLE);
+  ALTER TABLE "CMS_CONTENT" ADD CONSTRAINT "CMS_CONTENT_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table CONFIG
+--------------------------------------------------------
+
+  ALTER TABLE "CONFIG" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "CONFIG" MODIFY ("NAME" NOT NULL ENABLE);
+  ALTER TABLE "CONFIG" MODIFY ("VALUE_LOCAL" NOT NULL ENABLE);
+  ALTER TABLE "CONFIG" MODIFY ("VALUE_GLOBAL" NOT NULL ENABLE);
+  ALTER TABLE "CONFIG" MODIFY ("TYPE" NOT NULL ENABLE);
+  ALTER TABLE "CONFIG" ADD CONSTRAINT "CONFIG_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table CONTACT_FORM
+--------------------------------------------------------
+
+  ALTER TABLE "CONTACT_FORM" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "CONTACT_FORM" MODIFY ("FULL_NAME" NOT NULL ENABLE);
+  ALTER TABLE "CONTACT_FORM" MODIFY ("EMAIL" NOT NULL ENABLE);
+  ALTER TABLE "CONTACT_FORM" MODIFY ("MESSAGE" NOT NULL ENABLE);
+  ALTER TABLE "CONTACT_FORM" ADD CONSTRAINT "CONTACT_FORM_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS  ENABLE;
+--------------------------------------------------------
+--  Constraints for Table CUSTOMER_REVIEW
+--------------------------------------------------------
+
+  ALTER TABLE "CUSTOMER_REVIEW" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "CUSTOMER_REVIEW" MODIFY ("CUSTOMER_NAME" NOT NULL ENABLE);
+  ALTER TABLE "CUSTOMER_REVIEW" MODIFY ("REVIEW_CONTENT" NOT NULL ENABLE);
+  ALTER TABLE "CUSTOMER_REVIEW" ADD CONSTRAINT "CUSTOMER_REVIEW_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table DEVICE_ESIM_COMPATIBILITY
+--------------------------------------------------------
+
+  ALTER TABLE "DEVICE_ESIM_COMPATIBILITY" MODIFY ("BRAND" NOT NULL ENABLE);
+  ALTER TABLE "DEVICE_ESIM_COMPATIBILITY" MODIFY ("MODEL_NAME" NOT NULL ENABLE);
+  ALTER TABLE "DEVICE_ESIM_COMPATIBILITY" ADD PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table FAQ
+--------------------------------------------------------
+
+  ALTER TABLE "FAQ" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "FAQ" MODIFY ("QUESTION" NOT NULL ENABLE);
+  ALTER TABLE "FAQ" ADD CONSTRAINT "FAQ_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table FAQ_CATEGORY
+--------------------------------------------------------
+
+  ALTER TABLE "FAQ_CATEGORY" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "FAQ_CATEGORY" MODIFY ("CATEGORY_NAME" NOT NULL ENABLE);
+  ALTER TABLE "FAQ_CATEGORY" MODIFY ("CATEGORY_SLUG" NOT NULL ENABLE);
+  ALTER TABLE "FAQ_CATEGORY" ADD CONSTRAINT "FAQ_CATEGORY_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table MESSAGE_QUEUE
+--------------------------------------------------------
+
+  ALTER TABLE "MESSAGE_QUEUE" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE" MODIFY ("RECIPIENT" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE" ADD CONSTRAINT "MESSAGE_QUEUE_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table MESSAGE_QUEUE_HIS
+--------------------------------------------------------
+
+  ALTER TABLE "MESSAGE_QUEUE_HIS" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE_HIS" MODIFY ("MESSAGE_TYPE" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE_HIS" MODIFY ("RECIPIENT" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE_HIS" MODIFY ("STATUS" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_QUEUE_HIS" ADD CONSTRAINT "MESSAGE_QUEUE_HIS_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table MESSAGE_TEMPLATE
+--------------------------------------------------------
+
+  ALTER TABLE "MESSAGE_TEMPLATE" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_TEMPLATE" MODIFY ("TEMPLATE_CODE" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_TEMPLATE" MODIFY ("TEMPLATE_NAME" NOT NULL ENABLE);
+  ALTER TABLE "MESSAGE_TEMPLATE" ADD CONSTRAINT "MESSAGE_TEMPLATE_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table OTP_VERIFICATION
+--------------------------------------------------------
+
+  ALTER TABLE "OTP_VERIFICATION" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "OTP_VERIFICATION" MODIFY ("USER_EMAIL" NOT NULL ENABLE);
+  ALTER TABLE "OTP_VERIFICATION" MODIFY ("OTP_CODE" NOT NULL ENABLE);
+  ALTER TABLE "OTP_VERIFICATION" MODIFY ("EXPIRED_AT" NOT NULL ENABLE);
+  ALTER TABLE "OTP_VERIFICATION" ADD CONSTRAINT "OTP_VERIFICATION_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Constraints for Table USER_TOKEN
+--------------------------------------------------------
+
+  ALTER TABLE "USER_TOKEN" MODIFY ("ID" NOT NULL ENABLE);
+  ALTER TABLE "USER_TOKEN" MODIFY ("CUSTOMER_ID" NOT NULL ENABLE);
+  ALTER TABLE "USER_TOKEN" MODIFY ("ACCESS_TOKEN" NOT NULL ENABLE);
+  ALTER TABLE "USER_TOKEN" MODIFY ("EXPIRED_AT" NOT NULL ENABLE);
+  ALTER TABLE "USER_TOKEN" ADD CONSTRAINT "USER_TOKEN_PK" PRIMARY KEY ("ID")
+  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
+  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
+  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
+  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ENABLE;
+--------------------------------------------------------
+--  Ref Constraints for Table ARTICLE
+--------------------------------------------------------
+
+  ALTER TABLE "ARTICLE" ADD CONSTRAINT "ARTICLE_CATEGORY_FK" FOREIGN KEY ("CATEGORY_ID")
+	  REFERENCES "ARTICLE_CATEGORY" ("ID") ENABLE;
+--------------------------------------------------------
+--  Ref Constraints for Table ARTICLE_CATEGORY
+--------------------------------------------------------
+
+  ALTER TABLE "ARTICLE_CATEGORY" ADD CONSTRAINT "ARTICLE_CATEGORY_PARENT_FK" FOREIGN KEY ("PARENT_ID")
+	  REFERENCES "ARTICLE_CATEGORY" ("ID") ENABLE;
+--------------------------------------------------------
+--  Ref Constraints for Table FAQ
+--------------------------------------------------------
+
+  ALTER TABLE "FAQ" ADD CONSTRAINT "FAQ_CATEGORY_FK" FOREIGN KEY ("CATEGORY_ID")
+	  REFERENCES "FAQ_CATEGORY" ("ID") ENABLE;
+--------------------------------------------------------
+--  Ref Constraints for Table FAQ_CATEGORY
+--------------------------------------------------------
+
+  ALTER TABLE "FAQ_CATEGORY" ADD CONSTRAINT "FAQ_CATEGORY_PARENT_FK" FOREIGN KEY ("PARENT_ID")
+	  REFERENCES "FAQ_CATEGORY" ("ID") ENABLE;

+ 130 - 81
EsimLao/Esim.Apis/Business/Article/ArticleBusinessImpl.cs

@@ -46,7 +46,7 @@ namespace Esim.Apis.Business
 
                 // Query categories
                 var query = dbContext.ArticleCategories
-                    .Where(c => c.Status == true);
+                    .Where(c => c.Status.HasValue && c.Status.Value);
 
                 // Filter by parent category
                 if (request.parentId.HasValue)
@@ -71,20 +71,20 @@ namespace Esim.Apis.Business
                     .Select(c => new
                     {
                         c.Id,
-                        categoryName = lang == "en"
-                            ? (c.CategoryNameEn ?? c.CategoryName)
-                            : (c.CategoryNameLo ?? c.CategoryName),
+                        categoryName = lang == "en" ? (c.CategoryNameEn ?? c.CategoryName)
+                                     : lang == "vi" ? c.CategoryName
+                                     : (c.CategoryNameLo ?? c.CategoryName),
                         c.CategorySlug,
-                        description = lang == "en"
-                            ? (c.DescriptionEn ?? c.Description)
-                            : (c.DescriptionLo ?? c.Description),
+                        description = lang == "en" ? (c.DescriptionEn ?? c.Description)
+                                    : lang == "vi" ? c.Description
+                                    : (c.DescriptionLo ?? c.Description),
                         c.IconUrl,
                         c.ParentId,
                         c.DisplayOrder
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log,
                     url,
                     json,
@@ -107,7 +107,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log,
                 url,
                 json,
@@ -131,71 +131,9 @@ namespace Esim.Apis.Business
                 int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                 int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
 
-                // If slug is provided, return single article detail
-                if (!string.IsNullOrEmpty(request.slug))
-                {
-                    var article = dbContext.Articles
-                        .Where(a => a.Slug == request.slug && a.Status == true)
-                        .Select(a => new
-                        {
-                            a.Id,
-                            title = lang == "en"
-                                ? (a.TitleEn ?? a.Title)
-                                : (a.TitleLo ?? a.Title),
-                            a.Slug,
-                            summary = lang == "en"
-                                ? (a.SummaryEn ?? a.Summary)
-                                : (a.SummaryLo ?? a.Summary),
-                            content = lang == "en"
-                                ? (a.ContentEn ?? a.Content)
-                                : (a.ContentLo ?? a.Content),
-                            a.ThumbnailUrl,
-                            a.CoverImageUrl,
-                            metaDescription = lang == "en"
-                                ? (a.MetaDescriptionEn ?? a.MetaDescription)
-                                : (a.MetaDescriptionLo ?? a.MetaDescription),
-                            a.MetaKeywords,
-                            a.CategoryId,
-                            a.ViewCount,
-                            a.IsFeatured,
-                            a.PublishedDate,
-                            a.CreatedDate
-                        })
-                        .FirstOrDefault();
-
-                    if (article == null)
-                    {
-                        return ApiResponseHelper.BuildResponse(
-                            log,
-                            url,
-                            json,
-                            CommonErrorCode.Error,
-                            ConfigManager.Instance.GetConfigWebValue("ARTICLE_NOT_FOUND", lang),
-                            new { }
-                        );
-                    }
-
-                    // Increment view count
-                    var articleEntity = dbContext.Articles.FirstOrDefault(a => a.Slug == request.slug);
-                    if (articleEntity != null)
-                    {
-                        articleEntity.ViewCount = (articleEntity.ViewCount ?? 0) + 1;
-                        await dbContext.SaveChangesAsync();
-                    }
-
-                    return ApiResponseHelper.BuildResponse(
-                        log,
-                        url,
-                        json,
-                        CommonErrorCode.Success,
-                        ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
-                        new { article }
-                    );
-                }
-
                 // Query articles list
                 var query = dbContext.Articles
-                    .Where(a => a.Status == true);
+                    .Where(a => a.Status.HasValue && a.Status.Value);
 
                 // Filter by category
                 if (request.categoryId.HasValue)
@@ -206,7 +144,7 @@ namespace Esim.Apis.Business
                 // Filter by featured
                 if (request.isFeatured.HasValue && request.isFeatured.Value)
                 {
-                    query = query.Where(a => a.IsFeatured == true);
+                    query = query.Where(a => a.IsFeatured.HasValue && a.IsFeatured.Value);
                 }
 
                 // Get total count for pagination
@@ -223,13 +161,13 @@ namespace Esim.Apis.Business
                     .Select(a => new
                     {
                         a.Id,
-                        title = lang == "en"
-                            ? (a.TitleEn ?? a.Title)
-                            : (a.TitleLo ?? a.Title),
+                        title = lang == "en" ? (a.TitleEn ?? a.Title)
+                              : lang == "vi" ? a.Title
+                              : (a.TitleLo ?? a.Title),
                         a.Slug,
-                        summary = lang == "en"
-                            ? (a.SummaryEn ?? a.Summary)
-                            : (a.SummaryLo ?? a.Summary),
+                        summary = lang == "en" ? (a.SummaryEn ?? a.Summary)
+                                : lang == "vi" ? a.Summary
+                                : (a.SummaryLo ?? a.Summary),
                         a.ThumbnailUrl,
                         a.CategoryId,
                         a.ViewCount,
@@ -239,7 +177,7 @@ namespace Esim.Apis.Business
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log,
                     url,
                     json,
@@ -262,7 +200,118 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log,
+                url,
+                json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Get article detail by ID or slug
+        /// </summary>
+        public async Task<IActionResult> ArticleDetail(HttpRequest httpRequest, ArticleDetailReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+            try
+            {
+                // Validate request - must have either id or slug
+                if (!request.id.HasValue)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.RequiredFieldMissing,
+                        ConfigManager.Instance.GetConfigWebValue("REQUIRED_FIELD_MISSING"),
+                        new { }
+                    );
+                }
+
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                // Query by ID or slug
+                var query = dbContext.Articles.Where(a => a.Status.HasValue && a.Status.Value);
+
+                if (request.id.HasValue)
+                {
+                    query = query.Where(a => a.Id == request.id.Value);
+                }
+                else if (!string.IsNullOrEmpty(request.slug))
+                {
+                    query = query.Where(a => a.Slug == request.slug);
+                }
+
+                var article = query
+                    .Select(a => new
+                    {
+                        a.Id,
+                        title = lang == "en" ? (a.TitleEn ?? a.Title)
+                              : lang == "vi" ? a.Title
+                              : (a.TitleLo ?? a.Title),
+                        a.Slug,
+                        summary = lang == "en" ? (a.SummaryEn ?? a.Summary)
+                                : lang == "vi" ? a.Summary
+                                : (a.SummaryLo ?? a.Summary),
+                        content = lang == "en" ? (a.ContentEn ?? a.Content)
+                                : lang == "vi" ? a.Content
+                                : (a.ContentLo ?? a.Content),
+                        a.ThumbnailUrl,
+                        a.CoverImageUrl,
+                        metaDescription = lang == "en" ? (a.MetaDescriptionEn ?? a.MetaDescription)
+                                        : lang == "vi" ? a.MetaDescription
+                                        : (a.MetaDescriptionLo ?? a.MetaDescription),
+                        a.MetaKeywords,
+                        a.CategoryId,
+                        a.ViewCount,
+                        a.IsFeatured,
+                        a.PublishedDate,
+                        a.CreatedDate
+                    })
+                    .FirstOrDefault();
+
+                if (article == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.Error,
+                        ConfigManager.Instance.GetConfigWebValue("ARTICLE_NOT_FOUND", lang),
+                        new { }
+                    );
+                }
+
+                // Increment view count
+                var articleEntity = request.id.HasValue
+                    ? dbContext.Articles.FirstOrDefault(a => a.Id == request.id.Value)
+                    : dbContext.Articles.FirstOrDefault(a => a.Slug == request.slug);
+
+                if (articleEntity != null)
+                {
+                    articleEntity.ViewCount = (articleEntity.ViewCount ?? 0) + 1;
+                    await dbContext.SaveChangesAsync();
+                }
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log,
+                    url,
+                    json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new { article }
+                );
+            }
+            catch (Exception exception)
+            {
+                log.Error("Exception: ", exception);
+            }
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log,
                 url,
                 json,

+ 1 - 0
EsimLao/Esim.Apis/Business/Article/IArticleBusiness.cs

@@ -11,5 +11,6 @@ namespace Esim.Apis.Business
     {
         Task<IActionResult> ArticleCategory(HttpRequest httpRequest, ArticleCategoryReq request);
         Task<IActionResult> ArticleLoad(HttpRequest httpRequest, ArticleLoadReq request);
+        Task<IActionResult> ArticleDetail(HttpRequest httpRequest, ArticleDetailReq request);
     }
 }

+ 80 - 70
EsimLao/Esim.Apis/Business/Content/ContentBusinessImpl.cs

@@ -38,7 +38,7 @@ namespace Esim.Apis.Business
                 int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
 
                 var query = dbContext.Banners
-                    .Where(b => b.Status == true)
+                    .Where(b => b.Status.HasValue && b.Status.Value)
                     .Where(b => b.StartDate == null || b.StartDate <= DateTime.Now)
                     .Where(b => b.EndDate == null || b.EndDate >= DateTime.Now);
 
@@ -58,12 +58,12 @@ namespace Esim.Apis.Business
                     .Select(b => new
                     {
                         b.Id,
-                        title = lang == "en"
-                            ? (b.TitleEn ?? b.Title)
-                            : (b.TitleLo ?? b.Title),
-                        subtitle = lang == "en"
-                            ? (b.SubtitleEn ?? b.Subtitle)
-                            : (b.SubtitleLo ?? b.Subtitle),
+                        title = lang == "en" ? (b.TitleEn ?? b.Title)
+                              : lang == "vi" ? b.Title
+                              : (b.TitleLo ?? b.Title),
+                        subtitle = lang == "en" ? (b.SubtitleEn ?? b.Subtitle)
+                                 : lang == "vi" ? b.Subtitle
+                                 : (b.SubtitleLo ?? b.Subtitle),
                         b.ImageUrl,
                         b.ImageMobileUrl,
                         b.LinkUrl,
@@ -73,7 +73,7 @@ namespace Esim.Apis.Business
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
@@ -84,7 +84,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", ex);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -104,11 +104,11 @@ namespace Esim.Apis.Business
                 int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
 
                 var query = dbContext.CustomerReviews
-                    .Where(r => r.Status == true);
+                    .Where(r => r.Status.HasValue && r.Status.Value);
 
                 if (request.isFeatured.HasValue && request.isFeatured.Value)
                 {
-                    query = query.Where(r => r.IsFeatured == true);
+                    query = query.Where(r => r.IsFeatured.HasValue && r.IsFeatured.Value);
                 }
 
                 int totalCount = query.Count();
@@ -125,18 +125,18 @@ namespace Esim.Apis.Business
                         r.CustomerName,
                         r.AvatarUrl,
                         r.Rating,
-                        reviewContent = lang == "en"
-                            ? (r.ReviewContentEn ?? r.ReviewContent)
-                            : (r.ReviewContentLo ?? r.ReviewContent),
-                        destination = lang == "en"
-                            ? (r.DestinationEn ?? r.Destination)
-                            : (r.DestinationLo ?? r.Destination),
+                        reviewContent = lang == "en" ? (r.ReviewContentEn ?? r.ReviewContent)
+                                      : lang == "vi" ? r.ReviewContent
+                                      : (r.ReviewContentLo ?? r.ReviewContent),
+                        destination = lang == "en" ? (r.DestinationEn ?? r.Destination)
+                                    : lang == "vi" ? r.Destination
+                                    : (r.DestinationLo ?? r.Destination),
                         r.IsFeatured,
                         r.CreatedDate
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
@@ -147,7 +147,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", ex);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -164,17 +164,6 @@ namespace Esim.Apis.Business
             {
                 string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
 
-                // Validate required fields
-                if (string.IsNullOrEmpty(request.customerName) || string.IsNullOrEmpty(request.reviewContent))
-                {
-                    return ApiResponseHelper.BuildResponse(
-                        log, url, json,
-                        CommonErrorCode.RequiredFieldMissing,
-                        ConfigManager.Instance.GetConfigWebValue("REQUIRED_FIELD_MISSING", lang),
-                        new { }
-                    );
-                }
-
                 // Create new review (pending approval)
                 var review = new CustomerReview
                 {
@@ -190,7 +179,7 @@ namespace Esim.Apis.Business
                 dbContext.CustomerReviews.Add(review);
                 await dbContext.SaveChangesAsync();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("REVIEW_SUBMITTED", lang),
@@ -201,7 +190,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", ex);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -221,7 +210,7 @@ namespace Esim.Apis.Business
                 int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
 
                 var query = dbContext.FaqCategories
-                    .Where(c => c.Status == true);
+                    .Where(c => c.Status.HasValue && c.Status.Value);
 
                 int totalCount = query.Count();
                 int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
@@ -234,19 +223,19 @@ namespace Esim.Apis.Business
                     .Select(c => new
                     {
                         c.Id,
-                        categoryName = lang == "en"
-                            ? (c.CategoryNameEn ?? c.CategoryName)
-                            : (c.CategoryNameLo ?? c.CategoryName),
+                        categoryName = lang == "en" ? (c.CategoryNameEn ?? c.CategoryName)
+                                     : lang == "vi" ? c.CategoryName
+                                     : (c.CategoryNameLo ?? c.CategoryName),
                         c.CategorySlug,
-                        description = lang == "en"
-                            ? (c.DescriptionEn ?? c.Description)
-                            : (c.DescriptionLo ?? c.Description),
+                        description = lang == "en" ? (c.DescriptionEn ?? c.Description)
+                                    : lang == "vi" ? c.Description
+                                    : (c.DescriptionLo ?? c.Description),
                         c.IconUrl,
                         c.DisplayOrder
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
@@ -257,7 +246,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", ex);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -277,7 +266,7 @@ namespace Esim.Apis.Business
                 int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
 
                 var query = dbContext.Faqs
-                    .Where(f => f.Status == true);
+                    .Where(f => f.Status.HasValue && f.Status.Value);
 
                 if (request.categoryId.HasValue)
                 {
@@ -286,7 +275,7 @@ namespace Esim.Apis.Business
 
                 if (request.isFeatured.HasValue && request.isFeatured.Value)
                 {
-                    query = query.Where(f => f.IsFeatured == true);
+                    query = query.Where(f => f.IsFeatured.HasValue && f.IsFeatured.Value);
                 }
 
                 int totalCount = query.Count();
@@ -300,19 +289,19 @@ namespace Esim.Apis.Business
                     .Select(f => new
                     {
                         f.Id,
-                        question = lang == "en"
-                            ? (f.QuestionEn ?? f.Question)
-                            : (f.QuestionLo ?? f.Question),
-                        answer = lang == "en"
-                            ? (f.AnswerEn ?? f.Answer)
-                            : (f.AnswerLo ?? f.Answer),
+                        question = lang == "en" ? (f.QuestionEn ?? f.Question)
+                                 : lang == "vi" ? f.Question
+                                 : (f.QuestionLo ?? f.Question),
+                        answer = lang == "en" ? (f.AnswerEn ?? f.Answer)
+                               : lang == "vi" ? f.Answer
+                               : (f.AnswerLo ?? f.Answer),
                         f.CategoryId,
                         f.ViewCount,
                         f.IsFeatured
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
@@ -323,7 +312,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", ex);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -347,7 +336,7 @@ namespace Esim.Apis.Business
 
                 // Base query - only active devices
                 var query = dbContext.DeviceEsimCompatibilities
-                    .Where(d => d.Status == true && d.SupportsEsim == true);
+                    .Where(d => d.Status.HasValue && d.Status.Value && d.SupportsEsim.HasValue && d.SupportsEsim.Value);
 
                 // Filter by brand
                 if (!string.IsNullOrEmpty(request.brand))
@@ -364,7 +353,7 @@ namespace Esim.Apis.Business
                 // Filter by popular flag
                 if (request.isPopular.HasValue && request.isPopular.Value)
                 {
-                    query = query.Where(d => d.IsPopular == true);
+                    query = query.Where(d => d.IsPopular.HasValue && d.IsPopular.Value);
                 }
 
                 // Search by keyword in model name (all language variants)
@@ -393,20 +382,20 @@ namespace Esim.Apis.Business
                     {
                         d.Id,
                         d.Brand,
-                        modelName = lang == "en"
-                            ? (d.ModelNameEn ?? d.ModelName)
-                            : (d.ModelNameLo ?? d.ModelName),
+                        modelName = lang == "en" ? (d.ModelNameEn ?? d.ModelName)
+                                  : lang == "vi" ? d.ModelName
+                                  : (d.ModelNameLo ?? d.ModelName),
                         d.Category,
-                        notes = lang == "en"
-                            ? (d.NotesEn ?? d.Notes)
-                            : (d.NotesLo ?? d.Notes),
+                        notes = lang == "en" ? (d.NotesEn ?? d.Notes)
+                              : lang == "vi" ? d.Notes
+                              : (d.NotesLo ?? d.Notes),
                         supportsEsim = d.SupportsEsim ?? true,
                         isPopular = d.IsPopular ?? false,
                         displayOrder = d.DisplayOrder ?? 999
                     })
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, json,
                     CommonErrorCode.Success,
                     ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
@@ -427,7 +416,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, json,
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
@@ -444,22 +433,43 @@ namespace Esim.Apis.Business
             log.Debug("URL: " + url);
             try
             {
-                // Get distinct brands with device count
-                var brands = dbContext.DeviceEsimCompatibilities
-                    .Where(d => d.Status == true && d.SupportsEsim == true)
+                // Get language from header
+                string lang = CommonLogic.GetLanguage(httpRequest);
+
+                // Get all active devices for client-side filtering
+                var allDevices = dbContext.DeviceEsimCompatibilities
+                    .Where(d => d.Status.HasValue && d.Status.Value && d.SupportsEsim.HasValue && d.SupportsEsim.Value)
+                    .OrderBy(d => d.DisplayOrder)
+                    .ThenBy(d => d.ModelName)
+                    .ToList();
+
+                // Group devices by brand and include full device list
+                var brands = allDevices
                     .GroupBy(d => d.Brand)
                     .Select(g => new
                     {
                         brand = g.Key,
                         deviceCount = g.Count(),
-                        popularCount = g.Count(d => d.IsPopular == true)
+                        popularCount = g.Count(d => d.IsPopular.HasValue && d.IsPopular.Value),
+                        devices = g.Select(d => new
+                        {
+                            d.Id,
+                            modelName = lang == "en" ? (d.ModelNameEn ?? d.ModelName)
+                                      : lang == "vi" ? d.ModelName
+                                      : (d.ModelNameLo ?? d.ModelName),
+                            d.Category,
+                            d.IsPopular,
+                            d.DisplayOrder,
+                            notes = lang == "en" ? (d.NotesEn ?? d.Notes)
+                                  : lang == "vi" ? d.Notes
+                                  : (d.NotesLo ?? d.Notes)
+                        }).ToList()
                     })
                     .OrderBy(b => b.brand)
                     .ToList();
 
                 // Get distinct categories with device count
-                var categories = dbContext.DeviceEsimCompatibilities
-                    .Where(d => d.Status == true && d.SupportsEsim == true)
+                var categories = allDevices
                     .GroupBy(d => d.Category)
                     .Select(g => new
                     {
@@ -469,10 +479,10 @@ namespace Esim.Apis.Business
                     .OrderBy(c => c.category)
                     .ToList();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log, url, "",
                     CommonErrorCode.Success,
-                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS"),
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                     new
                     {
                         brands = brands,
@@ -484,7 +494,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log, url, "",
                 CommonErrorCode.SystemError,
                 ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),

+ 3 - 0
EsimLao/Esim.Apis/Business/User/IUserBusiness.cs

@@ -17,6 +17,9 @@ namespace Esim.Apis.Business
     {
         // Auth methods
         Task<IActionResult> RequestOtp(HttpRequest httpRequest, RequestOtpReq request);
+        Task<IActionResult> ResendOtp(HttpRequest httpRequest, RequestOtpReq request);
         Task<IActionResult> VerifyOtp(HttpRequest httpRequest, VerifyOtpReq request);
+        Task<IActionResult> GoogleLogin(HttpRequest httpRequest, GoogleLoginReq request);
+        Task<IActionResult> GoogleCallback(HttpRequest httpRequest, GoogleCallbackReq request);
     }
 }

+ 556 - 41
EsimLao/Esim.Apis/Business/User/UserBusinessImpl.cs

@@ -13,6 +13,10 @@ using Newtonsoft.Json;
 using System;
 using System.Threading.Tasks;
 using System.Xml.Serialization;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using Newtonsoft.Json.Linq;
+using System.Linq;
 
 namespace Esim.Apis.Business
 {
@@ -49,7 +53,7 @@ namespace Esim.Apis.Business
             {
                 if (string.IsNullOrEmpty(request.email))
                 {
-                    return ApiResponseHelper.BuildResponse(
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
                         log,
                         url,
                         json,
@@ -94,33 +98,68 @@ namespace Esim.Apis.Business
                     customerId = newCustomerId;
                 }
 
-                // Invalidate previous unused OTPs for this email
-                var oldOtps = dbContext.OtpVerifications
-                    .Where(o => o.UserEmail == request.email && o.IsUsed == false)
-                    .ToList();
+                // Check if there's an existing OTP record for this email (ANY record, used or unused)
+                int otpExpireMinutes = 5;
+                int minSecondsBetweenRequests = 60; // Anti-spam: minimum 60 seconds between requests
+                
+                var existingOtp = dbContext.OtpVerifications
+                    .Where(o => o.UserEmail == request.email)
+                    .OrderByDescending(o => o.CreatedDate)
+                    .FirstOrDefault();
 
-                foreach (var oldOtp in oldOtps)
+                if (existingOtp != null)
                 {
-                    oldOtp.IsUsed = true;
+                    // Anti-spam check: prevent rapid OTP requests
+                    var secondsSinceLastRequest = (DateTime.Now - (existingOtp.CreatedDate ?? DateTime.Now)).TotalSeconds;
+                    if (secondsSinceLastRequest < minSecondsBetweenRequests)
+                    {
+                        var waitSeconds = (int)(minSecondsBetweenRequests - secondsSinceLastRequest);
+                        log.Warn($"Spam prevention: OTP request too soon for {request.email}. Last request {secondsSinceLastRequest:F0}s ago.");
+                        
+                        return DotnetLib.Http.HttpResponse.BuildResponse(
+                            log,
+                            url,
+                            json,
+                            CommonErrorCode.OtpTooManyRequests,
+                            $"Please wait {waitSeconds} seconds before requesting a new OTP.",
+                            new { 
+                                waitSeconds = waitSeconds,
+                                canRequestAt = existingOtp.CreatedDate?.AddSeconds(minSecondsBetweenRequests)
+                            }
+                        );
+                    }
+                    
+                    // UPDATE existing record - reuse for this email to prevent table bloat
+                    existingOtp.OtpCode = otpCode;
+                    existingOtp.ExpiredAt = DateTime.Now.AddMinutes(otpExpireMinutes);
+                    existingOtp.AttemptCount = 0; // Reset attempt count
+                    existingOtp.IsUsed = false;   // Reset to unused (allow reuse)
+                    existingOtp.CustomerId = customerId; // Update customer ID if changed
+                    existingOtp.CreatedDate = DateTime.Now; // Update to current time
+                    
+                    log.Info($"Updated existing OTP record ID={existingOtp.Id} for {request.email} (was {(existingOtp.IsUsed == true ? "used" : "unused")})");
                 }
-
-                // Create new OTP record
-                int otpExpireMinutes = 5;
-                var otpId = (int)await Database.DbLogic.GenIdAsync(dbContext, "OTP_VERIFICATION_SEQ");
-                var otpVerification = new OtpVerification
+                else
                 {
-                    Id = otpId,
-                    CustomerId = customerId,
-                    UserEmail = request.email,
-                    OtpCode = otpCode,
-                    OtpType = 1, // Login OTP
-                    ExpiredAt = DateTime.Now.AddMinutes(otpExpireMinutes),
-                    IsUsed = false,
-                    AttemptCount = 0,
-                    CreatedDate = DateTime.Now
-                };
+                    // INSERT new record only for first-time email
+                    var otpId = (int)await Database.DbLogic.GenIdAsync(dbContext, "OTP_VERIFICATION_SEQ");
+                    var otpVerification = new OtpVerification
+                    {
+                        Id = otpId,
+                        CustomerId = customerId,
+                        UserEmail = request.email,
+                        OtpCode = otpCode,
+                        OtpType = 1, // Login OTP
+                        ExpiredAt = DateTime.Now.AddMinutes(otpExpireMinutes),
+                        IsUsed = false,
+                        AttemptCount = 0,
+                        CreatedDate = DateTime.Now
+                    };
+
+                    dbContext.OtpVerifications.Add(otpVerification);
+                    log.Info($"Created new OTP record for {request.email} (first time)");
+                }
 
-                dbContext.OtpVerifications.Add(otpVerification);
                 await dbContext.SaveChangesAsync();
 
                 // Skip email sending for test account
@@ -133,7 +172,7 @@ namespace Esim.Apis.Business
 
                     // Query template and get language-specific content
                     var template = dbContext.MessageTemplates
-                        .FirstOrDefault(t => t.TemplateCode == templateCode && t.Status == true);
+                        .FirstOrDefault(t => t.TemplateCode == templateCode && t.Status.HasValue && t.Status.Value);
 
                     if (template == null)
                     {
@@ -141,15 +180,15 @@ namespace Esim.Apis.Business
                         throw new Exception($"Email template '{templateCode}' not found");
                     }
 
-                    // Get subject based on language (fallback to default column if _LO/_EN is null)
-                    string emailSubject = lang == "en"
-                        ? (template.SubjectEn ?? template.Subject ?? "")
-                        : (template.SubjectLo ?? template.Subject ?? "");
+                    // Get subject based on language: vi=default, en=_EN, lo=_LO (default)
+                    string emailSubject = lang == "en" ? (template.SubjectEn ?? template.Subject ?? "")
+                                        : lang == "vi" ? (template.Subject ?? "")
+                                        : (template.SubjectLo ?? template.Subject ?? "");
 
-                    // Get content based on language (fallback to default column if _LO/_EN is null)
-                    string emailContent = lang == "en"
-                        ? (template.ContentEn ?? template.Content ?? "")
-                        : (template.ContentLo ?? template.Content ?? "");
+                    // Get content based on language: vi=default, en=_EN, lo=_LO (default)
+                    string emailContent = lang == "en" ? (template.ContentEn ?? template.Content ?? "")
+                                        : lang == "vi" ? (template.Content ?? "")
+                                        : (template.ContentLo ?? template.Content ?? "");
 
                     // Replace placeholders in content
                     emailContent = emailContent
@@ -183,7 +222,20 @@ namespace Esim.Apis.Business
 
                 log.Info($"OTP generated for {request.email}: {otpCode} - {(isTestAccount ? "Test account, no email sent" : "Email queued")}");
 
-                return ApiResponseHelper.BuildResponse(
+                //return DotnetLib.Http.HttpResponse.BuildResponse(
+                //    log,
+                //    url,
+                //    json,
+                //    CommonErrorCode.Success,
+                //    ConfigManager.Instance.GetConfigWebValue("OTP_SENT_SUCCESS"),
+                //    new
+                //    {
+                //        email = request.email,
+                //        expireInSeconds = otpExpireMinutes * 60
+                //    }
+                //);
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log,
                     url,
                     json,
@@ -200,7 +252,185 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log,
+                url,
+                json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Resend OTP - Only works if user has already requested OTP before
+        /// Has reduced cooldown (30 seconds vs 60 seconds for RequestOtp)
+        /// </summary>
+        public async Task<IActionResult> ResendOtp(HttpRequest httpRequest, RequestOtpReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => ResendOtp Request: " + json);
+            
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                
+                // Validate email is required
+                if (string.IsNullOrEmpty(request.email))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.RequiredFieldMissing,
+                        ConfigManager.Instance.GetConfigWebValue("EMAIL_REQUIRED", lang),
+                        new { }
+                    );
+                }
+
+                // Check if there's an existing OTP record for this email
+                var existingOtp = dbContext.OtpVerifications
+                    .Where(o => o.UserEmail == request.email)
+                    .OrderByDescending(o => o.CreatedDate)
+                    .FirstOrDefault();
+
+                // RESEND requires existing OTP - must have requested OTP before
+                if (existingOtp == null)
+                {
+                    log.Warn($"ResendOtp failed: No existing OTP record for {request.email}");
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.OtpNotRequested,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_NOT_REQUESTED", lang),
+                        new { }
+                    );
+                }
+
+                // RESEND has reduced cooldown: 60 seconds (vs 60 seconds for RequestOtp)
+                int minSecondsBetweenResend = 60;
+                var secondsSinceLastRequest = (DateTime.Now - (existingOtp.CreatedDate ?? DateTime.Now)).TotalSeconds;
+                
+                if (secondsSinceLastRequest < minSecondsBetweenResend)
+                {
+                    var waitSeconds = (int)(minSecondsBetweenResend - secondsSinceLastRequest);
+                    log.Warn($"ResendOtp: Too soon for {request.email}. Last request {secondsSinceLastRequest:F0}s ago.");
+                    
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.OtpTooManyRequests,
+                        $"Please wait {waitSeconds} seconds before resending OTP.",
+                        new { 
+                            waitSeconds = waitSeconds,
+                            canResendAt = existingOtp.CreatedDate?.AddSeconds(minSecondsBetweenResend)
+                        }
+                    );
+                }
+
+                // Generate new 6-digit OTP (fixed 111111 for test account abc@gmail.com)
+                bool isTestAccount = request.email.ToLower() == "abc@gmail.com";
+                string otpCode = isTestAccount ? "111111" : GenerateOtp();
+                
+                // OTP expires in 5 minutes
+                int otpExpireMinutes = 5;
+
+                // Get customer ID (should exist since OTP record exists)
+                var customer = dbContext.CustomerInfos
+                    .Where(c => c.Email == request.email)
+                    .FirstOrDefault();
+                decimal? customerId = customer?.Id ?? existingOtp.CustomerId;
+
+                // UPDATE existing OTP record with new code and expiry
+                existingOtp.OtpCode = otpCode;
+                existingOtp.ExpiredAt = DateTime.Now.AddMinutes(otpExpireMinutes);
+                existingOtp.AttemptCount = 0; // Reset attempt count
+                existingOtp.IsUsed = false;   // Reset to unused
+                existingOtp.CustomerId = customerId;
+                existingOtp.CreatedDate = DateTime.Now; // Update to track resend time
+                
+                log.Info($"ResendOtp: Updated OTP record ID={existingOtp.Id} for {request.email}");
+                
+                await dbContext.SaveChangesAsync();
+
+                // Skip email sending for test account
+                if (!isTestAccount)
+                {
+                    // Add to MESSAGE_QUEUE for background email sending
+                    string templateCode = "OTP_LOGIN";
+                    
+                    var template = dbContext.MessageTemplates
+                        .FirstOrDefault(t => t.TemplateCode == templateCode && t.Status.HasValue && t.Status.Value);
+
+                    if (template == null)
+                    {
+                        log.Error($"Template '{templateCode}' not found in MESSAGE_TEMPLATE");
+                        throw new Exception($"Email template '{templateCode}' not found");
+                    }
+
+                    // Get subject based on language
+                    string emailSubject = lang == "en" ? (template.SubjectEn ?? template.Subject ?? "")
+                                        : lang == "vi" ? (template.Subject ?? "")
+                                        : (template.SubjectLo ?? template.Subject ?? "");
+
+                    // Get content based on language
+                    string emailContent = lang == "en" ? (template.ContentEn ?? template.Content ?? "")
+                                        : lang == "vi" ? (template.Content ?? "")
+                                        : (template.ContentLo ?? template.Content ?? "");
+
+                    // Replace placeholders
+                    emailContent = emailContent
+                        .Replace("{{OTP_CODE}}", otpCode)
+                        .Replace("{{EXPIRE_MINUTES}}", otpExpireMinutes.ToString());
+
+                    emailSubject = emailSubject
+                        .Replace("{{OTP_CODE}}", otpCode)
+                        .Replace("{{EXPIRE_MINUTES}}", otpExpireMinutes.ToString());
+
+                    var emailMessageID = (int)await Database.DbLogic.GenIdAsync(dbContext, "MESSAGE_QUEUE_SEQ");
+                    var emailMessage = new MessageQueue
+                    {
+                        Id = emailMessageID,
+                        MessageType = 1, // Email
+                        Recipient = request.email,
+                        Subject = emailSubject,
+                        Content = emailContent,
+                        Priority = true, // High priority
+                        Status = 0, // Pending
+                        ScheduledAt = DateTime.Now,
+                        RetryCount = 0,
+                        MaxRetry = 3,
+                        CreatedBy = customerId,
+                        CreatedDate = DateTime.Now
+                    };
+
+                    dbContext.MessageQueues.Add(emailMessage);
+                    await dbContext.SaveChangesAsync();
+                }
+
+                log.Info($"ResendOtp: OTP resent for {request.email}: {otpCode} - {(isTestAccount ? "Test account, no email sent" : "Email queued")}");
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log,
+                    url,
+                    json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("OTP_RESENT_SUCCESS", lang),
+                    new
+                    {
+                        email = request.email,
+                        expireInSeconds = otpExpireMinutes * 60
+                    }
+                );
+            }
+            catch (Exception exception)
+            {
+                log.Error("ResendOtp Exception: ", exception);
+            }
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log,
                 url,
                 json,
@@ -223,7 +453,7 @@ namespace Esim.Apis.Business
                 if (string.IsNullOrEmpty(request.email) || string.IsNullOrEmpty(request.otpCode))
                 {
                     string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
-                    return ApiResponseHelper.BuildResponse(
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
                         log,
                         url,
                         json,
@@ -256,7 +486,7 @@ namespace Esim.Apis.Business
                     {
                         if (anyOtp.IsUsed == true)
                         {
-                            return ApiResponseHelper.BuildResponse(
+                            return DotnetLib.Http.HttpResponse.BuildResponse(
                                 log,
                                 url,
                                 json,
@@ -267,7 +497,7 @@ namespace Esim.Apis.Business
                         }
                         if (anyOtp.ExpiredAt <= DateTime.Now)
                         {
-                            return ApiResponseHelper.BuildResponse(
+                            return DotnetLib.Http.HttpResponse.BuildResponse(
                                 log,
                                 url,
                                 json,
@@ -278,7 +508,7 @@ namespace Esim.Apis.Business
                         }
                     }
 
-                    return ApiResponseHelper.BuildResponse(
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
                         log,
                         url,
                         json,
@@ -298,7 +528,7 @@ namespace Esim.Apis.Business
 
                 if (customer == null)
                 {
-                    return ApiResponseHelper.BuildResponse(
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
                         log,
                         url,
                         json,
@@ -353,7 +583,7 @@ namespace Esim.Apis.Business
                 dbContext.UserTokens.Add(userToken);
                 await dbContext.SaveChangesAsync();
 
-                return ApiResponseHelper.BuildResponse(
+                return DotnetLib.Http.HttpResponse.BuildResponse(
                     log,
                     url,
                     json,
@@ -375,7 +605,7 @@ namespace Esim.Apis.Business
             {
                 log.Error("Exception: ", exception);
             }
-            return ApiResponseHelper.BuildResponse(
+            return DotnetLib.Http.HttpResponse.BuildResponse(
                 log,
                 url,
                 json,
@@ -412,5 +642,290 @@ namespace Esim.Apis.Business
             return ipAddress ?? "Unknown";
         }
 
+        public async Task<IActionResult> GoogleLogin(HttpRequest httpRequest, GoogleLoginReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => GoogleLogin Request: " + json);
+            
+            try 
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request?.lang);
+                
+                var clientId = configuration["Google:ClientId"];
+                var redirectUri = configuration["Google:RedirectUri"];
+                
+                if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(redirectUri))
+                {
+                    log.Error("Google Auth configuration missing");
+                     return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.SystemError,
+                        ConfigManager.Instance.GetConfigWebValue("GOOGLE_CONFIG_MISSING", lang),
+                        new { }
+                    );
+                }
+
+                var googleUrl = $"https://accounts.google.com/o/oauth2/v2/auth?client_id={clientId}&redirect_uri={redirectUri}&response_type=code&scope=email%20profile";
+                
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.Success,
+                        ConfigManager.Instance.GetConfigWebValue("SUCCESS", lang),
+                        new { url = googleUrl }
+                    );
+            }
+            catch (Exception ex)
+            {
+                 log.Error("GoogleLogin Exception: ", ex);
+                 return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log,
+                    url,
+                    json,
+                    CommonErrorCode.SystemError,
+                    ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                    new { }
+                );
+            }
+        }
+
+        public async Task<IActionResult> GoogleCallback(HttpRequest httpRequest, GoogleCallbackReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => GoogleCallback Request: " + json);
+            
+            try
+            {
+                // Get language for response messages
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                
+                if (string.IsNullOrEmpty(request.code))
+                {
+                     return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.RequiredFieldMissing,
+                        ConfigManager.Instance.GetConfigWebValue("GOOGLE_CODE_REQUIRED", lang),
+                        new { }
+                    );
+                }
+
+                var clientId = configuration["Google:ClientId"];
+                var clientSecret = configuration["Google:ClientSecret"];
+                var redirectUri = !string.IsNullOrEmpty(request.redirectUri) ? request.redirectUri : configuration["Google:RedirectUri"];
+
+                using (var httpClient = new HttpClient())
+                {
+                    // 1. Exchange code for token
+                    var tokenRequestContent = new FormUrlEncodedContent(new[]
+                    {
+                        new KeyValuePair<string, string>("code", request.code),
+                        new KeyValuePair<string, string>("client_id", clientId),
+                        new KeyValuePair<string, string>("client_secret", clientSecret),
+                        new KeyValuePair<string, string>("redirect_uri", redirectUri),
+                        new KeyValuePair<string, string>("grant_type", "authorization_code")
+                    });
+
+                    var tokenResponse = await httpClient.PostAsync("https://oauth2.googleapis.com/token", tokenRequestContent);
+                    var tokenResponseString = await tokenResponse.Content.ReadAsStringAsync();
+                    
+                    if (!tokenResponse.IsSuccessStatusCode)
+                    {
+                         log.Error($"Google Token Exchange Failed: {tokenResponseString}");
+                         return DotnetLib.Http.HttpResponse.BuildResponse(
+                            log,
+                            url,
+                            json,
+                            CommonErrorCode.ExternalServiceError,
+                            ConfigManager.Instance.GetConfigWebValue("GOOGLE_TOKEN_EXCHANGE_FAILED", lang),
+                            new { error = tokenResponseString }
+                        );
+                    }
+
+                    var tokenData = JsonConvert.DeserializeObject<JObject>(tokenResponseString);
+                    var accessToken = tokenData["access_token"]?.ToString();
+
+                    if (string.IsNullOrEmpty(accessToken))
+                    {
+                         return DotnetLib.Http.HttpResponse.BuildResponse(
+                            log,
+                            url,
+                            json,
+                            CommonErrorCode.ExternalServiceError,
+                            ConfigManager.Instance.GetConfigWebValue("GOOGLE_NO_ACCESS_TOKEN", lang),
+                            new { }
+                        );
+                    }
+
+                    // 2. Get User Info
+                    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+                    var userInfoResponse = await httpClient.GetAsync("https://www.googleapis.com/oauth2/v2/userinfo");
+                    var userInfoString = await userInfoResponse.Content.ReadAsStringAsync();
+
+                    if (!userInfoResponse.IsSuccessStatusCode)
+                    {
+                         log.Error($"Google User Info Failed: {userInfoString}");
+                         return DotnetLib.Http.HttpResponse.BuildResponse(
+                            log,
+                            url,
+                            json,
+                            CommonErrorCode.ExternalServiceError,
+                            ConfigManager.Instance.GetConfigWebValue("GOOGLE_USERINFO_FAILED", lang),
+                            new { error = userInfoString }
+                        );
+                    }
+
+                    var userInfo = JsonConvert.DeserializeObject<JObject>(userInfoString);
+                    var email = userInfo["email"]?.ToString();
+                    var name = userInfo["name"]?.ToString(); // Full name
+                    var picture = userInfo["picture"]?.ToString();
+                    
+                    if (string.IsNullOrEmpty(email))
+                    {
+                         return DotnetLib.Http.HttpResponse.BuildResponse(
+                            log,
+                            url,
+                            json,
+                            CommonErrorCode.ExternalServiceError,
+                            ConfigManager.Instance.GetConfigWebValue("GOOGLE_NO_EMAIL", lang),
+                            new { }
+                        );
+                    }
+
+                    // 3. Login or Register logic
+                     var customer = dbContext.CustomerInfos
+                        .FirstOrDefault(c => c.Email == email);
+
+                    if (customer == null)
+                    {
+                        // Register new user
+                        var newCustomerId = await Database.DbLogic.GenIdAsync(dbContext, "CUSTOMER_INFO_SEQ");
+                        
+                        // Try to split name
+                        string surname = name;
+                        string lastname = "";
+                        if (!string.IsNullOrEmpty(name))
+                        {
+                            var parts = name.Split(' ');
+                            if (parts.Length > 1)
+                            {
+                                lastname = parts[parts.Length - 1];
+                                surname = string.Join(" ", parts.Take(parts.Length - 1));
+                            }
+                        }
+                        else 
+                        {
+                             surname = email.Split('@')[0];
+                        }
+
+                        customer = new CustomerInfo
+                        {
+                            Id = newCustomerId,
+                            Email = email,
+                            SurName = surname,
+                            LastName = lastname,
+                            AvatarUrl = picture, 
+                            Status = true,
+                            IsVerified = true, // Verified by Google
+                            CreatedDate = DateTime.Now,
+                            LastUpdate = DateTime.Now
+                        };
+                        dbContext.CustomerInfos.Add(customer);
+                        await dbContext.SaveChangesAsync();
+                        log.Info($"Created new customer via Google Login: ID={newCustomerId}, Email={email}");
+                    }
+                    else 
+                    {
+                        // Update existing user info if needed or just log them in
+                        customer.IsVerified = true; 
+                        if (string.IsNullOrEmpty(customer.AvatarUrl) && !string.IsNullOrEmpty(picture))
+                        {
+                            customer.AvatarUrl = picture;
+                        }
+                        customer.LastLoginDate = DateTime.Now;
+                        customer.LastUpdate = DateTime.Now;
+                        await dbContext.SaveChangesAsync();
+                        log.Info($"Existing customer logged in via Google: ID={customer.Id}, Email={email}");
+                    }
+
+                    // 4. Generate JWT
+                    int tokenExpireHours = 24;
+                    int refreshTokenExpireDays = 30;
+
+                    string jwtAccessToken = CommonLogic.GenToken(configuration, customer.Email ?? "", customer.Id.ToString() ?? "");
+                    string jwtRefreshToken = CommonLogic.GenRefreshToken(configuration, customer.Email ?? "");
+                    var expiresAt = DateTime.Now.AddHours(tokenExpireHours);
+                    var refreshExpiresAt = DateTime.Now.AddDays(refreshTokenExpireDays);
+
+                    // Revoke old tokens
+                    var oldTokens = dbContext.UserTokens
+                        .Where(t => t.CustomerId == customer.Id && t.IsRevoked == false)
+                        .ToList();
+
+                    foreach (var oldToken in oldTokens)
+                    {
+                        oldToken.IsRevoked = true;
+                    }
+
+                    // Save new token
+                    var tokenId = (int)await Database.DbLogic.GenIdAsync(dbContext, "USER_TOKEN_SEQ");
+                    var userToken = new UserToken
+                    {
+                        Id = tokenId,
+                        CustomerId = customer.Id,
+                        AccessToken = jwtAccessToken,
+                        RefreshToken = jwtRefreshToken,
+                        TokenType = "Bearer",
+                        DeviceInfo = httpRequest.Headers["User-Agent"].ToString(),
+                        IpAddress = GetClientIpAddress(httpRequest),
+                        ExpiredAt = expiresAt,
+                        RefreshExpiredAt = refreshExpiresAt,
+                        IsRevoked = false,
+                        CreatedDate = DateTime.Now,
+                        LastUsed = DateTime.Now
+                    };
+
+                    dbContext.UserTokens.Add(userToken);
+                    await dbContext.SaveChangesAsync();
+
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log,
+                        url,
+                        json,
+                        CommonErrorCode.Success,
+                        ConfigManager.Instance.GetConfigWebValue("GOOGLE_LOGIN_SUCCESS", lang),
+                        new
+                        {
+                            userId = customer.Id,
+                            email = customer.Email ?? "",
+                            fullName = $"{customer.SurName} {customer.LastName}".Trim(),
+                            avatarUrl = customer.AvatarUrl,
+                            accessToken = jwtAccessToken,
+                            refreshToken = jwtRefreshToken,
+                            expiresAt
+                        }
+                    );
+                }
+            }
+            catch (Exception exception)
+            {
+                log.Error("GoogleCallback Exception: ", exception);
+                 return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log,
+                    url,
+                    json,
+                    CommonErrorCode.SystemError,
+                    ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                    new { }
+                );
+            }
+        }
+
     }
 }

+ 13 - 2
EsimLao/Esim.Apis/Controllers/ArticleController.cs

@@ -45,7 +45,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.ArticleCategoryUrl)]
-        public async Task<IActionResult> ArticleCategory(ArticleCategoryReq request)
+        public async Task<IActionResult> ArticleCategory([FromBody] ArticleCategoryReq request)
         {
             return await articleBusiness.ArticleCategory(HttpContext.Request, request);
         }
@@ -56,11 +56,22 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.ArticleLoadUrl)]
-        public async Task<IActionResult> ArticleLoad(ArticleLoadReq request)
+        public async Task<IActionResult> ArticleLoad([FromBody] ArticleLoadReq request)
         {
             return await articleBusiness.ArticleLoad(HttpContext.Request, request);
         }
 
+        /// <summary>
+        /// Get article detail by ID or slug
+        /// POST /apis/article/detail
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ArticleDetailUrl)]
+        public async Task<IActionResult> ArticleDetail([FromBody] ArticleDetailReq request)
+        {
+            return await articleBusiness.ArticleDetail(HttpContext.Request, request);
+        }
+
         #endregion
     }
 }

+ 22 - 6
EsimLao/Esim.Apis/Controllers/ContentController.cs

@@ -29,7 +29,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.BannerLoadUrl)]
-        public async Task<IActionResult> BannerLoad(BannerLoadReq request)
+        public async Task<IActionResult> BannerLoad([FromBody] BannerLoadReq request)
         {
             return await contentBusiness.BannerLoad(HttpContext.Request, request);
         }
@@ -40,7 +40,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.CustomerReviewLoadUrl)]
-        public async Task<IActionResult> CustomerReviewLoad(CustomerReviewLoadReq request)
+        public async Task<IActionResult> CustomerReviewLoad([FromBody] CustomerReviewLoadReq request)
         {
             return await contentBusiness.CustomerReviewLoad(HttpContext.Request, request);
         }
@@ -51,8 +51,24 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.CustomerReviewCreateUrl)]
-        public async Task<IActionResult> CustomerReviewCreate(CustomerReviewCreateReq request)
+        public async Task<IActionResult> CustomerReviewCreate([FromBody] CustomerReviewCreateReq request)
         {
+            if (!ModelState.IsValid)
+            {
+                var errors = ModelState.Values
+                    .SelectMany(v => v.Errors)
+                    .Select(e => e.ErrorMessage)
+                    .ToList();
+                
+                string lang = Common.Logic.CommonLogic.GetLanguage(HttpContext.Request, request?.lang);
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, HttpContext.Request.Path, Newtonsoft.Json.JsonConvert.SerializeObject(request),
+                    CommonErrorCode.RequiredFieldMissing,
+                    string.Join("; ", errors),
+                    new { }
+                );
+            }
+            
             return await contentBusiness.CustomerReviewCreate(HttpContext.Request, request);
         }
 
@@ -62,7 +78,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.FaqCategoryLoadUrl)]
-        public async Task<IActionResult> FaqCategoryLoad(FaqCategoryLoadReq request)
+        public async Task<IActionResult> FaqCategoryLoad([FromBody] FaqCategoryLoadReq request)
         {
             return await contentBusiness.FaqCategoryLoad(HttpContext.Request, request);
         }
@@ -73,7 +89,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.FaqLoadUrl)]
-        public async Task<IActionResult> FaqLoad(FaqLoadReq request)
+        public async Task<IActionResult> FaqLoad([FromBody] FaqLoadReq request)
         {
             return await contentBusiness.FaqLoad(HttpContext.Request, request);
         }
@@ -84,7 +100,7 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.DeviceCompatibilityLoadUrl)]
-        public async Task<IActionResult> DeviceCompatibilityLoad(DeviceCompatibilityReq request)
+        public async Task<IActionResult> DeviceCompatibilityLoad([FromBody] DeviceCompatibilityReq request)
         {
             return await contentBusiness.DeviceCompatibilityLoad(HttpContext.Request, request);
         }

+ 41 - 2
EsimLao/Esim.Apis/Controllers/UserController.cs

@@ -43,21 +43,60 @@ namespace RevoSystem.Apis.Controllers
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.RequestOtpUrl)]
-        public async Task<IActionResult> RequestOtp(RequestOtpReq request)
+        public async Task<IActionResult> RequestOtp([FromBody] RequestOtpReq request)
         {
             return await userBusiness.RequestOtp(HttpContext.Request, request);
         }
 
+        /// <summary>
+        /// Resend OTP via email
+        /// POST /apis/auth/resend-otp
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ResendOtpUrl)]
+        public async Task<IActionResult> ResendOtp([FromBody] RequestOtpReq request)
+        {
+            return await userBusiness.ResendOtp(HttpContext.Request, request);
+        }
+
         /// <summary>
         /// Verify OTP and complete login
         /// POST /apis/auth/verify-otp
         /// </summary>
         [HttpPost]
         [Route(ApiUrlConstant.VerifyOtpUrl)]
-        public async Task<IActionResult> VerifyOtp(VerifyOtpReq request)
+        public async Task<IActionResult> VerifyOtp([FromBody] VerifyOtpReq request)
         {
             return await userBusiness.VerifyOtp(HttpContext.Request, request);
         }
 
+        /// <summary>
+        /// Get Google Login URL
+        /// POST /apis/auth/google-login
+        /// </summary>
+        /// <param name="request">Contains optional 'lang' parameter for response message language</param>
+        /// <returns>Returns JSON object with 'url' property containing the Google OAuth2 authorization URL</returns>
+        [ProducesResponseType(typeof(object), 200)]
+        [HttpPost]
+        [Route(ApiUrlConstant.GoogleLoginUrl)]
+        public async Task<IActionResult> GoogleLogin([FromBody] GoogleLoginReq request)
+        {
+            return await userBusiness.GoogleLogin(HttpContext.Request, request ?? new GoogleLoginReq());
+        }
+
+        /// <summary>
+        /// Google OAuth Callback (Exchange code for token)
+        /// POST /apis/auth/google-callback
+        /// </summary>
+        /// <param name="request">Contains the authorization 'code' (required) and 'redirectUri' (optional)</param>
+        /// <returns>Returns user profile and JWT tokens (accessToken, refreshToken)</returns>
+        [ProducesResponseType(typeof(object), 200)]
+        [HttpPost]
+        [Route(ApiUrlConstant.GoogleCallbackUrl)]
+        public async Task<IActionResult> GoogleCallback([FromBody] GoogleCallbackReq request)
+        {
+            return await userBusiness.GoogleCallback(HttpContext.Request, request);
+        }
+
     }
 }

+ 23 - 5
EsimLao/Esim.Apis/Program.cs

@@ -6,13 +6,24 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.IdentityModel.Tokens;
 
+using log4net;
+using log4net.Config;
+
 var builder = WebApplication.CreateBuilder(args);
 
+// Initialize log4net
+XmlConfigurator.Configure(new FileInfo(Path.Combine(builder.Environment.ContentRootPath, "log4net.config")));
+
 // Set global configuration for use by singletons like ConfigManager
 GlobalConfig.Configuration = builder.Configuration;
 
 // Add services to the container.
-builder.Services.AddControllersWithViews();
+builder.Services.AddControllersWithViews()
+    .AddJsonOptions(options =>
+    {
+        // Use camelCase for JSON property names (categoryId instead of CategoryId)
+        options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
+    });
 
 // Add DbContext with Oracle provider
 var connectionString = builder.Configuration.GetSection("Connection").Value;
@@ -33,8 +44,10 @@ builder.Services.AddCors(options =>
                 "http://localhost:3000",      // React development
                 "http://localhost:5173",      // Vite development
                 "http://localhost:4200",      // Angular development
-                "https://infigate.vn",        // Production domain
-                "https://www.infigate.vn"     // Production www domain
+                "http://simgetgo.vn",        // Production domain
+                "http://simgetgo.com",     // Production www domain
+                "https://simgetgo.vn",    // Production www domain
+                "https://simgetgo.com"     // Production www domain
             )
             .AllowAnyMethod()
             .AllowAnyHeader()
@@ -43,7 +56,7 @@ builder.Services.AddCors(options =>
 });
 
 // Configure JWT Authentication
-var jwtKey = builder.Configuration["Jwt:Key"] ?? "EsimLaoSecretKey12345678901234567890";
+var jwtKey = builder.Configuration["Jwt:Key"] ?? "EsimLaoSecretKey1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCD";
 var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "EsimLao";
 var jwtAudience = builder.Configuration["Jwt:Audience"] ?? "EsimLaoClient";
 
@@ -105,7 +118,12 @@ app.UseSwaggerUI();
 //    app.UseHsts();
 //}
 
-app.UseHttpsRedirection();
+// Only redirect to HTTPS in production
+if (!app.Environment.IsDevelopment())
+{
+    app.UseHttpsRedirection();
+}
+
 app.UseRouting();
 
 // Enable CORS - MUST be after UseRouting and before UseAuthentication

+ 20 - 7
EsimLao/Esim.Apis/Singleton/ConfigManager.cs

@@ -34,8 +34,8 @@ namespace Esim.Apis.Singleton
             var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "WEB");
             if (config != null)
             {
-                log.Debug($"Config found: {configName} = {config.ValueGlobal}");
-                return lang == "en" ? config.ValueGlobal : config.ValueLocal;
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
             }
             log.Warn($"Config not found: {configName}");
             return string.Empty;
@@ -46,25 +46,38 @@ namespace Esim.Apis.Singleton
             var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "SMS");
             if (config != null)
             {
-                log.Debug($"Config found: {configName} = {config.ValueGlobal}");
-                return lang == "en" ? config.ValueGlobal : config.ValueLocal;
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
             }
             log.Warn($"Config not found: {configName}");
             return string.Empty;
         }
 
-        public string GetConfigAppValue(string configName, string lang = "te")
+        public string GetConfigAppValue(string configName, string lang = "lo")
         {
             var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "APP");
             if (config != null)
             {
-                log.Debug($"Config found: {configName} = {config.ValueGlobal}");
-                return lang == "en" ? config.ValueGlobal : config.ValueLocal;
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
             }
             log.Warn($"Config not found: {configName}");
             return string.Empty;
         }
 
+        /// <summary>
+        /// Get config value by language: vi=Vietnamese, en=English, lo=Lao (default)
+        /// </summary>
+        private string GetValueByLang(Config config, string lang)
+        {
+            return lang switch
+            {
+                "vi" => config.Value ?? config.ValueLocal ?? "",
+                "en" => config.ValueGlobal ?? config.ValueLocal ?? "",
+                _ => config.ValueLocal ?? ""  // Default: Lao
+            };
+        }
+
         // loop 5p to refresh
         public void RefreshConfigs()
         {

+ 14 - 1
EsimLao/Esim.Apis/appsettings.json

@@ -8,7 +8,7 @@
   },
   "AllowedHosts": "*",
   "Jwt": {
-    "Key": "EsimLaoSecretKey12345678901234567890",
+    "Key": "EsimLaoSecretKey1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCD",
     "Issuer": "EsimLao",
     "Audience": "EsimLaoClient"
   },
@@ -17,6 +17,19 @@
       "Http": {
         "Url": "http://0.0.0.0:9106"
       }
+      //"Https": {
+      //  "Url": "https://0.0.0.0:9107",
+      //  "Certificate": {
+      //    "Path": "/path/to/certificate.pfx",
+      //    "Password": "your-password"
+      //  }
+      //}
     }
+  },
+  "Google": {
+    "ClientId": "510004579352-p8brlhu92qesea636ae2c1k96bq30u0j.apps.googleusercontent.com",
+    "ClientSecret": "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",
+    "RedirectUri": "https://simgetgo.vn"
   }
+
 }

+ 30 - 28
EsimLao/Esim.Apis/log4net.config

@@ -1,30 +1,32 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8" ?>
 <log4net>
-  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
-    <!-- File log hiện tại -->
-    <file value="../../logs/apis/full.log" />
-    <appendToFile value="true" />
-    <!-- Rolling theo ngày + size -->
-    <rollingStyle value="Composite" />
-    <datePattern value="dd_MM_yyyy'.log'" /> <!-- Hậu tố ngày -->
-    <staticLogFileName value="true" /> <!-- File mới nhất luôn là full.log -->
-    <!-- Giới hạn dung lượng -->
-    <maximumFileSize value="10MB" />
-    <maxSizeRollBackups value="30" />
-    <!-- Format log -->
-    <layout type="log4net.Layout.PatternLayout">
-      <conversionPattern value="%date %-5level %logger - %message%newline" />
-    </layout>
-  </appender>
-  <appender name="console" type="log4net.Appender.ConsoleAppender">
-    <layout type="log4net.Layout.PatternLayout">
-      <conversionPattern value="%date %level - %message%newline" />
-    </layout>
-    <threshold value="ALL" />
-  </appender>
-  <root>
-    <level value="DEBUG" />
-    <appender-ref ref="RollingFileAppender" />
-    <appender-ref ref="console" />
-  </root>
+	<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
+		<!-- File log hiện tại -->
+		<file value="../logs/full.log" />
+		<appendToFile value="true" />
+		<!-- Rolling theo ngày + size -->
+		<rollingStyle value="Composite" />
+		<datePattern value="dd_MM_yyyy'.log'" />
+		<!-- Hậu tố ngày -->
+		<staticLogFileName value="true" />
+		<!-- File mới nhất luôn là full.log -->
+		<!-- Giới hạn dung lượng -->
+		<maximumFileSize value="10MB" />
+		<maxSizeRollBackups value="30" />
+		<!-- Format log -->
+		<layout type="log4net.Layout.PatternLayout">
+			<conversionPattern value="%date %-5level %logger - %message%newline" />
+		</layout>
+	</appender>
+	<appender name="console" type="log4net.Appender.ConsoleAppender">
+		<layout type="log4net.Layout.PatternLayout">
+			<conversionPattern value="%date %level - %message%newline" />
+		</layout>
+		<threshold value="ALL" />
+	</appender>
+	<root>
+		<level value="DEBUG" />
+		<appender-ref ref="RollingFileAppender" />
+		<appender-ref ref="console" />
+	</root>
 </log4net>

+ 1 - 0
EsimLao/Esim.SendMail/Esim.SendMail.csproj

@@ -14,6 +14,7 @@
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
     <PackageReference Include="MailKit" Version="4.8.0" />
     <PackageReference Include="MimeKit" Version="4.8.0" />
+    <PackageReference Include="log4net" Version="2.0.15" />
   </ItemGroup>
 
   <ItemGroup>

+ 176 - 0
EsimLao/Esim.SendMail/ExpiredMessageCleanupWorker.cs

@@ -0,0 +1,176 @@
+using Database.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+
+namespace Esim.SendMail;
+
+/// <summary>
+/// Background worker to clean up expired messages from MESSAGE_QUEUE.
+/// Messages older than configured expiration days are moved to MESSAGE_QUEUE_HIS with failed status and deleted.
+/// </summary>
+public class ExpiredMessageCleanupWorker : BackgroundService
+{
+    private readonly ILogger<ExpiredMessageCleanupWorker> _logger;
+    private readonly IServiceProvider _serviceProvider;
+    private readonly int _intervalMinutes;
+    private readonly int _expirationDays;
+
+    // Message statuses
+    private const int STATUS_PENDING = 0;
+    private const int STATUS_PROCESSING = 1;
+    private const int STATUS_FAILED = 3;
+
+    public ExpiredMessageCleanupWorker(
+        ILogger<ExpiredMessageCleanupWorker> logger,
+        IServiceProvider serviceProvider,
+        IConfiguration configuration)
+    {
+        _logger = logger;
+        _serviceProvider = serviceProvider;
+        _intervalMinutes = int.Parse(configuration["Cleanup:IntervalMinutes"] ?? "60"); // Default: 1 hour
+        _expirationDays = int.Parse(configuration["Cleanup:ExpirationDays"] ?? "1"); // Default: 1 day
+    }
+
+    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+    {
+        _logger.LogInformation("ExpiredMessageCleanupWorker started. Interval: {Interval} minutes, Expiration: {Days} day(s)",
+            _intervalMinutes, _expirationDays);
+
+        // Wait a bit for initialization
+        await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
+
+        while (!stoppingToken.IsCancellationRequested)
+        {
+            try
+            {
+                await CleanupExpiredMessagesAsync(stoppingToken);
+            }
+            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
+            {
+                break;
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Error in cleanup loop");
+            }
+
+            try
+            {
+                await Task.Delay(TimeSpan.FromMinutes(_intervalMinutes), stoppingToken);
+            }
+            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
+            {
+                break;
+            }
+        }
+
+        _logger.LogInformation("ExpiredMessageCleanupWorker stopped.");
+    }
+
+    private async Task CleanupExpiredMessagesAsync(CancellationToken stoppingToken)
+    {
+        var startTime = DateTime.Now;
+
+        using var scope = _serviceProvider.CreateScope();
+        var dbContext = scope.ServiceProvider.GetRequiredService<ModelContext>();
+
+        try
+        {
+            // Find messages older than expiration days that are still pending or processing
+            var expirationDate = DateTime.Now.AddDays(-_expirationDays);
+            
+            var expiredMessages = await dbContext.MessageQueues
+                .Where(m => m.CreatedDate <= expirationDate
+                    && (m.Status == STATUS_PENDING || m.Status == STATUS_PROCESSING))
+                .OrderBy(m => m.CreatedDate)
+                .ToListAsync(stoppingToken);
+
+            if (!expiredMessages.Any())
+            {
+                _logger.LogDebug("No expired messages found");
+                return;
+            }
+
+            _logger.LogWarning("Found {Count} expired messages (older than {Days} day(s)). Moving to history and deleting...", 
+                expiredMessages.Count, _expirationDays);
+
+            // Log sample of expired messages for audit
+            var sampleSize = Math.Min(5, expiredMessages.Count);
+            for (int i = 0; i < sampleSize; i++)
+            {
+                var msg = expiredMessages[i];
+                var age = DateTime.Now - (msg.CreatedDate ?? DateTime.Now);
+                var subjectPreview = msg.Subject != null 
+                    ? msg.Subject.Substring(0, Math.Min(50, msg.Subject.Length))
+                    : "(no subject)";
+                _logger.LogInformation(
+                    "Expired message sample: ID={Id}, Recipient={Recipient}, Subject={Subject}, Age={Age:F1}h, Status={Status}, Retries={Retry}/{Max}",
+                    msg.Id, msg.Recipient, subjectPreview,
+                    age.TotalHours, msg.Status, msg.RetryCount ?? 0, msg.MaxRetry ?? 3);
+            }
+            if (expiredMessages.Count > sampleSize)
+            {
+                _logger.LogInformation("... and {More} more expired messages", expiredMessages.Count - sampleSize);
+            }
+
+            // Move to MESSAGE_QUEUE_HIS with failed status
+            await MoveToHistoryAsync(dbContext, expiredMessages, stoppingToken);
+
+            // Delete from MESSAGE_QUEUE
+            var ids = expiredMessages.Select(m => m.Id).ToList();
+            var deleteSql = $"DELETE FROM MESSAGE_QUEUE WHERE ID IN ({string.Join(",", ids)})";
+            await dbContext.Database.ExecuteSqlRawAsync(deleteSql, stoppingToken);
+
+            var elapsed = DateTime.Now - startTime;
+            _logger.LogInformation("Successfully cleaned up {Count} expired messages in {Elapsed:F0}ms. Messages archived to MESSAGE_QUEUE_HIS with FAILED status.",
+                expiredMessages.Count, elapsed.TotalMilliseconds);
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Error cleaning up expired messages");
+        }
+    }
+
+    private async Task MoveToHistoryAsync(
+        ModelContext dbContext,
+        List<MessageQueue> messages,
+        CancellationToken stoppingToken)
+    {
+        if (!messages.Any()) return;
+
+        try
+        {
+            var ids = string.Join(",", messages.Select(m => m.Id));
+
+            // Insert to history with STATUS = 3 (FAILED - EXPIRED)
+            var insertSql = $@"
+                INSERT INTO MESSAGE_QUEUE_HIS 
+                (ID, MESSAGE_TYPE, RECIPIENT, SUBJECT, CONTENT, TEMPLATE_CODE, TEMPLATE_DATA, 
+                 PRIORITY, STATUS, SCHEDULED_AT, PROCESSED_AT, RETRY_COUNT, MAX_RETRY, 
+                 ERROR_MESSAGE, CREATED_BY, CREATED_DATE, MOVED_DATE)
+                SELECT 
+                    ID, MESSAGE_TYPE, RECIPIENT, SUBJECT, CONTENT, TEMPLATE_CODE, TEMPLATE_DATA,
+                    PRIORITY, {STATUS_FAILED} AS STATUS, SCHEDULED_AT, SYSDATE AS PROCESSED_AT, RETRY_COUNT, MAX_RETRY,
+                    'EXPIRED: Message older than {_expirationDays} day(s) - Auto-deleted to prevent spam and table bloat. Created: ' || TO_CHAR(CREATED_DATE, 'YYYY-MM-DD HH24:MI:SS') AS ERROR_MESSAGE, 
+                    CREATED_BY, CREATED_DATE, SYSDATE
+                FROM MESSAGE_QUEUE
+                WHERE ID IN ({ids})";
+
+            await dbContext.Database.ExecuteSqlRawAsync(insertSql, stoppingToken);
+
+            _logger.LogDebug("Moved {Count} expired messages to MESSAGE_QUEUE_HIS with FAILED status", messages.Count);
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Failed to move expired messages to history");
+            throw; // Re-throw to prevent deletion if archival fails
+        }
+    }
+
+    public override async Task StopAsync(CancellationToken cancellationToken)
+    {
+        _logger.LogInformation("ExpiredMessageCleanupWorker stopping...");
+        await base.StopAsync(cancellationToken);
+        _logger.LogInformation("ExpiredMessageCleanupWorker stopped gracefully");
+    }
+}

+ 77 - 0
EsimLao/Esim.SendMail/Logging/Log4NetProvider.cs

@@ -0,0 +1,77 @@
+using log4net;
+using log4net.Config;
+using Microsoft.Extensions.Logging;
+using System.Collections.Concurrent;
+
+namespace Esim.SendMail.Logging;
+
+public class Log4NetProvider : ILoggerProvider
+{
+    private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers = new();
+
+    public Log4NetProvider() { }
+
+    public ILogger CreateLogger(string categoryName)
+    {
+        return _loggers.GetOrAdd(categoryName, name => new Log4NetLogger(name));
+    }
+
+    public void Dispose()
+    {
+        _loggers.Clear();
+    }
+}
+
+public class Log4NetLogger : ILogger
+{
+    private readonly ILog _log;
+
+    public Log4NetLogger(string categoryName)
+    {
+        _log = LogManager.GetLogger(typeof(Log4NetProvider).Assembly, categoryName);
+    }
+
+    public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
+
+    public bool IsEnabled(LogLevel logLevel)
+    {
+        return logLevel switch
+        {
+            LogLevel.Critical => _log.IsFatalEnabled,
+            LogLevel.Error => _log.IsErrorEnabled,
+            LogLevel.Warning => _log.IsWarnEnabled,
+            LogLevel.Information => _log.IsInfoEnabled,
+            LogLevel.Debug => _log.IsDebugEnabled,
+            LogLevel.Trace => _log.IsDebugEnabled,
+            _ => false
+        };
+    }
+
+    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
+    {
+        if (!IsEnabled(logLevel)) return;
+
+        var message = formatter(state, exception);
+        if (string.IsNullOrEmpty(message) && exception == null) return;
+
+        switch (logLevel)
+        {
+            case LogLevel.Critical: _log.Fatal(message, exception); break;
+            case LogLevel.Error: _log.Error(message, exception); break;
+            case LogLevel.Warning: _log.Warn(message, exception); break;
+            case LogLevel.Information: _log.Info(message, exception); break;
+            case LogLevel.Debug: _log.Debug(message, exception); break;
+            case LogLevel.Trace: _log.Debug(message, exception); break;
+        }
+    }
+}
+
+public static class Log4NetExtensions
+{
+    public static ILoggingBuilder AddLog4Net(this ILoggingBuilder builder, string configPath)
+    {
+        XmlConfigurator.Configure(new FileInfo(configPath));
+        builder.AddProvider(new Log4NetProvider());
+        return builder;
+    }
+}

+ 45 - 23
EsimLao/Esim.SendMail/MessageQueueWorker.cs

@@ -1,6 +1,7 @@
 using Database.Database;
 using Esim.SendMail.Services;
 using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Storage;
 using Microsoft.Extensions.Logging;
 
 namespace Esim.SendMail;
@@ -178,13 +179,11 @@ public class MessageQueueWorker : BackgroundService
         ModelContext dbContext, 
         CancellationToken stoppingToken)
     {
-        // Using Oracle's FOR UPDATE SKIP LOCKED to prevent duplicate processing
-        // This allows multiple workers to run safely
-        var sql = $@"
-            SELECT ID, MESSAGE_TYPE, RECIPIENT, SUBJECT, CONTENT, TEMPLATE_CODE, TEMPLATE_DATA,
-                   PRIORITY, STATUS, SCHEDULED_AT, PROCESSED_AT, RETRY_COUNT, MAX_RETRY,
-                   ERROR_MESSAGE, CREATED_BY, CREATED_DATE
-            FROM MESSAGE_QUEUE
+        // Step 1: Lock rows and get IDs using raw SQL with FOR UPDATE SKIP LOCKED
+        // This prevents duplicate processing across multiple workers
+        var lockSql = $@"
+            SELECT ID
+            FROM {dbContext.Model.FindEntityType(typeof(MessageQueue))?.GetSchemaQualifiedTableName() ?? "MESSAGE_QUEUE"}
             WHERE STATUS = {STATUS_PENDING}
               AND (SCHEDULED_AT IS NULL OR SCHEDULED_AT <= SYSDATE)
               AND (RETRY_COUNT IS NULL OR RETRY_COUNT < NVL(MAX_RETRY, 3))
@@ -194,27 +193,50 @@ public class MessageQueueWorker : BackgroundService
 
         try
         {
-            var messages = await dbContext.MessageQueues
-                .FromSqlRaw(sql)
-                .ToListAsync(stoppingToken);
-
-            // Mark as processing immediately
-            if (messages.Any())
+            // Execute raw SQL to lock rows and get IDs
+            var connection = dbContext.Database.GetDbConnection();
+            await dbContext.Database.OpenConnectionAsync(stoppingToken);
+            
+            var lockedIds = new List<int>();
+            using (var command = connection.CreateCommand())
             {
-                foreach (var msg in messages)
+                command.CommandText = lockSql;
+                command.Transaction = dbContext.Database.CurrentTransaction?.GetDbTransaction();
+                
+                using (var reader = await command.ExecuteReaderAsync(stoppingToken))
                 {
-                    msg.Status = STATUS_PROCESSING;
+                    while (await reader.ReadAsync(stoppingToken))
+                    {
+                        lockedIds.Add(reader.GetInt32(0));
+                    }
                 }
-                await dbContext.SaveChangesAsync(stoppingToken);
             }
 
+            if (!lockedIds.Any())
+            {
+                return new List<MessageQueue>();
+            }
+
+            // Step 2: Query the full entities using EF Core with the locked IDs
+            var messages = await dbContext.MessageQueues
+                .Where(m => lockedIds.Contains(m.Id))
+                .ToListAsync(stoppingToken);
+
+            // Step 3: Mark as processing immediately while rows are still locked
+            foreach (var msg in messages)
+            {
+                msg.Status = STATUS_PROCESSING;
+            }
+            await dbContext.SaveChangesAsync(stoppingToken);
+            
+            _logger.LogDebug("Locked and fetched {Count} messages for processing", messages.Count);
             return messages;
         }
         catch (Exception ex)
         {
-            _logger.LogWarning("Failed to get messages with row-locking, falling back: {Message}", ex.Message);
+            _logger.LogWarning(ex, "Failed to lock messages with FOR UPDATE, falling back to simple query");
             
-            // Fallback to simple query if FOR UPDATE fails
+            // Fallback: Simple EF Core query without locking
             var messages = await dbContext.MessageQueues
                 .Where(m => m.Status == STATUS_PENDING
                     && (m.ScheduledAt == null || m.ScheduledAt <= DateTime.Now)
@@ -224,13 +246,13 @@ public class MessageQueueWorker : BackgroundService
                 .Take(_maxMessagesPerRun)
                 .ToListAsync(stoppingToken);
 
-            // Mark as processing
             if (messages.Any())
             {
-                var ids = string.Join(",", messages.Select(m => m.Id));
-                await dbContext.Database.ExecuteSqlRawAsync(
-                    $"UPDATE MESSAGE_QUEUE SET STATUS = {STATUS_PROCESSING} WHERE ID IN ({ids})",
-                    stoppingToken);
+                foreach (var msg in messages)
+                {
+                    msg.Status = STATUS_PROCESSING;
+                }
+                await dbContext.SaveChangesAsync(stoppingToken);
             }
 
             return messages;

+ 9 - 1
EsimLao/Esim.SendMail/Program.cs

@@ -1,10 +1,14 @@
 using Database.Database;
 using Esim.SendMail.Services;
 using Microsoft.EntityFrameworkCore;
+using Esim.SendMail.Logging;
 using Microsoft.Extensions.Logging;
 
+
+
 namespace Esim.SendMail;
 
+
 public class Program
 {
     public static async Task Main(string[] args)
@@ -14,9 +18,12 @@ public class Program
         // Add configuration
         builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
 
+
         // Configure logging
         builder.Logging.ClearProviders();
         builder.Logging.AddConsole();
+        // Initialize and add Log4Net
+        builder.Logging.AddLog4Net(Path.Combine(builder.Environment.ContentRootPath, "log4net.config"));
         builder.Logging.SetMinimumLevel(LogLevel.Information);
 
         // Add DbContext
@@ -27,8 +34,9 @@ public class Program
         // Add Email Service as singleton for connection pooling
         builder.Services.AddSingleton<IEmailService, HighPerformanceEmailService>();
 
-        // Add the background worker service
+        // Add the background worker services
         builder.Services.AddHostedService<MessageQueueWorker>();
+        builder.Services.AddHostedService<ExpiredMessageCleanupWorker>();
 
         var host = builder.Build();
 

+ 8 - 4
EsimLao/Esim.SendMail/appsettings.json

@@ -1,11 +1,11 @@
 {
   "Connection": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1539))(CONNECT_DATA=(SERVICE_NAME=ORA12C)));User Id=laos_esim;Password=laos_esim;Connection Timeout=120;",
   "Email": {
-    "SmtpServer": "smtp.gmail.com",
+    "SmtpServer": "",
     "SmtpPort": 587,
-    "SenderEmail": "trongduc02@gmail.com",
-    "SenderName": "trongduc02",
-    "SenderPassword": "cjav iour aepq balt",
+    "SenderEmail": "",
+    "SenderName": "",
+    "SenderPassword": "",
     "EnableSsl": true,
     "MaxConcurrentSends": 10,
     "ConnectionPoolSize": 5,
@@ -18,6 +18,10 @@
     "MaxMessagesPerRun": 500,
     "MetricsLogIntervalSeconds": 60
   },
+  "Cleanup": {
+    "IntervalMinutes": 60,
+    "ExpirationDays": 1
+  },
   "Logging": {
     "LogLevel": {
       "Default": "Information",

+ 0 - 778
EsimLao/docs/api_auth_otp.txt

@@ -1,778 +0,0 @@
-# EsimLao Authentication API Documentation
-
-## Overview
-API xác thực người dùng qua email với OTP (One-Time Password).
-URL_UAT : http://149.28.132.56:8360/
----
-
-## 1. Request OTP
-
-Gửi mã OTP đến email người dùng để xác thực đăng nhập.
-
-### Endpoint
-```
-POST /apis/auth/request-otp
-```
-
-### Request Headers
-| Header | Value | Required |
-|--------|-------|----------|
-| Content-Type | application/json | Yes |
-
-### Request Body
-```json
-{
-    "email": "user@example.com",
-    "lang": "lo"  // Default: "lo" / en
-}
-```
-
-### Parameters
-| Field | Type | Required | Default | Description |
-|-------|------|----------|---------|-------------|
-| email | string | Yes | - | Email address của người dùng |
-| lang | string | No | "vi" | Ngôn ngữ email: `vi` (Tiếng Việt), `en` (English), `lo` (ລາວ) |
-
-### Response Success (200)
-```json
-{
-    "errorCode": "0",
-    "message": "<Config: OTP_SENT_SUCCESS>",
-    "data": {
-        "email": "user@example.com",
-        "expireInSeconds": 300
-    }
-}
-```
-
-### Response Error (200)
-```json
-// Email không được cung cấp
-{
-    "errorCode": "-801",
-    "message": "<Config: EMAIL_REQUIRED>",
-    "data": {}
-}
-
-// Lỗi hệ thống
-{
-    "errorCode": "-6",
-    "message": "<Config: SYSTEM_FAILURE>",
-    "data": {}
-}
-```
-
-### Response Fields
-| Field | Type | Description |
-|-------|------|-------------|
-| errorCode| string | "0" = Success, khác "0" = Error (xem Error Codes) |
-| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
-| data.email | string | Email đã gửi OTP |
-| data.expireInSeconds | int | Thời gian OTP hết hạn (giây) |
-
-### Notes
-- OTP gồm 6 chữ số
-- OTP có hiệu lực trong 5 phút
-- Mỗi lần request mới sẽ hủy các OTP cũ chưa sử dụng
-- Nếu email chưa tồn tại, hệ thống tự động tạo tài khoản mới
-
----
-
-## 2. Verify OTP
-
-Xác thực mã OTP và hoàn tất đăng nhập.
-
-### Endpoint
-```
-POST /apis/auth/verify-otp
-```
-
-### Request Headers
-| Header | Value | Required |
-|--------|-------|----------|
-| Content-Type | application/json | Yes |
-
-### Request Body
-```json
-{
-    "email": "user@example.com",
-    "otpCode": "123456",
-    "lang": "lo"  // Default: "lo" / en
-}
-```
-
-### Parameters
-| Field | Type | Required | Default | Description |
-|-------|------|----------|---------|-------------|
-| email | string | Yes | - | Email đã nhận OTP |
-| otpCode | string | Yes | - | Mã OTP 6 số |
-| lang | string | No | "lo" | Ngôn ngữ thông báo: `lo` (ລາວ), `en` (English) |
-
-### Response Success (200)
-```json
-{
-    "errorCode": "0",
-    "message": "<Config: LOGIN_SUCCESS>",
-    "data": {
-        "userId": 12345,
-        "email": "user@example.com",
-        "fullName": "Nguyen Van A",
-        "avatarUrl": "https://example.com/avatar.jpg",
-        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
-        "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
-        "expiresAt": "2024-12-30T10:00:00Z"
-    }
-}
-```
-
-### Response Error Cases
-```json
-// Thiếu email hoặc OTP
-{
-    "errorCode": "-801",
-    "message": "<Config: EMAIL_OTP_REQUIRED>",
-    "data": {}
-}
-
-// OTP không hợp lệ
-{
-    "errorCode": "-201",
-    "message": "<Config: OTP_INVALID>",
-    "data": {}
-}
-
-// OTP đã được sử dụng
-{
-    "errorCode": "-203",
-    "message": "<Config: OTP_ALREADY_USED>",
-    "data": {}
-}
-
-// OTP đã hết hạn
-{
-    "errorCode": "-202",
-    "message": "<Config: OTP_EXPIRED>",
-    "data": {}
-}
-
-// Không tìm thấy người dùng
-{
-    "errorCode": "-300",
-    "message": "<Config: USER_NOT_FOUND>",
-    "data": {}
-}
-
-// Lỗi hệ thống
-{
-    "errorCode": "-6",
-    "message": "<Config: SYSTEM_FAILURE>",
-    "data": {}
-}
-```
-
-### Response Fields
-| Field | Type | Description |
-|-------|------|-------------|
-| errorCode| string | "0" = Success, khác "0" = Error (xem Error Codes) |
-| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
-| data.userId | int | ID người dùng |
-| data.email | string | Email người dùng |
-| data.fullName | string | Họ tên đầy đủ |
-| data.avatarUrl | string | URL ảnh đại diện (nullable) |
-| data.accessToken | string | JWT access token |
-| data.refreshToken | string | Refresh token để làm mới access token |
-| data.expiresAt | datetime | Thời điểm access token hết hạn |
-
-### Notes
-- Access token có hiệu lực 24 giờ
-- Refresh token có hiệu lực 30 ngày
-- Mỗi lần đăng nhập thành công, các token cũ sẽ bị thu hồi
-
----
-
-## Error Codes
-
-### Success
-| errorCode| Constant | Description |
-|------|----------|-------------|
-| "0" | Success | Thành công (mọi request thành công đều trả về "0") |
-
-### General Errors (-1 to -99)
-| errorCode| Constant | Description |
-|------|----------|-------------|
-| "-1" | Error | Lỗi chung |
-| "-6" | SystemError | Lỗi hệ thống |
-
-### OTP Errors (-200 to -299)
-| errorCode| Constant | Description |
-|------|----------|-------------|
-| "-200" | OtpRequired | Yêu cầu OTP |
-| "-201" | OtpInvalid | OTP không hợp lệ |
-| "-202" | OtpExpired | OTP đã hết hạn |
-| "-203" | OtpAlreadyUsed | OTP đã được sử dụng |
-| "-204" | OtpMaxAttemptsExceeded | Vượt quá số lần thử |
-| "-205" | OtpSendFailed | Gửi OTP thất bại |
-| "-206" | OtpTooManyRequests | Request quá nhiều |
-
-### User Errors (-300 to -399)
-| errorCode| Constant | Description |
-|------|----------|-------------|
-| "-300" | UserNotFound | Không tìm thấy người dùng |
-| "-304" | InvalidEmail | Email không hợp lệ |
-
-### Validation Errors (-800 to -899)
-| errorCode| Constant | Description |
-|------|----------|-------------|
-| "-801" | RequiredFieldMissing | Thiếu trường bắt buộc |
-
----
-
-## Authentication
-
-Sau khi đăng nhập thành công, sử dụng `accessToken` trong header cho các API yêu cầu xác thực:
-
-```
-Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
-```
-
----
-
-## Flow Diagram
-
-```
-┌─────────────┐     ┌─────────────┐     ┌─────────────┐
-│   Client    │     │   API       │     │   Email     │
-└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
-       │                   │                   │
-       │ POST /request-otp │                   │
-       │──────────────────>│                   │
-       │                   │                   │
-       │                   │ Generate OTP      │
-       │                   │ Save to DB        │
-       │                   │ Queue Email       │
-       │                   │                   │
-       │    Response       │                   │
-       │<──────────────────│                   │
-       │                   │                   │
-       │                   │  Send OTP Email   │
-       │                   │──────────────────>│
-       │                   │                   │
-       │                   │                   │ OTP Email
-       │<──────────────────────────────────────│
-       │                   │                   │
-       │ POST /verify-otp  │                   │
-       │──────────────────>│                   │
-       │                   │                   │
-       │                   │ Verify OTP        │
-       │                   │ Generate JWT      │
-       │                   │                   │
-       │ Token Response    │                   │
-       │<──────────────────│                   │
-       │                   │                   │
-```
-
----
-
-## Example Usage (cURL)
-
-### Request OTP
-```bash
-curl -X POST https://api.esimlao.com/apis/auth/request-otp \
-  -H "Content-Type: application/json" \
-  -d '{
-    "email": "user@example.com",
-    "lang": "vi"
-  }'
-```
-
-### Verify OTP
-```bash
-curl -X POST https://api.esimlao.com/apis/auth/verify-otp \
-  -H "Content-Type: application/json" \
-  -d '{
-    "email": "user@example.com",
-    "otpCode": "123456"
-  }'
-```
-
-### Use Token
-```bash
-curl -X GET https://api.esimlao.com/apis/user/profile \
-  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-```
-
----
-
-## 3. Article Category
-
-Lấy danh sách danh mục bài viết.
-
-### Endpoint
-```
-POST /apis/article/category
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10,
-    "parentId": null
-}
-```
-
-| Field | Type | Default | Description |
-|-------|------|---------|-------------|
-| lang | string | "lo" | Ngôn ngữ: "lo", "en" (có thể truyền qua header Accept-Language) |
-| pageNumber | int | 0 | Trang hiện tại |
-| pageSize | int | 10 | Số item mỗi trang |
-| parentId | int? | null | ID danh mục cha (null = root) |
-
-### Response Success
-```json
-{
-    "errorCode": "0",
-    "message": "Success",
-    "data": {
-        "categories": [
-            {
-                "id": 1,
-                "categoryName": "Cẩm nang du lịch",
-                "categorySlug": "cam-nang-du-lich",
-                "description": "Mô tả...",
-                "iconUrl": "/icons/travel.png",
-                "parentId": null,
-                "displayOrder": 1
-            }
-        ],
-        "pagination": {
-            "pageNumber": 0,
-            "pageSize": 10,
-            "totalCount": 5,
-            "totalPages": 1
-        }
-    }
-}
-```
-
-### Response Fields - categories[]
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | ARTICLE_CATEGORY.ID | ID danh mục bài viết (Primary Key) |
-| categoryName | string | ARTICLE_CATEGORY.CATEGORY_NAME<br/>CATEGORY_NAME_EN<br/>CATEGORY_NAME_LO | Tên danh mục (theo ngôn ngữ được chọn) |
-| categorySlug | string | ARTICLE_CATEGORY.CATEGORY_SLUG | URL-friendly slug cho danh mục |
-| description | string | ARTICLE_CATEGORY.DESCRIPTION<br/>DESCRIPTION_EN<br/>DESCRIPTION_LO | Mô tả chi tiết danh mục |
-| iconUrl | string | ARTICLE_CATEGORY.ICON_URL | Đường dẫn icon của danh mục |
-| parentId | int? | ARTICLE_CATEGORY.PARENT_ID | ID danh mục cha (null = danh mục gốc) |
-| displayOrder | int | ARTICLE_CATEGORY.DISPLAY_ORDER | Thứ tự hiển thị (số nhỏ hơn hiển thị trước) |
-
-### Response Fields - pagination
-| Field | Type | Description |
-|-------|------|-------------|
-| pageNumber | int | Trang hiện tại (bắt đầu từ 0) |
-| pageSize | int | Số items trên mỗi trang |
-| totalCount | int | Tổng số items trong database |
-| totalPages | int | Tổng số trang (= ceiling(totalCount / pageSize)) |
-
----
-
-## 4. Article Load
-
-Lấy danh sách bài viết hoặc chi tiết 1 bài viết.
-
-### Endpoint
-```
-POST /apis/article/load
-```
-
-### Request (danh sách)
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10,
-    "categoryId": 1,
-    "isFeatured": false
-}
-```
-
-### Request (chi tiết)
-```json
-{
-    "lang": "lo",
-    "slug": "huong-dan-cai-dat-esim"
-}
-```
-
-| Field | Type | Default | Description |
-|-------|------|---------|-------------|
-| lang | string | "lo" | Ngôn ngữ (hoặc header Accept-Language) |
-| pageNumber | int | 0 | Trang hiện tại |
-| pageSize | int | 10 | Số item mỗi trang |
-| categoryId | int? | null | Lọc theo danh mục |
-| isFeatured | bool? | null | Lọc bài viết nổi bật |
-| slug | string? | null | Slug để lấy chi tiết bài viết |
-
-### Response Success (danh sách)
-```json
-{
-    "errorCode": "0",
-    "message": "Success",
-    "data": {
-        "articles": [
-            {
-                "id": 1,
-                "title": "Hướng dẫn cài đặt eSIM",
-                "slug": "huong-dan-cai-dat-esim",
-                "summary": "Tóm tắt...",
-                "thumbnailUrl": "/images/article1.jpg",
-                "categoryId": 1,
-                "viewCount": 150,
-                "isFeatured": true,
-                "isPinned": false,
-                "publishedDate": "2024-12-25"
-            }
-        ],
-        "pagination": {...}
-    }
-}
-```
-
-### Response Success (chi tiết)
-```json
-{
-    "errorCode": "0",
-    "message": "Success",
-    "data": {
-        "article": {
-            "id": 1,
-            "title": "Hướng dẫn cài đặt eSIM",
-            "slug": "huong-dan-cai-dat-esim",
-            "summary": "Tóm tắt...",
-            "content": "<p>Nội dung HTML...</p>",
-            "thumbnailUrl": "/images/article1.jpg",
-            "coverImageUrl": "/images/cover1.jpg",
-            "metaDescription": "SEO description",
-            "metaKeywords": "esim, laos",
-            "categoryId": 1,
-            "viewCount": 151,
-            "isFeatured": true,
-            "publishedDate": "2024-12-25",
-            "createdDate": "2024-12-20"
-        }
-    }
-}
-```
-
-### Response Fields - articles[] (List)
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | ARTICLE.ID | ID bài viết (Primary Key) |
-| title | string | ARTICLE.TITLE<br/>TITLE_EN<br/>TITLE_LO | Tiêu đề bài viết (theo ngôn ngữ) |
-| slug | string | ARTICLE.SLUG | URL-friendly slug (unique) |
-| summary | string | ARTICLE.SUMMARY<br/>SUMMARY_EN<br/>SUMMARY_LO | Tóm tắt ngắn gọn |
-| thumbnailUrl | string | ARTICLE.THUMBNAIL_URL | Ảnh thumbnail (dùng cho list) |
-| categoryId | int | ARTICLE.CATEGORY_ID | ID danh mục (FK → ARTICLE_CATEGORY) |
-| viewCount | int | ARTICLE.VIEW_COUNT | Số lượt xem |
-| isFeatured | bool | ARTICLE.IS_FEATURED | Bài viết nổi bật (true/false) |
-| isPinned | bool | ARTICLE.IS_PINNED | Bài viết được ghim (true/false) |
-| publishedDate | datetime | ARTICLE.PUBLISHED_DATE | Ngày xuất bản |
-
-### Response Fields - article (Detail)
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| *Tất cả fields từ List + thêm:* | | | |
-| content | string | ARTICLE.CONTENT<br/>CONTENT_EN<br/>CONTENT_LO | Nội dung HTML đầy đủ |
-| coverImageUrl | string | ARTICLE.COVER_IMAGE_URL | Ảnh bìa (dùng cho detail page) |
-| metaDescription | string | ARTICLE.META_DESCRIPTION<br/>META_DESCRIPTION_EN<br/>META_DESCRIPTION_LO | SEO meta description |
-| metaKeywords | string | ARTICLE.META_KEYWORDS | SEO keywords (comma-separated) |
-| createdDate | datetime | ARTICLE.CREATED_DATE | Ngày tạo bài viết |
-
----
-
-## 5. Banner Load
-
-Lấy danh sách banner.
-
-### Endpoint
-```
-POST /apis/content/banner
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10,
-    "position": "home"
-}
-```
-
-| Field | Type | Default | Description |
-|-------|------|---------|-------------|
-| lang | string | "lo" | Ngôn ngữ (hoặc header Accept-Language) |
-| pageNumber | int | 0 | Trang hiện tại |
-| pageSize | int | 10 | Số item mỗi trang |
-| position | string? | null | Vị trí: "home", "sidebar"... |
-
-### Response
-```json
-{
-    "errorCode": "0",
-    "data": {
-        "banners": [
-            {
-                "id": 1,
-                "title": "Banner Title",
-                "subtitle": "Subtitle",
-                "imageUrl": "/images/banner1.jpg",
-                "imageMobileUrl": "/images/banner1_m.jpg",
-                "linkUrl": "/promo",
-                "linkTarget": "_blank",
-                "position": "home",
-                "displayOrder": 1
-            }
-        ],
-        "pagination": {...}
-    }
-}
-```
-
-### Response Fields - banners[]
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | BANNER.ID | ID banner (Primary Key) |
-| title | string | BANNER.TITLE<br/>TITLE_EN<br/>TITLE_LO | Tiêu đề banner (theo ngôn ngữ) |
-| subtitle | string | BANNER.SUBTITLE<br/>SUBTITLE_EN<br/>SUBTITLE_LO | Phụ đề banner |
-| imageUrl | string | BANNER.IMAGE_URL | Ảnh banner (desktop) |
-| imageMobileUrl | string | BANNER.IMAGE_MOBILE_URL | Ảnh banner (mobile) |
-| linkUrl | string | BANNER.LINK_URL | URL đích khi click banner |
-| linkTarget | string | BANNER.LINK_TARGET | Target (_self, _blank,...) |
-| position | string | BANNER.POSITION | Vị trí hiển thị (home, category,...) |
-| displayOrder | int | BANNER.DISPLAY_ORDER | Thứ tự hiển thị |
-
-**Lọc tự động**: Chỉ trả về banners với `STATUS = 1` và trong khoảng `START_DATE ≤ now ≤ END_DATE`
-
----
-
-## 6. Customer Review Load
-
-Lấy đánh giá của khách hàng.
-
-### Endpoint
-```
-POST /apis/content/review
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10,
-    "isFeatured": true
-}
-```
-
-| Field | Type | Default | Description |
-|-------|------|---------|-------------|
-| lang | string | "lo" | Ngôn ngữ |
-| pageNumber | int | 0 | Trang |
-| pageSize | int | 10 | Số item |
-| isFeatured | bool? | null | Lọc review nổi bật |
-
-### Response
-```json
-{
-    "errorCode": "0",
-    "data": {
-        "reviews": [
-            {
-                "id": 1,
-                "customerName": "Nguyen Van A",
-                "avatarUrl": "/avatars/user1.jpg",
-                "rating": 1,
-                "reviewContent": "Dich vu rat tot...",
-                "destination": "Vientiane, Laos",
-                "isFeatured": true,
-                "createdDate": "2024-12-25"
-            }
-        ],
-        "pagination": {...}
-    }
-}
-```
-
-### Response Fields - reviews[]
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | CUSTOMER_REVIEW.ID | ID đánh giá (Primary Key) |
-| customerName | string | CUSTOMER_REVIEW.CUSTOMER_NAME | Tên khách hàng |
-| avatarUrl | string | CUSTOMER_REVIEW.AVATAR_URL | Ảnh đại diện (nullable) |
-| rating | int | CUSTOMER_REVIEW.RATING | Số sao (1-5) |
-| reviewContent | string | CUSTOMER_REVIEW.REVIEW_CONTENT<br/>REVIEW_CONTENT_EN<br/>REVIEW_CONTENT_LO | Nội dung đánh giá (theo ngôn ngữ) |
-| destination | string | CUSTOMER_REVIEW.DESTINATION<br/>DESTINATION_EN<br/>DESTINATION_LO | Địa điểm du lịch |
-| isFeatured | bool | CUSTOMER_REVIEW.IS_FEATURED | Review nổi bật |
-| createdDate | datetime | CUSTOMER_REVIEW.CREATED_DATE | Ngày tạo review |
-
-**Lọc tự động**: Chỉ trả về reviews với `STATUS = 1` (đã duyệt)
-
----
-
-## 6.1 Customer Review Create
-
-Khách hàng gửi đánh giá (chờ duyệt).
-
-### Endpoint
-```
-POST /apis/content/review/create
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "customerName": "Nguyen Van A",
-    "reviewContent": "Dich vu rat tot, toi rat hai long!",
-    "destination": "Vientiane, Laos",
-    "rating": 5
-}
-```
-
-| Field | Type | Required | Description |
-|-------|------|----------|-------------|
-| lang | string | No | Ngôn ngữ |
-| customerName | string | Yes | Tên khách hàng |
-| reviewContent | string | Yes | Nội dung đánh giá |
-| destination | string | No | Địa điểm |
-| rating | int | No | Đánh giá (1-5) |
-
-### Response Success
-```json
-{
-    "errorCode": "0",
-    "message": "Review submitted successfully",
-    "data": {
-        "reviewId": 123
-    }
-}
-```
-
-### Note
-- Review mới sẽ có `Status = false` (chờ admin duyệt)
-
----
-
-## 7. FAQ Category Load
-
-Lấy danh mục FAQ.
-
-### Endpoint
-```
-POST /apis/content/faq-category
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10
-}
-```
-
-### Response
-```json
-{
-    "errorCode": "0",
-    "data": {
-        "categories": [
-            {
-                "id": 1,
-                "categoryName": "Cài đặt eSIM",
-                "categorySlug": "cai-dat-esim",
-                "description": "Hướng dẫn cài đặt",
-                "iconUrl": "/icons/setup.png",
-                "displayOrder": 1
-            }
-        ],
-        "pagination": {...}
-    }
-}
-```
-
-### Response Fields - categories[]
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | FAQ_CATEGORY.ID | ID danh mục FAQ (Primary Key) |
-| categoryName | string | FAQ_CATEGORY.CATEGORY_NAME<br/>CATEGORY_NAME_EN<br/>CATEGORY_NAME_LO | Tên danh mục FAQ |
-| categorySlug | string | FAQ_CATEGORY.CATEGORY_SLUG | URL-friendly slug |
-| description | string | FAQ_CATEGORY.DESCRIPTION<br/>DESCRIPTION_EN<br/>DESCRIPTION_LO | Mô tả danh mục |
-| iconUrl | string | FAQ_CATEGORY.ICON_URL | Icon của danh mục |
-| displayOrder | int | FAQ_CATEGORY.DISPLAY_ORDER | Thứ tự hiển thị |
-
----
-
-## 8. FAQ Load
-
-Lấy danh sách câu hỏi thường gặp.
-
-### Endpoint
-```
-POST /apis/content/faq
-```
-
-### Request
-```json
-{
-    "lang": "lo",
-    "pageNumber": 0,
-    "pageSize": 10,
-    "categoryId": 1,
-    "isFeatured": false
-}
-```
-
-| Field | Type | Default | Description |
-|-------|------|---------|-------------|
-| lang | string | "lo" | Ngôn ngữ |
-| pageNumber | int | 0 | Trang |
-| pageSize | int | 10 | Số item |
-| categoryId | int? | null | Lọc theo danh mục |
-| isFeatured | bool? | null | Lọc FAQ nổi bật |
-
-### Response
-```json
-{
-    "errorCode": "0",
-    "data": {
-        "faqs": [
-            {
-                "id": 1,
-                "question": "Làm sao để cài đặt eSIM?",
-                "answer": "<p>Hướng dẫn chi tiết...</p>",
-                "categoryId": 1,
-                "viewCount": 100,
-                "isFeatured": true
-            }
-        ],
-        "pagination": {...}
-    }
-}
-```
-
-### Response Fields - faqs[]
-| Field | Type | DB Column | Description |
-|-------|------|-----------|-------------|
-| id | int | FAQ.ID | ID câu hỏi (Primary Key) |
-| question | string | FAQ.QUESTION<br/>QUESTION_EN<br/>QUESTION_LO | Câu hỏi (theo ngôn ngữ) |
-| answer | string | FAQ.ANSWER<br/>ANSWER_EN<br/>ANSWER_LO | Câu trả lời (HTML format) |
-| categoryId | int | FAQ.CATEGORY_ID | ID danh mục (FK → FAQ_CATEGORY) |
-| viewCount | int | FAQ.VIEW_COUNT | Số lượt xem |
-| isFeatured | bool | FAQ.IS_FEATURED | FAQ nổi bật |
-
-**Lọc tự động**: Chỉ trả về FAQs với `STATUS = 1`
-
----

+ 1444 - 0
EsimLao/docs/api_auth_otp_Esim.txt

@@ -0,0 +1,1444 @@
+# EsimLao Authentication API Documentation
+
+## Overview
+API xác thực người dùng qua email với OTP (One-Time Password).
+URL_UAT : http://149.28.132.56:8360/
+---
+
+## 1. Request OTP
+
+Gửi mã OTP đến email người dùng để xác thực đăng nhập.
+
+### Endpoint
+```
+POST /apis/auth/request-otp
+```
+
+### Request Headers
+| Header | Value | Required |
+|--------|-------|----------|
+| Content-Type | application/json | Yes |
+
+### Request Body
+```json
+{
+    "email": "user@example.com",
+    "lang": "lo"  // Default: "lo" / en
+}
+```
+
+### Parameters
+| Field | Type | Required | Default | Description |
+|-------|------|----------|---------|-------------|
+| email | string | Yes | - | Email address của người dùng |
+| lang | string | No | "vi" | Ngôn ngữ email: `vi` (Tiếng Việt), `en` (English), `lo` (ລາວ) |
+
+### Response Success (200)
+```json
+{
+    "errorCode": "0",
+    "message": "<Config: OTP_SENT_SUCCESS>",
+    "data": {
+        "email": "user@example.com",
+        "expireInSeconds": 300
+    }
+}
+```
+
+### Response Error (200)
+```json
+// Email không được cung cấp
+{
+    "errorCode": "-801",
+    "message": "<Config: EMAIL_REQUIRED>",
+    "data": {}
+}
+
+// Lỗi hệ thống
+{
+    "errorCode": "-6",
+    "message": "<Config: SYSTEM_FAILURE>",
+    "data": {}
+}
+```
+
+### Response Fields
+| Field | Type | Description |
+|-------|------|-------------|
+| errorCode| string | "0" = Success, khác "0" = Error (xem Error Codes) |
+| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
+| data.email | string | Email đã gửi OTP |
+| data.expireInSeconds | int | Thời gian OTP hết hạn (giây) |
+
+### Notes
+- OTP gồm 6 chữ số
+- OTP có hiệu lực trong 5 phút
+- Mỗi lần request mới sẽ hủy các OTP cũ chưa sử dụng
+- Nếu email chưa tồn tại, hệ thống tự động tạo tài khoản mới
+
+---
+
+## 1.1 Resend OTP
+
+Gửi lại mã OTP mới đến email (hủy OTP cũ).
+
+### Endpoint
+```
+POST /apis/auth/resend-otp
+```
+
+### Request Headers
+| Header | Value | Required |
+|--------|-------|----------|
+| Content-Type | application/json | Yes |
+
+### Request Body
+```json
+{
+    "email": "user@example.com",
+    "lang": "lo"  // Default: "lo" / en / vi
+}
+```
+
+### Response
+Tương tự **Request OTP**.
+
+---
+
+## 2. Verify OTP
+
+Xác thực mã OTP và hoàn tất đăng nhập.
+
+### Endpoint
+```
+POST /apis/auth/verify-otp
+```
+
+### Request Headers
+| Header | Value | Required |
+|--------|-------|----------|
+| Content-Type | application/json | Yes |
+
+### Request Body
+```json
+{
+    "email": "user@example.com",
+    "otpCode": "123456",
+    "lang": "lo"  // Default: "lo" / en
+}
+```
+
+### Parameters
+| Field | Type | Required | Default | Description |
+|-------|------|----------|---------|-------------|
+| email | string | Yes | - | Email đã nhận OTP |
+| otpCode | string | Yes | - | Mã OTP 6 số |
+| lang | string | No | "lo" | Ngôn ngữ thông báo: `lo` (ລາວ), `en` (English) |
+
+### Response Success (200)
+```json
+{
+    "errorCode": "0",
+    "message": "<Config: LOGIN_SUCCESS>",
+    "data": {
+        "userId": 12345,
+        "email": "user@example.com",
+        "fullName": "Nguyen Van A",
+        "avatarUrl": "https://example.com/avatar.jpg",
+        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
+        "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
+        "expiresAt": "2024-12-30T10:00:00Z"
+    }
+}
+```
+
+### Response Error Cases
+```json
+// Thiếu email hoặc OTP
+{
+    "errorCode": "-801",
+    "message": "<Config: EMAIL_OTP_REQUIRED>",
+    "data": {}
+}
+
+// OTP không hợp lệ
+{
+    "errorCode": "-201",
+    "message": "<Config: OTP_INVALID>",
+    "data": {}
+}
+
+// OTP đã được sử dụng
+{
+    "errorCode": "-203",
+    "message": "<Config: OTP_ALREADY_USED>",
+    "data": {}
+}
+
+// OTP đã hết hạn
+{
+    "errorCode": "-202",
+    "message": "<Config: OTP_EXPIRED>",
+    "data": {}
+}
+
+// Không tìm thấy người dùng
+{
+    "errorCode": "-300",
+    "message": "<Config: USER_NOT_FOUND>",
+    "data": {}
+}
+
+// Lỗi hệ thống
+{
+    "errorCode": "-6",
+    "message": "<Config: SYSTEM_FAILURE>",
+    "data": {}
+}
+```
+
+### Response Fields
+| Field | Type | Description |
+|-------|------|-------------|
+| errorCode| string | "0" = Success, khác "0" = Error (xem Error Codes) |
+| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
+| data.userId | int | ID người dùng |
+| data.email | string | Email người dùng |
+| data.fullName | string | Họ tên đầy đủ |
+| data.avatarUrl | string | URL ảnh đại diện (nullable) |
+| data.accessToken | string | JWT access token |
+| data.refreshToken | string | Refresh token để làm mới access token |
+| data.expiresAt | datetime | Thời điểm access token hết hạn |
+
+### Notes
+- Access token có hiệu lực 24 giờ
+- Refresh token có hiệu lực 30 ngày
+- Mỗi lần đăng nhập thành công, các token cũ sẽ bị thu hồi
+
+---
+
+## 2.1 Google Login - Get Authorization URL
+
+Lấy URL để redirect người dùng đến Google OAuth consent screen.
+
+### Endpoint
+```
+POST /apis/auth/google-login
+```
+
+### Request Headers
+| Header | Value | Required |
+|--------|-------|----------|
+| Content-Type | application/json | Yes |
+
+### Request Body
+```json
+{
+    "lang": "lo"  // Optional: "lo" (default), "en"
+}
+```
+
+### Parameters
+| Field | Type | Required | Default | Description |
+|-------|------|----------|---------|-------------|
+| lang | string | No | "lo" | Ngôn ngữ thông báo: `lo` (ລາວ), `en` (English) |
+
+### Response Success (200)
+```json
+{
+    "errorCode": "0",
+    "message": "<Config: SUCCESS>",
+    "data": {
+        "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=xxx&redirect_uri=xxx&response_type=code&scope=email%20profile"
+    }
+}
+```
+
+### Response Fields
+| Field | Type | Description |
+|-------|------|-------------|
+| errorCode | string | "0" = Success |
+| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
+| data.url | string | URL để redirect user đến Google OAuth |
+
+### Flow
+1. Frontend gọi API này để lấy Google OAuth URL
+2. Frontend redirect user đến URL nhận được
+3. User đăng nhập Google và cho phép quyền
+4. Google redirect về `redirect_uri` với `code` parameter
+5. Frontend gọi API `/apis/auth/google-callback` với `code` này
+
+### Response Error
+```json
+{
+    "errorCode": "-6",
+    "message": "<Config: GOOGLE_CONFIG_MISSING>",
+    "data": {}
+}
+```
+
+---
+
+## 2.2 Google Callback - Complete Login
+
+Xác thực authorization code từ Google và hoàn tất đăng nhập.
+- Nếu email chưa tồn tại: Tự động tạo tài khoản mới trong `CUSTOMER_INFO`
+- Nếu email đã tồn tại: Cập nhật thông tin và đăng nhập
+
+### Endpoint
+```
+POST /apis/auth/google-callback
+```
+
+### Request Headers
+| Header | Value | Required |
+|--------|-------|----------|
+| Content-Type | application/json | Yes |
+
+### Request Body
+```json
+{
+    "code": "4/0AXEWy...",
+    "redirectUri": "https://your-app.com/callback",
+    "lang": "lo"  // Optional: "lo" (default), "en"
+}
+```
+
+### Parameters
+| Field | Type | Required | Default | Description |
+|-------|------|----------|---------|-------------|
+| code | string | Yes | - | Authorization code từ Google (nhận qua URL callback) |
+| redirectUri | string | No | - | Redirect URI đã đăng ký với Google (nếu khác default) |
+| lang | string | No | "lo" | Ngôn ngữ thông báo: `lo` (ລາວ), `en` (English) |
+
+### Response Success (200) - GIỐNG API verify-otp
+```json
+{
+    "errorCode": "0",
+    "message": "<Config: GOOGLE_LOGIN_SUCCESS>",
+    "data": {
+        "userId": 12345,
+        "email": "user@gmail.com",
+        "fullName": "Nguyen Van A",
+        "avatarUrl": "https://lh3.googleusercontent.com/...",
+        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
+        "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
+        "expiresAt": "2024-12-30T10:00:00Z"
+    }
+}
+```
+
+### Response Fields (giống verify-otp)
+| Field | Type | Description |
+|-------|------|-------------|
+| errorCode | string | "0" = Success |
+| message | string | Thông báo từ CONFIG table (theo ngôn ngữ) |
+| data.userId | int | ID người dùng (từ CUSTOMER_INFO.ID) |
+| data.email | string | Email người dùng |
+| data.fullName | string | Họ tên đầy đủ (từ Google profile) |
+| data.avatarUrl | string | URL ảnh đại diện từ Google |
+| data.accessToken | string | JWT access token (24 giờ) |
+| data.refreshToken | string | Refresh token (30 ngày) |
+| data.expiresAt | datetime | Thời điểm access token hết hạn |
+
+### Database Operations
+Khi login thành công:
+1. **CUSTOMER_INFO**: 
+   - User mới: INSERT với `SUR_NAME`, `LAST_NAME`, `EMAIL`, `AVATAR_URL`, `IS_VERIFIED=1`
+   - User có sẵn: UPDATE `AVATAR_URL` (nếu trống), `LAST_LOGIN_DATE`, `IS_VERIFIED=1`
+2. **USER_TOKEN**: Revoke tokens cũ và tạo token mới
+
+### Response Error Cases
+```json
+// Code không được cung cấp
+{
+    "errorCode": "-801",
+    "message": "<Config: GOOGLE_CODE_REQUIRED>",
+    "data": {}
+}
+
+// Lỗi trao đổi token với Google
+{
+    "errorCode": "-700",
+    "message": "<Config: GOOGLE_TOKEN_EXCHANGE_FAILED>",
+    "data": { "error": "..." }
+}
+
+// Không nhận được email từ Google
+{
+    "errorCode": "-700",
+    "message": "<Config: GOOGLE_NO_EMAIL>",
+    "data": {}
+}
+
+// Lỗi hệ thống
+{
+    "errorCode": "-6",
+    "message": "<Config: SYSTEM_FAILURE>",
+    "data": {}
+}
+```
+
+### Notes
+- Access token có hiệu lực 24 giờ
+- Refresh token có hiệu lực 30 ngày
+- Mỗi lần đăng nhập thành công, các token cũ sẽ bị thu hồi
+- User đăng nhập qua Google tự động được đánh dấu `IS_VERIFIED = 1`
+- Nếu user chưa có avatar và Google cung cấp, sẽ tự động lưu
+
+---
+
+## Google OAuth Flow Diagram
+
+```
+┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
+│   Client    │     │   API       │     │   Google    │     │   Database  │
+└──────┬──────┘     └──────┬──────┘     └──────┬──────┘     └──────┬──────┘
+       │                   │                   │                   │
+       │ POST /google-login│                   │                   │
+       │──────────────────>│                   │                   │
+       │                   │                   │                   │
+       │   { url: "..." }  │                   │                   │
+       │<──────────────────│                   │                   │
+       │                   │                   │                   │
+       │  Redirect to URL  │                   │                   │
+       │──────────────────────────────────────>│                   │
+       │                   │                   │                   │
+       │                   │                   │ User Login        │
+       │                   │                   │ Grant Permission  │
+       │                   │                   │                   │
+       │ Callback with code│                   │                   │
+       │<──────────────────────────────────────│                   │
+       │                   │                   │                   │
+       │ POST /google-callback                 │                   │
+       │    { code: "..." }│                   │                   │
+       │──────────────────>│                   │                   │
+       │                   │                   │                   │
+       │                   │ Exchange code     │                   │
+       │                   │──────────────────>│                   │
+       │                   │                   │                   │
+       │                   │ access_token      │                   │
+       │                   │<──────────────────│                   │
+       │                   │                   │                   │
+       │                   │ Get user info     │                   │
+       │                   │──────────────────>│                   │
+       │                   │                   │                   │
+       │                   │ email, name, pic  │                   │
+       │                   │<──────────────────│                   │
+       │                   │                   │                   │
+       │                   │ Insert/Update CUSTOMER_INFO           │
+       │                   │ Create USER_TOKEN                     │
+       │                   │──────────────────────────────────────>│
+       │                   │                   │                   │
+       │  JWT Token Response                   │                   │
+       │<──────────────────│                   │                   │
+       │                   │                   │                   │
+```
+
+---
+
+## Example Usage (cURL) - Google Login
+
+### Step 1: Get Google OAuth URL
+```bash
+curl -X POST http://149.28.132.56:8360/apis/auth/google-login \
+  -H "Content-Type: application/json"
+```
+
+### Step 2: Complete Login with Code
+```bash
+curl -X POST http://149.28.132.56:8360/apis/auth/google-callback \
+  -H "Content-Type: application/json" \
+  -d '{
+    "code": "4/0AXEWy..."
+  }'
+```
+
+---
+
+## Error Codes
+
+### Success
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "0" | Success | Thành công (mọi request thành công đều trả về "0") |
+
+### General Errors (-1 to -99)
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "-1" | Error | Lỗi chung |
+| "-6" | SystemError | Lỗi hệ thống |
+
+### OTP Errors (-200 to -299)
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "-200" | OtpRequired | Yêu cầu OTP |
+| "-201" | OtpInvalid | OTP không hợp lệ |
+| "-202" | OtpExpired | OTP đã hết hạn |
+| "-203" | OtpAlreadyUsed | OTP đã được sử dụng |
+| "-204" | OtpMaxAttemptsExceeded | Vượt quá số lần thử |
+| "-205" | OtpSendFailed | Gửi OTP thất bại |
+| "-206" | OtpTooManyRequests | Request quá nhiều |
+
+### User Errors (-300 to -399)
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "-300" | UserNotFound | Không tìm thấy người dùng |
+| "-304" | InvalidEmail | Email không hợp lệ |
+
+### External Service Errors (-700 to -799)
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "-700" | ExternalServiceError | Lỗi từ dịch vụ bên ngoài (Google OAuth, etc.) |
+
+### Validation Errors (-800 to -899)
+| errorCode| Constant | Description |
+|------|----------|-------------|
+| "-801" | RequiredFieldMissing | Thiếu trường bắt buộc |
+
+---
+
+## Authentication
+
+Sau khi đăng nhập thành công, sử dụng `accessToken` trong header cho các API yêu cầu xác thực:
+
+```
+Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
+```
+
+---
+
+## Flow Diagram
+
+```
+┌─────────────┐     ┌─────────────┐     ┌─────────────┐
+│   Client    │     │   API       │     │   Email     │
+└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
+       │                   │                   │
+       │ POST /request-otp │                   │
+       │──────────────────>│                   │
+       │                   │                   │
+       │                   │ Generate OTP      │
+       │                   │ Save to DB        │
+       │                   │ Queue Email       │
+       │                   │                   │
+       │    Response       │                   │
+       │<──────────────────│                   │
+       │                   │                   │
+       │                   │  Send OTP Email   │
+       │                   │──────────────────>│
+       │                   │                   │
+       │                   │                   │ OTP Email
+       │<──────────────────────────────────────│
+       │                   │                   │
+       │ POST /verify-otp  │                   │
+       │──────────────────>│                   │
+       │                   │                   │
+       │                   │ Verify OTP        │
+       │                   │ Generate JWT      │
+       │                   │                   │
+       │ Token Response    │                   │
+       │<──────────────────│                   │
+       │                   │                   │
+```
+
+---
+
+## Example Usage (cURL)
+
+### Request OTP
+```bash
+curl -X POST https://api.esimlao.com/apis/auth/request-otp \
+  -H "Content-Type: application/json" \
+  -d '{
+    "email": "user@example.com",
+    "lang": "vi"
+  }'
+```
+
+### Verify OTP
+```bash
+curl -X POST https://api.esimlao.com/apis/auth/verify-otp \
+  -H "Content-Type: application/json" \
+  -d '{
+    "email": "user@example.com",
+    "otpCode": "123456"
+  }'
+```
+
+### Use Token
+```bash
+curl -X GET https://api.esimlao.com/apis/user/profile \
+  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
+```
+
+---
+
+## 3. Article Category
+
+Lấy danh sách danh mục bài viết.
+
+### Endpoint
+```
+POST /apis/article/category
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "parentId": null
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ: "lo", "en" (có thể truyền qua header Accept-Language) |
+| pageNumber | int | 0 | Trang hiện tại |
+| pageSize | int | 10 | Số item mỗi trang |
+| parentId | int? | null | ID danh mục cha (null = root) |
+
+### Response Success
+```json
+{
+    "errorCode": "0",
+    "message": "Success",
+    "data": {
+        "categories": [
+            {
+                "id": 1,
+                "categoryName": "Cẩm nang du lịch",
+                "categorySlug": "cam-nang-du-lich",
+                "description": "Mô tả...",
+                "iconUrl": "/icons/travel.png",
+                "parentId": null,
+                "displayOrder": 1
+            }
+        ],
+        "pagination": {
+            "pageNumber": 0,
+            "pageSize": 10,
+            "totalCount": 5,
+            "totalPages": 1
+        }
+    }
+}
+```
+
+### Response Fields - categories[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | ARTICLE_CATEGORY.ID | ID danh mục bài viết (Primary Key) |
+| categoryName | string | ARTICLE_CATEGORY.CATEGORY_NAME<br/>CATEGORY_NAME_EN<br/>CATEGORY_NAME_LO | Tên danh mục (theo ngôn ngữ được chọn) |
+| categorySlug | string | ARTICLE_CATEGORY.CATEGORY_SLUG | URL-friendly slug cho danh mục |
+| description | string | ARTICLE_CATEGORY.DESCRIPTION<br/>DESCRIPTION_EN<br/>DESCRIPTION_LO | Mô tả chi tiết danh mục |
+| iconUrl | string | ARTICLE_CATEGORY.ICON_URL | Đường dẫn icon của danh mục |
+| parentId | int? | ARTICLE_CATEGORY.PARENT_ID | ID danh mục cha (null = danh mục gốc) |
+| displayOrder | int | ARTICLE_CATEGORY.DISPLAY_ORDER | Thứ tự hiển thị (số nhỏ hơn hiển thị trước) |
+
+### Response Fields - pagination
+| Field | Type | Description |
+|-------|------|-------------|
+| pageNumber | int | Trang hiện tại (bắt đầu từ 0) |
+| pageSize | int | Số items trên mỗi trang |
+| totalCount | int | Tổng số items trong database |
+| totalPages | int | Tổng số trang (= ceiling(totalCount / pageSize)) |
+
+---
+
+## 4. Article Load (List)
+
+Lấy danh sách bài viết với pagination và filters.
+
+### Endpoint
+```
+POST /apis/article/load
+```
+
+### Request (tất cả bài viết)
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10
+}
+```
+
+### Request (lọc theo category)
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "categoryId": 1,
+    "isFeatured": false
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ (hoặc header Accept-Language) |
+| pageNumber | int | 0 | Trang hiện tại (0-indexed) |
+| pageSize | int | 10 | Số item mỗi trang |
+| categoryId | int? | **null** | **null = lấy tất cả**, có giá trị = lọc theo danh mục |
+| isFeatured | bool? | null | true = chỉ bài nổi bật, null = tất cả |
+
+### Response Success
+```json
+{
+    "errorCode": "0",
+    "message": "Success",
+    "data": {
+        "articles": [
+            {
+                "id": 1,
+                "title": "Hướng dẫn cài đặt eSIM",
+                "slug": "huong-dan-cai-dat-esim",
+                "summary": "Tóm tắt...",
+                "thumbnailUrl": "/images/article1.jpg",
+                "categoryId": 1,
+                "viewCount": 150,
+                "isFeatured": true,
+                "isPinned": false,
+                "publishedDate": "2024-12-25"
+            }
+        ],
+        "pagination": {
+            "pageNumber": 0,
+            "pageSize": 10,
+            "totalCount": 25,
+            "totalPages": 3
+        }
+    }
+}
+```
+
+### Response Fields - articles[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | ARTICLE.ID | **ID bài viết** - dùng để lấy chi tiết qua `/apis/article/detail` |
+| title | string | ARTICLE.TITLE<br/>TITLE_EN<br/>TITLE_LO | Tiêu đề bài viết (theo ngôn ngữ) |
+| slug | string | ARTICLE.SLUG | URL-friendly slug (unique) |
+| summary | string | ARTICLE.SUMMARY<br/>SUMMARY_EN<br/>SUMMARY_LO | Tóm tắt ngắn gọn |
+| thumbnailUrl | string | ARTICLE.THUMBNAIL_URL | Ảnh thumbnail (dùng cho list) |
+| categoryId | int | ARTICLE.CATEGORY_ID | ID danh mục (FK → ARTICLE_CATEGORY) |
+| viewCount | int | ARTICLE.VIEW_COUNT | Số lượt xem |
+| isFeatured | bool | ARTICLE.IS_FEATURED | Bài viết nổi bật (true/false) |
+| isPinned | bool | ARTICLE.IS_PINNED | Bài viết được ghim (true/false) |
+| publishedDate | datetime | ARTICLE.PUBLISHED_DATE | Ngày xuất bản |
+
+### Important Notes
+- **Ordering**: Danh sách sắp xếp theo:
+  1. `IS_PINNED` DESC (bài ghim lên đầu)
+  2. `PUBLISHED_DATE` DESC (mới nhất trước)
+  3. `CREATED_DATE` DESC
+- **Filter logic**:
+  - `categoryId = null` → Lấy **tất cả** bài viết
+  - `categoryId = 1` → Chỉ lấy bài viết thuộc category 1
+
+### cURL Examples
+
+#### Lấy tất cả bài viết
+```bash
+curl -X POST http://localhost:8360/apis/article/load \
+  -H "Content-Type: application/json" \
+  -d '{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10
+  }'
+```
+
+#### Lấy bài viết theo category
+```bash
+curl -X POST http://localhost:8360/apis/article/load \
+  -H "Content-Type: application/json" \
+  -d '{
+    "categoryId": 1,
+    "lang": "en",
+    "pageSize": 5
+  }'
+```
+
+#### Lấy bài viết nổi bật
+```bash
+curl -X POST http://localhost:8360/apis/article/load \
+  -H "Content-Type: application/json" \
+  -d '{
+    "isFeatured": true,
+    "lang": "lo",
+    "pageSize": 6
+  }'
+```
+
+---
+
+## 4.1 Article Detail
+
+Lấy chi tiết 1 bài viết theo ID hoặc slug.
+
+### Endpoint
+```
+POST /apis/article/detail
+```
+
+### Request (theo ID - khuyến nghị)
+```json
+{
+    "id": 1,
+    "lang": "lo"
+}
+```
+
+### Request (theo slug - SEO friendly)
+```json
+{
+    "slug": "huong-dan-cai-dat-esim",
+    "lang": "lo"
+}
+```
+
+| Field | Type | Required | Description |
+|-------|------|----------|-------------|
+| id | int? | Conditional | ID bài viết (lấy từ list API) |
+| slug | string? | Conditional | Slug của bài viết |
+| lang | string | No | Ngôn ngữ (default: "lo") |
+
+**Note**: Phải có **ít nhất một** trong `id` hoặc `slug`
+
+### Response Success
+```json
+{
+    "errorCode": "0",
+    "message": "Success",
+    "data": {
+        "article": {
+            "id": 1,
+            "title": "Hướng dẫn cài đặt eSIM",
+            "slug": "huong-dan-cai-dat-esim",
+            "summary": "Tóm tắt...",
+            "content": "<p>Nội dung HTML đầy đủ...</p>",
+            "thumbnailUrl": "/images/article1.jpg",
+            "coverImageUrl": "/images/cover1.jpg",
+            "metaDescription": "SEO description",
+            "metaKeywords": "esim, laos",
+            "categoryId": 1,
+            "viewCount": 151,
+            "isFeatured": true,
+            "publishedDate": "2024-12-25",
+            "createdDate": "2024-12-20"
+        }
+    }
+}
+```
+
+### Response Fields - article
+| Field | Type | DB Column | Description |
+|-------|------|----------|-------------|
+| id | int | ARTICLE.ID | ID bài viết (Primary Key) |
+| title | string | ARTICLE.TITLE<br/>TITLE_EN<br/>TITLE_LO | Tiêu đề bài viết (theo ngôn ngữ) |
+| slug | string | ARTICLE.SLUG | URL-friendly slug (unique) |
+| summary | string | ARTICLE.SUMMARY<br/>SUMMARY_EN<br/>SUMMARY_LO | Tóm tắt ngắn gọn |
+| content | string | ARTICLE.CONTENT<br/>CONTENT_EN<br/>CONTENT_LO | **Nội dung HTML đầy đủ** |
+| thumbnailUrl | string | ARTICLE.THUMBNAIL_URL | Ảnh thumbnail |
+| coverImageUrl | string | ARTICLE.COVER_IMAGE_URL | Ảnh bìa (dùng cho detail page) |
+| metaDescription | string | ARTICLE.META_DESCRIPTION<br/>META_DESCRIPTION_EN<br/>META_DESCRIPTION_LO | SEO meta description |
+| metaKeywords | string | ARTICLE.META_KEYWORDS | SEO keywords (comma-separated) |
+| categoryId | int | ARTICLE.CATEGORY_ID | ID danh mục |
+| viewCount | int | ARTICLE.VIEW_COUNT | Số lượt xem (**tự động +1 khi gọi API này**) |
+| isFeatured | bool | ARTICLE.IS_FEATURED | Bài viết nổi bật |
+| publishedDate | datetime | ARTICLE.PUBLISHED_DATE | Ngày xuất bản |
+| createdDate | datetime | ARTICLE.CREATED_DATE | Ngày tạo bài viết |
+
+### Important Notes
+- **Auto view count**: Mỗi lần gọi API này, `viewCount` tự động +1
+- **Recommended flow**:
+  1. Gọi `/apis/article/load` → Lấy `id` từ danh sách
+  2. Gọi `/apis/article/detail` với `id` đó
+
+### cURL Examples
+
+#### Lấy chi tiết theo ID
+```bash
+curl -X POST http://localhost:8360/apis/article/detail \
+  -H "Content-Type: application/json" \
+  -d '{
+    "id": 1,
+    "lang": "lo"
+  }'
+```
+
+#### Lấy chi tiết theo slug  
+```bash
+curl -X POST http://localhost:8360/apis/article/detail \
+  -H "Content-Type: application/json" \
+  -d '{
+    "slug": "huong-dan-cai-dat-esim",
+    "lang": "en"
+  }'
+```
+
+---
+
+## 5. Banner Load
+
+Lấy danh sách banner.
+
+### Endpoint
+```
+POST /apis/content/banner
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "position": "home"
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ (hoặc header Accept-Language) |
+| pageNumber | int | 0 | Trang hiện tại |
+| pageSize | int | 10 | Số item mỗi trang |
+| position | string? | null | Vị trí: "home", "sidebar"... |
+
+### Response
+```json
+{
+    "errorCode": "0",
+    "data": {
+        "banners": [
+            {
+                "id": 1,
+                "title": "Banner Title",
+                "subtitle": "Subtitle",
+                "imageUrl": "/images/banner1.jpg",
+                "imageMobileUrl": "/images/banner1_m.jpg",
+                "linkUrl": "/promo",
+                "linkTarget": "_blank",
+                "position": "home",
+                "displayOrder": 1
+            }
+        ],
+        "pagination": {...}
+    }
+}
+```
+
+### Response Fields - banners[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | BANNER.ID | ID banner (Primary Key) |
+| title | string | BANNER.TITLE<br/>TITLE_EN<br/>TITLE_LO | Tiêu đề banner (theo ngôn ngữ) |
+| subtitle | string | BANNER.SUBTITLE<br/>SUBTITLE_EN<br/>SUBTITLE_LO | Phụ đề banner |
+| imageUrl | string | BANNER.IMAGE_URL | Ảnh banner (desktop) |
+| imageMobileUrl | string | BANNER.IMAGE_MOBILE_URL | Ảnh banner (mobile) |
+| linkUrl | string | BANNER.LINK_URL | URL đích khi click banner |
+| linkTarget | string | BANNER.LINK_TARGET | Target (_self, _blank,...) |
+| position | string | BANNER.POSITION | Vị trí hiển thị (home, category,...) |
+| displayOrder | int | BANNER.DISPLAY_ORDER | Thứ tự hiển thị |
+
+**Lọc tự động**: Chỉ trả về banners với `STATUS = 1` và trong khoảng `START_DATE ≤ now ≤ END_DATE`
+
+---
+
+## 6. Customer Review Load
+
+Lấy đánh giá của khách hàng.
+
+### Endpoint
+```
+POST /apis/content/review
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "isFeatured": true
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ |
+| pageNumber | int | 0 | Trang |
+| pageSize | int | 10 | Số item |
+| isFeatured | bool? | null | Lọc review nổi bật |
+
+### Response
+```json
+{
+    "errorCode": "0",
+    "data": {
+        "reviews": [
+            {
+                "id": 1,
+                "customerName": "Nguyen Van A",
+                "avatarUrl": "/avatars/user1.jpg",
+                "rating": 1,
+                "reviewContent": "Dich vu rat tot...",
+                "destination": "Vientiane, Laos",
+                "isFeatured": true,
+                "createdDate": "2024-12-25"
+            }
+        ],
+        "pagination": {...}
+    }
+}
+```
+
+### Response Fields - reviews[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | CUSTOMER_REVIEW.ID | ID đánh giá (Primary Key) |
+| customerName | string | CUSTOMER_REVIEW.CUSTOMER_NAME | Tên khách hàng |
+| avatarUrl | string | CUSTOMER_REVIEW.AVATAR_URL | Ảnh đại diện (nullable) |
+| rating | int | CUSTOMER_REVIEW.RATING | Số sao (1-5) |
+| reviewContent | string | CUSTOMER_REVIEW.REVIEW_CONTENT<br/>REVIEW_CONTENT_EN<br/>REVIEW_CONTENT_LO | Nội dung đánh giá (theo ngôn ngữ) |
+| destination | string | CUSTOMER_REVIEW.DESTINATION<br/>DESTINATION_EN<br/>DESTINATION_LO | Địa điểm du lịch |
+| isFeatured | bool | CUSTOMER_REVIEW.IS_FEATURED | Review nổi bật |
+| createdDate | datetime | CUSTOMER_REVIEW.CREATED_DATE | Ngày tạo review |
+
+**Lọc tự động**: Chỉ trả về reviews với `STATUS = 1` (đã duyệt)
+
+---
+
+## 6.1 Customer Review Create
+
+Khách hàng gửi đánh giá (chờ duyệt).
+
+### Endpoint
+```
+POST /apis/content/review/create
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "customerName": "Nguyen Van A",
+    "reviewContent": "Dich vu rat tot, toi rat hai long!",
+    "destination": "Vientiane, Laos",
+    "rating": 5
+}
+```
+
+| Field | Type | Required | Description |
+|-------|------|----------|-------------|
+| lang | string | No | Ngôn ngữ |
+| customerName | string | Yes | Tên khách hàng |
+| reviewContent | string | Yes | Nội dung đánh giá |
+| destination | string | No | Địa điểm |
+| rating | int | No | Đánh giá (1-5) |
+
+### Response Success
+```json
+{
+    "errorCode": "0",
+    "message": "Review submitted successfully",
+    "data": {
+        "reviewId": 123
+    }
+}
+```
+
+### Note
+- Review mới sẽ có `Status = false` (chờ admin duyệt)
+
+---
+
+## 7. FAQ Category Load
+
+Lấy danh mục FAQ (hỗ trợ cấu trúc phân cấp).
+
+### Endpoint
+```
+POST /apis/content/faq-category
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "parentId": null
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ (hoặc header Accept-Language) |
+| pageNumber | int | 0 | Trang hiện tại |
+| pageSize | int | 10 | Số item mỗi trang |
+| parentId | int? | null | ID danh mục cha (null = lấy root categories) |
+
+### Response
+```json
+{
+    "errorCode": "0",
+    "data": {
+        "categories": [
+            {
+                "id": 1,
+                "categoryName": "Cài đặt eSIM",
+                "categorySlug": "cai-dat-esim",
+                "description": "Hướng dẫn cài đặt",
+                "iconUrl": "/icons/setup.png",
+                "parentId": null,
+                "displayOrder": 1
+            }
+        ],
+        "pagination": {...}
+    }
+}
+```
+
+### Response Fields - categories[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | FAQ_CATEGORY.ID | ID danh mục FAQ (Primary Key) |
+| categoryName | string | FAQ_CATEGORY.CATEGORY_NAME<br/>CATEGORY_NAME_EN<br/>CATEGORY_NAME_LO | Tên danh mục FAQ |
+| categorySlug | string | FAQ_CATEGORY.CATEGORY_SLUG | URL-friendly slug |
+| description | string | FAQ_CATEGORY.DESCRIPTION<br/>DESCRIPTION_EN<br/>DESCRIPTION_LO | Mô tả danh mục |
+| iconUrl | string | FAQ_CATEGORY.ICON_URL | Icon của danh mục |
+| parentId | int? | FAQ_CATEGORY.PARENT_ID | **ID danh mục cha (null = danh mục gốc)** |
+| displayOrder | int | FAQ_CATEGORY.DISPLAY_ORDER | Thứ tự hiển thị |
+
+### Use Cases
+- **Homepage FAQ**: `parentId = null` → Lấy danh mục gốc
+- **Support Center**: `parentId = <categoryId>` → Lấy danh mục con
+- Hỗ trợ cấu trúc phân cấp không giới hạn cấp độ
+
+---
+
+## 8. FAQ Load
+
+Lấy danh sách câu hỏi thường gặp.
+
+### Endpoint
+```
+POST /apis/content/faq
+```
+
+### Request
+```json
+{
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 10,
+    "categoryId": 1,
+    "isFeatured": false
+}
+```
+
+| Field | Type | Default | Description |
+|-------|------|---------|-------------|
+| lang | string | "lo" | Ngôn ngữ |
+| pageNumber | int | 0 | Trang |
+| pageSize | int | 10 | Số item |
+| categoryId | int? | null | Lọc theo danh mục |
+| isFeatured | bool? | null | Lọc FAQ nổi bật |
+
+### Response
+```json
+{
+    "errorCode": "0",
+    "data": {
+        "faqs": [
+            {
+                "id": 1,
+                "question": "Làm sao để cài đặt eSIM?",
+                "answer": "<p>Hướng dẫn chi tiết...</p>",
+                "categoryId": 1,
+                "viewCount": 100,
+                "isFeatured": true
+            }
+        ],
+        "pagination": {...}
+    }
+}
+```
+
+### Response Fields - faqs[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | FAQ.ID | ID câu hỏi (Primary Key) |
+| question | string | FAQ.QUESTION<br/>QUESTION_EN<br/>QUESTION_LO | Câu hỏi (theo ngôn ngữ) |
+| answer | string | FAQ.ANSWER<br/>ANSWER_EN<br/>ANSWER_LO | Câu trả lời (HTML format) |
+| categoryId | int | FAQ.CATEGORY_ID | ID danh mục (FK → FAQ_CATEGORY) |
+| viewCount | int | FAQ.VIEW_COUNT | Số lượt xem |
+| isFeatured | bool | FAQ.IS_FEATURED | FAQ nổi bật |
+
+**Lọc tự động**: Chỉ trả về FAQs với `STATUS = 1`
+
+---
+
+## 9. Device eSIM Compatibility - Get Metadata
+
+Lấy danh sách brands và categories để hiển thị tabs/filters cho tính năng kiểm tra thiết bị.
+
+### Endpoint
+```
+GET /apis/content/device-metadata
+```
+
+### Request
+Không cần body (GET request)
+
+### Response
+```json
+{
+    "errorCode": "0",
+    "message": "Success",
+    "data": {
+        "brands": [
+            {
+                "brand": "Apple",
+                "deviceCount": 24,
+                "popularCount": 24,
+                "devices": [
+                    {
+                        "id": 1,
+                        "modelName": "iPhone XS",
+                        "category": "Phone",
+                        "isPopular": true,
+                        "displayOrder": 1,
+                        "modelNameEn": "iPhone XS",
+                        "modelNameLo": "iPhone XS",
+                        "notes": "Tất cả phiên bản trừ China Mainland, Hong Kong, Macao",
+                        "notesEn": "All versions except China Mainland, Hong Kong, Macao",
+                        "notesLo": "ທຸກເວີຊັນຍົກເວັ້ນ China Mainland, Hong Kong, Macao"
+                    }
+                ]
+            },
+            {
+                "brand": "Samsung",
+                "deviceCount": 19,
+                "popularCount": 19,
+                "devices": [...]
+            }
+        ],
+        "categories": [
+            {
+                "category": "Phone",
+                "deviceCount": 67
+            },
+            {
+                "category": "Tablet",
+                "deviceCount": 4
+            }
+        ]
+    }
+}
+```
+
+### Response Fields - brands[]
+| Field | Type | Description |
+|-------|------|-------------|
+| brand | string | Tên hãng (Apple, Samsung, Google,...) |
+| deviceCount | int | Tổng số thiết bị của hãng này |
+| popularCount | int | Số thiết bị phổ biến (IS_POPULAR = 1) |
+| **devices[]** | array | **Danh sách tất cả thiết bị của brand** |
+
+### Response Fields - brands[].devices[]
+| Field | Type | Description |
+|-------|------|-------------|
+| id | int | ID thiết bị |
+| modelName | string | Tên model (mặc định Vietnamese) |
+| category | string | Loại thiết bị (Phone, Tablet, Laptop, Watch) |
+| isPopular | bool | Thiết bị phổ biến |
+| displayOrder | int | Thứ tự sắp xếp |
+| modelNameEn | string | Tên model tiếng Anh |
+| modelNameLo | string | Tên model tiếng Lào |
+| notes | string | Ghi chú (Vietnamese) |
+| notesEn | string | Ghi chú (English) |
+| notesLo | string | Ghi chú (Lao) |
+
+### Response Fields - categories[]
+| Field | Type | Description |
+|-------|------|-------------|
+| category | string | Loại thiết bị (Phone, Tablet, Laptop, Watch) |
+| deviceCount | int | Tổng số thiết bị thuộc category này |
+
+### Use Case
+API này trả về **TẤT CẢ** devices trong một lần gọi để:
+- Frontend có thể filter/search ở client-side
+- Hiển thị tabs cho từng brand với danh sách devices
+- Không cần pagination vì dùng cho client-side filtering
+- Giảm số lượng API calls
+
+### Important Notes
+- **Trả về toàn bộ devices** trong response (không phân trang)
+- Frontend tự filter theo brand/category/search
+- Chỉ devices có `STATUS = 1` và `SUPPORTS_ESIM = 1`
+- Sắp xếp theo `DISPLAY_ORDER`, `BRAND`, `MODEL_NAME`
+
+---
+
+## 10. Device eSIM Compatibility - Search & Filter
+
+Tìm kiếm và lọc danh sách thiết bị hỗ trợ eSIM.
+
+### Endpoint
+```
+POST /apis/content/device-compatibility
+```
+
+### Request Examples
+
+#### Example 1: Lấy tất cả devices phổ biến (Quick Lookup)
+```json
+{
+    "isPopular": true,
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 50
+}
+```
+
+#### Example 2: Filter theo brand (Tab Apple)
+```json
+{
+    "brand": "Apple",
+    "isPopular": true,
+    "lang": "en",
+    "pageNumber": 0,
+    "pageSize": 50
+}
+```
+
+#### Example 3: Search keyword
+```json
+{
+    "searchKeyword": "iPhone 13",
+    "lang": "lo",
+    "pageNumber": 0,
+    "pageSize": 20
+}
+```
+
+#### Example 4: Filter brand + category
+```json
+{
+    "brand": "Apple",
+    "category": "Tablet",
+    "lang": "en",
+    "pageNumber": 0,
+    "pageSize": 10
+}
+```
+
+### Request Parameters
+| Field | Type | Required | Default | Description |
+|-------|------|----------|---------|-------------|
+| brand | string | No | null | Filter theo hãng (Apple, Samsung, Google,...) |
+| category | string | No | null | Filter theo loại (Phone, Tablet, Laptop, Watch) |
+| searchKeyword | string | No | null | Tìm kiếm trong tên model (all languages) |
+| isPopular | bool | No | null | `true` = chỉ lấy thiết bị phổ biến (quick lookup) |
+| lang | string | No | "lo" | Ngôn ngữ response: "lo", "en" |
+| pageNumber | int | No | 0 | Trang hiện tại (0-indexed) |
+| pageSize | int | No | 50 | Số items/page (mặc định 50 cho device list) |
+
+### Response Success
+```json
+{
+    "errorCode": "0",
+    "message": "Success",
+    "data": {
+        "devices": [
+            {
+                "id": 1,
+                "brand": "Apple",
+                "modelName": "iPhone XS",
+                "category": "Phone",
+                "notes": "ທຸກເວີຊັນຍົກເວັ້ນ iPhone ຈາກ ຈີນແຜ່ນດິນໃຫຍ່, ຮ່ອງກົງ ແລະ ມາເກົາ",
+                "supportsEsim": true,
+                "isPopular": true,
+                "displayOrder": 1
+            },
+            {
+                "id": 2,
+                "brand": "Apple",
+                "modelName": "iPhone 13",
+                "category": "Phone",
+                "notes": null,
+                "supportsEsim": true,
+                "isPopular": true,
+                "displayOrder": 12
+            }
+        ],
+        "pagination": {
+            "pageNumber": 0,
+            "pageSize": 50,
+            "totalCount": 24,
+            "totalPages": 1
+        }
+    }
+}
+```
+
+### Response Fields - devices[]
+| Field | Type | DB Column | Description |
+|-------|------|-----------|-------------|
+| id | int | DEVICE_ESIM_COMPATIBILITY.ID | ID thiết bị (Primary Key) |
+| brand | string | DEVICE_ESIM_COMPATIBILITY.BRAND | Hãng sản xuất (Apple, Samsung,...) |
+| modelName | string | DEVICE_ESIM_COMPATIBILITY.MODEL_NAME<br/>MODEL_NAME_EN<br/>MODEL_NAME_LO | Tên model (theo ngôn ngữ được chọn) |
+| category | string | DEVICE_ESIM_COMPATIBILITY.CATEGORY | Loại thiết bị (Phone, Tablet, Laptop, Watch) |
+| notes | string | DEVICE_ESIM_COMPATIBILITY.NOTES<br/>NOTES_EN<br/>NOTES_LO | Lưu ý đặc biệt (nullable, theo ngôn ngữ) |
+| supportsEsim | bool | DEVICE_ESIM_COMPATIBILITY.SUPPORTS_ESIM | Hỗ trợ eSIM (luôn = true cho kết quả được trả về) |
+| isPopular | bool | DEVICE_ESIM_COMPATIBILITY.IS_POPULAR | Thiết bị phổ biến (hiển thị trong quick lookup) |
+| displayOrder | int | DEVICE_ESIM_COMPATIBILITY.DISPLAY_ORDER | Thứ tự sắp xếp |
+
+### Filter Logic
+- **Auto-filter**: Chỉ trả về devices với `STATUS = 1` và `SUPPORTS_ESIM = 1`
+- **Search**: Tìm kiếm keyword trong `MODEL_NAME`, `MODEL_NAME_EN`, `MODEL_NAME_LO` (case-insensitive)
+- **Ordering**: `DISPLAY_ORDER` ASC → `BRAND` ASC → `MODEL_NAME` ASC
+
+### cURL Examples
+
+#### Get metadata (brands & categories)
+```bash
+curl -X GET http://localhost:8360/apis/content/device-metadata \
+  -H "Content-Type: application/json"
+```
+
+#### Search for "iPhone 13"
+```bash
+curl -X POST http://localhost:8360/apis/content/device-compatibility \
+  -H "Content-Type: application/json" \
+  -d '{
+    "searchKeyword": "iPhone 13",
+    "lang": "en",
+    "pageSize": 20
+  }'
+```
+
+#### Get popular Apple devices
+```bash
+curl -X POST http://localhost:8360/apis/content/device-compatibility \
+  -H "Content-Type: application/json" \
+  -d '{
+    "brand": "Apple",
+    "isPopular": true,
+    "lang": "lo",
+    "pageSize": 50
+  }'
+```
+
+### Implementation Notes
+- **Sample Data**: 70+ devices đã có sẵn trong `Database/DeviceCompatibility_Schema.sql`
+- **Quick Lookup**: Set `isPopular=true` để chỉ lấy thiết bị phổ biến (Apple 24 devices, Samsung 19 devices, Google Pixel 10 devices)
+- **Full Search**: Không set `isPopular` và dùng `searchKeyword` để tìm kiếm toàn bộ database
+- **Multi-language**: Notes field hỗ trợ 3 ngôn ngữ (vi, en, lo)
+
+---

BIN
EsimLao/lib/DotnetLib.dll