XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

STHApplication

【MAUI】寄当家——安卓端交易管理系统

公开
关注 0 Fork 0 Star 0
UTF-8
using Microsoft.Data.Sqlite;

namespace JiDangJia.Core;

public static class FinanceCategories
{
    // Imported and automatic flows retain their codes. Manual selection shows
    // each name once per direction, including the old duplicate aliases.
    public static List<DbRow> Read(Database db,string direction,bool enabledOnly=true)=>db.Read(c=>Read(c,direction,enabledOnly));
    internal static List<DbRow> Read(SqliteConnection c,string direction,bool enabledOnly=true)=>Database.Query(c,
        "SELECT * FROM FinanceCategory WHERE type=@p0 ORDER BY sortOrder,createdAt,id",direction)
        .Where(r=>!enabledOnly||r.Int("enabled")==1)
        .GroupBy(r=>r.Text("label").Trim(),StringComparer.OrdinalIgnoreCase)
        .Select(g=>g.OrderByDescending(r=>r.Int("enabled")).ThenBy(r=>LegacyAlias(r.Text("code"))).ThenBy(r=>r.Int("sortOrder")).First()).ToList();
    private static bool LegacyAlias(string code)=>code is "RECYCLE_COST" or "OTHER_INCOME" or "OTHER_EXPENSE";
    public static (string Major,string Detail) Classification(string code)=>code switch
    {
        "INTEREST" or "STORAGE_FEE" or "C_FEE" or "PENALTY_IN" or "PRINCIPAL_IN" or "PAWN_OUT" or "DEAD_SALE"=>("PAWN","UNCLASSIFIED"),
        "RECYCLE_OUT" or "RECYCLE_COST" or "RECOVERY"=>("RECYCLE","UNCLASSIFIED"),
        "STOCK_OUT" or "SALE_IN" or "SALE_REFUND" or "STOCK_REFUND"=>("SALE","UNCLASSIFIED"),
        "RENT" or "UTILITIES" or "SALARY" or "FUNDING_COST"=>("STORE",code),
        _=>("OTHER",code.StartsWith("CUSTOM_",StringComparison.Ordinal)?code:"UNCLASSIFIED")
    };
}

public sealed partial class BusinessService
{
    public string SaveFinanceCategory(DbRow value)=>db.Write(c=>
    {
        var label=value.Text("label").Trim();var type=value.Text("type");
        if(label.Length is 0 or >30)throw new ArgumentException("分类名称请填写 1 至 30 个字符");
        if(type is not ("INCOME" or "EXPENSE"))throw new ArgumentException("请选择收入或支出");
        if(value.Money("sortOrder")<0||value.Money("sortOrder")>9999||value.Money("sortOrder")%1!=0)throw new ArgumentException("排序请填写 0 至 9999 的整数");
        var old=value.Id.Length>0?Database.Query(c,"SELECT * FROM FinanceCategory WHERE id=@p0",value.Id).FirstOrDefault():null;
        if(value.Id.Length>0&&old is null)throw new ArgumentException("分类不存在,请刷新列表");
        if(old is not null&&type!=old.Text("type"))throw new ArgumentException("已有分类的收支方向不能更改,请另建分类");
        var group=old is null?new List<DbRow>():Database.Query(c,"SELECT * FROM FinanceCategory WHERE type=@p0 AND TRIM(label)=@p1 COLLATE NOCASE",type,old.Text("label").Trim());
        var same=Database.Query(c,"SELECT * FROM FinanceCategory WHERE type=@p0 AND TRIM(label)=@p1 COLLATE NOCASE",type,label);
        if(same.Any(r=>!group.Any(g=>g.Id==r.Id)))throw new ArgumentException("已有同名分类,请修改或启用已有分类");
        if(old is null)group.Add(new(){["id"]=Database.Id("fc"),["shopId"]=Shop.Id,["code"]=Database.Id("CUSTOM").ToUpperInvariant(),["type"]=type,["createdAt"]=Database.Now});
        foreach(var row in group)
        {
            row["label"]=label;row["sortOrder"]=value.Int("sortOrder");row["enabled"]=value.Int("enabled")==1?1:0;row["updatedAt"]=Database.Now;
            Database.Upsert(c,"FinanceCategory",row);
        }
        var id=old?.Id??group[0].Id;Database.Log(c,"SAVE","FinanceCategory",id,label);return id;
    });
    public void EnableFinanceCategory(string id,bool enabled)
    {
        var row=db.Find("FinanceCategory",id)??throw new ArgumentException("分类不存在,请刷新列表");
        row["enabled"]=enabled?1:0;SaveFinanceCategory(row);
    }
}