Skip to content

Commit

Permalink
Merge pull request #12 from LerianStudio/develop
Browse files Browse the repository at this point in the history
Develop to Main
  • Loading branch information
MartinezAvellan authored May 21, 2024
2 parents 8adf22d + e345dde commit 04fcdc1
Show file tree
Hide file tree
Showing 40 changed files with 490 additions and 142 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
## [1.1.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.0.0...v1.1.0-beta.1) (2024-05-21)


### Features

* business message :sparkles: ([c6e3c97](https://github.com/LerianStudio/midaz/commit/c6e3c979edfd578d61f88525360d771336be7da8))
* create method that search instrument by name or code to cant insert again ([8e01080](https://github.com/LerianStudio/midaz/commit/8e01080e7a44656568b66aed0bfeee6dc6b336a7))
* create new method findbyalias :sparkles: ([6d86734](https://github.com/LerianStudio/midaz/commit/6d867340c58251cb45f13c08b89124187cb1e8f7))
* create two methods, validate type and validate currency validate ISO 4217 :bug: ([09c622b](https://github.com/LerianStudio/midaz/commit/09c622b908989bd334fab244e3639f312ca1b0df))
* re run mock :sparkles: ([5cd0b70](https://github.com/LerianStudio/midaz/commit/5cd0b7002a7fb416cf7a316cb050a565afa17182))


### Bug Fixes

* (cqrs): remove delete metadata when update object with field is null ([9142901](https://github.com/LerianStudio/midaz/commit/91429013d88bbfc5183487284bde8f11a4f00297))
* adjust make lint ([dacca62](https://github.com/LerianStudio/midaz/commit/dacca62bfcb272c9d70c10de95fdd4473d3b97c2))
* adjust path mock to generate new files and add new method interface in instrument :bug: ([ecbfce9](https://github.com/LerianStudio/midaz/commit/ecbfce9b4d74dbbb72df384c1f697c9ff9a8772e))
* ajust alias to receive nil :bug: ([19844fd](https://github.com/LerianStudio/midaz/commit/19844fdc8a507ac1060812630419c495cb7bf326))
* bugs and new implements features :bug: ([8b8ee76](https://github.com/LerianStudio/midaz/commit/8b8ee76dfd7a2d7c446eab205b627ddf1c87b622))
* business message :bug: ([d3c35d7](https://github.com/LerianStudio/midaz/commit/d3c35d7da834698a2b50e59e16db519132b8786b))
* create method to validate if code has letter uppercase :bug: ([36f6c0e](https://github.com/LerianStudio/midaz/commit/36f6c0e295f24a809acde2332d4b6c3b51eefd8b))
* env default local :bug: ([b1d8f04](https://github.com/LerianStudio/midaz/commit/b1d8f0492c7cdd0bc2828b55d5f632f1c2694adc))
* golint :bug: ([481e1fe](https://github.com/LerianStudio/midaz/commit/481e1fec585ad094dafccb0b4a4e0dc4df600f7c))
* lint :bug: ([9508657](https://github.com/LerianStudio/midaz/commit/950865748e3fdcf340599c92cd3143ffc737f87f))
* lint and error message :bug: ([be8637e](https://github.com/LerianStudio/midaz/commit/be8637eb10a2ec105a6da841eae56d7ac7b0827d))
* migration alias to receive null :bug: ([9c83a9c](https://github.com/LerianStudio/midaz/commit/9c83a9ccb693031b588a67e5f42b03cc5b26a509))
* regenerate mocks :bug: ([8592e17](https://github.com/LerianStudio/midaz/commit/8592e17ab449151972af43ebc64d6dfdc9975087))
* remove and update postman :bug: ([0971d13](https://github.com/LerianStudio/midaz/commit/0971d133c9ea969d9c063e8acb7a617edb620be2))
* remove json unmarshal from status in method find and findall ([021e5af](https://github.com/LerianStudio/midaz/commit/021e5af12b8ff6791bac9c694e5de157efbad4c7))
* removes omitempty to return field even than null :bug: ([030ea64](https://github.com/LerianStudio/midaz/commit/030ea6406baf1a5ced486e4b3b2ab577f44adedf))
* **ledger:** when string ParentOrganizationID is empty set nil ([6f6c044](https://github.com/LerianStudio/midaz/commit/6f6c0449c0833c333d06aeabcfeeeee1108c0256))

## 1.0.0 (2024-05-17)


Expand Down
3 changes: 2 additions & 1 deletion common/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ func InitLocalEnvConfig() *LocalEnvConfig {

envName := GetenvOrDefault("ENV_NAME", "local")

fmt.Printf("ENVIRONMENT NAME \u001B[31m(%s)\u001B[0m\n", envName)

if envName == "local" {
fmt.Printf("ENVIRONMENT NAME \u001B[31m(%s)\u001B[0m\n", envName)
localEnvConfigOnce.Do(func() {
if err := godotenv.Load(); err != nil {
fmt.Println("Skipping .env file. Current env ", envName)
Expand Down
15 changes: 15 additions & 0 deletions common/stringUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ func IsNilOrEmpty(s *string) bool {
return s == nil || strings.TrimSpace(*s) == ""
}

// IsUpper check if string is lower
func IsUpper(s string) error {
for _, r := range s {
if unicode.IsLetter(r) && !unicode.IsUpper(r) {
return ValidationError{
Code: "0004",
Title: "Invalid Data provided.",
Message: "Invalid Data provided.",
}
}
}

return nil
}

// CamelToSnakeCase converts a given camelCase string to snake_case format.
func CamelToSnakeCase(str string) string {
var buffer bytes.Buffer
Expand Down
136 changes: 136 additions & 0 deletions common/utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package common

import (
"slices"
"strconv"

"github.com/jackc/pgx/v5/pgconn"
)

// Contains checks if an item is in a slice. This function uses type parameters to work with any slice type.
Expand Down Expand Up @@ -45,3 +48,136 @@ func CheckMetadataKeyAndValueLength(limit int, metadata map[string]any) error {

return nil
}

// ValidateCountryAddress validate if country in object address contains in countries list using ISO 3166-1 alpha-2
func ValidateCountryAddress(country string) error {
countries := []string{
"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ",
"BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW",
"BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX",
"CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM",
"FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU",
"GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE",
"JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK",
"LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP",
"MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP",
"NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA",
"RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO",
"SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR",
"TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS",
"YE", "YT", "ZA", "ZM", "ZW",
}

if !slices.Contains(countries, country) {
return ValidationError{
Code: "0032",
Title: "Invalid Country Code",
Message: "The provided country code in the 'address.country' field does not conform to the ISO-3166 alpha-2 standard. Please provide a valid alpha-2 country code.",
}
}

return nil
}

// ValidateType validate type values of currencies
func ValidateType(t string) error {
types := []string{"crypto", "currency", "commodity", "others"}

if !slices.Contains(types, t) {
return ValidationError{
Code: "0033",
Title: "Invalid Code Format",
Message: "The 'code' field must be alphanumeric, in upper case, and must contain at least one letter. Please provide a valid code.",
}
}

return nil
}

// ValidateCurrency validate if code contains in currencies list using ISO 4217
func ValidateCurrency(code string) error {
currencies := []string{
"AFN", "ALL", "DZD", "USD", "EUR", "AOA", "XCD", "XCD", "ARS", "AMD", "AWG", "AUD", "EUR", "AZN", "BSD", "BHD",
"BDT", "BBD", "BYN", "EUR", "BZD", "XOF", "BMD", "BTN", "INR", "BOB", "BOV", "USD", "BAM", "BWP", "NOK", "BRL", "USD", "BND", "BGN",
"XOF", "BIF", "CVE", "KHR", "XAF", "CAD", "KYD", "XAF", "XAF", "CLF", "CLP", "CNY", "AUD", "AUD", "COP", "COU", "KMF", "CDF", "XAF",
"NZD", "CRC", "EUR", "CUC", "CUP", "ANG", "EUR", "CZK", "XOF", "DKK", "DJF", "XCD", "DOP", "USD", "EGP", "SVC", "USD", "XAF", "ERN",
"EUR", "ETB", "EUR", "FKP", "DKK", "FJD", "EUR", "EUR", "EUR", "XPF", "EUR", "XAF", "GMD", "GEL", "EUR", "GHS", "GIP", "EUR", "DKK",
"XCD", "EUR", "USD", "GTQ", "GBP", "GNF", "XOF", "GYD", "HTG", "USD", "AUD", "EUR", "HNL", "HKD", "HUF", "ISK", "INR", "IDR", "XDR",
"IRR", "IQD", "EUR", "GBP", "ILS", "EUR", "JMD", "JPY", "GBP", "JOD", "KZT", "KES", "AUD", "KPW", "KRW", "KWD", "KGS", "LAK", "EUR",
"LBP", "LSL", "ZAR", "LRD", "LYD", "CHF", "EUR", "EUR", "MOP", "MGA", "MWK", "MYR", "MVR", "XOF", "EUR", "USD", "EUR", "MRU", "MUR",
"EUR", "XUA", "MXN", "MXV", "USD", "MDL", "EUR", "MNT", "EUR", "XCD", "MAD", "MZN", "MMK", "NAD", "ZAR", "AUD", "NPR", "EUR", "XPF",
"NZD", "NIO", "XOF", "NGN", "NZD", "AUD", "USD", "NOK", "OMR", "PKR", "USD", "PAB", "USD", "PGK", "PYG", "PEN", "PHP", "NZD", "PLN",
"EUR", "USD", "QAR", "MKD", "RON", "RUB", "RWF", "EUR", "EUR", "SHP", "XCD", "XCD", "EUR", "EUR", "XCD", "WST", "EUR", "STN", "SAR",
"XOF", "RSD", "SCR", "SLE", "SGD", "ANG", "XSU", "EUR", "EUR", "SBD", "SOS", "ZAR", "SSP", "EUR", "LKR", "SDG", "SRD", "NOK", "SZL",
"SEK", "CHE", "CHF", "CHW", "SYP", "TWD", "TJS", "TZS", "THB", "USD", "XOF", "NZD", "TOP", "TTD", "TND", "TRY", "TMT", "USD", "AUD",
"UGX", "UAH", "AED", "GBP", "USD", "USD", "USN", "UYI", "UYU", "UZS", "VUV", "VEF", "VED", "VND", "USD", "USD", "XPF", "MAD", "YER",
"ZMW", "ZWL", "EUR",
}

if !slices.Contains(currencies, code) {
return ValidationError{
Code: "0005",
Title: "Invalid Data provided.",
Message: "Invalid Data provided.",
}
}

return nil
}

// ValidatePGError validate pgError and return business error
func ValidatePGError(pgErr *pgconn.PgError, entityType string) error {
switch pgErr.ConstraintName {
case "account_parent_account_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Invalid Parent Account ID",
Code: "0029",
Message: "The specified parent account ID does not exist. Please verify the ID is correct and attempt your request again.",
}
case "account_instrument_code_fkey":
return ValidationError{
EntityType: entityType,
Title: "Instrument Code Not Found",
Code: "0034",
Message: "The provided instrument code does not exist in our records. Please verify the instrument code and try again.",
}
case "account_portfolio_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Portfolio ID Not Found",
Code: "0035",
Message: "The provided product ID does not exist in our records. Please verify the product ID and try again.",
}
case "account_product_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Product ID Not Found",
Code: "0036",
Message: "The provided product ID does not exist in our records. Please verify the product ID and try again.",
}
case "account_ledger_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Ledger ID Not Found",
Code: "0037",
Message: "The provided ledger ID does not exist in our records. Please verify the ledger ID and try again.",
}
case "account_organization_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Organization ID Not Found",
Code: "0038",
Message: "The provided organization ID does not exist in our records. Please verify the organization ID and try again.",
}
case "account_parent_organization_id_fkey":
return ValidationError{
EntityType: entityType,
Title: "Parent Organization ID Not Found",
Code: "0039",
Message: "The provided parent organization ID does not exist in our records. Please verify the parent organization ID and try again.",
}
default:
return pgErr
}
}
2 changes: 1 addition & 1 deletion components/ledger/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ENV_NAME=production
#ENV_NAME=production #default local
SERVER_PORT=3000
SERVER_ADDRESS=:${SERVER_PORT}
MONGO_HOST=mongodb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
Expand All @@ -13,6 +14,7 @@ import (
"github.com/LerianStudio/midaz/common/mpostgres"
a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgconn"
"github.com/lib/pq"
)

Expand Down Expand Up @@ -73,6 +75,11 @@ func (r *AccountPostgreSQLRepository) Create(ctx context.Context, account *a.Acc
record.DeletedAt,
)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
return nil, common.ValidatePGError(pgErr, reflect.TypeOf(a.Account{}).Name())
}

return nil, err
}

Expand Down Expand Up @@ -196,6 +203,32 @@ func (r *AccountPostgreSQLRepository) Find(ctx context.Context, organizationID,
return account.ToEntity(), nil
}

// FindByAlias find account from the database using Organization and Ledger id and Alias.
func (r *AccountPostgreSQLRepository) FindByAlias(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, alias string) (bool, error) {
db, err := r.connection.GetDB(ctx)
if err != nil {
return false, err
}

rows, err := db.QueryContext(ctx, "SELECT * FROM account WHERE organization_id = $1 AND ledger_id = $2 AND portfolio_id = $3 AND alias LIKE $4 AND deleted_at IS NULL ORDER BY created_at DESC",
organizationID, ledgerID, portfolioID, alias)
if err != nil {
return false, err
}
defer rows.Close()

if rows.Next() {
return true, common.EntityConflictError{
EntityType: reflect.TypeOf(a.Account{}).Name(),
Title: "Alias has been taken",
Code: "0020",
Message: fmt.Sprintf("The alias %s has been taken already. Please, inform another one.", alias),
}
}

return false, nil
}

// ListByIDs retrieves Accounts entities from the database using the provided IDs.
func (r *AccountPostgreSQLRepository) ListByIDs(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, ids []uuid.UUID) ([]*a.Account, error) {
db, err := r.connection.GetDB(ctx)
Expand Down Expand Up @@ -277,7 +310,7 @@ func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID
args = append(args, record.StatusDescription)
}

if account.Alias != "" {
if !common.IsNilOrEmpty(account.Alias) {
updates = append(updates, "alias = $"+strconv.Itoa(len(args)+1))
args = append(args, record.Alias)
}
Expand Down Expand Up @@ -312,6 +345,11 @@ func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID

result, err := db.ExecContext(ctx, query, args...)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
return nil, common.ValidatePGError(pgErr, reflect.TypeOf(a.Account{}).Name())
}

return nil, err
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/LerianStudio/midaz/common/mpostgres"
i "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/instrument"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgconn"
"github.com/lib/pq"
)

Expand Down Expand Up @@ -51,6 +52,11 @@ func (r *InstrumentPostgreSQLRepository) Create(ctx context.Context, instrument
record.ID, record.Name, record.Type, record.Code, record.Status, record.StatusDescription,
record.LedgerID, record.OrganizationID, record.CreatedAt, record.UpdatedAt, record.DeletedAt)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
return nil, common.ValidatePGError(pgErr, reflect.TypeOf(i.Instrument{}).Name())
}

return nil, err
}

Expand All @@ -71,6 +77,32 @@ func (r *InstrumentPostgreSQLRepository) Create(ctx context.Context, instrument
return record.ToEntity(), nil
}

// FindByNameOrCode retrieves Instrument entities by nam or code from the database.
func (r *InstrumentPostgreSQLRepository) FindByNameOrCode(ctx context.Context, organizationID, ledgerID uuid.UUID, name, code string) (bool, error) {
db, err := r.connection.GetDB(ctx)
if err != nil {
return false, err
}

rows, err := db.QueryContext(ctx, "SELECT * FROM instrument WHERE organization_id = $1 AND ledger_id = $2 AND name LIKE $3 OR code = $4 AND deleted_at IS NULL ORDER BY created_at DESC",
organizationID, ledgerID, name, code)
if err != nil {
return false, err
}
defer rows.Close()

if rows.Next() {
return true, common.EntityConflictError{
EntityType: reflect.TypeOf(i.Instrument{}).Name(),
Code: "0003",
Title: "Invalid Data provided.",
Message: "Invalid Data provided.",
}
}

return false, nil
}

// FindAll retrieves Instrument entities from the database.
func (r *InstrumentPostgreSQLRepository) FindAll(ctx context.Context, organizationID, ledgerID uuid.UUID) ([]*i.Instrument, error) {
db, err := r.connection.GetDB(ctx)
Expand Down Expand Up @@ -206,6 +238,11 @@ func (r *InstrumentPostgreSQLRepository) Update(ctx context.Context, organizatio

result, err := db.ExecContext(ctx, query, args...)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
return nil, common.ValidatePGError(pgErr, reflect.TypeOf(i.Instrument{}).Name())
}

return nil, err
}

Expand Down
Loading

0 comments on commit 04fcdc1

Please sign in to comment.