Add domestic vendor push infrastructure
This commit is contained in:
@@ -13,7 +13,10 @@ namespace MiaoJiZhang.Api.Controllers;
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api/transactions")]
|
||||
public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : ControllerBase
|
||||
public class TransactionsController(
|
||||
AppDbContext db,
|
||||
LedgerResolver ledgers,
|
||||
BudgetPushService budgetPush) : ControllerBase
|
||||
{
|
||||
private long Uid => long.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub")!);
|
||||
|
||||
@@ -68,13 +71,22 @@ public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : C
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
};
|
||||
db.Transactions.Add(tx);
|
||||
await using var writeScope = await db.Database.BeginTransactionAsync();
|
||||
try
|
||||
{
|
||||
await db.SaveChangesAsync();
|
||||
if (tx.Type == TransactionType.Expense)
|
||||
{
|
||||
await budgetPush.EvaluateAsync(Uid,
|
||||
[new BudgetExpenseChange(tx.LedgerId, tx.CategoryId, tx.OccurredAt, tx.Amount)]);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
await writeScope.CommitAsync();
|
||||
return Ok(ToDto(tx, cat));
|
||||
}
|
||||
catch (DbUpdateException) when (clientRequestId is not null)
|
||||
{
|
||||
await writeScope.RollbackAsync();
|
||||
// Another channel may have committed the same recognition candidate
|
||||
// after the initial lookup. Resolve the unique-key race as idempotent success.
|
||||
db.Entry(tx).State = EntityState.Detached;
|
||||
@@ -161,6 +173,17 @@ public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : C
|
||||
}
|
||||
try
|
||||
{
|
||||
await db.SaveChangesAsync(ct);
|
||||
var expenseChanges = mapped
|
||||
.Where(item => !existing.ContainsKey(item.Transaction.ClientRequestId ?? "") &&
|
||||
item.Transaction.Type == TransactionType.Expense)
|
||||
.Select(item => new BudgetExpenseChange(
|
||||
item.Transaction.LedgerId,
|
||||
item.Transaction.CategoryId,
|
||||
item.Transaction.OccurredAt,
|
||||
item.Transaction.Amount))
|
||||
.ToList();
|
||||
await budgetPush.EvaluateAsync(Uid, expenseChanges, ct);
|
||||
await db.SaveChangesAsync(ct);
|
||||
await transactionScope.CommitAsync(ct);
|
||||
return Ok(mapped.Select(item => new RecognitionBatchTransactionDto(
|
||||
@@ -223,6 +246,10 @@ public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : C
|
||||
message = "账单已在其他设备修改,请选择保留本地或云端版本",
|
||||
server = ToDto(tx, await db.Categories.FindAsync(tx.CategoryId) ?? category),
|
||||
});
|
||||
var expenseChanges = new List<BudgetExpenseChange>();
|
||||
if (tx.Type == TransactionType.Expense)
|
||||
expenseChanges.Add(new BudgetExpenseChange(
|
||||
tx.LedgerId, tx.CategoryId, tx.OccurredAt, -tx.Amount));
|
||||
tx.LedgerId = ledgerId.Value;
|
||||
tx.CategoryId = category.Id;
|
||||
tx.Category = category;
|
||||
@@ -232,7 +259,14 @@ public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : C
|
||||
tx.PaymentMethod = req.PaymentMethod?.Trim();
|
||||
tx.OccurredAt = NormalizeOccurredAt(req.OccurredAt);
|
||||
tx.UpdatedAt = DateTime.UtcNow;
|
||||
if (tx.Type == TransactionType.Expense)
|
||||
expenseChanges.Add(new BudgetExpenseChange(
|
||||
tx.LedgerId, tx.CategoryId, tx.OccurredAt, tx.Amount));
|
||||
await using var writeScope = await db.Database.BeginTransactionAsync();
|
||||
await db.SaveChangesAsync();
|
||||
await budgetPush.EvaluateAsync(Uid, expenseChanges);
|
||||
await db.SaveChangesAsync();
|
||||
await writeScope.CommitAsync();
|
||||
return Ok(ToDto(tx, category));
|
||||
}
|
||||
|
||||
@@ -291,7 +325,15 @@ public class TransactionsController(AppDbContext db, LedgerResolver ledgers) : C
|
||||
}); tx.IsDeleted = false;
|
||||
tx.DeletedAt = null;
|
||||
tx.UpdatedAt = DateTime.UtcNow;
|
||||
await using var writeScope = await db.Database.BeginTransactionAsync();
|
||||
await db.SaveChangesAsync();
|
||||
if (tx.Type == TransactionType.Expense)
|
||||
{
|
||||
await budgetPush.EvaluateAsync(Uid,
|
||||
[new BudgetExpenseChange(tx.LedgerId, tx.CategoryId, tx.OccurredAt, tx.Amount)]);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
await writeScope.CommitAsync();
|
||||
return Ok(ToDto(tx, tx.Category));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user