add category property: ignore_transactions - allow to ignore transactions (dashboard)
This commit is contained in:
parent
55a83619fc
commit
079a037f5a
6 changed files with 63 additions and 23 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@
|
|||
:required="field.required"
|
||||
/>
|
||||
|
||||
<BFormSelect
|
||||
v-if="(field.widget ?? 'text') === 'select'"
|
||||
:id="'form-input-' + key"
|
||||
v-model="form.data[field.key]"
|
||||
:options="field.options"
|
||||
:required="field.required"
|
||||
/>
|
||||
|
||||
<div v-if="field.widget === 'rules'">
|
||||
<div
|
||||
v-if="form.data[field.key] !== null && form.data[field.key].length > 0"
|
||||
|
|
@ -197,7 +205,7 @@ const updateLimit = () => {
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ $light-grey: #e9ecef;
|
|||
}
|
||||
}
|
||||
|
||||
* {
|
||||
overscroll-behavior: contain !important;
|
||||
}
|
||||
|
||||
.cursor {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue