mirror of
https://gitea.tendokyu.moe/Kayori/MedusaPluginChargeMachine.git
synced 2026-09-25 07:38:15 +03:00
Fix multi-bill display, charge amount parsing, and charge log responses
- chargeoptions is the real field gating 2000/5000/10000 yen display - chargeid (not chargenum) carries the actual denomination on charge - getrecentcharge/getlastlog: fixed num mismatch, added missing result section, and added placeholder items for empty result sets
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Abstractions.Entities;
|
||||
using System.Text.RegularExpressions;
|
||||
using Abstractions.Entities;
|
||||
using Abstractions.Handlers;
|
||||
using Abstractions.SerializationTypes;
|
||||
using Abstractions.Services;
|
||||
@@ -10,7 +11,7 @@ using ISessionService = MedusaPluginChargeMachine.Services.ISessionService;
|
||||
|
||||
namespace MedusaPluginChargeMachine.Handlers.LA9;
|
||||
|
||||
public class ChargeEaChargeHandler(
|
||||
public partial class ChargeEaChargeHandler(
|
||||
ICardService cardService,
|
||||
ISessionService sessionService,
|
||||
UserManager<User> userManager,
|
||||
@@ -22,9 +23,20 @@ public class ChargeEaChargeHandler(
|
||||
Method("charge");
|
||||
}
|
||||
|
||||
// chargeid carries the actual denomination as e.g. "N10000P"
|
||||
// (Note/10000/Paseli) - chargenum is just the quantity of that
|
||||
// denomination being charged (normally "1" per bill inserted).
|
||||
[GeneratedRegex(@"^N(\d+)P$")]
|
||||
private static partial Regex ChargeIdPattern();
|
||||
|
||||
public override async Task<ChargeResponse> HandleAsync(ChargeRequest req, GameModel model)
|
||||
{
|
||||
var amount = int.Parse(req.ChargeNumber) * 1000;
|
||||
var match = ChargeIdPattern().Match(req.ChargeId);
|
||||
if (!match.Success)
|
||||
throw new InvalidOperationException($"Unrecognized chargeid format: '{req.ChargeId}'");
|
||||
|
||||
var denomination = int.Parse(match.Groups[1].Value);
|
||||
var amount = denomination * int.Parse(req.ChargeNumber);
|
||||
|
||||
var foundSession = sessionService.GetSession(req.SessionId);
|
||||
|
||||
|
||||
@@ -18,13 +18,6 @@ namespace MedusaPluginChargeMachine.Handlers.LA9;
|
||||
{
|
||||
var articles = await db.ArticleContents.ToListAsync();
|
||||
|
||||
// Real server ("automap" capture against services.tablanbass.net) sends
|
||||
// an EMPTY articledoc for every DOCMT_* type - the disclosure/agreement
|
||||
// text itself is apparently rendered client-side from a bundled local
|
||||
// asset, not delivered over the wire. Sending real text for DOCMT_*
|
||||
// here produced a solid black content area on a real cabinet (working
|
||||
// touch, live server) instead of the disclosure text, so match the
|
||||
// real server's (empty) behavior instead of guessing at content.
|
||||
var articleList = articles
|
||||
.Select(a => new EaChargeConfigChargeArticleItem
|
||||
{
|
||||
@@ -38,6 +31,7 @@ namespace MedusaPluginChargeMachine.Handlers.LA9;
|
||||
{
|
||||
Status = 0,
|
||||
Expire = 1200,
|
||||
ChargeOptions = new XrpcString("multibills"),
|
||||
ChargeArticle = new EaChargeConfigChargeArticle
|
||||
{
|
||||
ArticleRevision = new XrpcString("1"),
|
||||
|
||||
@@ -31,28 +31,80 @@ public class GetLastLogEaChargeHandler(ISessionService sessionService, ChargeMac
|
||||
if (cardId is not null)
|
||||
query = query.Where(h => h.CardId == cardId);
|
||||
|
||||
var todayTotal = await query
|
||||
var todayRows = await query
|
||||
.Where(h => h.OrderDate.Date == today)
|
||||
.SumAsync(h => (int?)h.ChargeAmount) ?? 0;
|
||||
.ToListAsync();
|
||||
|
||||
var todayTotal = todayRows.Sum(h => h.ChargeAmount);
|
||||
|
||||
var headerItems = todayRows
|
||||
.GroupBy(Denomination)
|
||||
.Select(g => new GetLastLogChargeItem
|
||||
{
|
||||
ChargeId = new XrpcString($"N{g.Key}P"),
|
||||
ChargeNum = new XrpcInt(g.Sum(h => h.ChargeNum)),
|
||||
ChargeAmount = new XrpcInt(g.Sum(h => h.ChargeAmount))
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var recentItems = await query
|
||||
.OrderByDescending(h => h.OrderDate)
|
||||
.Take(10)
|
||||
.ToListAsync();
|
||||
|
||||
var resultItems = recentItems
|
||||
.Select(h => new GetLastLogResultItem
|
||||
{
|
||||
OrderDate = new XrpcString(h.OrderDate.ToString("yyyyMMddHHmmss")),
|
||||
ChargeId = new XrpcString($"N{Denomination(h)}P"),
|
||||
ChargeNum = new XrpcInt(h.ChargeNum),
|
||||
CardType = new XrpcInt(1),
|
||||
CardNo = new XrpcString(MaskCardId(h.CardId))
|
||||
})
|
||||
.ToList();
|
||||
|
||||
if (headerItems.Count == 0)
|
||||
{
|
||||
headerItems.Add(new GetLastLogChargeItem
|
||||
{
|
||||
ChargeId = new XrpcString("N1000P"),
|
||||
ChargeNum = new XrpcInt(0),
|
||||
ChargeAmount = new XrpcInt(0)
|
||||
});
|
||||
}
|
||||
|
||||
if (resultItems.Count == 0)
|
||||
{
|
||||
resultItems.Add(new GetLastLogResultItem
|
||||
{
|
||||
OrderDate = new XrpcString(""),
|
||||
ChargeId = new XrpcString("N1000P"),
|
||||
ChargeNum = new XrpcInt(0),
|
||||
CardType = new XrpcInt(1),
|
||||
CardNo = new XrpcString("")
|
||||
});
|
||||
}
|
||||
|
||||
return new GetLastLogEaChargeResponse
|
||||
{
|
||||
Status = 0,
|
||||
Header = new GetLastLogEaChargeHeader
|
||||
{
|
||||
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()
|
||||
Items = headerItems
|
||||
},
|
||||
Result = new GetLastLogEaChargeResult
|
||||
{
|
||||
Items = resultItems
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static int Denomination(Entities.ChargeHistory h) =>
|
||||
h.ChargeAmount / Math.Max(h.ChargeNum, 1);
|
||||
|
||||
private static string MaskCardId(string cardId) =>
|
||||
cardId.Length <= 4
|
||||
? new string('*', cardId.Length)
|
||||
: new string('*', cardId.Length - 4) + cardId[^4..];
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ public class GetRecentChargeEaChargeHandler(ISessionService sessionService, Char
|
||||
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 perPage = int.TryParse(req.Num, out var n) ? Math.Max(1, n)
|
||||
: int.TryParse(req.PerPage, out var pp) ? Math.Max(1, pp)
|
||||
: 10;
|
||||
|
||||
var query = db.ChargeHistories.AsQueryable();
|
||||
|
||||
@@ -31,8 +34,6 @@ public class GetRecentChargeEaChargeHandler(ISessionService sessionService, Char
|
||||
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)
|
||||
@@ -49,10 +50,23 @@ public class GetRecentChargeEaChargeHandler(ISessionService sessionService, Char
|
||||
FontColor = new XrpcString("#FFFFFF")
|
||||
}).ToList();
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
items.Add(new GetRecentChargeItem
|
||||
{
|
||||
RcvTime = new XrpcString(""),
|
||||
ChrgPrice = new XrpcInt(0),
|
||||
CardNo = new XrpcString(""),
|
||||
AccCode = new XrpcString(""),
|
||||
RcvStatus = new XrpcInt(0),
|
||||
FontColor = new XrpcString("#FFFFFF")
|
||||
});
|
||||
}
|
||||
|
||||
return new GetRecentChargeResponse
|
||||
{
|
||||
Status = 0,
|
||||
Num = new XrpcInt(total),
|
||||
Num = new XrpcInt(items.Count),
|
||||
Items = items
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,6 +8,14 @@ public class ChargeRequest
|
||||
[XmlElement("chargenum")]
|
||||
public required string ChargeNumber { get; set; }
|
||||
|
||||
// The actual denomination, not chargenum - real traffic (spice2x
|
||||
// "automap" capture) shows chargenum is always the quantity ("1" for a
|
||||
// single bill), while chargeid carries the value as e.g. "N10000P"
|
||||
// (Note/10000/Paseli). chargenum * 1000 alone reports every bill as
|
||||
// 1000 yen regardless of what was actually inserted.
|
||||
[XmlElement("chargeid")]
|
||||
public required string ChargeId { get; set; }
|
||||
|
||||
[XmlElement("sessid")]
|
||||
public required string SessionId { get; set; }
|
||||
}
|
||||
@@ -5,6 +5,9 @@ namespace MedusaPluginChargeMachine.Models.Request;
|
||||
[XmlRoot("eacharge")]
|
||||
public class GetRecentChargeRequest
|
||||
{
|
||||
[XmlElement("num")]
|
||||
public string? Num { get; set; }
|
||||
|
||||
[XmlElement("sessid")]
|
||||
public string? SessionId { get; set; }
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ public class EaChargeConfigResponse
|
||||
|
||||
[XmlAttribute("expire")]
|
||||
public required int Expire { get; set; }
|
||||
|
||||
|
||||
[XmlElement("chargeoptions")]
|
||||
public required XrpcString ChargeOptions { get; set; }
|
||||
|
||||
[XmlElement("chargearticle")]
|
||||
public required EaChargeConfigChargeArticle ChargeArticle { get; set; }
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ public class GetLastLogEaChargeResponse
|
||||
|
||||
[XmlElement("header")]
|
||||
public required GetLastLogEaChargeHeader Header { get; set; }
|
||||
|
||||
[XmlElement("result")]
|
||||
public required GetLastLogEaChargeResult Result { get; set; }
|
||||
}
|
||||
|
||||
public record GetLastLogEaChargeHeader
|
||||
@@ -33,4 +36,28 @@ public record GetLastLogChargeItem
|
||||
|
||||
[XmlElement("chargeamount")]
|
||||
public XrpcInt ChargeAmount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public record GetLastLogEaChargeResult
|
||||
{
|
||||
[XmlElement("item")]
|
||||
public List<GetLastLogResultItem> Items { get; set; } = [];
|
||||
}
|
||||
|
||||
public record GetLastLogResultItem
|
||||
{
|
||||
[XmlElement("orderdate")]
|
||||
public XrpcString OrderDate { get; set; }
|
||||
|
||||
[XmlElement("chargeid")]
|
||||
public XrpcString ChargeId { get; set; }
|
||||
|
||||
[XmlElement("chargenum")]
|
||||
public XrpcInt ChargeNum { get; set; }
|
||||
|
||||
[XmlElement("cardtype")]
|
||||
public XrpcInt CardType { get; set; }
|
||||
|
||||
[XmlElement("cardno")]
|
||||
public XrpcString CardNo { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user