Adding journal entries and database tables. Increased starting balances.
This commit is contained in:
@@ -1,14 +1,40 @@
|
||||
namespace FinancialApi.Application;
|
||||
|
||||
public record Account(int Id, decimal Balance)
|
||||
public record Account(int Id, decimal Balance, string AccountType)
|
||||
{
|
||||
public Account ApplyPosting(decimal amount, EntryType entryType)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
throw new ArgumentException("Credit amount must be positive.");
|
||||
}
|
||||
|
||||
var newBalance = Balance;
|
||||
if (AccountType == "Revenue")
|
||||
{
|
||||
newBalance = entryType == EntryType.Credit ? newBalance + amount : newBalance - amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
newBalance = entryType == EntryType.Debit ? newBalance - amount : newBalance + amount;
|
||||
}
|
||||
|
||||
|
||||
if (newBalance < 0 && AccountType == "Liability")
|
||||
{
|
||||
throw new InvalidOperationException("Insufficient funds.");
|
||||
}
|
||||
|
||||
return this with { Balance = newBalance };
|
||||
}
|
||||
|
||||
public Account ApplyFee(decimal amount)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
throw new ArgumentException("Fee must be positive.");
|
||||
}
|
||||
|
||||
|
||||
if (Balance - amount < 0)
|
||||
{
|
||||
throw new InvalidOperationException("Insufficient funds.");
|
||||
@@ -16,18 +42,19 @@ public record Account(int Id, decimal Balance)
|
||||
|
||||
return this with { Balance = Balance - amount };
|
||||
}
|
||||
|
||||
|
||||
public Account Debit(decimal amount)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
throw new ArgumentException("Debit amount must be positive.");
|
||||
}
|
||||
|
||||
if (Balance - amount < 0)
|
||||
{
|
||||
throw new InvalidOperationException("Insufficient funds.");
|
||||
}
|
||||
|
||||
|
||||
return this with { Balance = Balance - amount };
|
||||
}
|
||||
|
||||
@@ -37,7 +64,7 @@ public record Account(int Id, decimal Balance)
|
||||
{
|
||||
throw new ArgumentException("Credit amount must be positive.");
|
||||
}
|
||||
|
||||
|
||||
return this with { Balance = Balance + amount };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace FinancialApi.Application;
|
||||
|
||||
public record BalancedJournal
|
||||
{
|
||||
public JournalEntry Entry { get; }
|
||||
|
||||
private BalancedJournal(JournalEntry entry) => Entry = entry;
|
||||
|
||||
public static BalancedJournal Create(Guid id, string description, DateTimeOffset createdAt, List<JournalLine> lines)
|
||||
{
|
||||
var debits = lines.Where(l => l.Type == EntryType.Debit).Sum(l => l.Amount);
|
||||
var credits = lines.Where(l => l.Type == EntryType.Credit).Sum(l => l.Amount);
|
||||
|
||||
if (debits != credits)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"GAAP Violation: Total Debits ({debits}) must equal Total Credits ({credits})!"
|
||||
);
|
||||
}
|
||||
|
||||
return new(new JournalEntry(id, description, createdAt, lines));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace FinancialApi.Application;
|
||||
|
||||
public enum EntryType
|
||||
{
|
||||
Debit,
|
||||
Credit
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace FinancialApi.Application;
|
||||
|
||||
public record JournalEntry
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string Description { get; init; }
|
||||
public DateTimeOffset CreatedAt { get; init; }
|
||||
public List<JournalLine> Lines { get; init; } = [];
|
||||
|
||||
private JournalEntry()
|
||||
{
|
||||
}
|
||||
|
||||
internal JournalEntry(Guid id, string description, DateTimeOffset createdAt, List<JournalLine> lines)
|
||||
{
|
||||
Lines = lines;
|
||||
Id = id;
|
||||
Description = description;
|
||||
CreatedAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace FinancialApi.Application;
|
||||
|
||||
public record JournalLine(int AccountId, decimal Amount, EntryType Type);
|
||||
@@ -6,6 +6,7 @@ namespace FinancialApi.Infrastructure;
|
||||
public class AccountDbContext(DbContextOptions<AccountDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<Account> Accounts => Set<Account>();
|
||||
public DbSet<JournalEntry> JournalEntries => Set<JournalEntry>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -13,8 +14,21 @@ public class AccountDbContext(DbContextOptions<AccountDbContext> options) : DbCo
|
||||
.HasKey(x => x.Id);
|
||||
|
||||
modelBuilder.Entity<Account>().HasData(
|
||||
new Account(1, 100.00m),
|
||||
new Account(2, 500.00m)
|
||||
new Account(1, 10000000.00m, "Credit"),
|
||||
new Account(2, 50000000.00m, "Liability"),
|
||||
new Account(99999, 0.00m, "Revenue")
|
||||
);
|
||||
|
||||
modelBuilder.Entity<JournalEntry>(builder =>
|
||||
{
|
||||
builder.HasKey(x => x.Id);
|
||||
builder.OwnsMany(x => x.Lines, line =>
|
||||
{
|
||||
line.WithOwner().HasForeignKey("JournalEntryId");
|
||||
line.Property<int>("Id").ValueGeneratedOnAdd();
|
||||
line.HasKey("Id");
|
||||
line.Property(x => x.Type).HasConversion<string>();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,53 @@ using Wolverine.Persistence;
|
||||
|
||||
namespace FinancialApi.Infrastructure;
|
||||
|
||||
public static class ApplyFeeHandler
|
||||
{
|
||||
public static Task<Account?> LoadAsync(
|
||||
ApplyFeeCommand cmd,
|
||||
AccountDbContext db) => db.Accounts.AsNoTracking().SingleOrDefaultAsync(x => x.Id == cmd.AccountId);
|
||||
|
||||
[Transactional]
|
||||
public static (IStorageAction<Account> UpdatedAccount, FeeAppliedEvent Event) Handle(
|
||||
ApplyFeeCommand cmd,
|
||||
Account account)
|
||||
{
|
||||
var updatedAccount = account.ApplyFee(cmd.Amount);
|
||||
|
||||
var @event = new FeeAppliedEvent(account.Id, cmd.Amount);
|
||||
|
||||
return (Storage.Update(updatedAccount), @event);
|
||||
}
|
||||
}
|
||||
|
||||
public record ApplyFeeCommand(int AccountId, decimal Amount);
|
||||
|
||||
public record FeeAppliedEvent(int AccountId, decimal Amount);
|
||||
public record FeePair(Account CustomerAccount, Account RevenueAccount);
|
||||
|
||||
public record FeeAppliedEvent(int AccountId, decimal Amount);
|
||||
|
||||
public static class ApplyFeeHandler
|
||||
{
|
||||
public static async Task<FeePair?> LoadAsync(
|
||||
ApplyFeeCommand cmd,
|
||||
AccountDbContext db)
|
||||
{
|
||||
var customer = await db.Accounts.AsNoTracking().SingleOrDefaultAsync(x => x.Id == cmd.AccountId);
|
||||
var revenue = await db.Accounts.AsNoTracking().SingleOrDefaultAsync(x => x.Id == 99999);
|
||||
return (customer == null || revenue == null) ? null : new FeePair(customer, revenue);
|
||||
}
|
||||
|
||||
[Transactional]
|
||||
public static (
|
||||
IStorageAction<Account> CustomerWrite,
|
||||
IStorageAction<Account> RevenueWrite,
|
||||
IStorageAction<JournalEntry> JournalWrite,
|
||||
FeeAppliedEvent Event
|
||||
)
|
||||
Handle(
|
||||
ApplyFeeCommand cmd,
|
||||
FeePair pair
|
||||
)
|
||||
{
|
||||
var updatedCustomer = pair.CustomerAccount.ApplyPosting(cmd.Amount, EntryType.Debit);
|
||||
var updatedRevenue = pair.RevenueAccount.ApplyPosting(cmd.Amount, EntryType.Credit);
|
||||
var lines = new List<JournalLine>
|
||||
{
|
||||
new(pair.CustomerAccount.Id, cmd.Amount, EntryType.Debit),
|
||||
new(9999, cmd.Amount, EntryType.Credit)
|
||||
};
|
||||
var journalEntry = BalancedJournal.Create(Guid.NewGuid(),
|
||||
$"Service Fee Applied: {cmd.Amount} to Account {cmd.AccountId}",
|
||||
DateTimeOffset.UtcNow, lines);
|
||||
|
||||
var @event = new FeeAppliedEvent(cmd.AccountId, cmd.Amount);
|
||||
|
||||
return (
|
||||
Storage.Update(updatedCustomer),
|
||||
Storage.Update(updatedRevenue),
|
||||
Storage.Insert(journalEntry.Entry),
|
||||
@event
|
||||
);
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using FinancialApi.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinancialApi.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(AccountDbContext))]
|
||||
[Migration("20260715093924_AddJournal")]
|
||||
partial class AddJournal
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
|
||||
|
||||
modelBuilder.Entity("FinancialApi.Application.Account", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("AccountType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("Balance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
AccountType = "Credit",
|
||||
Balance = 100.00m
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 2,
|
||||
AccountType = "Liability",
|
||||
Balance = 500.00m
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 99999,
|
||||
AccountType = "Revenue",
|
||||
Balance = 0.00m
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("JournalEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
|
||||
{
|
||||
b.OwnsMany("FinancialApi.Application.JournalLine", "Lines", b1 =>
|
||||
{
|
||||
b1.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<int>("AccountId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<Guid>("JournalEntryId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("JournalEntryId");
|
||||
|
||||
b1.ToTable("JournalLine");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("JournalEntryId");
|
||||
});
|
||||
|
||||
b.Navigation("Lines");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinancialApi.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddJournal : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "AccountType",
|
||||
table: "Accounts",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "JournalEntries",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_JournalEntries", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "JournalLine",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
AccountId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Amount = table.Column<decimal>(type: "TEXT", nullable: false),
|
||||
Type = table.Column<string>(type: "TEXT", nullable: false),
|
||||
JournalEntryId = table.Column<Guid>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_JournalLine", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_JournalLine_JournalEntries_JournalEntryId",
|
||||
column: x => x.JournalEntryId,
|
||||
principalTable: "JournalEntries",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 1,
|
||||
column: "AccountType",
|
||||
value: "Credit");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 2,
|
||||
column: "AccountType",
|
||||
value: "Liability");
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "Accounts",
|
||||
columns: new[] { "Id", "AccountType", "Balance" },
|
||||
values: new object[] { 99999, "Revenue", 0.00m });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_JournalLine_JournalEntryId",
|
||||
table: "JournalLine",
|
||||
column: "JournalEntryId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "JournalLine");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "JournalEntries");
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 99999);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AccountType",
|
||||
table: "Accounts");
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FinancialApi.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class UpdateAccountBalances : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 1,
|
||||
column: "Balance",
|
||||
value: 10000000.00m);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 2,
|
||||
column: "Balance",
|
||||
value: 50000000.00m);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 1,
|
||||
column: "Balance",
|
||||
value: 100.00m);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Accounts",
|
||||
keyColumn: "Id",
|
||||
keyValue: 2,
|
||||
column: "Balance",
|
||||
value: 500.00m);
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-2
@@ -1,4 +1,5 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using FinancialApi.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
@@ -22,6 +23,10 @@ namespace FinancialApi.Infrastructure.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("AccountType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("Balance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
@@ -33,14 +38,74 @@ namespace FinancialApi.Infrastructure.Migrations
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
Balance = 100.00m
|
||||
AccountType = "Credit",
|
||||
Balance = 10000000.00m
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 2,
|
||||
Balance = 500.00m
|
||||
AccountType = "Liability",
|
||||
Balance = 50000000.00m
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 99999,
|
||||
AccountType = "Revenue",
|
||||
Balance = 0.00m
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("JournalEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
|
||||
{
|
||||
b.OwnsMany("FinancialApi.Application.JournalLine", "Lines", b1 =>
|
||||
{
|
||||
b1.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<int>("AccountId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<Guid>("JournalEntryId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("JournalEntryId");
|
||||
|
||||
b1.ToTable("JournalLine");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("JournalEntryId");
|
||||
});
|
||||
|
||||
b.Navigation("Lines");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,31 @@ public static class TransferFundsHandler
|
||||
public static (
|
||||
IStorageAction<Account> SourceWrite,
|
||||
IStorageAction<Account> DestWrite,
|
||||
IStorageAction<JournalEntry> JournalWrite,
|
||||
FundsTransferredEvent Event
|
||||
) Handle(TransferFundsCommand cmd, TransferPair pair)
|
||||
{
|
||||
var updatedSource = pair.Source.Debit(cmd.Amount);
|
||||
var updatedDest = pair.Destination.Credit(cmd.Amount);
|
||||
|
||||
var sourcePersistence = Storage.Update(updatedSource);
|
||||
var destPersistence = Storage.Update(updatedDest);
|
||||
var lines = new List<JournalLine>
|
||||
{
|
||||
new (pair.Source.Id, cmd.Amount, EntryType.Debit),
|
||||
new (pair.Destination.Id, cmd.Amount, EntryType.Credit)
|
||||
};
|
||||
|
||||
var journalEntry =
|
||||
BalancedJournal.Create(Guid.NewGuid(),
|
||||
$"Transfer: {cmd.Amount} from {cmd.SourceAccountId} to {cmd.DestinationAccountId}",
|
||||
DateTimeOffset.UtcNow, lines);
|
||||
|
||||
var @event = new FundsTransferredEvent(cmd.SourceAccountId, cmd.DestinationAccountId, cmd.Amount);
|
||||
|
||||
return (sourcePersistence, destPersistence, @event);
|
||||
return (
|
||||
Storage.Update(updatedSource),
|
||||
Storage.Update(updatedDest),
|
||||
Storage.Insert(journalEntry.Entry),
|
||||
@event
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ Content-Type: application/json
|
||||
|
||||
{
|
||||
"accountId": 1,
|
||||
"amount": 5.0
|
||||
"amount": 500.0
|
||||
}
|
||||
|
||||
### Transfer Between Accounts
|
||||
@@ -22,5 +22,5 @@ Content-Type: application/json
|
||||
{
|
||||
"sourceAccountId": 1,
|
||||
"destinationAccountId": 2,
|
||||
"amount": 30.00
|
||||
"amount": 3000.00
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user