Skip to content

Commit

Permalink
Feat/provider calculation (#15)
Browse files Browse the repository at this point in the history
* implement distance calculation

* fix implement distance calculation

* fix-test implementation

* delete some code

* implement calculate and timeArrival provider jne

* fix and new provider calculation

* feat: implement provider calculation

* feat: implement calculation for all provider

* fix: how to call provider calculation in  business layer

* ref: struct name, provider to calculation

---------

Co-authored-by: Reinaldy Rafli <[email protected]>
  • Loading branch information
khairulharu and aldy505 authored Apr 27, 2024
1 parent d669ef1 commit 06c3237
Show file tree
Hide file tree
Showing 12 changed files with 654 additions and 0 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)
}
})
}
42 changes: 42 additions & 0 deletions repository/provider/jne.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package provider

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

type JNE struct {
Rate primitive.Rate
}

func NewJneCalculation(jneRate *primitive.Rate) repository.ProviderCalculation {
return &JNE{
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.Rate.PerKilometer)

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

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

return int64(distanceCost + weightCost + volumeCost)
}

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

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

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

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 {
jntRate := newJneRate()

JNE := provider.NewJneCalculation(&jntRate)

result := JNE.CalculateTimeOfArrival(distance)

return result
}

func TestProviderJne(t *testing.T) {
testCases := []struct {
distance float64
dimension primitive.Dimension
weight float64
}{
{distance: 4500.0},
{dimension: primitive.Dimension{
Width: 30,
Height: 20,
Depth: 30,
}},
{weight: 45},
}

jneRate := newJneRate()

JNE := provider.NewJneCalculation(&jneRate)

for _, testcase := range testCases {
t.Run("test calculate price", func(t *testing.T) {
result := JNE.CalculatePrice(float64(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)
}
})
}
for _, testCase := range testCases {
t.Run("test time of arrival", func(t *testing.T) {
time := JNE.CalculateTimeOfArrival(testCase.distance)

expectedTime := createJneTimeArrival(t, testCase.distance)

if reflect.DeepEqual(time, expectedTime) == false {
t.Errorf("error get time arrival is : %v hours ", time)
}
})
}

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 06c3237

Please sign in to comment.