Skip to content

Commit 58e9221

Browse files
authored
feat: Improve multiple income tax calculation response (#166)
* feat: Improve multiple income tax calculation response
1 parent 85164ba commit 58e9221

File tree

2 files changed

+130
-52
lines changed

2 files changed

+130
-52
lines changed

internal/service/service.go

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package service
44
import (
55
"context"
66
"fmt"
7+
"strings"
78
"time"
89

910
"github.com/obalunenko/georgia-tax-calculator/internal/converter"
@@ -47,21 +48,49 @@ func (d DateRequest) String() string {
4748

4849
// CalculateResponse model.
4950
type CalculateResponse struct {
50-
TaxRate taxes.TaxRate
51-
YearIncome models.Money
52-
IncomeConverted models.Money
53-
Tax models.Money
51+
TaxRate taxes.TaxRate
52+
YearIncome models.Money
53+
Incomes []ConvertResponse
54+
TotalIncomeConverted models.Money
55+
Tax models.Money
5456
}
5557

5658
func (c CalculateResponse) String() string {
57-
var resp string
59+
var resp strings.Builder
5860

59-
resp += fmt.Sprintf("Tax Rate: %s\n", c.TaxRate.String())
60-
resp += fmt.Sprintf("Year Income: %s\n", c.YearIncome.String())
61-
resp += fmt.Sprintf("Converted: %s\n", c.IncomeConverted.String())
62-
resp += fmt.Sprintf("Taxes: %s", c.Tax.String())
61+
resp.WriteString(fmt.Sprintf("Tax Rate: %s\n", c.TaxRate.String()))
6362

64-
return resp
63+
resp.WriteString(fmt.Sprintf("Year Income: %s\n", c.YearIncome.String()))
64+
65+
if len(c.Incomes) != 0 {
66+
resp.WriteString("Incomes:\n")
67+
68+
for i := range c.Incomes {
69+
inc := c.Incomes[i]
70+
71+
raw := inc.String()
72+
73+
if strings.TrimSpace(raw) == "" {
74+
continue
75+
}
76+
77+
resp.WriteString(fmt.Sprintf("\t- %d:\n", i+1))
78+
79+
lines := strings.Split(raw, "\n")
80+
81+
for _, line := range lines {
82+
if strings.TrimSpace(line) != "" {
83+
resp.WriteString(fmt.Sprintf("\t\t%s\n", line))
84+
}
85+
}
86+
}
87+
}
88+
89+
resp.WriteString(fmt.Sprintf("Total Income Converted: %s\n", c.TotalIncomeConverted.String()))
90+
91+
resp.WriteString(fmt.Sprintf("Taxes: %s", c.Tax.String()))
92+
93+
return resp.String()
6594
}
6695

6796
// ConvertRequest model.
@@ -144,7 +173,7 @@ func (s service) Convert(ctx context.Context, p ConvertRequest) (*ConvertRespons
144173
return nil, err
145174
}
146175

147-
date := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
176+
date := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
148177

149178
mv, err := moneyutils.Parse(p.Amount)
150179
if err != nil {
@@ -194,6 +223,8 @@ func (s service) Calculate(ctx context.Context, req CalculateRequest) (*Calculat
194223
txs float64
195224
)
196225

226+
incomes := make([]ConvertResponse, 0, len(req.Income))
227+
197228
for _, p := range req.Income {
198229
r := ConvertRequest{
199230
DateRequest: DateRequest{
@@ -211,9 +242,16 @@ func (s service) Calculate(ctx context.Context, req CalculateRequest) (*Calculat
211242
return nil, fmt.Errorf("failed to convert income: %w", err)
212243
}
213244

245+
incomes = append(incomes, ConvertResponse{
246+
Date: convertResp.Date,
247+
Amount: convertResp.Amount,
248+
Converted: convertResp.Converted,
249+
Rate: convertResp.Rate,
250+
})
251+
214252
tax, err := taxes.Calc(convertResp.Converted, tt)
215253
if err != nil {
216-
return nil, fmt.Errorf("failed to Calculate taxes: %w", err)
254+
return nil, fmt.Errorf("failed to calculate taxes: %w", err)
217255
}
218256

219257
yi = moneyutils.Add(yi, convertResp.Converted.Amount)
@@ -222,10 +260,11 @@ func (s service) Calculate(ctx context.Context, req CalculateRequest) (*Calculat
222260
}
223261

224262
return &CalculateResponse{
225-
TaxRate: tr,
226-
YearIncome: models.NewMoney(yi, currencies.GEL),
227-
IncomeConverted: models.NewMoney(inc, currencies.GEL),
228-
Tax: models.NewMoney(txs, currencies.GEL),
263+
TaxRate: tr,
264+
YearIncome: models.NewMoney(yi, currencies.GEL),
265+
Incomes: incomes,
266+
TotalIncomeConverted: models.NewMoney(inc, currencies.GEL),
267+
Tax: models.NewMoney(txs, currencies.GEL),
229268
}, nil
230269
}
231270

internal/service/service_test.go

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func Test_service_Convert(t *testing.T) {
7070
},
7171
},
7272
want: &ConvertResponse{
73-
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.Local),
73+
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.UTC),
7474
Amount: models.Money{
7575
Amount: 568,
7676
Currency: currencies.AED,
@@ -195,7 +195,21 @@ func Test_service_Calculate(t *testing.T) {
195195
Amount: 1067.99,
196196
Currency: currencies.GEL,
197197
},
198-
IncomeConverted: models.Money{
198+
Incomes: []ConvertResponse{
199+
{
200+
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.UTC),
201+
Amount: models.Money{
202+
Amount: 1000,
203+
Currency: currencies.EUR,
204+
},
205+
Converted: models.Money{
206+
Amount: 1000,
207+
Currency: currencies.GEL,
208+
},
209+
Rate: models.NewMoney(1, ""),
210+
},
211+
},
212+
TotalIncomeConverted: models.Money{
199213
Amount: 1000,
200214
Currency: currencies.GEL,
201215
},
@@ -247,7 +261,33 @@ func Test_service_Calculate(t *testing.T) {
247261
Amount: 1267.99,
248262
Currency: currencies.GEL,
249263
},
250-
IncomeConverted: models.Money{
264+
Incomes: []ConvertResponse{
265+
{
266+
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.UTC),
267+
Amount: models.Money{
268+
Amount: 1000,
269+
Currency: currencies.EUR,
270+
},
271+
Converted: models.Money{
272+
Amount: 1000,
273+
Currency: currencies.GEL,
274+
},
275+
Rate: models.NewMoney(1, ""),
276+
},
277+
{
278+
Date: time.Date(2023, time.June, 8, 0, 0, 0, 0, time.UTC),
279+
Amount: models.Money{
280+
Amount: 200,
281+
Currency: currencies.USD,
282+
},
283+
Converted: models.Money{
284+
Amount: 200,
285+
Currency: currencies.GEL,
286+
},
287+
Rate: models.NewMoney(1, ""),
288+
},
289+
},
290+
TotalIncomeConverted: models.Money{
251291
Amount: 1200,
252292
Currency: currencies.GEL,
253293
},
@@ -331,62 +371,61 @@ func Test_service_Calculate(t *testing.T) {
331371
}
332372

333373
func TestCalculateResponse_String(t *testing.T) {
334-
type fields struct {
335-
Date time.Time
336-
TaxRate taxes.TaxRate
337-
YearIncome models.Money
338-
Income models.Money
339-
IncomeConverted models.Money
340-
Tax models.Money
341-
}
342-
343374
tests := []struct {
344375
name string
345-
fields fields
376+
fields CalculateResponse
346377
want string
347378
}{
348379
{
349-
name: "",
350-
fields: fields{
351-
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.Local),
380+
name: "one income",
381+
fields: CalculateResponse{
352382
TaxRate: taxes.TaxRate{
353383
Type: taxes.TaxTypeEmployment,
354384
Rate: 0.2,
355385
},
356386
YearIncome: models.Money{
357-
Amount: 0,
387+
Amount: 1267.99,
358388
Currency: currencies.GEL,
359389
},
360-
Income: models.Money{
361-
Amount: 568.99,
362-
Currency: currencies.AED,
390+
Incomes: []ConvertResponse{
391+
{
392+
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.UTC),
393+
Amount: models.Money{
394+
Amount: 568.99,
395+
Currency: currencies.AED,
396+
},
397+
Converted: models.Money{
398+
Amount: 789.99,
399+
Currency: currencies.GEL,
400+
},
401+
Rate: models.NewMoney(1.39, ""),
402+
},
363403
},
364-
IncomeConverted: models.Money{
404+
TotalIncomeConverted: models.Money{
365405
Amount: 789.99,
366-
Currency: currencies.EUR,
406+
Currency: currencies.GEL,
367407
},
368408
Tax: models.Money{
369-
Amount: 99.02,
370-
Currency: currencies.AMD,
409+
Amount: 157.99,
410+
Currency: currencies.GEL,
371411
},
372412
},
373413
want: "Tax Rate: Employment 20 %\n" +
374-
"Year Income: 0 GEL\n" +
375-
"Converted: 789.99 EUR\n" +
376-
"Taxes: 99.02 AMD",
414+
"Year Income: 1267.99 GEL\n" +
415+
"Incomes:\n" +
416+
"\t- 1:\n" +
417+
"\t\tDate: 2022-12-08\n" +
418+
"\t\tAmount: 568.99 AED\n" +
419+
"\t\tConverted: 789.99 GEL\n" +
420+
"\t\tRate: 1.39\n" +
421+
"Total Income Converted: 789.99 GEL\n" +
422+
"Taxes: 157.99 GEL",
377423
},
378424
}
379425

380426
for _, tt := range tests {
381427
t.Run(tt.name, func(t *testing.T) {
382-
c := CalculateResponse{
383-
TaxRate: tt.fields.TaxRate,
384-
YearIncome: tt.fields.YearIncome,
385-
IncomeConverted: tt.fields.IncomeConverted,
386-
Tax: tt.fields.Tax,
387-
}
388-
389-
assert.Equalf(t, tt.want, c.String(), "String()")
428+
assert.Equalf(t, tt.want, tt.fields.String(), "String()")
390429
})
391430
}
392431
}
@@ -407,7 +446,7 @@ func TestConvertResponse_String(t *testing.T) {
407446
{
408447
name: "",
409448
fields: fields{
410-
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.Local),
449+
Date: time.Date(2022, time.December, 8, 0, 0, 0, 0, time.UTC),
411450
Amount: models.Money{
412451
Amount: 568.99,
413452
Currency: currencies.AED,

0 commit comments

Comments
 (0)