Merge pull request 'Ajouter transactions' (#5) from feature/transactions into main
Reviewed-on: #5
This commit is contained in:
commit
e38eee6354
5 changed files with 145 additions and 8 deletions
|
@ -61,6 +61,8 @@ var apiCmd = &cobra.Command{
|
|||
|
||||
e.GET("/v2/membres/:membre_id/", handlers.GetMembre)
|
||||
|
||||
e.POST("/v2/transactions/", handlers.PostTransactions)
|
||||
|
||||
// Check bottin is ready
|
||||
|
||||
bottinHealthResponse, err := bottinConnection.GetHealth()
|
||||
|
|
58
data/data.go
58
data/data.go
|
@ -1,6 +1,7 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.agecem.com/agecem/bottin-agenda/models"
|
||||
|
@ -71,6 +72,63 @@ func (d *DataClient) Seed() (int64, error) {
|
|||
return rows, nil
|
||||
}
|
||||
|
||||
// InsertTransactions inserts a slice of Transaction into a database, returning the amount inserted and any error encountered
|
||||
func (d *DataClient) InsertTransactions(transactions []models.Transaction) (int64, error) {
|
||||
var rowsInserted int64
|
||||
|
||||
// Start transaction
|
||||
tx, err := d.DB.Beginx()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return rowsInserted, err
|
||||
}
|
||||
|
||||
for _, transaction := range transactions {
|
||||
// Check values
|
||||
if transaction.MembreID == "" {
|
||||
tx.Rollback()
|
||||
return 0, errors.New("Cannot insert transaction with no membre_id")
|
||||
}
|
||||
|
||||
result, err := tx.NamedExec("INSERT INTO transactions (membre_id, given_at, is_perpetual) VALUES (:membre_id, current_timestamp, :is_perpetual);", &transaction)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return 0, err
|
||||
}
|
||||
|
||||
rows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return 0, err
|
||||
}
|
||||
|
||||
rowsInserted += rows
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return rowsInserted, err
|
||||
}
|
||||
|
||||
return rowsInserted, nil
|
||||
}
|
||||
|
||||
func (d *DataClient) GetTransaction(membreID string, is_perpetual bool) (models.Transaction, error) {
|
||||
var transaction models.Transaction
|
||||
|
||||
//err := d.DB.NamedQuery("SELECT * FROM transactions WHERE membre_id=:membre_id AND is_perpetual=:is_perpetual LIMIT 1;"
|
||||
err := d.DB.Get(&transaction, "SELECT * FROM transactions WHERE membre_id = $1 AND is_perpetual = $2 LIMIT 1;", membreID, is_perpetual)
|
||||
if err != nil {
|
||||
return transaction, err
|
||||
}
|
||||
|
||||
if transaction.ID == "" {
|
||||
return transaction, fmt.Errorf("No transaction found")
|
||||
}
|
||||
|
||||
return transaction, nil
|
||||
}
|
||||
|
||||
/*
|
||||
// InsertMembres inserts a slice of Membre into a database, returning the amount inserted and any error encountered
|
||||
func (d *DataClient) InsertMembres(membres []models.Membre) (int64, error) {
|
||||
|
|
|
@ -36,13 +36,13 @@ services:
|
|||
restart: 'unless-stopped'
|
||||
command: ['bottin-agenda', '--config', '/etc/bottin-agenda/web.yaml', 'web']
|
||||
|
||||
# adminer:
|
||||
# image: adminer
|
||||
# restart: always
|
||||
# ports:
|
||||
# - 8088:8080
|
||||
# depends_on:
|
||||
# - db
|
||||
adminer:
|
||||
image: adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 8088:8080
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
|
77
handlers/transaction.go
Normal file
77
handlers/transaction.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"git.agecem.com/agecem/bottin-agenda/data"
|
||||
"git.agecem.com/agecem/bottin-agenda/models"
|
||||
"git.agecem.com/agecem/bottin-agenda/responses"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func PostTransactions(c echo.Context) error {
|
||||
var statusCode int = http.StatusInternalServerError
|
||||
var response responses.PostTransactionsResponse
|
||||
|
||||
var transactions []models.Transaction
|
||||
|
||||
if err := c.Bind(&transactions); err != nil {
|
||||
statusCode = http.StatusBadRequest
|
||||
response.Message = fmt.Sprintf("Error during c.Bind(): %s", err)
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
||||
|
||||
client, err := data.NewDataClientFromViper()
|
||||
if err != nil {
|
||||
response.Message = fmt.Sprintf("Error during data.NewDataClientFromViper(): %s", err)
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
||||
defer client.DB.Close()
|
||||
|
||||
if len(transactions) == 0 {
|
||||
response.Message = fmt.Sprintf("Nothing to do")
|
||||
statusCode = http.StatusOK
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
||||
|
||||
// Check for already-existing transactions
|
||||
for _, transaction := range transactions {
|
||||
transaction, err := client.GetTransaction(transaction.MembreID, transaction.IsPerpetual)
|
||||
if err != nil {
|
||||
if err.Error() != "sql: no rows in result set" {
|
||||
response.Message = fmt.Sprintf("Error during client.GetTransaction(): %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if transaction.ID != "" {
|
||||
agendaType := "non-perpetual"
|
||||
if transaction.IsPerpetual {
|
||||
agendaType = "perpetual"
|
||||
}
|
||||
|
||||
response.Message = fmt.Sprintf("Membre %s already received %s", transaction.MembreID, agendaType)
|
||||
|
||||
statusCode = http.StatusBadRequest
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
||||
}
|
||||
|
||||
rows, err := client.InsertTransactions(transactions)
|
||||
if err != nil {
|
||||
response.Message = fmt.Sprintf("Error during client.InsertTransactions(): %s", err)
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
||||
|
||||
response.Data.RowsInserted = rows
|
||||
|
||||
statusCode = http.StatusCreated
|
||||
response.Message = "Insert successful"
|
||||
|
||||
return c.JSON(statusCode, response)
|
||||
}
|
|
@ -4,7 +4,7 @@ import "time"
|
|||
|
||||
var Schema = `
|
||||
CREATE TABLE transactions (
|
||||
id PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
membre_id VARCHAR(7),
|
||||
given_at TIMESTAMP,
|
||||
is_perpetual BOOLEAN
|
||||
|
|
Loading…
Reference in a new issue