Skip to content

Commit

Permalink
feat: implement calculation for all provider
Browse files Browse the repository at this point in the history
  • Loading branch information
khairulharu committed Jan 26, 2024
1 parent 3dc4ade commit 128d090
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 89 deletions.
30 changes: 30 additions & 0 deletions primitive/rate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package primitive

import "errors"

type Rate struct {
PerKilogram int64
PerKilometer int64
PerCmCubic int64
KilometerPerHour int64
}

func (rate Rate) Validate() error {
if rate.PerKilogram < 0 {
return errors.New("rate in kilogram lower than 0")
}

if rate.PerKilometer < 0 {
return errors.New("rate in kilometer lower than 0")
}

if rate.PerCmCubic < 0 {
return errors.New("rate cm cubic is lower than 0")
}

if rate.KilometerPerHour < 0 {
return errors.New("kilometer per hour lower than 0")
}

return nil
}
16 changes: 16 additions & 0 deletions primitive/rate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package primitive_test

import (
"mock-shipping-provider/primitive"
"testing"
)

func TestRateInsuficient(t *testing.T) {
var rate primitive.Rate

err := rate.Validate()

if err != nil {
t.Error("get errorrrr")
}
}
41 changes: 41 additions & 0 deletions repository/provider/anteraja.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package provider

import (
"mock-shipping-provider/primitive"
"mock-shipping-provider/repository"
)

type Anteraja struct {
Rate primitive.Rate
}

func NewAnterajaCalculation(anterAjaRate *primitive.Rate) repository.ProviderCalculation {
return &Anteraja{
Rate: primitive.Rate{
PerKilometer: anterAjaRate.PerKilometer,
PerKilogram: anterAjaRate.PerKilogram,
PerCmCubic: anterAjaRate.PerCmCubic,
KilometerPerHour: anterAjaRate.KilometerPerHour,
},
}
}

func (anterAja *Anteraja) CalculatePrice(distance float64, dimension primitive.Dimension, weight float64) int64 {
volume := dimension.Width * dimension.Height * dimension.Depth

distanceCost := distance * float64(anterAja.Rate.PerKilometer)

weightCost := weight * float64(anterAja.Rate.PerKilogram)

volumeCost := volume * float64(anterAja.Rate.PerCmCubic)

return int64(distanceCost + weightCost + volumeCost)
}

func (anterAja *Anteraja) CalculateTimeOfArrival(distance float64) int64 {
if distance < float64(anterAja.Rate.KilometerPerHour) {
return 1
}

return int64(distance / float64(anterAja.Rate.KilometerPerHour))
}
90 changes: 90 additions & 0 deletions repository/provider/anteraja_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package provider_test

import (
"mock-shipping-provider/primitive"
"mock-shipping-provider/repository/provider"
"reflect"
"testing"
)

func newRateAnterAja() primitive.Rate {
return primitive.Rate{
PerKilogram: 700,
PerKilometer: 500,
PerCmCubic: 400,
KilometerPerHour: 60,
}
}

func createAnterAjaPrice(t *testing.T, distance float64, dimension primitive.Dimension, weight float64) int64 {
anterAjaRate := newRateAnterAja()

AnterAja := provider.NewAnterajaCalculation(&anterAjaRate)

result := AnterAja.CalculatePrice(distance, dimension, weight)

return result
}

func createAnterAjaTimeArrival(t *testing.T, distance float64) int64 {
anterAjaRate := newRateAnterAja()

AnterAja := provider.NewAnterajaCalculation(&anterAjaRate)

result := AnterAja.CalculateTimeOfArrival(distance)

return result
}

func TestAnterAjaCalculation(t *testing.T) {
anterAjaRate := newRateAnterAja()

AnterAja := provider.NewAnterajaCalculation(&anterAjaRate)

testCases := []struct {
distance float64
dimension primitive.Dimension
weight float64
}{
{distance: 3400},
{dimension: primitive.Dimension{
Height: 40,
Depth: 50,
Width: 9,
}},
{weight: 2},
}

for _, testCase := range testCases {
t.Run("calculate the price", func(t *testing.T) {
result := AnterAja.CalculatePrice(testCase.distance, testCase.dimension, testCase.weight)

expectedPrice := createAnterAjaPrice(t, testCase.distance, testCase.dimension, testCase.weight)

if reflect.DeepEqual(result, expectedPrice) == false {
t.Errorf("get %v and expected %v", result, expectedPrice)
}
})
}

for _, testCase := range testCases {
t.Run("calculate time an arrival", func(t *testing.T) {
result := AnterAja.CalculateTimeOfArrival(testCase.distance)

expectedTime := createAnterAjaTimeArrival(t, testCase.distance)

if result != expectedTime {
t.Errorf("error mean code err or paramter msiign argument get %v and expected %v", result, expectedTime)
}

})
}

t.Run("when distance return an hour", func(t *testing.T) {
result := AnterAja.CalculateTimeOfArrival(30)

if result != 1 {
t.Errorf("error time is must one hour get %v", result)
}
})
}
27 changes: 13 additions & 14 deletions repository/provider/jne.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,37 @@ import (
)

type JNE struct {
RatePerKilogram int64
RatePerKilometer int64
RatePerCmCubic int64
KilometerPerHour int64
Rate primitive.Rate
}

func NewJneCalculation() repository.ProviderCalculation {
func NewJneCalculation(jneRate *primitive.Rate) repository.ProviderCalculation {
return &JNE{
RatePerKilogram: 3120,
RatePerKilometer: 4150,
RatePerCmCubic: 1245,
KilometerPerHour: 60,
Rate: primitive.Rate{
PerKilogram: jneRate.PerKilogram,
PerKilometer: jneRate.PerKilometer,
PerCmCubic: jneRate.PerCmCubic,
KilometerPerHour: jneRate.KilometerPerHour,
},
}
}

func (jne *JNE) CalculatePrice(distance float64, dimension primitive.Dimension, weight float64) int64 {

volume := dimension.Width * dimension.Height * dimension.Depth

distanceCost := distance * float64(jne.RatePerKilometer)
distanceCost := distance * float64(jne.Rate.PerKilometer)

weightCost := weight * float64(jne.RatePerKilogram)
weightCost := weight * float64(jne.Rate.PerKilogram)

volumeCost := volume * float64(jne.RatePerCmCubic)
volumeCost := volume * float64(jne.Rate.PerCmCubic)

return int64(distanceCost + weightCost + volumeCost)
}

func (jne *JNE) CalculateTimeOfArrival(distance float64) int64 {
if int64(distance) < jne.KilometerPerHour {
if int64(distance) < jne.Rate.KilometerPerHour {
return 1
}

return int64(distance) / jne.KilometerPerHour
return int64(distance) / jne.Rate.KilometerPerHour
}
37 changes: 29 additions & 8 deletions repository/provider/jne_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,29 @@ import (
"testing"
)

func createJneCalculation(t *testing.T, distance float64, dimension primitive.Dimension, weight float64) int64 {
JNE := provider.NewJneCalculation()
func newJneRate() primitive.Rate {
return primitive.Rate{
PerKilogram: 900,
PerKilometer: 800,
PerCmCubic: 600,
KilometerPerHour: 60,
}
}

func createJneCalculatePrice(t *testing.T, distance float64, dimension primitive.Dimension, weight float64) int64 {
jntRate := newJneRate()

JNE := provider.NewJneCalculation(&jntRate)

result := JNE.CalculatePrice(distance, dimension, weight)

return result
}

func createJneTimeArrival(t *testing.T, distance float64) int64 {
JNE := provider.NewJneCalculation()
jntRate := newJneRate()

JNE := provider.NewJneCalculation(&jntRate)

result := JNE.CalculateTimeOfArrival(distance)

Expand All @@ -38,13 +51,15 @@ func TestProviderJne(t *testing.T) {
{weight: 45},
}

jneRate := newJneRate()

JNE := provider.NewJneCalculation(&jneRate)

for _, testcase := range testCases {
t.Run("test calculate price", func(t *testing.T) {
JNE := provider.NewJneCalculation()

result := JNE.CalculatePrice(float64(testcase.distance), testcase.dimension, testcase.weight)

expectedPrice := createJneCalculation(t, testcase.distance, testcase.dimension, testcase.weight)
expectedPrice := createJneCalculatePrice(t, testcase.distance, testcase.dimension, testcase.weight)

if reflect.DeepEqual(result, expectedPrice) == false {
t.Errorf("must not error but get %v and %v different price meaning code error", result, expectedPrice)
Expand All @@ -53,8 +68,6 @@ func TestProviderJne(t *testing.T) {
}
for _, testCase := range testCases {
t.Run("test time of arrival", func(t *testing.T) {
JNE := provider.NewJneCalculation()

time := JNE.CalculateTimeOfArrival(testCase.distance)

expectedTime := createJneTimeArrival(t, testCase.distance)
Expand All @@ -64,4 +77,12 @@ func TestProviderJne(t *testing.T) {
}
})
}

t.Run("when distance return an hour", func(t *testing.T) {
result := JNE.CalculateTimeOfArrival(30)

if result != (1) {
t.Errorf("error time is must one hour get %v", result)
}
})
}
40 changes: 40 additions & 0 deletions repository/provider/jnt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package provider

import (
"mock-shipping-provider/primitive"
"mock-shipping-provider/repository"
)

type JNT struct {
Rate primitive.Rate
}

func NewJntCalculation(jntRate *primitive.Rate) repository.ProviderCalculation {
return &JNT{
Rate: primitive.Rate{
PerKilogram: jntRate.PerKilogram,
PerKilometer: jntRate.PerKilometer,
PerCmCubic: jntRate.PerCmCubic,
KilometerPerHour: jntRate.KilometerPerHour,
},
}
}

func (jnt *JNT) CalculatePrice(distance float64, dimension primitive.Dimension, weight float64) int64 {
volume := dimension.Width * dimension.Height * dimension.Depth

distanceCost := distance * float64(jnt.Rate.PerKilometer)

weightCost := weight * float64(jnt.Rate.PerKilogram)

volumeCost := volume * float64(jnt.Rate.PerCmCubic)

return int64(distanceCost + weightCost + volumeCost)
}

func (jnt *JNT) CalculateTimeOfArrival(distance float64) int64 {
if distance < float64(jnt.Rate.KilometerPerHour) {
return 1
}
return int64(distance) / jnt.Rate.KilometerPerHour
}
Loading

0 comments on commit 128d090

Please sign in to comment.