Skip to content

Commit

Permalink
Merge pull request #43 from moneymanagerex/new_models-2
Browse files Browse the repository at this point in the history
Add TransactionSplit, ScheduledSplit
  • Loading branch information
georgeef authored Sep 25, 2024
2 parents 42688c8 + fb0ca64 commit 838560a
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 0 deletions.
16 changes: 16 additions & 0 deletions MMEX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
920823FC2CA4A15C00388AB2 /* StockHistoryRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920823FB2CA4A15C00388AB2 /* StockHistoryRepository.swift */; };
920823FE2CA4A3F700388AB2 /* TagData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920823FD2CA4A3F700388AB2 /* TagData.swift */; };
920824002CA4A4AA00388AB2 /* TagRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920823FF2CA4A4AA00388AB2 /* TagRepository.swift */; };
920824022CA4AD0C00388AB2 /* TransactionSplitData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920824012CA4AD0C00388AB2 /* TransactionSplitData.swift */; };
920824042CA4ADC100388AB2 /* ScheduledSplitData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920824032CA4ADC100388AB2 /* ScheduledSplitData.swift */; };
920824062CA4AE0A00388AB2 /* TransactionSplitRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920824052CA4AE0A00388AB2 /* TransactionSplitRepository.swift */; };
920824082CA4B05700388AB2 /* ScheduledSplitRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920824072CA4B05700388AB2 /* ScheduledSplitRepository.swift */; };
929EF65F2C9FF2DE0051A3E6 /* AssetData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF65E2C9FF2DE0051A3E6 /* AssetData.swift */; };
929EF6612C9FF2FD0051A3E6 /* StockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF6602C9FF2FD0051A3E6 /* StockData.swift */; };
929EF6632C9FF3ED0051A3E6 /* AssetRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF6622C9FF3ED0051A3E6 /* AssetRepository.swift */; };
Expand Down Expand Up @@ -94,6 +98,10 @@
920823FB2CA4A15C00388AB2 /* StockHistoryRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StockHistoryRepository.swift; sourceTree = "<group>"; };
920823FD2CA4A3F700388AB2 /* TagData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TagData.swift; sourceTree = "<group>"; };
920823FF2CA4A4AA00388AB2 /* TagRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TagRepository.swift; sourceTree = "<group>"; };
920824012CA4AD0C00388AB2 /* TransactionSplitData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionSplitData.swift; sourceTree = "<group>"; };
920824032CA4ADC100388AB2 /* ScheduledSplitData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledSplitData.swift; sourceTree = "<group>"; };
920824052CA4AE0A00388AB2 /* TransactionSplitRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionSplitRepository.swift; sourceTree = "<group>"; };
920824072CA4B05700388AB2 /* ScheduledSplitRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduledSplitRepository.swift; sourceTree = "<group>"; };
929EF65E2C9FF2DE0051A3E6 /* AssetData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetData.swift; sourceTree = "<group>"; };
929EF6602C9FF2FD0051A3E6 /* StockData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StockData.swift; sourceTree = "<group>"; };
929EF6622C9FF3ED0051A3E6 /* AssetRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetRepository.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -310,7 +318,9 @@
A3C142932C8FE13E00D3CEC0 /* PayeeRepository.swift */,
920823FF2CA4A4AA00388AB2 /* TagRepository.swift */,
A3C142952C8FE15E00D3CEC0 /* TransactionRepository.swift */,
920824052CA4AE0A00388AB2 /* TransactionSplitRepository.swift */,
929EF66E2CA0BC2D0051A3E6 /* ScheduledRepository.swift */,
920824072CA4B05700388AB2 /* ScheduledSplitRepository.swift */,
);
path = Repositories;
sourceTree = "<group>";
Expand Down Expand Up @@ -375,7 +385,9 @@
A3C1424D2C8B335900D3CEC0 /* PayeeData.swift */,
920823FD2CA4A3F700388AB2 /* TagData.swift */,
A3C142662C8F2AF500D3CEC0 /* TransactionData.swift */,
920824012CA4AD0C00388AB2 /* TransactionSplitData.swift */,
929EF66C2CA0BA5E0051A3E6 /* ScheduledData.swift */,
920824032CA4ADC100388AB2 /* ScheduledSplitData.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -482,6 +494,7 @@
A37E7D8E2C9AC4C900B4ECFC /* PrivacyPolicyView.swift in Sources */,
A3C142612C8E9DBF00D3CEC0 /* PayeeAddView.swift in Sources */,
A39B1B382C99A0D8003E5562 /* CurrencyListView.swift in Sources */,
920824082CA4B05700388AB2 /* ScheduledSplitRepository.swift in Sources */,
A30061762CA3B58700011B1A /* AssetDetailView.swift in Sources */,
929EF6632C9FF3ED0051A3E6 /* AssetRepository.swift in Sources */,
A350BDC12CA26415006669D5 /* InfotableViewModel.swift in Sources */,
Expand All @@ -497,6 +510,7 @@
A3C142502C8B366400D3CEC0 /* PayeeListView.swift in Sources */,
A379C1A72CA3B79E00CC8E2C /* AssetAddView.swift in Sources */,
A3C142672C8F2AF500D3CEC0 /* TransactionData.swift in Sources */,
920824042CA4ADC100388AB2 /* ScheduledSplitData.swift in Sources */,
A3462F642C9426F500F79145 /* InsightsViewModel.swift in Sources */,
A3C142AC2C909C1C00D3CEC0 /* TransactionEditView.swift in Sources */,
A3C142962C8FE15E00D3CEC0 /* TransactionRepository.swift in Sources */,
Expand All @@ -506,6 +520,7 @@
920823FE2CA4A3F700388AB2 /* TagData.swift in Sources */,
A379C1A92CA3B9EB00CC8E2C /* AssetListView.swift in Sources */,
920824002CA4A4AA00388AB2 /* TagRepository.swift in Sources */,
920824062CA4AE0A00388AB2 /* TransactionSplitRepository.swift in Sources */,
A3C142AA2C90721800D3CEC0 /* TransactionListView2.swift in Sources */,
A3C142A62C90417700D3CEC0 /* TransactionAddView2.swift in Sources */,
A3C142472C89CB4200D3CEC0 /* AccountDetailView.swift in Sources */,
Expand Down Expand Up @@ -534,6 +549,7 @@
920823F82CA498B500388AB2 /* CurrencyHistoryRepository.swift in Sources */,
A37E7D8A2C9AC30700B4ECFC /* HelpFAQView.swift in Sources */,
929EF66D2CA0BA5E0051A3E6 /* ScheduledData.swift in Sources */,
920824022CA4AD0C00388AB2 /* TransactionSplitData.swift in Sources */,
A3363EE32C9323A5004696C7 /* CategoryEditView.swift in Sources */,
A3C142652C8ED8EA00D3CEC0 /* AccountEditView.swift in Sources */,
A3C142632C8ED8C000D3CEC0 /* AccountAddView.swift in Sources */,
Expand Down
30 changes: 30 additions & 0 deletions MMEX/Models/ScheduledSplitData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ScheduledSplit.swift
// MMEX
//
// Created 2024-09-25 by George Ef ([email protected])
//

import Foundation
import SQLite

struct ScheduledSplitData: ExportableEntity {
var id : Int64 = 0
var schedId : Int64 = 0
var categId : Int64 = 0
var amount : Double = 0.0
var notes : String = ""
}

extension ScheduledSplitData: DataProtocol {
static let dataName = "ScheduledSplit"

func shortDesc() -> String {
"\(self.id)"
}
}

extension ScheduledSplitData {
static let sampleData: [ScheduledSplitData] = [
]
}
30 changes: 30 additions & 0 deletions MMEX/Models/TransactionSplitData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// TransactionSplit.swift
// MMEX
//
// Created 2024-09-25 by George Ef ([email protected])
//

import Foundation
import SQLite

struct TransactionSplitData: ExportableEntity {
var id : Int64 = 0
var transId : Int64 = 0
var categId : Int64 = 0
var amount : Double = 0.0
var notes : String = ""
}

extension TransactionSplitData: DataProtocol {
static let dataName = "TransactionSplit"

func shortDesc() -> String {
"\(self.id)"
}
}

extension TransactionSplitData {
static let sampleData: [TransactionSplitData] = [
]
}
8 changes: 8 additions & 0 deletions MMEX/Repositories/AccountRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ extension AccountRepository {
.order(Self.col_name)
)
}

// load account of a stock
func pluck(for stock: StockData) -> AccountData? {
return pluck(
from: Self.table.filter(Self.col_id == stock.accountId),
key: "\(stock.accountId)"
)
}
}

// TODO: move to ViewModels
Expand Down
8 changes: 8 additions & 0 deletions MMEX/Repositories/CategoryRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,12 @@ extension CategoryRepository {
func load() -> [CategoryData] {
return select(from: Self.table)
}

// load category of a payeer
func pluck(for payee: PayeeData) -> CategoryData? {
return pluck(
from: Self.table.filter(Self.col_id == payee.categoryId),
key: "\(payee.categoryId)"
)
}
}
16 changes: 16 additions & 0 deletions MMEX/Repositories/CurrencyRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,20 @@ extension CurrencyRepository {
.order(Self.col_name)
)
}

// load currency of an account
func pluck(for account: AccountData) -> CurrencyData? {
return pluck(
from: Self.table.filter(Self.col_id == account.currencyId),
key: "\(account.currencyId)"
)
}

// load currency of an asset
func pluck(for asset: AssetData) -> CurrencyData? {
return pluck(
from: Self.table.filter(Self.col_id == asset.currencyId),
key: "\(asset.currencyId)"
)
}
}
88 changes: 88 additions & 0 deletions MMEX/Repositories/ScheduledSplitRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// ScheduledSplitRepository.swift
// MMEX
//
// Created 2024-09-25 by George Ef ([email protected])
//

import Foundation
import SQLite

class ScheduledSplitRepository: RepositoryProtocol {
typealias RepositoryData = ScheduledSplitData

let db: Connection?
init(db: Connection?) {
self.db = db
}

static let repositoryName = "BUDGETSPLITTRANSACTIONS_V1"
static let table = SQLite.Table(repositoryName)

// column | type | other
// -----------------+---------+------
// SPLITTRANSID | INTEGER | PRIMARY KEY
// TRANSID | INTEGER | NOT NULL
// CATEGID | INTEGER |
// SPLITTRANSAMOUNT | NUMERIC |
// NOTES | TEXT |

// column expressions
static let col_id = SQLite.Expression<Int64>("SPLITTRANSID")
static let col_transId = SQLite.Expression<Int64>("TRANSID")
static let col_categId = SQLite.Expression<Int64?>("CATEGID")
static let col_amount = SQLite.Expression<Double?>("SPLITTRANSAMOUNT")
static let col_notes = SQLite.Expression<String?>("NOTES")

// cast NUMERIC to REAL
static let cast_amount = cast(col_amount) as SQLite.Expression<Double?>

static func selectQuery(from table: SQLite.Table) -> SQLite.Table {
return table.select(
col_id,
col_transId,
col_categId,
cast_amount,
col_notes
)
}

static func selectData(_ row: SQLite.Row) -> ScheduledSplitData {
return ScheduledSplitData(
id : row[col_id],
schedId : row[col_transId],
categId : row[col_categId] ?? -1,
amount : row[cast_amount] ?? 0,
notes : row[col_notes] ?? ""
)
}

static func itemSetters(_ split: ScheduledSplitData) -> [SQLite.Setter] {
return [
col_transId <- split.schedId,
col_categId <- split.categId,
col_amount <- split.amount,
col_notes <- split.notes
]
}
}

extension ScheduledSplitRepository {
// load all splits
func load() -> [ScheduledSplitData] {
return select(from: Self.table
.order(Self.col_transId, Self.col_id)
)
}

// load splits of a scheduled transaction
func load(forScheduledId schedId: Int64) -> [ScheduledSplitData] {
return select(from: Self.table
.filter(Self.col_transId == schedId)
.order(Self.col_id)
)
}
func load(for sched: ScheduledData) -> [ScheduledSplitData] {
return load(forScheduledId: sched.id)
}
}
88 changes: 88 additions & 0 deletions MMEX/Repositories/TransactionSplitRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// TransactionSplitRepository.swift
// MMEX
//
// Created 2024-09-25 by George Ef ([email protected])
//

import Foundation
import SQLite

class TransactionSplitRepository: RepositoryProtocol {
typealias RepositoryData = TransactionSplitData

let db: Connection?
init(db: Connection?) {
self.db = db
}

static let repositoryName = "SPLITTRANSACTIONS_V1"
static let table = SQLite.Table(repositoryName)

// column | type | other
// -----------------+---------+------
// SPLITTRANSID | INTEGER | PRIMARY KEY
// TRANSID | INTEGER | NOT NULL
// CATEGID | INTEGER |
// SPLITTRANSAMOUNT | NUMERIC |
// NOTES | TEXT |

// column expressions
static let col_id = SQLite.Expression<Int64>("SPLITTRANSID")
static let col_transId = SQLite.Expression<Int64>("TRANSID")
static let col_categId = SQLite.Expression<Int64?>("CATEGID")
static let col_amount = SQLite.Expression<Double?>("SPLITTRANSAMOUNT")
static let col_notes = SQLite.Expression<String?>("NOTES")

// cast NUMERIC to REAL
static let cast_amount = cast(col_amount) as SQLite.Expression<Double?>

static func selectQuery(from table: SQLite.Table) -> SQLite.Table {
return table.select(
col_id,
col_transId,
col_categId,
cast_amount,
col_notes
)
}

static func selectData(_ row: SQLite.Row) -> TransactionSplitData {
return TransactionSplitData(
id : row[col_id],
transId : row[col_transId],
categId : row[col_categId] ?? -1,
amount : row[cast_amount] ?? 0,
notes : row[col_notes] ?? ""
)
}

static func itemSetters(_ split: TransactionSplitData) -> [SQLite.Setter] {
return [
col_transId <- split.transId,
col_categId <- split.categId,
col_amount <- split.amount,
col_notes <- split.notes
]
}
}

extension TransactionSplitRepository {
// load all splits
func load() -> [TransactionSplitData] {
return select(from: Self.table
.order(Self.col_transId, Self.col_id)
)
}

// load splits of a transaction
func load(forTransactionId transId: Int64) -> [TransactionSplitData] {
return select(from: Self.table
.filter(Self.col_transId == transId)
.order(Self.col_id)
)
}
func load(for trans: TransactionData) -> [TransactionSplitData] {
return load(forTransactionId: trans.id)
}
}

0 comments on commit 838560a

Please sign in to comment.