diff --git a/backend/controller/crud/crud.go b/backend/controller/crud/crud.go
index c85a9a5..ccbd99f 100644
--- a/backend/controller/crud/crud.go
+++ b/backend/controller/crud/crud.go
@@ -11,23 +11,41 @@ import (
"gitnet.fr/deblan/budget/database/manager"
"gorm.io/gorm"
"gorm.io/gorm/clause"
+
+ "github.com/go-playground/locales/fr"
+ ut "github.com/go-playground/universal-translator"
+ "github.com/go-playground/validator/v10"
+ fr_translations "github.com/go-playground/validator/v10/translations/fr"
)
type UpdateCallback func(*gorm.DB, interface{}, interface{}) (interface{}, error)
type CreateCallback func(*gorm.DB, interface{}) (interface{}, error)
type Error struct {
- Code int `json:"code"`
- Message string `json:"message"`
+ Code int `json:"code"`
+ Message string `json:"message"`
+ Errors validator.ValidationErrorsTranslations `json:"errors"`
}
type Controller struct {
- Config Configuration
+ Config Configuration
+ Validator *validator.Validate
+ Trans ut.Translator
}
func New() *Controller {
c := Controller{}
+ fr := fr.New()
+ uni := ut.New(fr, fr)
+
+ trans, _ := uni.GetTranslator("fr")
+ validate := validator.New()
+ fr_translations.RegisterDefaultTranslations(validate, trans)
+
+ c.Validator = validate
+ c.Trans = trans
+
return &c
}
@@ -155,10 +173,13 @@ func (ctrl *Controller) Create(c echo.Context, body interface{}, createCallback
})
}
- if err := c.Validate(body); err != nil {
+ if err := ctrl.Validator.Struct(body); err != nil {
+ errs := err.(validator.ValidationErrors)
+
return c.JSON(400, Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: errs.Translate(ctrl.Trans),
})
}
@@ -211,10 +232,13 @@ func (ctrl *Controller) Update(c echo.Context, body interface{}, updateCallback
})
}
- if err := c.Validate(body); err != nil {
+ if err := ctrl.Validator.Struct(body); err != nil {
+ errs := err.(validator.ValidationErrors)
+
return c.JSON(400, Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: errs.Translate(ctrl.Trans),
})
}
diff --git a/backend/controller/transaction/controller.go b/backend/controller/transaction/controller.go
index 93afafd..e1dfac2 100644
--- a/backend/controller/transaction/controller.go
+++ b/backend/controller/transaction/controller.go
@@ -5,6 +5,7 @@ import (
"io"
"strconv"
+ "github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
"gitnet.fr/deblan/budget/backend/controller/crud"
"gitnet.fr/deblan/budget/backend/message"
@@ -86,7 +87,10 @@ func (ctrl *Controller) Create(c echo.Context) error {
if err != nil {
return c.JSON(400, crud.Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: validator.ValidationErrorsTranslations{
+ "BankAccount": message.BlankBankAccount,
+ },
})
}
@@ -96,7 +100,10 @@ func (ctrl *Controller) Create(c echo.Context) error {
if count == 0 {
return c.JSON(400, crud.Error{
Code: 400,
- Message: "Invalid bank account",
+ Message: message.InvalidForm,
+ Errors: validator.ValidationErrorsTranslations{
+ "BankAccount": message.UnknownBankAccount,
+ },
})
}
@@ -104,7 +111,10 @@ func (ctrl *Controller) Create(c echo.Context) error {
if err != nil {
return c.JSON(400, crud.Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: validator.ValidationErrorsTranslations{
+ "File": message.BlankFile,
+ },
})
}
@@ -112,7 +122,10 @@ func (ctrl *Controller) Create(c echo.Context) error {
if err != nil {
return c.JSON(400, crud.Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: validator.ValidationErrorsTranslations{
+ "File": message.UnproccessableFile,
+ },
})
}
@@ -126,7 +139,10 @@ func (ctrl *Controller) Create(c echo.Context) error {
if err != nil {
return c.JSON(400, crud.Error{
Code: 400,
- Message: err.Error(),
+ Message: message.InvalidForm,
+ Errors: validator.ValidationErrorsTranslations{
+ "File": message.InvalidFile,
+ },
})
}
diff --git a/backend/message/message.go b/backend/message/message.go
index be386e1..600e379 100644
--- a/backend/message/message.go
+++ b/backend/message/message.go
@@ -1,8 +1,14 @@
package message
var (
- LoginRequired = "Login required"
- FileNotFound = "File not found"
- NotFound = "Not found"
- BadRequest = "Bad request"
+ LoginRequired = "Login required"
+ FileNotFound = "File not found"
+ NotFound = "Not found"
+ BadRequest = "Bad request"
+ InvalidForm = "Le formulaire n'est pas valide"
+ BlankBankAccount = "Le compte bancaire n'est pas renseigné"
+ UnknownBankAccount = "Le compte bancaire n'existe pas"
+ BlankFile = "Le fichier n'est pas renseigné"
+ UnproccessableFile = "Le fichier ne peut être traité"
+ InvalidFile = "Le fichier n'est pas valide"
)
diff --git a/frontend/js/lib/request.js b/frontend/js/lib/request.js
index aa509d5..e524447 100644
--- a/frontend/js/lib/request.js
+++ b/frontend/js/lib/request.js
@@ -21,4 +21,15 @@ const request = async (endpoint, options) => {
return fetch(endpoint, createRequestOptions(options)).then((response) => response.json())
}
-export { createRequestOptions, request, requestCallback }
+const requestErrorBuilder = (response) => {
+ let value = response.message
+ const errors = Object.values(response.errors ?? {})
+
+ if (errors.length) {
+ value += `
${errors.map((e) => `- ${e}
`).join('')}
`
+ }
+
+ return value
+}
+
+export { createRequestOptions, request, requestCallback, requestErrorBuilder }
diff --git a/frontend/js/models/saving_account.js b/frontend/js/models/saving_account.js
index 8ff3c9e..e3a2e46 100644
--- a/frontend/js/models/saving_account.js
+++ b/frontend/js/models/saving_account.js
@@ -56,10 +56,14 @@ const remove = async (id, callback, callbackError) => {
const fixData = (data) => {
if (data.blocked_amount) {
data.blocked_amount = parseFloat(data.blocked_amount)
+ } else {
+ data.blocked_amount = 0.0
}
if (data.released_amount) {
data.released_amount = parseFloat(data.released_amount)
+ } else {
+ data.released_amount = 0.0
}
return data
diff --git a/frontend/js/views/bank_account/CreateView.vue b/frontend/js/views/bank_account/CreateView.vue
index ed17cfd..a7b67b0 100644
--- a/frontend/js/views/bank_account/CreateView.vue
+++ b/frontend/js/views/bank_account/CreateView.vue
@@ -32,7 +32,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
@@ -51,6 +51,7 @@ import FormView from './../../components/crud/FormView.vue'
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { create, createForm } from '../../models/bank_account'
+import { requestErrorBuilder } from '../../lib/request'
const router = useRouter()
const form = ref(null)
@@ -60,7 +61,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
doBack()
}
diff --git a/frontend/js/views/bank_account/EditView.vue b/frontend/js/views/bank_account/EditView.vue
index ef24794..1a1c60f 100644
--- a/frontend/js/views/bank_account/EditView.vue
+++ b/frontend/js/views/bank_account/EditView.vue
@@ -45,7 +45,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
@@ -63,6 +63,7 @@ import FormView from './../../components/crud/FormView.vue'
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { update, remove, getOne, createForm } from '../../models/bank_account'
+import { requestErrorBuilder } from '../../lib/request'
const route = useRoute()
const router = useRouter()
@@ -95,7 +96,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
doBack()
}
diff --git a/frontend/js/views/category/CreateView.vue b/frontend/js/views/category/CreateView.vue
index f3b19f3..a6b57ac 100644
--- a/frontend/js/views/category/CreateView.vue
+++ b/frontend/js/views/category/CreateView.vue
@@ -32,7 +32,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
@@ -51,6 +51,7 @@ import FormView from './../../components/crud/FormView.vue'
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { create, createForm } from '../../models/category'
+import { requestErrorBuilder } from '../../lib/request'
const router = useRouter()
const form = ref(null)
@@ -60,7 +61,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
router.replace({ name: 'category_edit', params: { id: data.id } })
}
diff --git a/frontend/js/views/category/EditView.vue b/frontend/js/views/category/EditView.vue
index bfec4e2..5bc3f9b 100644
--- a/frontend/js/views/category/EditView.vue
+++ b/frontend/js/views/category/EditView.vue
@@ -61,7 +61,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
{
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
form.value = null
addTransaction = false
diff --git a/frontend/js/views/saving_account/CreateView.vue b/frontend/js/views/saving_account/CreateView.vue
index 1997349..482aad0 100644
--- a/frontend/js/views/saving_account/CreateView.vue
+++ b/frontend/js/views/saving_account/CreateView.vue
@@ -32,7 +32,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
@@ -51,6 +51,7 @@ import FormView from './../../components/crud/FormView.vue'
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { create, createForm } from '../../models/saving_account'
+import { requestErrorBuilder } from '../../lib/request'
const router = useRouter()
const form = ref(null)
@@ -60,7 +61,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
doBack()
}
diff --git a/frontend/js/views/saving_account/EditView.vue b/frontend/js/views/saving_account/EditView.vue
index 0f04075..9b726d5 100644
--- a/frontend/js/views/saving_account/EditView.vue
+++ b/frontend/js/views/saving_account/EditView.vue
@@ -45,7 +45,7 @@
variant="warning"
:model-value="true"
>
- {{ form.error }}
+
@@ -63,6 +63,7 @@ import FormView from './../../components/crud/FormView.vue'
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { update, remove, getOne, createForm } from '../../models/saving_account'
+import { requestErrorBuilder } from '../../lib/request'
const route = useRoute()
const router = useRouter()
@@ -96,7 +97,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
doBack()
}
diff --git a/frontend/js/views/transaction/ListView.vue b/frontend/js/views/transaction/ListView.vue
index 28d58c3..5c5d71e 100644
--- a/frontend/js/views/transaction/ListView.vue
+++ b/frontend/js/views/transaction/ListView.vue
@@ -54,8 +54,9 @@
{{ form.error }}
+ >
+
+
@@ -107,6 +108,7 @@ import { useRouter, RouterView } from 'vue-router'
import { getList, getListFields, getListFilters, createForm, importFile } from '../../models/transaction'
import { getList as getAccountList } from '../../models/bank_account'
import { getList as getCategoryList } from '../../models/category'
+import { requestErrorBuilder } from '../../lib/request'
const endpoint = `/api/transaction`
const order = ref(getStorage(`${endpoint}:order`))
@@ -183,7 +185,7 @@ const doSave = () => {
form.value.data,
(data) => {
if (data.code === 400) {
- form.value.error = data.message
+ form.value.error = requestErrorBuilder(data)
} else {
form.value = null
formShow.value = false
diff --git a/frontend/js/views/user/CreateView.vue b/frontend/js/views/user/CreateView.vue
index f6e266c..cf6f801 100644
--- a/frontend/js/views/user/CreateView.vue
+++ b/frontend/js/views/user/CreateView.vue
@@ -26,6 +26,14 @@
class="p-3"
@submit="submit"
>
+
+
+
@@ -36,13 +44,13 @@