Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[R-Order] Setup order implementation #36

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ run:
rm -rf .terraform.lock.hcl
make build
terraform init -plugin-dir .terraform.d/plugins/
TF_LOG=INFO terraform plan
TF_LOG=INFO terraform apply -auto-approve
rm -rf terraform.tfstat*

watch:
while true; do \
inotifywait -e modify,create,delete -r internal/provider/*.go && make run; \
inotifywait -e modify,create,delete -r internal/provider/*.go && make run; \
done

localSetup:
Expand Down
3 changes: 3 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type dominosProvider struct {
// provider is built and ran locally, and "test" when running acceptance
// testing.
version string

providerdata providerData
}

type providerData struct {
Expand Down Expand Up @@ -61,6 +63,7 @@ func (p *dominosProvider) Configure(ctx context.Context, req provider.ConfigureR

data.CreditCard.CardType = types.String{Value: string("VISA")}

p.providerdata = data
p.configured = true
}

Expand Down
126 changes: 118 additions & 8 deletions internal/provider/resource_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package provider

import (
"context"
"encoding/json"
"fmt"
"strconv"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/mnthomson/terraform-provider-dominos/internal/utils"
)

// Ensure provider defined types fully satisfy framework interfaces
Expand All @@ -28,7 +33,7 @@ As far as I know there is no way to cancel a dominos order programmatically, so
You should receive an email confirmation almost instantly, and that email will have the store's phone number in it.
`,
Attributes: map[string]tfsdk.Attribute{
"api_object": {
"address_api_object": {
Description: "The computed json payload for the specified address.",
Required: true,
Type: types.StringType,
Expand All @@ -45,11 +50,6 @@ You should receive an email confirmation almost instantly, and that email will h
Required: true,
Type: types.Int64Type,
},
"price_only": {
Description: "DRY RUN: This will only display the total price of the order (and not actually order).",
Optional: true,
Type: types.BoolType,
},
"total_price": {
Description: "The computed total price of the order.",
Computed: true,
Expand All @@ -73,24 +73,134 @@ type resourceOrderData struct {
AddressAPIObj types.String `tfsdk:"address_api_object"`
ItemCodes types.List `tfsdk:"item_codes"`
StoreID types.Int64 `tfsdk:"store_id"`
PriceOnly types.Bool `tfsdk:"price_only"`
TotalPrice types.Number `tfsdk:"total_price"`
}

type resourceOrder struct {
provider dominosProvider
}

type Address struct {
Street string `json:"Street"`
City string `json:"City"`
Region string `json:"Region"`
PostalCode string `json:"PostalCode"`
Type string `json:"Type" default:"House"`
DeliveryInstructions string `json:"DeliveryInstructions"`
}

type Payment struct {
Type string `json:"Type" default:"DoorCredit"`
Amount float64 `json:"Amount"`
Number string `json:"Number" default:""`
CardType string `json:"CardType" default:""`
Expiration string `json:"Expiration" default:""`
SecurityCode string `json:"SecurityCode" default:""`
PostalCode string `json:"PostalCode" default:""`
ProviderID string `json:"ProviderID" default:""`
// PaymentMethodID string `json:"PaymentMethodID"`
// OTP string `json:"OTP"`
// GpmPaymentType string `json:"gpmPaymentType"`
}

type Product interface{}

type DominosOrderData struct {
Order struct {
Address Address `json:"Address"`
Coupons []struct{} `json:"Coupons"`
CustomerID string `json:"CustomerID" default:""`
Email string `json:"Email"`
Extension string `json:"Extension" default:""`
FirstName string `json:"FirstName"`
LastName string `json:"LastName"`
LanguageCode string `json:"LanguageCode" default:"en"`
OrderChannel string `json:"OrderChannel" default:"OLO"`
OrderID string `json:"OrderID" default:""`
OrderMethod string `json:"OrderMethod" default:"Web"`
OrderTaker struct{} `json:"OrderTaker"`
Payments []Payment `json:"Payments"`
Phone string `json:"Phone"`
PhonePrefix string `json:"PhonePrefix" default:""`
Products []Product `json:"Products"`
ServiceMethod string `json:"ServiceMethod" default:"Delivery"`
SourceOrganizationURI string `json:"SourceOrganizationURI" default:"order.dominos.com"`
StoreID string `json:"StoreID"`
Tags struct{} `json:"Tags"`
Version string `json:"Version" default:"1.0"`
NoCombine bool `json:"NoCombine" default:"true"`
Partners struct{} `json:"Partners"`
HotspotsLite bool `json:"HotspotsLite" default:"false"`
OrderInfoCollection []struct{} `json:"OrderInfoCollection"`
NewUser bool `json:"NewUser" default:"true"`
} `json:"Order"`
}

func (r resourceOrder) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data resourceOrderData
var providerdata providerData

diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)

resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

providerdata = r.provider.providerdata
order_data := &DominosOrderData{}

// Order data defaults
err := utils.Set(&(order_data.Order), "default")
if err != nil {
resp.Diagnostics.AddError("Error Setting Defaults", fmt.Sprintf("%s", err))
return
}

// Address defaults
err = utils.Set(&(order_data.Order.Address), "default")
if err != nil {
resp.Diagnostics.AddError("Error Setting Defaults", fmt.Sprintf("%s", err))
return
}

// Provided address data
err = json.Unmarshal([]byte(data.AddressAPIObj.Value), &(order_data.Order.Address))
if err != nil {
resp.Diagnostics.AddError("Error unmarshalling AddressAPIObj", fmt.Sprintf("%s", err))
return
}

// Provided personal data
order_data.Order.FirstName = providerdata.FirstName.Value
order_data.Order.LastName = providerdata.LastName.Value
order_data.Order.Email = providerdata.EmailAddr.Value
order_data.Order.Phone = providerdata.PhoneNumber.Value

// Misc
order_data.Order.StoreID = strconv.FormatInt(data.StoreID.Value, 10)

/* Validate Order */

/* Price Order */

/* Order order */
// Add Payment details

// Payment defaults
err = utils.Set(&(order_data.Order.Address), "default")
if err != nil {
resp.Diagnostics.AddError("Error Setting Defaults", fmt.Sprintf("%s", err))
return
}

// Set price

//Printing output
output_bytes, _ := json.Marshal(order_data)
output := string(output_bytes)
fmt.Println(output)

diags = resp.State.Set(ctx, &data)
resp.Diagnostics.Append(diags...)
}
Expand Down
44 changes: 44 additions & 0 deletions internal/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package utils

import (
"fmt"
"reflect"
"strconv"
)

func setField(field reflect.Value, defaultVal string) error {

if !field.CanSet() {
return fmt.Errorf("Can't set value\n")
}

switch field.Kind() {

case reflect.Int:
if val, err := strconv.ParseInt(defaultVal, 10, 64); err == nil {
field.Set(reflect.ValueOf(int(val)).Convert(field.Type()))

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types

Incorrect conversion of a 64-bit integer from [strconv.ParseInt](1) to a lower bit size type int without an upper bound check.
}
case reflect.String:
field.Set(reflect.ValueOf(defaultVal).Convert(field.Type()))
}
return nil
}

func Set(ptr interface{}, tag string) error {
if reflect.TypeOf(ptr).Kind() != reflect.Ptr {
return fmt.Errorf("Not a pointer")
}

v := reflect.ValueOf(ptr).Elem()
t := v.Type()

for i := 0; i < t.NumField(); i++ {
if defaultVal := t.Field(i).Tag.Get(tag); defaultVal != "-" {
if err := setField(v.Field(i), defaultVal); err != nil {
return err
}

}
}
return nil
}