From fa610a9bc61760db14b6331f6a0a54d88dab6cc0 Mon Sep 17 00:00:00 2001 From: Kayori Date: Sun, 9 Aug 2026 17:28:14 +0200 Subject: [PATCH] Add EF Core persistence for charge machine plugin Introduce ChargeMachineDbContext (SQLite) with ArticleContent and ChargeHistory entities, plus migrations, and wire it up via ConfigurePluginServices/OnAppInitialize with startup migration and article-content seeding. - ChargeEaChargeHandler now records each charge to ChargeHistory - GetConfigEaChargeHandler serves article config from the DB instead of hardcoded values, and adds multibills/readagreement fields - GetLastLogEaChargeHandler returns real daily totals and recent charge items from history, keyed by session card - Add GetRecentChargeEaChargeHandler (paginated charge history) and OpChPassEaChargeHandler (PIN change) - Update handlers to the new HandleAsync/primary-constructor style, file-scoped namespaces - Bump EF Core/Identity packages and Abstractions reference to net10.0/10.0.10 --- .../ChargeMachineDbContext.cs | 10 ++ .../ChargeMachineDbContextFactory.cs | 14 ++ .../ChargeMachinePlugin.cs | 52 +++++-- .../Entities/ArticleContent.cs | 10 ++ .../Entities/ChargeHistory.cs | 10 ++ .../Handlers/LA9/ChargeEaChargeHandler.cs | 71 +++++---- .../Handlers/LA9/GetConfigEaChargeHandler.cs | 138 ++++++------------ .../Handlers/LA9/GetLastLogEaChargeHandler.cs | 47 ++++-- .../LA9/GetRecentChargeEaChargeHandler.cs | 74 ++++++++++ .../Handlers/LA9/OpChPassEaChargeHandler.cs | 40 +++++ .../MedusaPluginChargeMachine.csproj | 18 ++- .../20260809152017_InitialCreate.Designer.cs | 63 ++++++++ .../20260809152017_InitialCreate.cs | 53 +++++++ .../ChargeMachineDbContextModelSnapshot.cs | 60 ++++++++ .../Models/Request/GetLastLogRequest.cs | 10 ++ .../Models/Request/GetRecentChargeRequest.cs | 28 ++++ .../Models/Request/OpChPassRequest.cs | 16 ++ .../Models/Response/EaChargeConfigResponse.cs | 8 +- .../Response/GetLastLogEaChargeResponse.cs | 19 ++- .../Response/GetRecentChargeResponse.cs | 39 +++++ .../Models/Response/OpChPassResponse.cs | 15 ++ 21 files changed, 641 insertions(+), 154 deletions(-) create mode 100644 MedusaPluginChargeMachine/ChargeMachineDbContext.cs create mode 100644 MedusaPluginChargeMachine/ChargeMachineDbContextFactory.cs create mode 100644 MedusaPluginChargeMachine/Entities/ArticleContent.cs create mode 100644 MedusaPluginChargeMachine/Entities/ChargeHistory.cs create mode 100644 MedusaPluginChargeMachine/Handlers/LA9/GetRecentChargeEaChargeHandler.cs create mode 100644 MedusaPluginChargeMachine/Handlers/LA9/OpChPassEaChargeHandler.cs create mode 100644 MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.Designer.cs create mode 100644 MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.cs create mode 100644 MedusaPluginChargeMachine/Migrations/ChargeMachineDbContextModelSnapshot.cs create mode 100644 MedusaPluginChargeMachine/Models/Request/GetLastLogRequest.cs create mode 100644 MedusaPluginChargeMachine/Models/Request/GetRecentChargeRequest.cs create mode 100644 MedusaPluginChargeMachine/Models/Request/OpChPassRequest.cs create mode 100644 MedusaPluginChargeMachine/Models/Response/GetRecentChargeResponse.cs create mode 100644 MedusaPluginChargeMachine/Models/Response/OpChPassResponse.cs diff --git a/MedusaPluginChargeMachine/ChargeMachineDbContext.cs b/MedusaPluginChargeMachine/ChargeMachineDbContext.cs new file mode 100644 index 0000000..a580aaa --- /dev/null +++ b/MedusaPluginChargeMachine/ChargeMachineDbContext.cs @@ -0,0 +1,10 @@ +using MedusaPluginChargeMachine.Entities; +using Microsoft.EntityFrameworkCore; + +namespace MedusaPluginChargeMachine; + +public class ChargeMachineDbContext(DbContextOptions options) : DbContext(options) +{ + public DbSet ChargeHistories { get; set; } + public DbSet ArticleContents { get; set; } +} diff --git a/MedusaPluginChargeMachine/ChargeMachineDbContextFactory.cs b/MedusaPluginChargeMachine/ChargeMachineDbContextFactory.cs new file mode 100644 index 0000000..df56f5d --- /dev/null +++ b/MedusaPluginChargeMachine/ChargeMachineDbContextFactory.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace MedusaPluginChargeMachine; + +public class ChargeMachineDbContextFactory : IDesignTimeDbContextFactory +{ + public ChargeMachineDbContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite("Data Source=database/ChargeMachine.db;"); + return new ChargeMachineDbContext(optionsBuilder.Options); + } +} diff --git a/MedusaPluginChargeMachine/ChargeMachinePlugin.cs b/MedusaPluginChargeMachine/ChargeMachinePlugin.cs index f697965..9b8dd8e 100644 --- a/MedusaPluginChargeMachine/ChargeMachinePlugin.cs +++ b/MedusaPluginChargeMachine/ChargeMachinePlugin.cs @@ -1,14 +1,15 @@ -using Abstractions; +using Abstractions; +using MedusaPluginChargeMachine.Entities; using MedusaPluginChargeMachine.Services; using Microsoft.AspNetCore.Builder; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System.Text; namespace MedusaPluginChargeMachine; -public class ChargeMachinePlugin: IMedusaPlugin +public class ChargeMachinePlugin : IMedusaPlugin { - public string Name => "Charge Machine"; public string Version => "1.0.0"; public string Description => "Plugin for the paseli charge machine"; @@ -18,15 +19,46 @@ public class ChargeMachinePlugin: IMedusaPlugin public Encoding? ForcedEncoding => null; public Delegate DoesProfileExist => () => false; - public Task OnBuilderInitialize(WebApplicationBuilder builder) + public Task OnBuilderInitialize(WebApplicationBuilder builder) => Task.CompletedTask; + + public void ConfigurePluginServices(IServiceCollection services) { - builder.Services.AddSingleton(); - - return Task.CompletedTask; + services.AddSingleton(); + services.AddDbContext(o => + o.UseSqlite("Data Source=database/ChargeMachine.db;")); } - public Task OnAppInitialize(WebApplication app) + public async Task OnAppInitialize(WebApplication app, IServiceProvider pluginServices) { - return Task.CompletedTask; + await using var scope = pluginServices.CreateAsyncScope(); + var db = scope.ServiceProvider.GetRequiredService(); + await db.Database.MigrateAsync(); + await SeedArticleContentsAsync(db); } -} \ No newline at end of file + + private static async Task SeedArticleContentsAsync(ChargeMachineDbContext db) + { + if (await db.ArticleContents.AnyAsync()) + return; + + var defaults = new List + { + new() { ArticleType = "DOCMT_0000", ArticleDoc = "" }, + new() { ArticleType = "DOCMT_0001", ArticleDoc = "PASELI Charge Machine" }, + new() { ArticleType = "DOCMT_0002", ArticleDoc = "" }, + new() { ArticleType = "DOCMT_0003", ArticleDoc = "" }, + new() { ArticleType = "URL_0001_A", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0001_B", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0002_A", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0002_B", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0003_A", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0003_B", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0004_A", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "URL_0041_B", ArticleDoc = "https://localhost:5173/" }, + new() { ArticleType = "PASELIUNIT", ArticleDoc = "P" }, + }; + + db.ArticleContents.AddRange(defaults); + await db.SaveChangesAsync(); + } +} diff --git a/MedusaPluginChargeMachine/Entities/ArticleContent.cs b/MedusaPluginChargeMachine/Entities/ArticleContent.cs new file mode 100644 index 0000000..84c6210 --- /dev/null +++ b/MedusaPluginChargeMachine/Entities/ArticleContent.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace MedusaPluginChargeMachine.Entities; + +public class ArticleContent +{ + [Key] + public required string ArticleType { get; set; } + public required string ArticleDoc { get; set; } +} diff --git a/MedusaPluginChargeMachine/Entities/ChargeHistory.cs b/MedusaPluginChargeMachine/Entities/ChargeHistory.cs new file mode 100644 index 0000000..2f87d2d --- /dev/null +++ b/MedusaPluginChargeMachine/Entities/ChargeHistory.cs @@ -0,0 +1,10 @@ +namespace MedusaPluginChargeMachine.Entities; + +public class ChargeHistory +{ + public int Id { get; set; } + public required string CardId { get; set; } + public int ChargeNum { get; set; } + public int ChargeAmount { get; set; } + public DateTime OrderDate { get; set; } +} diff --git a/MedusaPluginChargeMachine/Handlers/LA9/ChargeEaChargeHandler.cs b/MedusaPluginChargeMachine/Handlers/LA9/ChargeEaChargeHandler.cs index 29b709f..2736e16 100644 --- a/MedusaPluginChargeMachine/Handlers/LA9/ChargeEaChargeHandler.cs +++ b/MedusaPluginChargeMachine/Handlers/LA9/ChargeEaChargeHandler.cs @@ -1,44 +1,55 @@ -using System.Xml.Linq; -using Abstractions.Entities; +using Abstractions.Entities; using Abstractions.Handlers; using Abstractions.SerializationTypes; using Abstractions.Services; +using MedusaPluginChargeMachine.Entities; using MedusaPluginChargeMachine.Models.Request; using MedusaPluginChargeMachine.Models.Response; using Microsoft.AspNetCore.Identity; using ISessionService = MedusaPluginChargeMachine.Services.ISessionService; -namespace MedusaPluginChargeMachine.Handlers.LA9 +namespace MedusaPluginChargeMachine.Handlers.LA9; + +public class ChargeEaChargeHandler( + ICardService cardService, + ISessionService sessionService, + UserManager userManager, + ChargeMachineDbContext db) : Handler { - public class ChargeEaChargeHandler(ICardService cardService, ISessionService sessionService, UserManager userManager): Handler + public override void Configure() { - public override void Configure() + Module("eacharge"); + Method("charge"); + } + + public override async Task HandleAsync(ChargeRequest req, string model) + { + var amount = int.Parse(req.ChargeNumber) * 1000; + + var foundSession = sessionService.GetSession(req.SessionId); + + var card = await cardService.FindByCardId(foundSession.refId)!; + + card!.User.PaseliAmount += amount; + + await userManager.UpdateAsync(card.User); + + db.ChargeHistories.Add(new ChargeHistory { - Module("eacharge"); - Method("charge"); - } - public override async Task HandleAsync(ChargeRequest req, string model) + CardId = foundSession.refId, + ChargeNum = int.Parse(req.ChargeNumber), + ChargeAmount = amount, + OrderDate = DateTime.UtcNow + }); + await db.SaveChangesAsync(); + + return new ChargeResponse { - var amount = int.Parse(req.ChargeNumber) * 1000; - - var foundSession = sessionService.GetSession(req.SessionId); - - var card = await cardService.FindByCardId(foundSession.refId)!; - - card!.User.PaseliAmount += amount; - - await userManager.UpdateAsync(card.User); - - var chargeResponse = new ChargeResponse() - { - Status = 0, - Balance = new XrpcInt(card.User.PaseliAmount), - ChargeDailyLimit = new XrpcInt(100000), - ChargeDaily = new XrpcInt(0), - ChargePoint = new XrpcInt(amount) - }; - - return chargeResponse; - } + Status = 0, + Balance = new XrpcInt(card.User.PaseliAmount), + ChargeDailyLimit = new XrpcInt(100000), + ChargeDaily = new XrpcInt(0), + ChargePoint = new XrpcInt(amount) + }; } } diff --git a/MedusaPluginChargeMachine/Handlers/LA9/GetConfigEaChargeHandler.cs b/MedusaPluginChargeMachine/Handlers/LA9/GetConfigEaChargeHandler.cs index 591f1d2..92982e0 100644 --- a/MedusaPluginChargeMachine/Handlers/LA9/GetConfigEaChargeHandler.cs +++ b/MedusaPluginChargeMachine/Handlers/LA9/GetConfigEaChargeHandler.cs @@ -1,108 +1,52 @@ -using System.Xml.Linq; using Abstractions.Handlers; using Abstractions.SerializationTypes; +using MedusaPluginChargeMachine.Models.Request; using MedusaPluginChargeMachine.Models.Response; +using Microsoft.EntityFrameworkCore; -namespace MedusaPluginChargeMachine.Handlers.LA9 +namespace MedusaPluginChargeMachine.Handlers.LA9; + +public class GetConfigEaChargeHandler(ChargeMachineDbContext db) : Handler { - public class GetConfigEaChargeHandler: HandlerWithoutRequest + public override void Configure() { - public override void Configure() - { - Module("eacharge"); - Method("getconf"); - } + Module("eacharge"); + Method("getconf"); + } - public override EaChargeConfigResponse Handle(string model) - { - var eaChargeConfig = new EaChargeConfigResponse() + public override async Task HandleAsync(EmptyRequest _, string model) + { + var articles = await db.ArticleContents.ToListAsync(); + + var articleList = articles + .Select(a => new EaChargeConfigChargeArticleItem { - Status = 0, - Expire = 1200, - ChargeArticle = new EaChargeConfigChargeArticle() - { - ArticleRevision = new XrpcString("1"), - ArticleList = [ - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("DOCMT_0000"), - ArticleDoc = new XrpcString("") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("DOCMT_0001"), - ArticleDoc = new XrpcString("") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("DOCMT_0002"), - ArticleDoc = new XrpcString("") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("DOCMT_0003"), - ArticleDoc = new XrpcString("") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0001_A"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0001_B"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0002_A"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0002_B"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0003_A"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0003_B"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0004_A"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("URL_0041_B"), - ArticleDoc = new XrpcString("http://eagate.573.jp") - }, - new EaChargeConfigChargeArticleItem() - { - ArticleType = new XrpcString("PASELIUNIT"), - ArticleDoc = new XrpcString("P") - }, - ] - }, - ChargeDetail = new EaChargeConfigChargeDetail() - { - ChargeDaily = new XrpcInt(0), - ChargeDailyLimit = new XrpcInt(100000) - }, - ChargeStatus = new EaChargeConfigChargeStatus() - { - CurrentCode = new XrpcInt(0), - LastChargeStatus = new XrpcInt(1) - } - }; + ArticleType = new XrpcString(a.ArticleType), + ArticleDoc = new XrpcString(a.ArticleDoc) + }) + .ToList(); - return eaChargeConfig; - } + return new EaChargeConfigResponse + { + Status = 0, + Expire = 1200, + MultiBills = new XrpcInt(1), + ReadAgreement = new XrpcInt(0), + ChargeArticle = new EaChargeConfigChargeArticle + { + ArticleRevision = new XrpcString("1"), + ArticleList = articleList + }, + ChargeDetail = new EaChargeConfigChargeDetail + { + ChargeDaily = new XrpcInt(0), + ChargeDailyLimit = new XrpcInt(100000) + }, + ChargeStatus = new EaChargeConfigChargeStatus + { + CurrentCode = new XrpcInt(0), + LastChargeStatus = new XrpcInt(1) + } + }; } } diff --git a/MedusaPluginChargeMachine/Handlers/LA9/GetLastLogEaChargeHandler.cs b/MedusaPluginChargeMachine/Handlers/LA9/GetLastLogEaChargeHandler.cs index 6c80444..ab7e9fb 100644 --- a/MedusaPluginChargeMachine/Handlers/LA9/GetLastLogEaChargeHandler.cs +++ b/MedusaPluginChargeMachine/Handlers/LA9/GetLastLogEaChargeHandler.cs @@ -1,11 +1,14 @@ -using System.Xml.Linq; using Abstractions.Handlers; using Abstractions.SerializationTypes; +using MedusaPluginChargeMachine.Models.Request; using MedusaPluginChargeMachine.Models.Response; +using MedusaPluginChargeMachine.Services; +using Microsoft.EntityFrameworkCore; namespace MedusaPluginChargeMachine.Handlers.LA9; -public class GetLastLogEaChargeHandler : HandlerWithoutRequest +public class GetLastLogEaChargeHandler(ISessionService sessionService, ChargeMachineDbContext db) + : Handler { public override void Configure() { @@ -13,17 +16,43 @@ public class GetLastLogEaChargeHandler : HandlerWithoutRequest HandleAsync(GetLastLogRequest req, string model) { - var getLastLog = new GetLastLogEaChargeResponse() + var today = DateTime.UtcNow.Date; + var cardId = (string?)null; + + if (req.SessionId is not null) + { + var session = sessionService.GetSession(req.SessionId); + cardId = session.refId; + } + + var query = db.ChargeHistories.AsQueryable(); + if (cardId is not null) + query = query.Where(h => h.CardId == cardId); + + var todayTotal = await query + .Where(h => h.OrderDate.Date == today) + .SumAsync(h => (int?)h.ChargeAmount) ?? 0; + + var recentItems = await query + .OrderByDescending(h => h.OrderDate) + .Take(10) + .ToListAsync(); + + return new GetLastLogEaChargeResponse { Status = 0, - Header = new GetLastLogEaChargeHeader() + Header = new GetLastLogEaChargeHeader { - Chargedaily = new XrpcInt(0) + Chargedaily = new XrpcInt(todayTotal), + Items = recentItems.Select((h, i) => new GetLastLogChargeItem + { + ChargeId = new XrpcString(h.Id.ToString()), + ChargeNum = new XrpcInt(h.ChargeNum), + ChargeAmount = new XrpcInt(h.ChargeAmount) + }).ToList() } }; - - return getLastLog; } -} \ No newline at end of file +} diff --git a/MedusaPluginChargeMachine/Handlers/LA9/GetRecentChargeEaChargeHandler.cs b/MedusaPluginChargeMachine/Handlers/LA9/GetRecentChargeEaChargeHandler.cs new file mode 100644 index 0000000..6375f2b --- /dev/null +++ b/MedusaPluginChargeMachine/Handlers/LA9/GetRecentChargeEaChargeHandler.cs @@ -0,0 +1,74 @@ +using Abstractions.Handlers; +using Abstractions.SerializationTypes; +using MedusaPluginChargeMachine.Models.Request; +using MedusaPluginChargeMachine.Models.Response; +using MedusaPluginChargeMachine.Services; +using Microsoft.EntityFrameworkCore; + +namespace MedusaPluginChargeMachine.Handlers.LA9; + +public class GetRecentChargeEaChargeHandler(ISessionService sessionService, ChargeMachineDbContext db) + : Handler +{ + public override void Configure() + { + Module("eacharge"); + Method("getrecentcharge"); + } + + public override async Task HandleAsync(GetRecentChargeRequest req, string model) + { + var cardId = ResolveCardId(req); + + var page = int.TryParse(req.Page, out var p) ? Math.Max(1, p) : 1; + var perPage = int.TryParse(req.PerPage, out var pp) ? Math.Max(1, pp) : 10; + + var query = db.ChargeHistories.AsQueryable(); + + if (cardId is not null) + query = query.Where(h => h.CardId == cardId); + + if (req.TargetDate is not null && DateTime.TryParse(req.TargetDate, out var targetDate)) + query = query.Where(h => h.OrderDate.Date == targetDate.Date); + + var total = await query.CountAsync(); + + var rows = await query + .OrderByDescending(h => h.OrderDate) + .Skip((page - 1) * perPage) + .Take(perPage) + .ToListAsync(); + + var items = rows.Select(h => new GetRecentChargeItem + { + RcvTime = new XrpcString(h.OrderDate.ToString("yyyyMMddHHmmss")), + ChrgPrice = new XrpcInt(h.ChargeAmount), + CardNo = new XrpcString(MaskCardId(h.CardId)), + AccCode = new XrpcString(""), + RcvStatus = new XrpcInt(0), + FontColor = new XrpcString("#FFFFFF") + }).ToList(); + + return new GetRecentChargeResponse + { + Status = 0, + Num = new XrpcInt(total), + Items = items + }; + } + + private string? ResolveCardId(GetRecentChargeRequest req) + { + if (req.SessionId is not null) + { + try { return sessionService.GetSession(req.SessionId).refId; } + catch { /* fall through to cardid */ } + } + return req.CardId; + } + + private static string MaskCardId(string cardId) => + cardId.Length <= 4 + ? new string('*', cardId.Length) + : new string('*', cardId.Length - 4) + cardId[^4..]; +} diff --git a/MedusaPluginChargeMachine/Handlers/LA9/OpChPassEaChargeHandler.cs b/MedusaPluginChargeMachine/Handlers/LA9/OpChPassEaChargeHandler.cs new file mode 100644 index 0000000..bb191d4 --- /dev/null +++ b/MedusaPluginChargeMachine/Handlers/LA9/OpChPassEaChargeHandler.cs @@ -0,0 +1,40 @@ +using Abstractions.Entities; +using Abstractions.Handlers; +using Abstractions.Services; +using MedusaPluginChargeMachine.Models.Request; +using MedusaPluginChargeMachine.Models.Response; +using MedusaPluginChargeMachine.Services; +using Microsoft.AspNetCore.Identity; +using Abstractions.SerializationTypes; + +namespace MedusaPluginChargeMachine.Handlers.LA9; + +public class OpChPassEaChargeHandler( + ISessionService sessionService, + ICardService cardService, + UserManager userManager) : Handler +{ + public override void Configure() + { + Module("eacharge"); + Method("opchpass"); + } + + public override async Task HandleAsync(OpChPassRequest req, string model) + { + var session = sessionService.GetSession(req.SessionId); + var card = await cardService.FindByCardId(session.refId); + + if (card is null) + return new OpChPassResponse { Status = 1, Result = new XrpcInt(1) }; + + var valid = await cardService.ValidatePinAsync(card.KonamiId, req.Passwd); + if (!valid) + return new OpChPassResponse { Status = 1, Result = new XrpcInt(1) }; + + card.User.Pin = req.NewPasswd; + await userManager.UpdateAsync(card.User); + + return new OpChPassResponse { Status = 0, Result = new XrpcInt(0) }; + } +} diff --git a/MedusaPluginChargeMachine/MedusaPluginChargeMachine.csproj b/MedusaPluginChargeMachine/MedusaPluginChargeMachine.csproj index a99fec1..99774b0 100644 --- a/MedusaPluginChargeMachine/MedusaPluginChargeMachine.csproj +++ b/MedusaPluginChargeMachine/MedusaPluginChargeMachine.csproj @@ -4,19 +4,27 @@ net10.0 enable enable + false + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName)\ - ..\..\Medusa.net\Abstractions\bin\Debug\net9.0\Abstractions.dll + ..\..\Medusa.net\Abstractions\bin\Debug\net10.0\Abstractions.dll + false - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.Designer.cs b/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.Designer.cs new file mode 100644 index 0000000..2c923fd --- /dev/null +++ b/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.Designer.cs @@ -0,0 +1,63 @@ +// +using System; +using MedusaPluginChargeMachine; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MedusaPluginChargeMachine.Migrations +{ + [DbContext(typeof(ChargeMachineDbContext))] + [Migration("20260809152017_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.10"); + + modelBuilder.Entity("MedusaPluginChargeMachine.Entities.ArticleContent", b => + { + b.Property("ArticleType") + .HasColumnType("TEXT"); + + b.Property("ArticleDoc") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("ArticleType"); + + b.ToTable("ArticleContents"); + }); + + modelBuilder.Entity("MedusaPluginChargeMachine.Entities.ChargeHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CardId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ChargeAmount") + .HasColumnType("INTEGER"); + + b.Property("ChargeNum") + .HasColumnType("INTEGER"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ChargeHistories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.cs b/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.cs new file mode 100644 index 0000000..6102199 --- /dev/null +++ b/MedusaPluginChargeMachine/Migrations/20260809152017_InitialCreate.cs @@ -0,0 +1,53 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MedusaPluginChargeMachine.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ArticleContents", + columns: table => new + { + ArticleType = table.Column(type: "TEXT", nullable: false), + ArticleDoc = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ArticleContents", x => x.ArticleType); + }); + + migrationBuilder.CreateTable( + name: "ChargeHistories", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CardId = table.Column(type: "TEXT", nullable: false), + ChargeNum = table.Column(type: "INTEGER", nullable: false), + ChargeAmount = table.Column(type: "INTEGER", nullable: false), + OrderDate = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChargeHistories", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ArticleContents"); + + migrationBuilder.DropTable( + name: "ChargeHistories"); + } + } +} diff --git a/MedusaPluginChargeMachine/Migrations/ChargeMachineDbContextModelSnapshot.cs b/MedusaPluginChargeMachine/Migrations/ChargeMachineDbContextModelSnapshot.cs new file mode 100644 index 0000000..4f69c53 --- /dev/null +++ b/MedusaPluginChargeMachine/Migrations/ChargeMachineDbContextModelSnapshot.cs @@ -0,0 +1,60 @@ +// +using System; +using MedusaPluginChargeMachine; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MedusaPluginChargeMachine.Migrations +{ + [DbContext(typeof(ChargeMachineDbContext))] + partial class ChargeMachineDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.10"); + + modelBuilder.Entity("MedusaPluginChargeMachine.Entities.ArticleContent", b => + { + b.Property("ArticleType") + .HasColumnType("TEXT"); + + b.Property("ArticleDoc") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("ArticleType"); + + b.ToTable("ArticleContents"); + }); + + modelBuilder.Entity("MedusaPluginChargeMachine.Entities.ChargeHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CardId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ChargeAmount") + .HasColumnType("INTEGER"); + + b.Property("ChargeNum") + .HasColumnType("INTEGER"); + + b.Property("OrderDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ChargeHistories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MedusaPluginChargeMachine/Models/Request/GetLastLogRequest.cs b/MedusaPluginChargeMachine/Models/Request/GetLastLogRequest.cs new file mode 100644 index 0000000..0672c30 --- /dev/null +++ b/MedusaPluginChargeMachine/Models/Request/GetLastLogRequest.cs @@ -0,0 +1,10 @@ +using System.Xml.Serialization; + +namespace MedusaPluginChargeMachine.Models.Request; + +[XmlRoot("eacharge")] +public class GetLastLogRequest +{ + [XmlElement("sessid")] + public string? SessionId { get; set; } +} diff --git a/MedusaPluginChargeMachine/Models/Request/GetRecentChargeRequest.cs b/MedusaPluginChargeMachine/Models/Request/GetRecentChargeRequest.cs new file mode 100644 index 0000000..333cc5e --- /dev/null +++ b/MedusaPluginChargeMachine/Models/Request/GetRecentChargeRequest.cs @@ -0,0 +1,28 @@ +using System.Xml.Serialization; + +namespace MedusaPluginChargeMachine.Models.Request; + +[XmlRoot("eacharge")] +public class GetRecentChargeRequest +{ + [XmlElement("sessid")] + public string? SessionId { get; set; } + + [XmlElement("cardid")] + public string? CardId { get; set; } + + [XmlElement("cardtype")] + public string? CardType { get; set; } + + [XmlElement("ectype")] + public string? EcType { get; set; } + + [XmlElement("targetdate")] + public string? TargetDate { get; set; } + + [XmlElement("perpage")] + public string? PerPage { get; set; } + + [XmlElement("page")] + public string? Page { get; set; } +} diff --git a/MedusaPluginChargeMachine/Models/Request/OpChPassRequest.cs b/MedusaPluginChargeMachine/Models/Request/OpChPassRequest.cs new file mode 100644 index 0000000..3b982e2 --- /dev/null +++ b/MedusaPluginChargeMachine/Models/Request/OpChPassRequest.cs @@ -0,0 +1,16 @@ +using System.Xml.Serialization; + +namespace MedusaPluginChargeMachine.Models.Request; + +[XmlRoot("eacharge")] +public class OpChPassRequest +{ + [XmlElement("sessid")] + public required string SessionId { get; set; } + + [XmlElement("passwd")] + public required string Passwd { get; set; } + + [XmlElement("newpasswd")] + public required string NewPasswd { get; set; } +} diff --git a/MedusaPluginChargeMachine/Models/Response/EaChargeConfigResponse.cs b/MedusaPluginChargeMachine/Models/Response/EaChargeConfigResponse.cs index 469b75f..75c6e8d 100644 --- a/MedusaPluginChargeMachine/Models/Response/EaChargeConfigResponse.cs +++ b/MedusaPluginChargeMachine/Models/Response/EaChargeConfigResponse.cs @@ -12,7 +12,13 @@ public class EaChargeConfigResponse [XmlAttribute("expire")] public required int Expire { get; set; } - + + [XmlElement("multibills")] + public XrpcInt MultiBills { get; set; } + + [XmlElement("readagreement")] + public XrpcInt ReadAgreement { get; set; } + [XmlElement("chargearticle")] public required EaChargeConfigChargeArticle ChargeArticle { get; set; } diff --git a/MedusaPluginChargeMachine/Models/Response/GetLastLogEaChargeResponse.cs b/MedusaPluginChargeMachine/Models/Response/GetLastLogEaChargeResponse.cs index af82c64..27fb3ce 100644 --- a/MedusaPluginChargeMachine/Models/Response/GetLastLogEaChargeResponse.cs +++ b/MedusaPluginChargeMachine/Models/Response/GetLastLogEaChargeResponse.cs @@ -3,13 +3,13 @@ using Abstractions.SerializationTypes; namespace MedusaPluginChargeMachine.Models.Response; -[XmlRoot("getlastlog")] +[XmlRoot("eacharge")] [Serializable] public class GetLastLogEaChargeResponse { [XmlAttribute("status")] public int Status { get; set; } - + [XmlElement("header")] public required GetLastLogEaChargeHeader Header { get; set; } } @@ -18,4 +18,19 @@ public record GetLastLogEaChargeHeader { [XmlElement("chargedaily")] public XrpcInt Chargedaily { get; set; } + + [XmlElement("item")] + public List Items { get; set; } = []; +} + +public record GetLastLogChargeItem +{ + [XmlElement("chargeid")] + public XrpcString ChargeId { get; set; } + + [XmlElement("chargenum")] + public XrpcInt ChargeNum { get; set; } + + [XmlElement("chargeamount")] + public XrpcInt ChargeAmount { get; set; } } \ No newline at end of file diff --git a/MedusaPluginChargeMachine/Models/Response/GetRecentChargeResponse.cs b/MedusaPluginChargeMachine/Models/Response/GetRecentChargeResponse.cs new file mode 100644 index 0000000..f4f3668 --- /dev/null +++ b/MedusaPluginChargeMachine/Models/Response/GetRecentChargeResponse.cs @@ -0,0 +1,39 @@ +using System.Xml.Serialization; +using Abstractions.SerializationTypes; + +namespace MedusaPluginChargeMachine.Models.Response; + +[XmlRoot("eacharge")] +[Serializable] +public class GetRecentChargeResponse +{ + [XmlAttribute("status")] + public int Status { get; set; } + + [XmlElement("num")] + public XrpcInt Num { get; set; } + + [XmlElement("item")] + public List Items { get; set; } = []; +} + +public record GetRecentChargeItem +{ + [XmlElement("rcvtime")] + public XrpcString RcvTime { get; set; } + + [XmlElement("chrgprice")] + public XrpcInt ChrgPrice { get; set; } + + [XmlElement("cardno")] + public XrpcString CardNo { get; set; } + + [XmlElement("acccode")] + public XrpcString AccCode { get; set; } + + [XmlElement("rcvstatus")] + public XrpcInt RcvStatus { get; set; } + + [XmlElement("fontcolor")] + public XrpcString FontColor { get; set; } +} diff --git a/MedusaPluginChargeMachine/Models/Response/OpChPassResponse.cs b/MedusaPluginChargeMachine/Models/Response/OpChPassResponse.cs new file mode 100644 index 0000000..fab2294 --- /dev/null +++ b/MedusaPluginChargeMachine/Models/Response/OpChPassResponse.cs @@ -0,0 +1,15 @@ +using System.Xml.Serialization; +using Abstractions.SerializationTypes; + +namespace MedusaPluginChargeMachine.Models.Response; + +[XmlRoot("eacharge")] +[Serializable] +public class OpChPassResponse +{ + [XmlAttribute("status")] + public int Status { get; set; } + + [XmlElement("result")] + public XrpcInt Result { get; set; } +}