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); }