https://github.com/duyquang6/wager-management-be
  
  
    A best practices Go source project with unit-test and integration test, also use skaffold & helm to automate CI & CD at local to optimize development cycle  
    https://github.com/duyquang6/wager-management-be
  
golang helm mysql skaffold-example
        Last synced: 8 months ago 
        JSON representation
    
A best practices Go source project with unit-test and integration test, also use skaffold & helm to automate CI & CD at local to optimize development cycle
- Host: GitHub
- URL: https://github.com/duyquang6/wager-management-be
- Owner: duyquang6
- Created: 2021-11-30T11:36:19.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2021-12-02T15:51:40.000Z (almost 4 years ago)
- Last Synced: 2025-03-02T01:44:05.827Z (8 months ago)
- Topics: golang, helm, mysql, skaffold-example
- Language: Go
- Homepage:
- Size: 66.4 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
- 
            Metadata Files:
            - Readme: README.md
 
Awesome Lists containing this project
README
          ## Dependencies
- Docker
- Go 1.17
- MySQL 8.0.25
## Bootstrap
- Run `chmod +x start.sh` if start.sh script does not have privileged to run
- Run `./start.sh --bootstrap` quick bootstrap app (include build, start docker, migrate schema and start app), it will ready to accept connection to :8080 local
- Run `make docker.local.stop` to cleanup
## For developing
- Get tools for developing: `make install-go-tools`
- Build app docker image: run `make build.docker.image`
- Startup local docker compose: `make docker.local.start`
- Stop local docker compose: `make docker.local.stop`
- Migrate schema database: run `./start.sh --migrate`
## Automate CI CD local
Or you can use skaffold to automate that pipeline
- Install skaffold, helm latest, minikube latest version
- Run `skaffold dev --port-forward`
- Every change to source code, will trigger build, unit-test and deploy locally
## Testing & Coverage
- Run integration test(docker, go1.17 required): `./start.sh --integration`
- Run unittest: `make test.unit`
- Check coverage: `make coverage`
- Clean up report files: `make clean`
## cURL request & response format case by case
### Create Wager endpoint
**total_wager_value violate**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 0,
"odds": 120,
"selling_percentage": 40,
"selling_price": 200
}'
```
Response:
```
{
    "error": "Field:TotalWagerValue Error:This field must be larger than 0"
}
```
**odds violate**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 0,
"selling_percentage": 40,
"selling_price": 200
}'
```
Response:
```
{
    "error": "Field:Odds Error:This field must be larger than 0"
}
```
**selling_percentage violate lower bound**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 120,
"selling_percentage": 0,
"selling_price": 200
}'
```
Response:
```
{
    "error": "Field:SellingPercentage Error:This field must be larger or equal 1"
}
```
**selling_percentage violate upper bound**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 120,
"selling_percentage": 101,
"selling_price": 200
}'
```
```
{
    "error": "Field:SellingPercentage Error:This field must be lesser or equal 100"
}
```
**selling_price violate monetary format**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 120,
"selling_percentage": 101,
"selling_price": 200.255
}'
```
Response
```
{
    "error": "Field:SellingPrice Error:Invalid monetary format, only accept 2 decimal point"
}
```
**selling_price violate total_wager_value * total_wager_value**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 120,
"selling_percentage": 40,
"selling_price": 40
}'
```
Response
```
{
    "error": "field SellingPrice must be larger than TotalWagerValue * SellingPercentage"
}
```
**Success**
```
curl --location --request POST 'http://localhost:8080/wagers' \
--header 'Content-Type: application/json' \
--data-raw '{
"total_wager_value": 100,
"odds": 120,
"selling_percentage": 40,
"selling_price": 200
}'
```
Response
```
{
    "id": 6,
    "total_wager_value": 100,
    "odds": 120,
    "selling_percentage": 40,
    "selling_price": 200,
    "current_selling_price": 200,
    "percentage_sold": null,
    "amount_sold": null,
    "placed_at": 1638097000
}
```
### List wager endpoint:
Default page 1, limit 10
```
curl --location --request GET 'http://localhost:8080/wagers'
```
Response
```
[
    {
        "id": 1,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 40.01,
        "current_selling_price": 40.01,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638096517
    },
    {
        "id": 2,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638096519
    },
]
```
```
curl --location --request GET 'http://localhost:8080/wagers?page=2&limit=10’
```
Response
```[
    {
        "id": 11,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638097075
    },
    {
        "id": 12,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638097075
    },
    {
        "id": 13,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638097075
    },
    {
        "id": 14,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638097076
    },
    {
        "id": 15,
        "total_wager_value": 100,
        "odds": 120,
        "selling_percentage": 40,
        "selling_price": 200,
        "current_selling_price": 200,
        "percentage_sold": null,
        "amount_sold": null,
        "placed_at": 1638097076
    }
]
```
**Violate limit**
```
curl --location --request GET 'http://localhost:8080/wagers?page=2&limit=0'
```
Response
```
{
    "error": "Field:Limit Error:This field must be larger or equal 1"
}
```
**Violate page**
```
curl --location --request GET 'http://localhost:8080/wagers?page=2&limit=0'
```
Response
```
{
    "error": "Field:Page Error:This field must be larger or equal 1"
}
```
### Create purchase endpoint
**Violate buying price required**
```
curl --location --request POST 'http://localhost:8080/buy/1' \
    --header 'Content-Type: application/json' \
    --data-raw '{
    "buying_price": 0
    }'
```
Response
```
{
    "error": "Field:BuyingPrice Error:This field must be larger than 0"
}
```
**Violate buying price larger than current_selling_price**
```
curl --location --request POST 'http://localhost:8080/buy/1' \
    --header 'Content-Type: application/json' \
    --data-raw '{
    "buying_price": 500
    }'
```
Response
```
{
    "error": "buying price must be smaller or equal current selling price"
}
```
**Violate Wager ID not found**
```
curl --location --request POST 'http://localhost:8080/buy/1' \
--header 'Content-Type: application/json' \
--data-raw '{
    "buying_price": 500
}'
```
Response
```
{
    "error": "related wager id 1 not found"
}
```
**Success**
```
curl --location --request POST 'http://localhost:8080/buy/1' \
    --header 'Content-Type: application/json' \
    --data-raw '{
    "buying_price": 49.98
    }'
```
Response
```
{
    "id": 1,
    "buying_price": 49.98,
    "wager_id": 1,
    "bought_at": 1638099523
}
```