finnow/finnow-api/source/transaction/service.d

114 lines
3.3 KiB
D

module transaction.service;
import handy_http_primitives;
import std.datetime;
import transaction.api;
import transaction.model;
import transaction.data;
import profile.data;
import account.model;
import util.money;
import util.pagination;
// Transactions Services
Page!TransactionsListItem getTransactions(ProfileDataSource ds, in PageRequest pageRequest) {
Page!TransactionsListItem page = ds.getTransactionRepository()
.findAll(pageRequest);
return page; // Return an empty page for now!
}
void addTransaction2(ProfileDataSource ds, in AddTransactionPayload payload) {
// TODO
}
void addTransaction(
ProfileDataSource ds,
SysTime timestamp,
SysTime addedAt,
ulong amount,
Currency currency,
string description,
Optional!ulong vendorId,
Optional!ulong categoryId,
Optional!ulong creditedAccountId,
Optional!ulong debitedAccountId,
TransactionLineItem[] lineItems,
string[] tags
) {
if (creditedAccountId.isNull && debitedAccountId.isNull) {
throw new Exception("At least one account must be linked to a transaction.");
}
auto journalEntryRepo = ds.getAccountJournalEntryRepository();
auto txRepo = ds.getTransactionRepository();
Transaction tx = txRepo.insert(
timestamp,
addedAt,
amount,
currency,
description,
vendorId,
categoryId
);
if (creditedAccountId) {
journalEntryRepo.insert(
timestamp,
creditedAccountId.value,
tx.id,
amount,
AccountJournalEntryType.CREDIT,
currency
);
}
if (debitedAccountId) {
journalEntryRepo.insert(
timestamp,
debitedAccountId.value,
tx.id,
amount,
AccountJournalEntryType.DEBIT,
currency
);
}
if (tags.length > 0) {
ds.getTransactionTagRepository().updateTags(tx.id, tags);
}
}
// Vendors Services
TransactionVendor[] getAllVendors(ProfileDataSource ds) {
return ds.getTransactionVendorRepository().findAll();
}
TransactionVendor getVendor(ProfileDataSource ds, ulong vendorId) {
return ds.getTransactionVendorRepository().findById(vendorId)
.orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND));
}
TransactionVendor createVendor(ProfileDataSource ds, in VendorPayload payload) {
auto vendorRepo = ds.getTransactionVendorRepository();
if (vendorRepo.existsByName(payload.name)) {
throw new HttpStatusException(HttpStatus.BAD_REQUEST, "Vendor name is already in use.");
}
return vendorRepo.insert(payload.name, payload.description);
}
TransactionVendor updateVendor(ProfileDataSource ds, ulong vendorId, in VendorPayload payload) {
TransactionVendorRepository repo = ds.getTransactionVendorRepository();
TransactionVendor existingVendor = repo.findById(vendorId)
.orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND));
if (payload.name != existingVendor.name && repo.existsByName(payload.name)) {
throw new HttpStatusException(
HttpStatus.BAD_REQUEST,
"Vendor name is already in use."
);
}
return repo.updateById(vendorId, payload.name, payload.description);
}
void deleteVendor(ProfileDataSource ds, ulong vendorId) {
ds.getTransactionVendorRepository().deleteById(vendorId);
}