Skip to content

Commit

Permalink
save commit
Browse files Browse the repository at this point in the history
  • Loading branch information
praslnx8 committed Jan 16, 2024
1 parent 48bbe46 commit 7057fff
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 120 deletions.
8 changes: 4 additions & 4 deletions lib/api/apis/goal_investment_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ class GoalInvestmentApi {
goalId: goalId, investmentId: investmentId, split: split));
}

Future<List<GoalInvestmentEnrichedDO>> getBy(
Future<List<GoalInvestmentDO>> getBy(
{final int? goalId, final int? investmentId}) async {
if (goalId != null) {
return (_db.select(_db.goalInvestmentEnrichedView)
return (_db.select(_db.goalInvestmentTable)
..where((t) => t.goalId.equals(goalId)))
.get();
} else if (investmentId != null) {
return (_db.select(_db.goalInvestmentEnrichedView)
return (_db.select(_db.goalInvestmentTable)
..where((t) => t.investmentId.equals(investmentId)))
.get();
}
return _db.select(_db.goalInvestmentEnrichedView).get();
throw Exception('Invalid getBy call');
}

Future<int> update(
Expand Down
5 changes: 5 additions & 0 deletions lib/api/apis/sip_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class SipApi {
}
}

Future<SipDO> getById({required final int id}) async {
return (_db.select(_db.sipTable)..where((t) => t.id.equals(id)))
.getSingle();
}

Future<int> update(
{required final int id,
required final int investmentId,
Expand Down
12 changes: 8 additions & 4 deletions lib/api/apis/transaction_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,21 @@ class TransactionApi {
createdOn: createdOn));
}

Future<List<TransactionDO>> getBy({final int? investmentId}) async {
if (investmentId == null) {
Future<List<TransactionDO>> getBy(
{final int? investmentId, final int? sipId}) async {
if (investmentId != null) {
return (_db.select(_db.transactionTable)
..where((t) => t.investmentId.equals(investmentId))
..orderBy([(t) => OrderingTerm.desc(t.createdOn)]))
.get();
} else {
} else if (sipId != null) {
return (_db.select(_db.transactionTable)
..where((t) => t.investmentId.equals(investmentId))
..where((t) => t.sipId.equals(sipId))
..orderBy([(t) => OrderingTerm.desc(t.createdOn)]))
.get();
}

throw Exception('Invalid getBy call');
}

Future<int> update(
Expand Down
27 changes: 1 addition & 26 deletions lib/api/db/app_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,30 +147,6 @@ abstract class InvestmentEnrichedView extends View {
..groupBy([investment.id]);
}

@DataClassName('GoalInvestmentEnrichedDO')
abstract class GoalInvestmentEnrichedView extends View {
GoalInvestmentTable get goalInvestment;
GoalTable get goal;
InvestmentTable get investment;

Expression<String> get goalName => goal.name;
Expression<String> get investmentName => investment.name;

@override
Query as() => select([
goalInvestment.id,
goalInvestment.goalId,
goalInvestment.investmentId,
goalInvestment.split,
goalName,
investmentName
]).from(goalInvestment).join([
innerJoin(goal, goal.id.equalsExp(goalInvestment.goalId)),
innerJoin(
investment, investment.id.equalsExp(goalInvestment.investmentId)),
]);
}

@DriftDatabase(tables: [
BasketTable,
InvestmentTable,
Expand All @@ -179,8 +155,7 @@ abstract class GoalInvestmentEnrichedView extends View {
SipTable,
GoalInvestmentTable,
], views: [
InvestmentEnrichedView,
GoalInvestmentEnrichedView,
InvestmentEnrichedView
])
class AppDatabase extends _$AppDatabase {
static AppDatabase? _instance;
Expand Down
55 changes: 1 addition & 54 deletions lib/api/db/app_database.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions lib/contract/sip_frequency.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,25 @@ enum SipFrequency {
weekly,
biweekly,
monthly,
quarterly,
yearly,
}

Duration getDuration(SipFrequency frequency) {
switch (frequency) {
case SipFrequency.daily:
return const Duration(days: 1);
case SipFrequency.weekly:
return const Duration(days: 7);
case SipFrequency.biweekly:
return const Duration(days: 14);
case SipFrequency.monthly:
return const Duration(days: 30);
case SipFrequency.quarterly:
return const Duration(days: 90);
case SipFrequency.yearly:
return const Duration(days: 365);
default:
throw Exception('Invalid frequency');
}
}
18 changes: 17 additions & 1 deletion lib/domain/models/basket.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Basket {
{required this.id,
required this.name,
required this.description,
InvestmentApi? investmentApi})
final InvestmentApi? investmentApi})
: _investmentApi = investmentApi ?? InvestmentApi();

Future<int> getTotalInvestments() {
Expand All @@ -31,6 +31,22 @@ class Basket {
investedAmounts.reduce((value, element) => value + element));
}

Future<double> getValue({final bool considerFuturePayments = false}) async {
return _investmentApi
.getBy(basketId: id)
.then((investments) => investments
.map((investmentDO) => Investment.from(investmentDO: investmentDO)))
.then((investments) => Future.wait(investments
.map((investment) => investment.getValueOn(date: DateTime.now(), considerFuturePayments: considerFuturePayments))))
.then((values) => values.reduce((value, element) => value + element));
}

Future<List<Investment>> getInvestments() {
return _investmentApi.getBy(basketId: id).then((investments) => investments
.map((investmentDO) => Investment.from(investmentDO: investmentDO))
.toList());
}

static Basket from({required final BasketDO basketDO}) {
return Basket(
id: basketDO.id,
Expand Down
25 changes: 24 additions & 1 deletion lib/domain/models/goal.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:wealth_wave/api/apis/goal_investment_api.dart';
import 'package:wealth_wave/api/apis/investment_api.dart';
import 'package:wealth_wave/api/db/app_database.dart';
import 'package:wealth_wave/contract/goal_importance.dart';
import 'package:wealth_wave/domain/models/investment.dart';

class Goal {
final int id;
Expand All @@ -11,6 +14,9 @@ class Goal {
final double inflation;
final GoalImportance importance;

final GoalInvestmentApi _goalInvestmentApi;
final InvestmentApi _investmentApi;

Goal(
{required this.id,
required this.name,
Expand All @@ -19,7 +25,24 @@ class Goal {
required this.maturityDate,
required this.inflation,
required this.amountUpdatedOn,
required this.importance});
required this.importance,
final GoalInvestmentApi? goalInvestmentApi,
final InvestmentApi? investmentApi})
: _goalInvestmentApi = goalInvestmentApi ?? GoalInvestmentApi(),
_investmentApi = investmentApi ?? InvestmentApi();

Future<Map<Investment, double>> getInvestments() async {
return _goalInvestmentApi
.getBy(goalId: id)
.then((goalInvestments) => Future.wait(goalInvestments.map(
(goalInvestment) => _investmentApi
.getById(id: goalInvestment.investmentId)
.then((investmentDO) =>
Investment.from(investmentDO: investmentDO))
.then((investment) =>
MapEntry(investment, goalInvestment.split)))))
.then((entries) => Map.fromEntries(entries));
}

static Goal from({required final GoalDO goalDO}) {
return Goal(
Expand Down
61 changes: 50 additions & 11 deletions lib/domain/models/investment.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import 'package:wealth_wave/api/apis/basket_api.dart';
import 'package:wealth_wave/api/apis/goal_api.dart';
import 'package:wealth_wave/api/apis/goal_investment_api.dart';
import 'package:wealth_wave/api/apis/sip_api.dart';
import 'package:wealth_wave/api/apis/transaction_api.dart';
import 'package:wealth_wave/api/db/app_database.dart';
import 'package:wealth_wave/contract/risk_level.dart';
import 'package:wealth_wave/domain/models/basket.dart';
import 'package:wealth_wave/domain/models/goal.dart';
import 'package:wealth_wave/domain/models/irr_calculator.dart';
import 'package:wealth_wave/domain/models/payment.dart';
import 'package:wealth_wave/domain/models/sip.dart';
import 'package:wealth_wave/domain/models/transaction.dart';

class Investment {
Expand All @@ -20,6 +26,9 @@ class Investment {
final TransactionApi _transactionApi;
final IRRCalculator _irrCalculator;
final BasketApi _basketApi;
final GoalInvestmentApi _goalInvestmentApi;
final GoalApi _goalApi;
final SipApi _sipApi;

Investment(
{required this.id,
Expand All @@ -31,12 +40,18 @@ class Investment {
required this.valueUpdatedOn,
required this.basketId,
required this.maturityDate,
TransactionApi? transactionApi,
IRRCalculator? irrCalculator,
BasketApi? basketApi})
final TransactionApi? transactionApi,
final IRRCalculator? irrCalculator,
final BasketApi? basketApi,
final GoalInvestmentApi? goalInvestmentApi,
final GoalApi? goalApi,
final SipApi? sipApi})
: _transactionApi = transactionApi ?? TransactionApi(),
_irrCalculator = irrCalculator ?? IRRCalculator(),
_basketApi = basketApi ?? BasketApi();
_basketApi = basketApi ?? BasketApi(),
_goalInvestmentApi = goalInvestmentApi ?? GoalInvestmentApi(),
_goalApi = goalApi ?? GoalApi(),
_sipApi = sipApi ?? SipApi();

Future<double> getTotalInvestedAmount() async {
return _transactionApi
Expand All @@ -50,22 +65,29 @@ class Investment {
.reduce((value, element) => value + element));
}

Future<double> getValueOn(DateTime date) async {
Future<double> getValueOn(
{required final DateTime date,
bool considerFuturePayments = false}) async {
final payments = await getTransactions().then((transactions) => transactions
.map((transaction) => Payment.from(transaction: transaction))
.toList(growable: true));
if (considerFuturePayments) {
getSips().then((sips) => Future.wait(sips.map((sip) => sip
.getFuturePayment(till: date)
.then((futurePayments) => payments.addAll(futurePayments)))));
}

if (value != null && valueUpdatedOn != null) {
final transactions = await getTransactions();
final irr = _irrCalculator.calculateIRR(
transactions: transactions,
value: value!,
valueUpdatedOn: valueUpdatedOn!);
payments: payments, value: value!, valueUpdatedOn: valueUpdatedOn!);
if (irr == null) {
return value!;
}
return _irrCalculator.calculateValueOnIRR(
irr: irr, date: date, value: value!, valueUpdatedOn: valueUpdatedOn!);
} else if (irr != null) {
final transactions = await getTransactions();
return _irrCalculator.calculateTransactedValueOnIRR(
transactions: transactions, irr: irr!, date: date);
payments: payments, irr: irr!, date: date);
} else {
throw Exception('Value and IRR are null');
}
Expand All @@ -88,6 +110,23 @@ class Investment {
return null;
}

Future<Map<Goal, double>> getInvestments() async {
return _goalInvestmentApi
.getBy(goalId: id)
.then((goalInvestments) => Future.wait(goalInvestments.map(
(goalInvestment) => _goalApi
.getBy(id: goalInvestment.goalId)
.then((goalDO) => Goal.from(goalDO: goalDO))
.then((goal) => MapEntry(goal, goalInvestment.split)))))
.then((entries) => Map.fromEntries(entries));
}

Future<List<SIP>> getSips() async {
return _sipApi
.getBy(investmentId: id)
.then((sips) => sips.map((sipDO) => SIP.from(sipDO: sipDO)).toList());
}

static Investment from({required final InvestmentDO investmentDO}) {
return Investment(
id: investmentDO.id,
Expand Down
Loading

0 comments on commit 7057fff

Please sign in to comment.