Skip to content

Commit a170c74

Browse files
committed
Improve documentation.
1 parent 523aeff commit a170c74

9 files changed

+289
-243
lines changed

pkg/report/file_storage.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package report
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"time"
9+
10+
"github.com/idexter/dip-visa-app/pkg/visa"
11+
)
12+
13+
// FileStorage implement FileStorage for Visa Application reports.
14+
type FileStorage struct {
15+
Dir string
16+
}
17+
18+
// NewFileStorage creates new FileStorage instance.
19+
func NewFileStorage() *FileStorage {
20+
return &FileStorage{Dir: defaultDir}
21+
}
22+
23+
// SaveApplicationReport saves Application report in to database.
24+
func (rs *FileStorage) SaveApplicationReport(vs visa.Report) error {
25+
data, err := json.Marshal(StoredReport{
26+
ID: vs.ID,
27+
ApplicationID: vs.ApplicationID,
28+
Applicant: vs.Applicant,
29+
Accepted: vs.Accepted,
30+
UpdatedAt: time.Now(),
31+
})
32+
if err != nil {
33+
return fmt.Errorf("could not marshall violations, reason %w", err)
34+
}
35+
36+
err = ioutil.WriteFile(fmt.Sprintf("%s/violations-%d.json", rs.Dir, vs.ApplicationID), data, os.FileMode(0777))
37+
if err != nil {
38+
return fmt.Errorf("could not write violations, reason %w", err)
39+
}
40+
41+
return nil
42+
}
43+
44+
// LoadApplicationReport loads Visa Application Report from database by applicationID.
45+
func (rs *FileStorage) LoadApplicationReport(applicationID int) (*visa.Report, error) {
46+
47+
b, err := ioutil.ReadFile(fmt.Sprintf("%s/violations-%d.json", rs.Dir, applicationID))
48+
if err != nil {
49+
return nil, fmt.Errorf("could not read violations, reason %w", err)
50+
}
51+
52+
sr := &StoredReport{}
53+
err = json.Unmarshal(b, &sr)
54+
if err != nil {
55+
return nil, fmt.Errorf("could not unmarshall, reason %w", err)
56+
}
57+
58+
return &visa.Report{
59+
ID: sr.ID,
60+
ApplicationID: sr.ApplicationID,
61+
Applicant: sr.Applicant,
62+
Accepted: sr.Accepted,
63+
}, nil
64+
}

pkg/report/report.go

+2-56
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
// Package report implements Visa Application Report persistent storage and
2+
// also implements default Report Printer.
13
package report
24

35
import (
4-
"encoding/json"
56
"fmt"
6-
"io/ioutil"
7-
"os"
87
"time"
98

109
"github.com/idexter/dip-visa-app/pkg/visa"
@@ -21,59 +20,6 @@ type StoredReport struct {
2120
UpdatedAt time.Time `json:"updated_at"`
2221
}
2322

24-
// FileStorage implement FileStorage for Visa Application reports.
25-
type FileStorage struct {
26-
Dir string
27-
}
28-
29-
// NewFileStorage creates new FileStorage instance.
30-
func NewFileStorage() *FileStorage {
31-
return &FileStorage{Dir: defaultDir}
32-
}
33-
34-
// SaveApplicationReport saves Application report in to database.
35-
func (rs *FileStorage) SaveApplicationReport(vs visa.Report) error {
36-
data, err := json.Marshal(StoredReport{
37-
ID: vs.ID,
38-
ApplicationID: vs.ApplicationID,
39-
Applicant: vs.Applicant,
40-
Accepted: vs.Accepted,
41-
UpdatedAt: time.Now(),
42-
})
43-
if err != nil {
44-
return fmt.Errorf("could not marshall violations, reason %w", err)
45-
}
46-
47-
err = ioutil.WriteFile(fmt.Sprintf("%s/violations-%d.json", rs.Dir, vs.ApplicationID), data, os.FileMode(0777))
48-
if err != nil {
49-
return fmt.Errorf("could not write violations, reason %w", err)
50-
}
51-
52-
return nil
53-
}
54-
55-
// LoadApplicationReport loads Visa Application Report from database by applicationID.
56-
func (rs *FileStorage) LoadApplicationReport(applicationID int) (*visa.Report, error) {
57-
58-
b, err := ioutil.ReadFile(fmt.Sprintf("%s/violations-%d.json", rs.Dir, applicationID))
59-
if err != nil {
60-
return nil, fmt.Errorf("could not read violations, reason %w", err)
61-
}
62-
63-
sr := &StoredReport{}
64-
err = json.Unmarshal(b, &sr)
65-
if err != nil {
66-
return nil, fmt.Errorf("could not unmarshall, reason %w", err)
67-
}
68-
69-
return &visa.Report{
70-
ID: sr.ID,
71-
ApplicationID: sr.ApplicationID,
72-
Applicant: sr.Applicant,
73-
Accepted: sr.Accepted,
74-
}, nil
75-
}
76-
7723
// PrintApplicationReport prints information about visa report.
7824
func PrintApplicationReport(vs visa.Report) error {
7925
fmt.Printf("\n\nID: %d\nApplicant: %s\nAccepted: %v\n\n", vs.ApplicationID, vs.Applicant, vs.Accepted)
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package storage
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"io/ioutil"
8+
9+
"github.com/idexter/dip-visa-app/pkg/visa"
10+
)
11+
12+
// FileApplicationsStorage implements file Visa Applications storage.
13+
type FileApplicationsStorage struct {
14+
Database string
15+
}
16+
17+
// NewFileApplicationsStorage creates new FileApplicationsStorage.
18+
func NewFileApplicationsStorage() *FileApplicationsStorage {
19+
return &FileApplicationsStorage{Database: defaultApplicationsDB}
20+
}
21+
22+
// GetVisaApplication gets visa application by application id.
23+
func (as *FileApplicationsStorage) GetVisaApplication(id int) (*visa.Application, error) {
24+
25+
var apps []StoredApplication
26+
b, err := ioutil.ReadFile(as.Database)
27+
if err != nil {
28+
return nil, fmt.Errorf("couldn't read applications database %w", err)
29+
}
30+
31+
if err := json.Unmarshal(b, &apps); err != nil {
32+
return nil, fmt.Errorf("couldn't unmarshal applications database %w", err)
33+
}
34+
35+
for _, v := range apps {
36+
if v.ID == id {
37+
return &visa.Application{
38+
ID: v.ID,
39+
Name: v.Name,
40+
Arrival: v.Arrival,
41+
Departure: v.Departure,
42+
Money: v.Money,
43+
}, nil
44+
}
45+
}
46+
47+
return nil, errors.New("application was not found")
48+
}

pkg/storage/file_visas_storage.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package storage
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
8+
"github.com/idexter/dip-visa-app/pkg/visa"
9+
)
10+
11+
// FileVisasStorage implements Visas database based on files.
12+
type FileVisasStorage struct {
13+
Database string
14+
}
15+
16+
// NewFileVisasStorage creates new instance for FileVisasStorage.
17+
func NewFileVisasStorage() *FileVisasStorage {
18+
return &FileVisasStorage{Database: defaultVisasDB}
19+
}
20+
21+
// GetPreviousVisas gets previous Visas for provided applicant.
22+
func (vs *FileVisasStorage) GetPreviousVisas(applicantName string) ([]visa.Visa, error) {
23+
24+
var visas map[string][]StoredVisa
25+
b, err := ioutil.ReadFile(vs.Database)
26+
if err != nil {
27+
return nil, fmt.Errorf("couldn't read visas database %w", err)
28+
}
29+
30+
if err := json.Unmarshal(b, &visas); err != nil {
31+
return nil, fmt.Errorf("couldn't unmarshal visas database %w", err)
32+
}
33+
34+
var ret = make([]visa.Visa, len(visas))
35+
36+
if v, ok := visas[applicantName]; ok {
37+
for _, current := range v {
38+
ret = append(ret, visa.Visa{
39+
From: current.From,
40+
To: current.To,
41+
Arrival: current.Departure,
42+
Departure: current.Arrival,
43+
})
44+
}
45+
}
46+
47+
return ret, nil
48+
}

pkg/storage/storage.go

+6-88
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1+
// Package storage implements persistent storages for different types of business models.
2+
// It also uses different structures to store data in filesystem.
3+
// It's not required but implemented to demonstrate layer separation.
14
package storage
25

3-
import (
4-
"encoding/json"
5-
"errors"
6-
"fmt"
7-
"io/ioutil"
8-
"time"
6+
import "time"
97

10-
"github.com/idexter/dip-visa-app/pkg/visa"
11-
)
8+
const defaultApplicationsDB = "data/applications.json"
9+
const defaultVisasDB = "data/visas.json"
1210

1311
// StoredApplication describes Visa Application stored in Database.
1412
type StoredApplication struct {
@@ -19,90 +17,10 @@ type StoredApplication struct {
1917
Money float64 `json:"money"`
2018
}
2119

22-
const defaultApplicationsDB = "data/applications.json"
23-
const defaultVisasDB = "data/visas.json"
24-
25-
// FileApplicationsStorage implements file Visa Applications storage.
26-
type FileApplicationsStorage struct {
27-
Database string
28-
}
29-
30-
// NewFileApplicationsStorage creates new FileApplicationsStorage.
31-
func NewFileApplicationsStorage() *FileApplicationsStorage {
32-
return &FileApplicationsStorage{Database: defaultApplicationsDB}
33-
}
34-
35-
// GetVisaApplication gets visa application by application id.
36-
func (as *FileApplicationsStorage) GetVisaApplication(id int) (*visa.Application, error) {
37-
38-
var apps []StoredApplication
39-
b, err := ioutil.ReadFile(as.Database)
40-
if err != nil {
41-
return nil, fmt.Errorf("couldn't read applications database %w", err)
42-
}
43-
44-
if err := json.Unmarshal(b, &apps); err != nil {
45-
return nil, fmt.Errorf("couldn't unmarshal applications database %w", err)
46-
}
47-
48-
for _, v := range apps {
49-
if v.ID == id {
50-
return &visa.Application{
51-
ID: v.ID,
52-
Name: v.Name,
53-
Arrival: v.Arrival,
54-
Departure: v.Departure,
55-
Money: v.Money,
56-
}, nil
57-
}
58-
}
59-
60-
return nil, errors.New("application was not found")
61-
}
62-
6320
// StoredVisa describes Visa stored in database.
6421
type StoredVisa struct {
6522
From time.Time `json:"from"`
6623
To time.Time `json:"to"`
6724
Arrival time.Time `json:"arrival"`
6825
Departure time.Time `json:"departure"`
6926
}
70-
71-
// FileVisasStorage implements Visas database based on files.
72-
type FileVisasStorage struct {
73-
Database string
74-
}
75-
76-
// NewFileVisasStorage creates new instance for FileVisasStorage.
77-
func NewFileVisasStorage() *FileVisasStorage {
78-
return &FileVisasStorage{Database: defaultVisasDB}
79-
}
80-
81-
// GetPreviousVisas gets previous Visas for provided applicant.
82-
func (vs *FileVisasStorage) GetPreviousVisas(applicantName string) ([]visa.Visa, error) {
83-
84-
var visas map[string][]StoredVisa
85-
b, err := ioutil.ReadFile(vs.Database)
86-
if err != nil {
87-
return nil, fmt.Errorf("couldn't read visas database %w", err)
88-
}
89-
90-
if err := json.Unmarshal(b, &visas); err != nil {
91-
return nil, fmt.Errorf("couldn't unmarshal visas database %w", err)
92-
}
93-
94-
var ret = make([]visa.Visa, len(visas))
95-
96-
if v, ok := visas[applicantName]; ok {
97-
for _, current := range v {
98-
ret = append(ret, visa.Visa{
99-
From: current.From,
100-
To: current.To,
101-
Arrival: current.Departure,
102-
Departure: current.Arrival,
103-
})
104-
}
105-
}
106-
107-
return ret, nil
108-
}

pkg/visa/models.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package visa
2+
3+
import "time"
4+
5+
// MaxTimeToStay described maximum time in hours from arrival to departure.
6+
const MaxTimeToStay = 24 * 90
7+
8+
// Application described Visa Application domain model.
9+
type Application struct {
10+
ID int
11+
Name string
12+
Arrival time.Time
13+
Departure time.Time
14+
Money float64
15+
}
16+
17+
// Visa described Visa domain model.
18+
type Visa struct {
19+
From time.Time
20+
To time.Time
21+
Arrival time.Time
22+
Departure time.Time
23+
}
24+
25+
// Report described Visa Application Report domain model.
26+
// In other words this structure described Visa Application Result.
27+
type Report struct {
28+
ID int64
29+
ApplicationID int
30+
Applicant string
31+
Accepted bool
32+
}

0 commit comments

Comments
 (0)