-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
337 additions
and
376 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,40 @@ | ||
import 'package:wealth_wave/api/apis/investment_api.dart'; | ||
import 'package:wealth_wave/api/db/app_database.dart'; | ||
import 'package:wealth_wave/domain/models/investment.dart'; | ||
|
||
class Basket { | ||
final int id; | ||
final String name; | ||
final String? description; | ||
final int investmentCount; | ||
final double investedValue; | ||
|
||
final InvestmentApi _investmentApi; | ||
|
||
Basket( | ||
{required this.id, | ||
required this.name, | ||
required this.description, | ||
required this.investmentCount, | ||
required this.investedValue}); | ||
InvestmentApi? investmentApi}) | ||
: _investmentApi = investmentApi ?? InvestmentApi(); | ||
|
||
static Basket from( | ||
{required final BasketDO basket, | ||
required final List<Investment> investments}) { | ||
return Basket( | ||
id: basket.id, | ||
name: basket.name, | ||
description: basket.description, | ||
investments: investments); | ||
Future<int> getTotalInvestments() { | ||
return _investmentApi.getBy(basketId: id).then((value) => value.length); | ||
} | ||
|
||
double get totalValue { | ||
return investments.fold(0, (previousValue, investment) { | ||
return previousValue + investment.totalInvestedAmount; | ||
}); | ||
Future<double> getInvestedValue() async { | ||
return _investmentApi | ||
.getBy(basketId: id) | ||
.then((investments) => investments | ||
.map((investmentDO) => Investment.from(investmentDO: investmentDO))) | ||
.then((investments) => Future.wait(investments | ||
.map((investment) => investment.getTotalInvestedAmount()))) | ||
.then((investedAmounts) => | ||
investedAmounts.reduce((value, element) => value + element)); | ||
} | ||
|
||
int get investmentCount { | ||
return investments.length; | ||
static Basket from({required final BasketDO basketDO}) { | ||
return Basket( | ||
id: basketDO.id, | ||
name: basketDO.name, | ||
description: basketDO.description); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,35 @@ | ||
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; | ||
final String name; | ||
final String? description; | ||
final double amount; | ||
final DateTime createdDate; | ||
final DateTime amountUpdatedOn; | ||
final DateTime maturityDate; | ||
final double inflation; | ||
final double targetAmount; | ||
final DateTime targetDate; | ||
final GoalImportance importance; | ||
final Map<Investment, double> taggedInvestments; | ||
|
||
Goal( | ||
{required this.id, | ||
required this.name, | ||
required this.description, | ||
required this.amount, | ||
required this.createdDate, | ||
required this.maturityDate, | ||
required this.inflation, | ||
required this.targetAmount, | ||
required this.targetDate, | ||
required this.importance, | ||
required this.taggedInvestments}); | ||
|
||
double getIrr({bool considerFutureTransactions = false}) { | ||
double totalValue = 0.0; | ||
double weightedSum = 0.0; | ||
|
||
for (var investment in taggedInvestments.keys) { | ||
//totalValue += investment.getFutureValueOn(date: targetDate, considerFutureTransactions: false); | ||
//weightedSum += investedAmount * growthRate; | ||
} | ||
|
||
if (totalValue == 0.0) { | ||
return 0.0; | ||
} | ||
|
||
return weightedSum / totalValue; | ||
} | ||
|
||
double getInvestedAmount() { | ||
return taggedInvestments.keys | ||
.map((e) => e.totalInvestedAmount * (taggedInvestments[e] ?? 0)) | ||
.reduce((a, b) => a + b); | ||
} | ||
|
||
double getInvestedValue() { | ||
if (taggedInvestments.isEmpty) { | ||
return 0; | ||
} | ||
// return taggedInvestments.keys | ||
// .map((e) => (e.value / 100) * (taggedInvestments[e] ?? 0)) | ||
// .reduce((a, b) => a + b); | ||
return 0; | ||
required this.amountUpdatedOn, | ||
required this.importance}); | ||
|
||
static Goal from({required final GoalDO goalDO}) { | ||
return Goal( | ||
id: goalDO.id, | ||
name: goalDO.name, | ||
description: goalDO.description, | ||
amount: goalDO.amount, | ||
maturityDate: goalDO.maturityDate, | ||
inflation: goalDO.inflation, | ||
amountUpdatedOn: goalDO.amountUpdatedOn, | ||
importance: goalDO.importance); | ||
} | ||
|
||
double getProgress() { | ||
double progress = | ||
targetAmount > 0 ? getFutureValueOnTargetDate() / targetAmount : 0; | ||
if (progress > 1) { | ||
return 1; | ||
} | ||
return progress; | ||
} | ||
|
||
double getYearsLeft() { | ||
return targetDate.difference(DateTime.now()).inDays.toDouble() / 365; | ||
} | ||
|
||
double getFutureValueOnTargetDate() { | ||
if (taggedInvestments.isEmpty) { | ||
return 0; | ||
} | ||
// return taggedInvestments.entries | ||
// .map((e) => e.key.getFutureValueOn(targetDate) * e.value / 100) | ||
// .reduce((a, b) => a + b); | ||
return 0; | ||
} | ||
|
||
static Goal from( | ||
{required final GoalDO goal, | ||
required final Map<Investment, double> taggedInvestments}) => | ||
Goal( | ||
id: goal.id, | ||
name: goal.name, | ||
description: goal.description, | ||
amount: goal.amount, | ||
createdDate: goal.date, | ||
inflation: goal.inflation, | ||
targetAmount: goal.targetAmount, | ||
targetDate: goal.targetDate, | ||
importance: goal.importance, | ||
taggedInvestments: taggedInvestments); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,103 @@ | ||
import 'dart:math'; | ||
|
||
import 'package:wealth_wave/api/apis/basket_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/irr_calculator.dart'; | ||
import 'package:wealth_wave/domain/models/sip.dart'; | ||
import 'package:wealth_wave/domain/models/basket.dart'; | ||
import 'package:wealth_wave/domain/models/irr_calculator.dart'; | ||
import 'package:wealth_wave/domain/models/transaction.dart'; | ||
|
||
class Investment { | ||
final int id; | ||
final String name; | ||
final String? description; | ||
final RiskLevel riskLevel; | ||
final double? currentValue; | ||
final double? value; | ||
final double? irr; | ||
final DateTime? currentValueUpdatedOn; | ||
final DateTime? valueUpdatedOn; | ||
final DateTime? maturityDate; | ||
final int? basketId; | ||
final String? basketName; | ||
final double totalInvestedAmount; | ||
final int totalTransactions; | ||
final List<Transaction> transactions; | ||
final List<SIP> sips; | ||
final List<GoalInvestmentEnrichedMappingDO> taggedGoals; | ||
|
||
final TransactionApi _transactionApi; | ||
final IRRCalculator _irrCalculator; | ||
final BasketApi _basketApi; | ||
|
||
Investment( | ||
{required this.id, | ||
required this.name, | ||
required this.description, | ||
required this.riskLevel, | ||
required this.irr, | ||
required this.currentValue, | ||
required this.currentValueUpdatedOn, | ||
required this.value, | ||
required this.valueUpdatedOn, | ||
required this.basketId, | ||
required this.basketName, | ||
required this.maturityDate, | ||
required this.totalInvestedAmount, | ||
required this.totalTransactions, | ||
required this.transactions, | ||
required this.sips, | ||
required this.taggedGoals}); | ||
|
||
double? getIrr() { | ||
if (irr != null) { | ||
return irr; | ||
} else if (currentValue != null && currentValueUpdatedOn != null) { | ||
return IRRCalculator().calculateIRR( | ||
transactions: transactions, | ||
finalValue: currentValue!, | ||
finalDate: currentValueUpdatedOn!, | ||
); | ||
} | ||
TransactionApi? transactionApi, | ||
IRRCalculator? irrCalculator, | ||
BasketApi? basketApi}) | ||
: _transactionApi = transactionApi ?? TransactionApi(), | ||
_irrCalculator = irrCalculator ?? IRRCalculator(), | ||
_basketApi = basketApi ?? BasketApi(); | ||
|
||
return null; | ||
Future<double> getTotalInvestedAmount() async { | ||
return _transactionApi | ||
.getBy(investmentId: id) | ||
.then((transactions) => transactions | ||
.map((transactionDO) => | ||
Transaction.from(transactionDO: transactionDO)) | ||
.toList()) | ||
.then((transactions) => transactions | ||
.map((transaction) => transaction.amount) | ||
.reduce((value, element) => value + element)); | ||
} | ||
|
||
double getFutureValueOn({required DateTime date, required bool considerFutureTransactions}) { | ||
double? irr = getIrr(); | ||
if (currentValue != null) { | ||
Future<double> getValueOn(DateTime date) async { | ||
if (value != null && valueUpdatedOn != null) { | ||
final transactions = await getTransactions(); | ||
final irr = _irrCalculator.calculateIRR( | ||
transactions: transactions, | ||
value: value!, | ||
valueUpdatedOn: valueUpdatedOn!); | ||
if (irr == null) { | ||
return currentValue!; | ||
} else { | ||
return currentValue! * | ||
pow(1 + irr, date.difference(currentValueUpdatedOn!).inDays / 365); | ||
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); | ||
} else { | ||
if (irr == null) { | ||
return 0; | ||
} | ||
double futureValue = 0; | ||
for (var transaction in transactions) { | ||
//TODO consider maturity date of investment | ||
//TODO filter transaction above the date given. | ||
double years = date.difference(transaction.createdOn).inDays / 365; | ||
futureValue += transaction.amount / pow(1 + irr, years); | ||
} | ||
for(var sip in sips) { | ||
//Include future value of sip. | ||
} | ||
throw Exception('Value and IRR are null'); | ||
} | ||
} | ||
|
||
return futureValue; | ||
Future<List<Transaction>> getTransactions() async { | ||
return _transactionApi.getBy(investmentId: id).then((transactions) => | ||
transactions | ||
.map((transactionDO) => | ||
Transaction.from(transactionDO: transactionDO)) | ||
.toList()); | ||
} | ||
|
||
Future<Basket?> getBasket() async { | ||
if (basketId != null) { | ||
return _basketApi | ||
.getBy(id: basketId!) | ||
.then((basketDO) => Basket.from(basketDO: basketDO)); | ||
} | ||
return null; | ||
} | ||
|
||
static Investment from( | ||
{required final InvestmentEnrichedDO investment, | ||
required final List<TransactionDO> transactions, | ||
required final List<SipDO> sips, | ||
required final List<GoalInvestmentEnrichedMappingDO> | ||
goalInvestmentMappings}) { | ||
static Investment from({required final InvestmentDO investmentDO}) { | ||
return Investment( | ||
id: investment.id, | ||
name: investment.name, | ||
description: investment.description, | ||
riskLevel: investment.riskLevel, | ||
maturityDate: investment.maturityDate, | ||
currentValue: investment.currentValue, | ||
currentValueUpdatedOn: investment.currentValueUpdatedOn, | ||
irr: investment.irr, | ||
basketId: investment.basketId ?? 0, | ||
basketName: investment.basketName ?? '', | ||
totalInvestedAmount: investment.totalInvestedAmount ?? 0, | ||
totalTransactions: investment.totalTransactions ?? 0, | ||
transactions: transactions | ||
.map((transaction) => Transaction.from(transaction: transaction)) | ||
.toList(), | ||
sips: sips.map((sip) => SIP.from(sip: sip)).toList(), | ||
taggedGoals: goalInvestmentMappings); | ||
id: investmentDO.id, | ||
name: investmentDO.name, | ||
description: investmentDO.description, | ||
riskLevel: investmentDO.riskLevel, | ||
irr: investmentDO.irr, | ||
value: investmentDO.value, | ||
valueUpdatedOn: investmentDO.valueUpdatedOn, | ||
basketId: investmentDO.basketId, | ||
maturityDate: investmentDO.maturityDate); | ||
} | ||
} |
Oops, something went wrong.