Skip to content

Commit 65f9e9a

Browse files
Merge pull request #54 from brazzcore/feature/53-fix-critical-data-gen
[Feature/53] :: fix critical data gen
2 parents d2bc7b9 + dd349da commit 65f9e9a

File tree

27 files changed

+240
-277
lines changed

27 files changed

+240
-277
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,35 @@ func main() {
6969
// Generate a mock address
7070
address, err := mocker.NewAddress()
7171
if err != nil {
72+
// Error messages are localized where translation keys are available
7273
log.Fatal(err)
7374
}
7475
fmt.Printf("Address: %s, %d - %s, %s (%s) - %s\n", address.Street, address.Number, address.City, address.State, address.UF, address.ZIP)
7576

7677
// Generate a mock person
7778
person, err := mocker.NewPerson()
7879
if err != nil {
80+
// Error messages are localized where translation keys are available
7981
log.Fatal(err)
8082
}
8183
fmt.Printf("Person: %s %s, Gender: %s, Age: %d, CPF: %s\n", person.FirstNameMale, person.LastName, person.Gender.Identity, person.Age, person.CPF.Number)
8284

8385
// Generate a mock company
8486
company, err := mocker.NewCompany()
8587
if err != nil {
88+
// Error messages are localized where translation keys are available
8689
log.Fatal(err)
8790
}
8891
fmt.Printf("Company: %s, CNPJ: %s\n", company.BrazilianCompany.Name, company.BrazilianCompany.CNPJ)
8992
}
93+
94+
```
95+
96+
### Error Messages & Localization
97+
98+
Error messages are localized where translation keys are available. When an error occurs (e.g., invalid data, unsupported language, or generation failure), the error message will be presented in the language configured for the `Mocker` instance, if a translation exists. In some cases, fallback or hardcoded errors may occur if translation coverage is incomplete.
99+
100+
You do not need to perform any extra steps for error localization — Mocai handles this automatically for all supported languages where translation keys are present.
90101
```
91102
92103
> **Note:** Each call to a method like `NewPerson()` or `NewAddress()` generates a new mock with random data. The `Mocker` instance is immutable regarding its configuration (language, formatting, random source).

docs/localization/pt/README-PT.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,35 @@ func main() {
6767
// Gera um endereço fictício
6868
address, err := mocker.NewAddress()
6969
if err != nil {
70+
// As mensagens de erro são localizadas quando há chave de tradução disponível
7071
log.Fatal(err)
7172
}
7273
fmt.Printf("Endereço: %s, %d - %s, %s (%s) - %s\n", address.Street, address.Number, address.City, address.State, address.UF, address.ZIP)
7374

7475
// Gera uma pessoa fictícia
7576
person, err := mocker.NewPerson()
7677
if err != nil {
78+
// As mensagens de erro são localizadas quando há chave de tradução disponível
7779
log.Fatal(err)
7880
}
7981
fmt.Printf("Pessoa: %s %s, Gênero: %s, Idade: %d, CPF: %s\n", person.FirstNameMale, person.LastName, person.Gender.Identity, person.Age, person.CPF.Number)
8082

8183
// Gera uma empresa fictícia
8284
company, err := mocker.NewCompany()
8385
if err != nil {
86+
// As mensagens de erro são localizadas quando há chave de tradução disponível
8487
log.Fatal(err)
8588
}
8689
fmt.Printf("Empresa: %s, CNPJ: %s\n", company.BrazilianCompany.Name, company.BrazilianCompany.CNPJ)
8790
}
91+
92+
```
93+
94+
### Mensagens de Erro e Localização
95+
96+
As mensagens de erro são localizadas quando há chave de tradução disponível. Quando ocorre um erro (ex: dados inválidos, idioma não suportado ou falha na geração), a mensagem será apresentada no idioma configurado para a instância do `Mocker`, se houver tradução. Em alguns casos, mensagens fixas podem aparecer caso a cobertura de traduções não seja completa.
97+
98+
Não é necessário realizar nenhuma etapa extra para a localização das mensagens de erro — o Mocai faz isso automaticamente para todos os idiomas suportados onde há chave de tradução.
8899
```
89100
90101
> **Nota:** Cada chamada de método como `NewPerson()` ou `NewAddress()` gera um novo mock com dados aleatórios. A instância do `Mocker` é imutável quanto à configuração (idioma, formatação, fonte de aleatoriedade).

pkg/mocai/entities/address/errors.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,9 @@ package address
22

33
import "errors"
44

5-
// Package address defines common errors used during address generation and validation.
6-
// These errors represent specific failure scenarios and should be wrapped with additional
7-
// context when returned.
85
var (
9-
ErrNoStreets = errors.New("no data available for streets")
10-
ErrNoCities = errors.New("no data available for cities")
11-
ErrNoStates = errors.New("no data available for states")
12-
ErrNoUFs = errors.New("no data available for UFs")
13-
ErrNoZips = errors.New("no data available for zips")
6+
ErrNoStreets = errors.New("address: no streets available")
7+
ErrNoCities = errors.New("address: no cities available")
8+
ErrNoStates = errors.New("address: no states available")
9+
ErrNoZips = errors.New("address: no zip codes available")
1410
)

pkg/mocai/entities/address/generator.go

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,23 @@ func NewAddress(lang string, rnd translations.RandSource) (*Address, error) {
3232
}
3333

3434
func generateAddress(lang string, rnd translations.RandSource) (*Address, error) {
35-
streets := translations.GetList(lang, "address_street")
36-
cities := translations.GetList(lang, "address_city")
37-
states := translations.GetList(lang, "address_state")
38-
ufs := translations.GetList(lang, "address_uf")
39-
zips := translations.GetList(lang, "address_zip")
35+
supportedLang := lang
36+
if translations.GetUFMap(lang) == nil {
37+
supportedLang = "ptbr"
38+
}
39+
if rnd == nil {
40+
rnd = translations.NewSafeRandSource(translations.DefaultRandSource())
41+
}
42+
43+
streets := translations.GetList(supportedLang, "address_street")
44+
cities := translations.GetList(supportedLang, "address_city")
45+
states := translations.GetList(supportedLang, "address_state")
46+
zips := translations.GetList(supportedLang, "address_zip")
4047

4148
slicesToCheck := []SlicesToCheck{
4249
{streets, ErrNoStreets},
4350
{cities, ErrNoCities},
4451
{states, ErrNoStates},
45-
{ufs, ErrNoUFs},
4652
{zips, ErrNoZips},
4753
}
4854

@@ -57,11 +63,29 @@ func generateAddress(lang string, rnd translations.RandSource) (*Address, error)
5763
}
5864
}
5965

60-
// performs a random selection using a custom random source
66+
// select the index for state and UF in a paired manner
67+
stateIdx := rnd.Intn(len(states))
68+
state := states[stateIdx]
69+
70+
var uf string
71+
72+
ufMap := translations.GetUFMap(supportedLang)
73+
if ufMap != nil {
74+
uf = ufMap[state]
75+
}
76+
if uf == "" {
77+
ufs := translations.GetList(supportedLang, "address_uf")
78+
if len(ufs) > stateIdx {
79+
uf = ufs[stateIdx]
80+
} else if len(ufs) > 0 {
81+
uf = ufs[rnd.Intn(len(ufs))]
82+
} else {
83+
uf = ""
84+
}
85+
}
86+
6187
street := streets[rnd.Intn(len(streets))]
6288
city := cities[rnd.Intn(len(cities))]
63-
state := states[rnd.Intn(len(states))]
64-
uf := ufs[rnd.Intn(len(ufs))]
6589
zip := zips[rnd.Intn(len(zips))]
6690

6791
return &Address{

pkg/mocai/entities/certificate/countries/brazilian_certificates.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package countries
22

33
import (
44
"fmt"
5-
"math/rand"
65
"time"
76

87
"github.com/brazzcore/mocai/pkg/mocai/translations"
@@ -55,23 +54,23 @@ type BrazilianCertificates struct {
5554
}
5655

5756
func NewBrazilCertificatesCustom(lang string, isFormatted bool, rnd translations.RandSource) (*BrazilianCertificates, error) {
58-
cert, err := generateBrazilianCertificatesCustom(lang, isFormatted, rnd)
57+
cert, err := generateBrazilianCertificates(lang, isFormatted, rnd)
5958
if err != nil {
6059
return nil, err
6160
}
6261
return cert, nil
6362
}
6463

65-
func generateBrazilianCertificatesCustom(lang string, formatted bool, rnd translations.RandSource) (*BrazilianCertificates, error) {
66-
createdBirthCertificate, err := generateBirthCertificateCustom(lang, formatted, rnd)
64+
func generateBrazilianCertificates(lang string, formatted bool, rnd translations.RandSource) (*BrazilianCertificates, error) {
65+
createdBirthCertificate, err := generateBirthCertificate(lang, formatted, rnd)
6766
if err != nil {
6867
return nil, err
6968
}
70-
createdMarriageCertificate, err := generateMarriageCertificateCustom(lang, formatted, rnd)
69+
createdMarriageCertificate, err := generateMarriageCertificate(lang, formatted, rnd)
7170
if err != nil {
7271
return nil, err
7372
}
74-
createdDeathCertificate, err := generateDeathCertificateCustom(lang, formatted, rnd)
73+
createdDeathCertificate, err := generateDeathCertificate(lang, formatted, rnd)
7574
if err != nil {
7675
return nil, err
7776
}
@@ -83,37 +82,37 @@ func generateBrazilianCertificatesCustom(lang string, formatted bool, rnd transl
8382
return createdBrazilianCertificates, nil
8483
}
8584

86-
func generateCertificateCustom(rnd translations.RandSource, formatted bool, certificateType int, lang ...string) (*BaseCertificate, error) {
87-
l := "pt_br"
85+
func generateCertificate(rnd translations.RandSource, formatted bool, certificateType int, lang ...string) (*BaseCertificate, error) {
86+
l := "ptbr"
8887
if len(lang) > 0 && lang[0] != "" {
8988
l = lang[0]
9089
}
9190
if rnd == nil {
92-
rnd = rand.New(rand.NewSource(int64(rand.Int())))
91+
rnd = translations.DefaultRandSource()
9392
}
9493
vitalRecordsOffice := rnd.Intn(899999-100000+1) + 100000
9594
if vitalRecordsOffice < 0 {
96-
return nil, fmt.Errorf("%w: %s", ErrInvalidVitalRecordsOffice, translations.Get(l, "invalid_vital_records_office_number"))
95+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_vital_records_office_number"))
9796
}
9897
archiveCode := 1
9998
serviceType := 55
10099
birthYear := rnd.Intn(time.Now().Year()-2010+1) + 2010
101100
bookNumber := rnd.Intn(89999-10000+1) + 10000
102101
if bookNumber < 0 {
103-
return nil, fmt.Errorf("%w, %s", ErrInvalidBookNumber, translations.Get(l, "invalid_book_number"))
102+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_book_number"))
104103
}
105104
pageNumber := rnd.Intn(899-100+1) + 100
106105
if pageNumber < 0 {
107-
return nil, ErrInvalidPageNumber
106+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_page_number"))
108107
}
109108
termNumber := rnd.Intn(8999999-1000000+1) + 1000000
110109
if termNumber < 0 {
111-
return nil, fmt.Errorf("%w, %s", ErrInvalidTermNumber, translations.Get(l, "invalid_term_number"))
110+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_term_number"))
112111
}
113112
numberWithoutCheckDigits := fmt.Sprintf("%06d%02d%02d%04d%d%05d%03d%07d",
114113
vitalRecordsOffice, archiveCode, serviceType, birthYear, certificateType, bookNumber, pageNumber, termNumber)
115114
if len(numberWithoutCheckDigits) != 30 {
116-
return nil, fmt.Errorf("%w, %s", ErrInvalidNumberWithoutCheckDigits, translations.Get(l, "invalid_number_without_check_digits"))
115+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_number_without_check_digits"))
117116
}
118117
checkDigits := calculateCheckDigits(numberWithoutCheckDigits)
119118
certificateNumber := fmt.Sprintf("%s%02s", numberWithoutCheckDigits, checkDigits)
@@ -122,7 +121,7 @@ func generateCertificateCustom(rnd translations.RandSource, formatted bool, cert
122121
vitalRecordsOffice, archiveCode, serviceType, birthYear, certificateType, bookNumber, pageNumber, termNumber, checkDigits)
123122
}
124123
if certificateNumber == "" {
125-
return nil, fmt.Errorf("%w: %s", ErrInvalidCertificate, translations.Get(l, "invalid_certificate"))
124+
return nil, fmt.Errorf("%s", translations.Get(l, "invalid_certificate"))
126125
}
127126
createdBaseCertificate := &BaseCertificate{
128127
VitalRecordsOffice: vitalRecordsOffice,
@@ -139,8 +138,8 @@ func generateCertificateCustom(rnd translations.RandSource, formatted bool, cert
139138
return createdBaseCertificate, nil
140139
}
141140

142-
func generateBirthCertificateCustom(lang string, formatted bool, rnd translations.RandSource) (*BirthCertificate, error) {
143-
base, err := generateCertificateCustom(rnd, formatted, brazilianBirthCertificateType)
141+
func generateBirthCertificate(lang string, formatted bool, rnd translations.RandSource) (*BirthCertificate, error) {
142+
base, err := generateCertificate(rnd, formatted, brazilianBirthCertificateType, lang)
144143
if err != nil {
145144
return nil, err
146145
}
@@ -150,8 +149,8 @@ func generateBirthCertificateCustom(lang string, formatted bool, rnd translation
150149
return createdBirthCertificate, nil
151150
}
152151

153-
func generateMarriageCertificateCustom(lang string, formatted bool, rnd translations.RandSource) (*MarriageCertificate, error) {
154-
base, err := generateCertificateCustom(rnd, formatted, brazilianMarriageCertificateType)
152+
func generateMarriageCertificate(lang string, formatted bool, rnd translations.RandSource) (*MarriageCertificate, error) {
153+
base, err := generateCertificate(rnd, formatted, brazilianMarriageCertificateType, lang)
155154
if err != nil {
156155
return nil, err
157156
}
@@ -161,8 +160,8 @@ func generateMarriageCertificateCustom(lang string, formatted bool, rnd translat
161160
return createdMarriageCertificate, nil
162161
}
163162

164-
func generateDeathCertificateCustom(lang string, formatted bool, rnd translations.RandSource) (*DeathCertificate, error) {
165-
base, err := generateCertificateCustom(rnd, formatted, brazilianDeathCertificateType)
163+
func generateDeathCertificate(lang string, formatted bool, rnd translations.RandSource) (*DeathCertificate, error) {
164+
base, err := generateCertificate(rnd, formatted, brazilianDeathCertificateType, lang)
166165
if err != nil {
167166
return nil, err
168167
}

pkg/mocai/entities/certificate/countries/errors.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

pkg/mocai/entities/cnpj/errors.go

Lines changed: 0 additions & 7 deletions
This file was deleted.

pkg/mocai/entities/company/countries/brazilian_company.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package countries
22

33
import (
44
"fmt"
5-
"math/rand"
65

76
"github.com/brazzcore/mocai/pkg/mocai/entities/cnpj"
87
"github.com/brazzcore/mocai/pkg/mocai/translations"
@@ -18,10 +17,10 @@ type BrazilianCompany struct {
1817
func GenerateBrazilianCompany(lang string, formatted bool, rnd translations.RandSource) (BrazilianCompany, error) {
1918
companyNames := translations.GetList(lang, "company_name")
2019
if len(companyNames) == 0 {
21-
return BrazilianCompany{}, fmt.Errorf("%w, %s", ErrNoCompanyNamesAvailable, translations.Get(lang, "no_company_names_available"))
20+
return BrazilianCompany{}, fmt.Errorf("%s", translations.Get(lang, "no_company_names_available"))
2221
}
2322
if rnd == nil {
24-
rnd = defaultRandSource()
23+
rnd = translations.DefaultRandSource()
2524
}
2625
companyName := companyNames[rnd.Intn(len(companyNames))]
2726

@@ -30,18 +29,14 @@ func GenerateBrazilianCompany(lang string, formatted bool, rnd translations.Rand
3029
return BrazilianCompany{}, err
3130
}
3231
if companyName == "" {
33-
return BrazilianCompany{}, fmt.Errorf("%w, %s", ErrGeneratingBrazilianCompany, translations.Get(lang, "error_generating_brazilian_company"))
32+
return BrazilianCompany{}, fmt.Errorf("%s", translations.Get(lang, "error_generating_brazilian_company"))
3433
}
3534
if cnpjVal == "" {
36-
return BrazilianCompany{}, fmt.Errorf("%w, %s", ErrGeneratingCNPJ, translations.Get(lang, "invalid_cnpj"))
35+
return BrazilianCompany{}, fmt.Errorf("%s", translations.Get(lang, "invalid_cnpj"))
3736
}
3837
createdCompany := BrazilianCompany{
3938
Name: companyName,
4039
CNPJ: cnpjVal,
4140
}
4241
return createdCompany, nil
4342
}
44-
45-
func defaultRandSource() translations.RandSource {
46-
return rand.New(rand.NewSource(int64(rand.Int())))
47-
}

pkg/mocai/entities/company/countries/errors.go

Lines changed: 0 additions & 12 deletions
This file was deleted.

pkg/mocai/entities/cpf/errors.go

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)