feat(expense): import expense
This commit is contained in:
1
go.mod
1
go.mod
@@ -20,6 +20,7 @@ require (
|
|||||||
github.com/go-playground/locales v0.13.0 // indirect
|
github.com/go-playground/locales v0.13.0 // indirect
|
||||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||||
|
github.com/gocarina/gocsv v0.0.0-20211020200912-82fc2684cc48 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -142,6 +142,8 @@ github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
|
|||||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gocarina/gocsv v0.0.0-20211020200912-82fc2684cc48 h1:hLeicZW4XBuaISuJPfjkprg0SP0xxsQmb31aJZ6lnIw=
|
||||||
|
github.com/gocarina/gocsv v0.0.0-20211020200912-82fc2684cc48/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package expense
|
package expense
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lib/pq"
|
|
||||||
"nos-comptes/internal/storage/dao/postgresql"
|
"nos-comptes/internal/storage/dao/postgresql"
|
||||||
|
"nos-comptes/internal/utils"
|
||||||
|
|
||||||
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
@@ -14,13 +16,16 @@ func (db *Database) CreateExpense(expense *Expense) error {
|
|||||||
INSERT INTO public.expense
|
INSERT INTO public.expense
|
||||||
(account_id, value, type_expense, expense_date, libelle)
|
(account_id, value, type_expense, expense_date, libelle)
|
||||||
VALUES
|
VALUES
|
||||||
($1, $2, $3, $4)
|
($1, $2, $3, $4, $5)
|
||||||
RETURNING id, created_at
|
RETURNING id, created_at
|
||||||
`
|
`
|
||||||
|
|
||||||
err := db.Session.
|
err := db.Session.
|
||||||
QueryRow(q, expense.AccountId, expense.Value, expense.TypeExpense, expense.ExpenseDate, expense.Libelle).
|
QueryRow(q, expense.AccountId, expense.Value, expense.TypeExpense, expense.ExpenseDate, expense.Libelle).
|
||||||
Scan(&expense.ID, &expense.CreatedAt)
|
Scan(&expense.ID, &expense.CreatedAt)
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
}
|
||||||
if errPq, ok := err.(*pq.Error); ok {
|
if errPq, ok := err.(*pq.Error); ok {
|
||||||
return postgresql.HandlePgError(errPq)
|
return postgresql.HandlePgError(errPq)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package expense
|
package expense
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/csv"
|
||||||
"net/http"
|
"net/http"
|
||||||
"nos-comptes/handler"
|
"nos-comptes/handler"
|
||||||
|
"nos-comptes/internal/account"
|
||||||
"nos-comptes/internal/storage/dao/postgresql"
|
"nos-comptes/internal/storage/dao/postgresql"
|
||||||
"nos-comptes/internal/storage/model"
|
"nos-comptes/internal/storage/model"
|
||||||
"nos-comptes/internal/storage/validators"
|
"nos-comptes/internal/storage/validators"
|
||||||
@@ -12,13 +14,48 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
service *Service
|
service *Service
|
||||||
db *Database
|
db *Database
|
||||||
|
accountService *account.Service
|
||||||
*handler.Context
|
*handler.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) ImportExpenseFromCSV(gc *gin.Context) {
|
||||||
|
}
|
||||||
func (c *Context) CreateAnExpense(gc *gin.Context) {
|
func (c *Context) CreateAnExpense(gc *gin.Context) {
|
||||||
accountID := gc.Param("accountId")
|
accountID := gc.Param("accountId")
|
||||||
|
userId := gc.Param("userId")
|
||||||
|
csvHeaderFile, err := gc.FormFile("attachment")
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
csvFile, err := csvHeaderFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
csvr := csv.NewReader(csvFile)
|
||||||
|
csvr.FieldsPerRecord = -1
|
||||||
|
csvr.Comma = ';'
|
||||||
|
filedata, err := csvr.ReadAll()
|
||||||
|
|
||||||
|
account, err := c.accountService.GetASpecificAccountForUser(userId, accountID)
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = c.service.ProcessCSVFile(filedata, account)
|
||||||
|
if err != nil {
|
||||||
|
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
var expense Expense
|
var expense Expense
|
||||||
var expenseEditable ExpenseEditable
|
var expenseEditable ExpenseEditable
|
||||||
if err := gc.BindJSON(&expenseEditable); err != nil {
|
if err := gc.BindJSON(&expenseEditable); err != nil {
|
||||||
@@ -26,7 +63,7 @@ func (c *Context) CreateAnExpense(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
expense = Expense{ExpenseEditable: expenseEditable, AccountId: accountID}
|
expense = Expense{ExpenseEditable: expenseEditable, AccountId: accountID}
|
||||||
err := c.service.CreateExpense(&expense)
|
err = c.service.CreateExpense(&expense)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.GetLogger().Info(err)
|
utils.GetLogger().Info(err)
|
||||||
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
utils.JSONErrorWithMessage(gc.Writer, model.ErrInternalServer, err.Error())
|
||||||
@@ -65,5 +102,6 @@ func (c *Context) GetAnExpenses(context *gin.Context) {
|
|||||||
func NewHandler(ctx *handler.Context, db *postgresql.DatabasePostgreSQL) *Context {
|
func NewHandler(ctx *handler.Context, db *postgresql.DatabasePostgreSQL) *Context {
|
||||||
database := NewDatabase(db)
|
database := NewDatabase(db)
|
||||||
service := NewService(database)
|
service := NewService(database)
|
||||||
return &Context{service: service, db: database, Context: ctx}
|
accountService := account.NewService(account.NewDatabase(db))
|
||||||
|
return &Context{service: service, db: database, accountService: accountService, Context: ctx}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package expense
|
package expense
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"nos-comptes/internal/account"
|
||||||
"nos-comptes/internal/storage/dao"
|
"nos-comptes/internal/storage/dao"
|
||||||
"nos-comptes/internal/storage/model"
|
"nos-comptes/internal/storage/model"
|
||||||
"nos-comptes/internal/utils"
|
"nos-comptes/internal/utils"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
@@ -35,6 +39,62 @@ func (s Service) CreateExpense(expense *Expense) error {
|
|||||||
return s.db.CreateExpense(expense)
|
return s.db.CreateExpense(expense)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Service) ProcessCSVFile(filedata [][]string, account *account.Account) error {
|
||||||
|
switch account.Provider {
|
||||||
|
case "caisse-epargne":
|
||||||
|
return s.processCaisseEpargne(filedata, account)
|
||||||
|
case "boursorama":
|
||||||
|
return s.processBoursorama(filedata, account)
|
||||||
|
case "bnp":
|
||||||
|
return s.processBnp(filedata, account)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) processCaisseEpargne(filedata [][]string, account *account.Account) error {
|
||||||
|
for _, val := range filedata[4:] {
|
||||||
|
expenseDate, err := time.Parse("02/01/06", val[0])
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
amount := val[3]
|
||||||
|
typeExpense := "D"
|
||||||
|
if amount == "" {
|
||||||
|
amount = val[4]
|
||||||
|
typeExpense = "C"
|
||||||
|
}
|
||||||
|
amountParsed, err := strconv.ParseFloat(strings.Trim(strings.ReplaceAll(amount, ",", "."), "+"), 32)
|
||||||
|
if err != nil {
|
||||||
|
utils.GetLogger().Info(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
expense := &Expense{
|
||||||
|
ExpenseEditable: ExpenseEditable{
|
||||||
|
Value: float32(amountParsed),
|
||||||
|
Libelle: val[2],
|
||||||
|
TypeExpense: typeExpense,
|
||||||
|
ExpenseDate: expenseDate,
|
||||||
|
},
|
||||||
|
AccountId: account.ID,
|
||||||
|
}
|
||||||
|
s.CreateExpense(expense)
|
||||||
|
utils.GetLogger().Info(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) processBoursorama(filedata [][]string, account *account.Account) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) processBnp(filedata [][]string, account *account.Account) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewService(database *Database) *Service {
|
func NewService(database *Database) *Service {
|
||||||
return &Service{db: database}
|
return &Service{db: database}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user