Skip to content

Commit 11beeb2

Browse files
committed
testing group and null names discards
1 parent 1d0db59 commit 11beeb2

File tree

9 files changed

+481
-96
lines changed

9 files changed

+481
-96
lines changed

Diff for: core/database/src/main/sqldelight/br/com/mob1st/core/database/Schema.sq

+60-44
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ CREATE TABLE IF NOT EXISTS CategoryTypes(
1010
description IN ('fixed', 'variable', 'seasonal')
1111
)
1212
);
13+
CREATE UNIQUE INDEX IF NOT EXISTS idx_category_types__description ON CategoryTypes(description);
14+
CREATE TRIGGER IF NOT EXISTS prevent_update_CategoryTypes
15+
BEFORE UPDATE OF description ON CategoryTypes
16+
BEGIN
17+
SELECT RAISE(
18+
ABORT,
19+
'Update of description is not allowed in CategoryTypes'
20+
);
21+
END;
22+
1323
CREATE UNIQUE INDEX IF NOT EXISTS idx_category_types_description ON CategoryTypes(description);
1424
INSERT INTO CategoryTypes(description)
1525
VALUES ('fixed'), ('variable'), ('seasonal');
@@ -22,7 +32,9 @@ CREATE TABLE IF NOT EXISTS Suggestions(
2232
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
2333
FOREIGN KEY(type_id) REFERENCES CategoryTypes(id)
2434
);
25-
CREATE INDEX IF NOT EXISTS idx_suggestions_type_isexpense ON Suggestions(type_id, is_expense);
35+
CREATE INDEX IF NOT EXISTS idx_suggestions__is_expense ON Suggestions(is_expense);
36+
CREATE INDEX IF NOT EXISTS idx_suggestions__type_id ON Suggestions(type_id);
37+
2638
CREATE TRIGGER IF NOT EXISTS prevent_update_Suggestions
2739
BEFORE UPDATE OF created_at ON Suggestions
2840
BEGIN
@@ -31,54 +43,60 @@ BEGIN
3143
'Update of created_at is not allowed in Suggestions'
3244
);
3345
END;
34-
-- Insert fixed suggestions
46+
-- Insert fixed expense suggestions
3547
INSERT INTO Suggestions(name, type_id, is_expense)
36-
SELECT 'rent', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
48+
SELECT 'rent_or_mortgage', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
3749

3850
INSERT INTO Suggestions(name, type_id, is_expense)
39-
SELECT 'electricity', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
51+
SELECT 'property_taxes', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
4052

4153
INSERT INTO Suggestions(name, type_id, is_expense)
42-
SELECT 'internet', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
54+
SELECT 'health_insurance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
4355

4456
INSERT INTO Suggestions(name, type_id, is_expense)
45-
SELECT 'cell_phone_bill', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
57+
SELECT 'car_insurance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
4658

4759
INSERT INTO Suggestions(name, type_id, is_expense)
48-
SELECT 'tv_streaming', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
60+
SELECT 'public_transport', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
4961

5062
INSERT INTO Suggestions(name, type_id, is_expense)
51-
SELECT 'music_streaming', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
63+
SELECT 'home_insurance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
5264

5365
INSERT INTO Suggestions(name, type_id, is_expense)
54-
SELECT 'health_insurance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
66+
SELECT 'loan_payments', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
5567

5668
INSERT INTO Suggestions(name, type_id, is_expense)
57-
SELECT 'insurance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
69+
SELECT 'internet_subscription', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
5870

5971
INSERT INTO Suggestions(name, type_id, is_expense)
60-
SELECT 'mortgage', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
72+
SELECT 'cell_phone_plan', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
6173

6274
INSERT INTO Suggestions(name, type_id, is_expense)
63-
SELECT 'property_taxes', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
75+
SELECT 'cable_or_streaming_services', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
76+
77+
INSERT INTO Suggestions(name, type_id, is_expense)
78+
SELECT 'music_streaming_services', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
6479

6580
INSERT INTO Suggestions(name, type_id, is_expense)
66-
SELECT 'salaries', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
81+
SELECT 'magazine_or_newspaper_subscriptions', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
6782

6883
INSERT INTO Suggestions(name, type_id, is_expense)
6984
SELECT 'gym', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
7085

7186
INSERT INTO Suggestions(name, type_id, is_expense)
72-
SELECT 'personal_education', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
87+
SELECT 'association_fees', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
7388

7489
INSERT INTO Suggestions(name, type_id, is_expense)
75-
SELECT 'children_school', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
90+
SELECT 'private_retirement_plans', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
91+
92+
INSERT INTO Suggestions(name, type_id, is_expense)
93+
SELECT 'personal_education', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
7694

7795
INSERT INTO Suggestions(name, type_id, is_expense)
78-
SELECT 'car_maintenance', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
96+
SELECT 'children_school', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
7997

8098
INSERT INTO Suggestions(name, type_id, is_expense)
81-
SELECT 'transport', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
99+
SELECT 'childcare', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'fixed';
82100

83101
-- Insert variable suggestions
84102
INSERT INTO Suggestions(name, type_id, is_expense)
@@ -88,43 +106,40 @@ INSERT INTO Suggestions(name, type_id, is_expense)
88106
SELECT 'dining_out', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
89107

90108
INSERT INTO Suggestions(name, type_id, is_expense)
91-
SELECT 'entertainment', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
92-
93-
INSERT INTO Suggestions(name, type_id, is_expense)
94-
SELECT 'clothing', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
109+
SELECT 'food_delivery', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
95110

96111
INSERT INTO Suggestions(name, type_id, is_expense)
97-
SELECT 'transportation', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
112+
SELECT 'weekday_lunch', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
98113

99114
INSERT INTO Suggestions(name, type_id, is_expense)
100-
SELECT 'fuel', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
115+
SELECT 'coffee_snacks', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
101116

102117
INSERT INTO Suggestions(name, type_id, is_expense)
103-
SELECT 'healthcare', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
118+
SELECT 'transportation_fuel', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
104119

105120
INSERT INTO Suggestions(name, type_id, is_expense)
106-
SELECT 'personal_care', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
121+
SELECT 'public_transport_tickets', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
107122

108123
INSERT INTO Suggestions(name, type_id, is_expense)
109-
SELECT 'subscriptions', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
124+
SELECT 'cinema', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
110125

111126
INSERT INTO Suggestions(name, type_id, is_expense)
112-
SELECT 'education', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
127+
SELECT 'sports_tickets', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
113128

114129
INSERT INTO Suggestions(name, type_id, is_expense)
115-
SELECT 'gifts', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
130+
SELECT 'eletronic_games', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
116131

117132
INSERT INTO Suggestions(name, type_id, is_expense)
118-
SELECT 'vacations', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
133+
SELECT 'bars', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
119134

120135
INSERT INTO Suggestions(name, type_id, is_expense)
121-
SELECT 'hobbies', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
136+
SELECT 'night_clubs', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
122137

123138
INSERT INTO Suggestions(name, type_id, is_expense)
124-
SELECT 'pets', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
139+
SELECT 'household_supplies', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
125140

126141
INSERT INTO Suggestions(name, type_id, is_expense)
127-
SELECT 'repairs', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
142+
SELECT 'fitness_recreation', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'variable';
128143

129144
-- Insert fixed incomes
130145
INSERT INTO Suggestions(name, type_id, is_expense)
@@ -136,6 +151,7 @@ SELECT 'pension', types.id, 0 FROM CategoryTypes AS types WHERE types.descriptio
136151
INSERT INTO Suggestions(name, type_id, is_expense)
137152
SELECT 'rental_income', types.id, 0 FROM CategoryTypes AS types WHERE types.description = 'fixed';
138153

154+
-- Insert seasonal suggestions
139155
INSERT INTO Suggestions(name, type_id, is_expense)
140156
SELECT 'holiday_gifts', types.id, 1 FROM CategoryTypes AS types WHERE types.description = 'seasonal';
141157

@@ -174,7 +190,8 @@ END;
174190

175191
/**
176192
* A category is a group of balance movements.
177-
* This is the main table of the database, storing the categories of the user and helping to organize the balance movements.
193+
* This is the main table of the database, storing the categories of the user and helping to organize
194+
* the balance movements.
178195
*/
179196
CREATE TABLE IF NOT EXISTS Categories(
180197
id INTEGER PRIMARY KEY,
@@ -187,7 +204,10 @@ CREATE TABLE IF NOT EXISTS Categories(
187204
FOREIGN KEY(linked_suggestion_id) REFERENCES Suggestions(id)
188205
);
189206
CREATE INDEX IF NOT EXISTS idx_categories__description ON Categories(name);
190-
CREATE INDEX IF NOT EXISTS idx_categories_amount ON Categories(amount DESC);
207+
CREATE INDEX IF NOT EXISTS idx_categories__is_expense ON Categories(is_expense);
208+
CREATE INDEX IF NOT EXISTS idx_categories__linked_suggestion_id ON Categories(
209+
linked_suggestion_id
210+
);
191211

192212
CREATE TRIGGER IF NOT EXISTS prevent_update_Categories
193213
BEFORE UPDATE OF created_at ON Categories
@@ -208,7 +228,8 @@ CREATE TABLE IF NOT EXISTS FixedRecurrences(
208228
FOREIGN KEY(category_id) REFERENCES Categories(id) ON DELETE CASCADE,
209229
UNIQUE(category_id, day_of_month)
210230
);
211-
CREATE UNIQUE INDEX IF NOT EXISTS idx_fixed_recurrent_category_day_of_month ON FixedRecurrences(category_id, day_of_month);
231+
CREATE UNIQUE INDEX IF NOT EXISTS idx_fixed_recurrece__category_id_X_day_of_month
232+
ON FixedRecurrences(category_id, day_of_month);
212233

213234
/**
214235
* A variable balance movement is a balance movement that happens every week.
@@ -220,10 +241,8 @@ CREATE TABLE IF NOT EXISTS VariableRecurrences(
220241
FOREIGN KEY (category_id) REFERENCES Categories(id) ON DELETE CASCADE,
221242
UNIQUE(category_id, day_of_week)
222243
);
223-
CREATE UNIQUE INDEX IF NOT EXISTS idx_variable_recurrence_dayofweek ON VariableRecurrences(
224-
category_id,
225-
day_of_week
226-
);
244+
CREATE UNIQUE INDEX IF NOT EXISTS idx_variable_recurrence__category_id_X_day_of_week
245+
ON VariableRecurrences(category_id, day_of_week);
227246

228247
/**
229248
* A seasonal balance movement is a balance movement that happens every year.
@@ -236,11 +255,8 @@ CREATE TABLE IF NOT EXISTS SeasonalRecurrences(
236255
FOREIGN KEY(category_id) REFERENCES Categories(id) ON DELETE CASCADE,
237256
UNIQUE(category_id, month, day)
238257
);
239-
CREATE UNIQUE INDEX IF NOT EXISTS idx_seasonal_balance_movement_monthday ON SeasonalRecurrences(
240-
category_id,
241-
month,
242-
day
243-
);
258+
CREATE UNIQUE INDEX IF NOT EXISTS idx_seasonal_recurrences__category_id_X_month_X_day
259+
ON SeasonalRecurrences(category_id, month, day);
244260

245261
CREATE TRIGGER IF NOT EXISTS ensure_reference_id_in_one_table_FixedRecurrences
246262
BEFORE INSERT ON FixedRecurrences

Diff for: features/finances/impl/src/main/kotlin/br/com/mob1st/features/finances/impl/data/repositories/suggestions/SelectSuggestionsMapper.kt

+83-16
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import br.com.mob1st.features.finances.impl.data.repositories.categories.SelectC
77
import br.com.mob1st.features.finances.impl.domain.entities.Category
88
import br.com.mob1st.features.finances.impl.domain.entities.CategorySuggestion
99
import br.com.mob1st.features.finances.publicapi.domain.entities.CategoryType
10+
import timber.log.Timber
1011

1112
/**
1213
* Maps a list of [SelectSuggestions] provided by the database to a list of [CategorySuggestion] domain entity.
13-
* It uses the [SelectCategoryViewsMapper] to map the linked categories. For that it's important to use the same contract
14-
* in the query used to get the category data.
14+
* It uses the [SelectCategoryViewsMapper] to map the linked categories. For that it's important to use the same
15+
* contract in the query used to get the category data.
1516
* @property listCategoryViewMapper The mapper for the category data.
1617
*/
1718
internal class SelectSuggestionsMapper(
@@ -24,22 +25,80 @@ internal class SelectSuggestionsMapper(
2425
* @return The list of [CategorySuggestion] domain entities.
2526
* @see SelectCategoryViewsMapper
2627
*/
27-
fun map(type: CategoryType, query: List<SelectSuggestions>): List<CategorySuggestion> {
28+
fun map(
29+
type: CategoryType,
30+
query: List<SelectSuggestions>,
31+
): List<CategorySuggestion> {
2832
return query.groupBy { it.sug_id }.mapNotNull { entry ->
2933
val first = entry.value.first()
30-
val name = first.sug_name.asSuggestionName() ?: return@mapNotNull null
34+
val name = first.sug_name.asSuggestionName()
35+
if (name == null) {
36+
Timber.w("Unknown suggestion name: $this. Suggestion will be discarded from the list.")
37+
return@mapNotNull null
38+
}
39+
val linkedCategory = runCatching {
40+
listCategoryViewMapper.map(type, entry)
41+
}.onFailure {
42+
Timber.e(it, "Error mapping category view ${first.cat_id} from suggestion ${first.sug_id}.")
43+
return@mapNotNull null
44+
}.getOrNull()
3145
CategorySuggestion(
3246
id = RowId(first.sug_id),
3347
name = name,
34-
linkedCategory = listCategoryViewMapper.map(type, entry),
48+
linkedCategory = linkedCategory,
3549
)
3650
}
3751
}
3852
}
3953

54+
@Suppress("CyclomaticComplexMethod")
4055
private fun String.asSuggestionName(): CategorySuggestion.Name? {
4156
return when (this) {
42-
"rent" -> CategorySuggestion.Name.Rent
57+
"rent_or_mortgage" -> CategorySuggestion.Name.RentOrMortgage
58+
"property_taxes" -> CategorySuggestion.Name.PropertyTaxes
59+
"health_insurance" -> CategorySuggestion.Name.HealthInsurance
60+
"car_insurance" -> CategorySuggestion.Name.CarInsurance
61+
"public_transport" -> CategorySuggestion.Name.PublicTransport
62+
"home_insurance" -> CategorySuggestion.Name.HomeInsurance
63+
"loan_payments" -> CategorySuggestion.Name.LoanPayments
64+
"internet_subscription" -> CategorySuggestion.Name.InternetSubscription
65+
"cell_phone_plan" -> CategorySuggestion.Name.CellPhonePlan
66+
"cable_or_streaming_services" -> CategorySuggestion.Name.CableOrStreamingServices
67+
"music_streaming_services" -> CategorySuggestion.Name.MusicStreamingServices
68+
"magazine_or_newspaper_subscriptions" -> CategorySuggestion.Name.MagazineOrNewspaperSubscriptions
69+
"gym" -> CategorySuggestion.Name.Gym
70+
"association_fees" -> CategorySuggestion.Name.AssociationFees
71+
"private_retirement_plans" -> CategorySuggestion.Name.PrivateRetirementPlans
72+
"personal_education" -> CategorySuggestion.Name.PersonalEducation
73+
"children_school" -> CategorySuggestion.Name.ChildrenSchool
74+
"childcare" -> CategorySuggestion.Name.Childcare
75+
"groceries" -> CategorySuggestion.Name.Groceries
76+
"dining_out" -> CategorySuggestion.Name.DiningOut
77+
"food_delivery" -> CategorySuggestion.Name.FoodDelivery
78+
"weekday_lunch" -> CategorySuggestion.Name.WeekdayLunch
79+
"coffee_snacks" -> CategorySuggestion.Name.CoffeeSnacks
80+
"transportation_fuel" -> CategorySuggestion.Name.TransportationFuel
81+
"public_transport_tickets" -> CategorySuggestion.Name.PublicTransportTickets
82+
"cinema" -> CategorySuggestion.Name.Cinema
83+
"sports_tickets" -> CategorySuggestion.Name.SportsTickets
84+
"electronic_games" -> CategorySuggestion.Name.ElectronicGames
85+
"bars" -> CategorySuggestion.Name.Bars
86+
"night_clubs" -> CategorySuggestion.Name.NightClubs
87+
"household_supplies" -> CategorySuggestion.Name.HouseholdSupplies
88+
"fitness_recreation" -> CategorySuggestion.Name.FitnessRecreation
89+
"holiday_gifts" -> CategorySuggestion.Name.HolidayGifts
90+
"vacation_travel" -> CategorySuggestion.Name.VacationTravel
91+
"back_to_school_supplies" -> CategorySuggestion.Name.BackToSchoolSupplies
92+
"winter_clothing" -> CategorySuggestion.Name.WinterClothing
93+
"summer_activities" -> CategorySuggestion.Name.SummerActivities
94+
"garden_supplies" -> CategorySuggestion.Name.GardenSupplies
95+
"home_heating" -> CategorySuggestion.Name.HomeHeating
96+
"holiday_decorations" -> CategorySuggestion.Name.HolidayDecorations
97+
"tax_preparation_fees" -> CategorySuggestion.Name.TaxPreparationFees
98+
"spring_cleaning" -> CategorySuggestion.Name.SpringCleaning
99+
"salary" -> CategorySuggestion.Name.Salary
100+
"pension" -> CategorySuggestion.Name.Pension
101+
"rental_income" -> CategorySuggestion.Name.RentalIncome
43102
else -> null
44103
}
45104
}
@@ -48,22 +107,30 @@ private fun SelectCategoryViewsMapper.map(
48107
type: CategoryType,
49108
entry: Map.Entry<Long, List<SelectSuggestions>>,
50109
): Category? {
51-
val views = entry.value.mapNotNull { it.asCategoryView() }
52-
// the firstOrNull only works if the contract of the relation between suggestion and category keep 1x1.
53-
// if it changes this logic also might change
54-
return map(type, views).firstOrNull()
110+
val views = entry.value.mapNotNull {
111+
it.asCategoryView()
112+
}
113+
val categories = map(type, views)
114+
if (categories.size > 1) {
115+
// the relation contract between suggestion and category should be 1:1
116+
// it can be ignored, but it's important to log it.
117+
Timber.w("More than one category was mapped for a single suggestion.")
118+
}
119+
return categories.firstOrNull()
55120
}
56121

57122
private fun SelectSuggestions.asCategoryView(): Category_view? {
58-
return cat_id?.let {
59-
check(cat_linked_suggestion_id == sug_id)
60-
// manually creates the SqlDelight generated class to reuse the mapper
123+
return cat_id?.let { id ->
124+
check(cat_linked_suggestion_id == sug_id) {
125+
"The category's linked suggestion id must be the same as the suggestion id."
126+
}
127+
// manually creates the SqlDelight generated class to reuse the SelectCategoryViewsMapper method
61128
Category_view(
62-
cat_id = cat_id,
63-
cat_name = sug_name,
129+
cat_id = id,
130+
cat_name = checkNotNull(cat_name),
64131
cat_is_expense = checkNotNull(cat_is_expense),
65132
cat_amount = checkNotNull(cat_amount),
66-
cat_created_at = checkNotNull(cat_created_at),
133+
cat_created_at = cat_created_at.orEmpty(),
67134
cat_linked_suggestion_id = cat_linked_suggestion_id,
68135
frc_day_of_month = frc_day_of_month,
69136
vrc_day_of_week = vrc_day_of_week,

0 commit comments

Comments
 (0)