diff --git a/config.ini b/config.ini
index b2084f4..a5e62bf 100644
--- a/config.ini
+++ b/config.ini
@@ -13,8 +13,8 @@ url = "https://loolwsd.deblan.org"
path = "./_data/"
[log]
-; level = "debug"
-level = "warn"
+level = "debug"
+; level = "warn"
[database]
dsn = "root:root@tcp(127.0.0.1:3306)/budget?parseTime=true"
diff --git a/database/model/category.go b/database/model/category.go
index cd588e3..1a6adfc 100644
--- a/database/model/category.go
+++ b/database/model/category.go
@@ -5,14 +5,15 @@ import (
)
type Category struct {
- ID uint `gorm:"primaryKey" json:"id"`
- Label string `gorm:"unique;not null" json:"label"`
- Color string `gorm:"not null;default:#9eb1e7" json:"color"`
- MonthThreshold *float64 `json:"month_threshold"`
- CreatedAt time.Time `json:"created_at"`
- UpdatedAt time.Time `json:"updated_at"`
- Transactions []Transaction `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"transactions"`
- Rules []CategoryRule `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"rules"`
+ ID uint `gorm:"primaryKey" json:"id"`
+ Label string `gorm:"unique;not null" json:"label"`
+ Color string `gorm:"not null;default:#9eb1e7" json:"color"`
+ MonthThreshold *float64 `json:"month_threshold"`
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
+ Transactions []Transaction `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"transactions"`
+ Rules []CategoryRule `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"rules"`
+ IgnoreTransactions *bool `gorm:"not null;default:0" json:"ignore_transactions"`
}
func NewCategory(label, color string, rules []CategoryRule, monthThreshold *float64) *Category {
diff --git a/frontend/js/views/CategoriesView.vue b/frontend/js/views/CategoriesView.vue
index 8c92d1d..06a563f 100644
--- a/frontend/js/views/CategoriesView.vue
+++ b/frontend/js/views/CategoriesView.vue
@@ -62,6 +62,14 @@
:required="field.required"
/>
+
+
{
const doRemoveRule = (item, key) => {
let values = []
- item.forEach((v, k) => {
+ item.forEach((iv, k) => {
if (k !== key) {
values.push(v)
}
@@ -281,6 +289,8 @@ const doEdit = (item) => {
})
}
+ data.ignore_transactions = data.ignore_transactions ? 1 : 0,
+
form.value = {
action: `${endpoint}/${item.id}`,
method: 'POST',
@@ -300,6 +310,16 @@ const doEdit = (item) => {
required: false,
key: 'month_threshold',
},
+ {
+ label: 'Ignorer les transactions liées',
+ widget: 'select',
+ required: false,
+ options: [
+ {value: 0, 'text': 'Non'},
+ {value: 1, 'text': 'Oui'},
+ ],
+ key: 'ignore_transactions',
+ },
{
label: 'Couleur',
type: 'color',
@@ -319,7 +339,7 @@ const doEdit = (item) => {
}
const doAdd = () => {
- const data = {id: null, label: null, color: '#9eb1e7', rules: [], month_threshold: null}
+ const data = {id: null, label: null, color: '#9eb1e7', rules: [], month_threshold: null, ignore_transactions: 0}
form.value = {
action: `${endpoint}`,
@@ -346,6 +366,16 @@ const doAdd = () => {
required: false,
key: 'month_threshold',
},
+ {
+ label: 'Ignorer les transactions liées',
+ widget: 'select',
+ required: false,
+ options: [
+ {value: 0, 'text': 'Non'},
+ {value: 1, 'text': 'Oui'},
+ ],
+ key: 'ignore_transactions',
+ },
{
label: 'Couleur',
type: 'color',
@@ -397,6 +427,8 @@ const doSave = (e) => {
form.value.data.month_threshold = null
}
+ form.value.data.ignore_transactions = form.value.data.ignore_transactions === 1,
+
form.value.data.rules.forEach((value, key) => {
if (value.amount !== null && value.amount !== "") {
form.value.data.rules[key].amount = parseFloat(value.amount)
diff --git a/frontend/js/views/DashboardView.vue b/frontend/js/views/DashboardView.vue
index c4a2ff9..9d3b39f 100644
--- a/frontend/js/views/DashboardView.vue
+++ b/frontend/js/views/DashboardView.vue
@@ -303,7 +303,7 @@ const refresh = () => {
fetch(`/api/transaction?${new URLSearchParams(query)}`)
.then((response) => response.json())
.then((value) => {
- data.value = value.rows
+ data.value = value.rows.filter((row) => !row.category || row.category.ignore_transactions === false)
isLoading.value = false
})
}
@@ -313,7 +313,7 @@ onMounted(() => {
refresh()
- fetch('/api/category?order=label&sort=asc')
+ fetch('/api/category?order=label&sort=asc&ignore_transactions__eq=0')
.then((response) => response.json())
.then((data) => {
categories.value = data.rows
diff --git a/frontend/scss/main.scss b/frontend/scss/main.scss
index 561dcd7..78254f4 100644
--- a/frontend/scss/main.scss
+++ b/frontend/scss/main.scss
@@ -32,6 +32,10 @@ $light-grey: #e9ecef;
}
}
+* {
+ overscroll-behavior: contain !important;
+}
+
.cursor {
cursor: pointer;
}
diff --git a/web/controller/category/controller.go b/web/controller/category/controller.go
index ce1cbdd..4bd89f4 100644
--- a/web/controller/category/controller.go
+++ b/web/controller/category/controller.go
@@ -17,7 +17,7 @@ func (ctrl *Controller) Config() crud.Configuration {
Table: "categories",
Model: model.Category{},
Models: []model.Category{},
- ValidOrders: []string{"id", "label", "month_threshold"},
+ ValidOrders: []string{"id", "label", "month_threshold", "ignore_transactions"},
DefaultLimit: 100,
CreateModel: func() interface{} {
return new(model.Category)
@@ -75,10 +75,11 @@ func (ctrl *Controller) Create(c echo.Context) error {
}
type body struct {
- Label string `json:"label" form:"label" validate:"required"`
- MonthThreshold *float64 `json:"month_threshold" form:"month_threshold"`
- Color string `json:"color" form:"color" validate:"required"`
- Rules []model.CategoryRule `json:"rules" form:"rules"`
+ Label string `json:"label" form:"label" validate:"required"`
+ MonthThreshold *float64 `json:"month_threshold" form:"month_threshold"`
+ Color string `json:"color" form:"color" validate:"required"`
+ Rules []model.CategoryRule `json:"rules" form:"rules"`
+ IgnoreTransactions bool `json:"ignore_transactions" form:"ignore_transactions"`
}
return ctrl.crud.With(ctrl.Config()).Create(c, new(body), func(db *gorm.DB, v interface{}) (interface{}, error) {
@@ -97,10 +98,11 @@ func (ctrl *Controller) Update(c echo.Context) error {
}
type body struct {
- Label string `json:"label" form:"label" validate:"required"`
- Color string `json:"color" form:"color" validate:"required"`
- MonthThreshold *float64 `json:"month_threshold" form:"month_threshold"`
- Rules []model.CategoryRule `json:"rules" form:"rules"`
+ Label string `json:"label" form:"label" validate:"required"`
+ Color string `json:"color" form:"color" validate:"required"`
+ MonthThreshold *float64 `json:"month_threshold" form:"month_threshold"`
+ IgnoreTransactions bool `json:"ignore_transactions" form:"ignore_transactions"`
+ Rules []model.CategoryRule `json:"rules" form:"rules"`
}
return ctrl.crud.With(ctrl.Config()).Update(c, new(body), func(db *gorm.DB, a, b interface{}) (interface{}, error) {
@@ -113,6 +115,7 @@ func (ctrl *Controller) Update(c echo.Context) error {
dbItem.Label = update.Label
dbItem.Color = update.Color
dbItem.MonthThreshold = update.MonthThreshold
+ dbItem.IgnoreTransactions = &update.IgnoreTransactions
if dbItem.MonthThreshold == nil {
manager.Get().Db.Model(&dbItem).Update("month_threshold", gorm.Expr("NULL"))