housecall

package module
v1.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2024 License: MIT Imports: 12 Imported by: 0

README

Go Version Build

HouseCall Pro API wrapper

Package provides a wrapper for interacting with the HouseCallPro API. Written in pure GoLang

go get github.com/BeelineRoutes/housecall

House Call OAuth flow

Offical documentation for the API can be found here.

First have your user go to https://api.housecallpro.com/oauth/authorize?response_type=code&client_id=clientId&redirect_uri=https://your-url.com

This will return to your redirect url with a "code" as a url param https://your-url.com/housecall?code=urlParamCode

Usage

import (
    "github.com/BeelineRoutes/housecall"
    "github.com/pkg/errors" 
    "log"
)

clientId := "ca96e4cd990507c2995b9633bd9caa679bee26e99f98572ba54751ab4ff24886" // your special client id
clientSecret := "1fd00f12ab1d3d13c6bf746aa1868bd591af098100d800195b56b6fa97795d73" // your secret
redirectUrl := "https://your-domain.com" // this can be whatever, you tell House Call what you want when you create your account

hc, err := housecall.NewHouseCall (clientId, clientSecret, redirectUrl) // create the hc object
if err != nil { log.Fatal (err) }

// now you can do something like convert the code you got from the url to a long-lived token and refresh token
params := r.URL.Query()
code := ""
if len(params["code"]) > 0 && len(params["code"][0]) > 0 {
    code = params[term][0]
} else {
    t.Fatal ("was expecting a url param 'code' to be set")
}

token, refresh, err := hc.TokensFromCode (context.TODO(), code)
// handle the error gracefully
switch errors.Cause (err) {
case housecall.ErrInvalidCode: // specific error for an invalid/expired code
    log.Printf ("Code appears invalid, most likely it's expired. %s", err.Error())

case nil:
    log.Printf ("Code is valid!")

default:
    log.Fatalf ("Unknown error occured : %s", err.Error())
}

// token is used as the bearer for future calls
// refresh can be used to generate a new token when it expires

History

This is actively being developed and while the goal is to prevent breaking changes, this is still in an early alpha.

  • 0.1 Initial version allows for validating a client OAuth token and retrieving the Token and Refresh tokens

  • 0.2 Start and end dates used for filtering jobs

  • 0.3 URL params for additional filtering of jobs

  • 0.4 Writes updates back to HCP to update jobs and their assigned employees

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidCode    = errors.New("OAuth code not valid")
	ErrAuthExpired    = errors.New("OAuth expired")
	ErrTooManyRecords = errors.New("Too many records returned")
)

Functions

This section is empty.

Types

type Address

type Address struct {
	Id        string `json:"id"`
	Type      string `json:"type"`
	Street    string `json:"street"`
	Street2   string `json:"street_line_2"`
	City      string `json:"city"`
	State     string `json:"state"`
	Zip       string `json:"zip"`
	Country   string `json:"country"`
	Latitude  string `json:"latitude"`
	Longitude string `json:"longitude"`
}

func (Address) ToString added in v0.1.3

func (this Address) ToString() string

this became the most complicated thing, but just trying to return an empty string when appropriate

type Appointment added in v1.14.1

type Appointment struct {
	Id                string    `json:"id"`
	Start             time.Time `json:"start_time"`
	End               time.Time `json:"end_time"`
	Window            int       `json:"arrival_window_minutes"`
	AssignedEmployees []string  `json:"dispatched_employees_ids"`
}

type Company added in v0.1.5

type Company struct {
	Id                   string  `json:"id"`
	PhoneNumber          string  `json:"phone_number"`
	Email                string  `json:"support_email"`
	Name                 string  `json:"name"`
	Address              Address `json:"address"`
	Website              string  `json:"website"`
	DefaultArrivalWindow int     `json:"default_arrival_window"`
	TimeZone             string  `json:"time_zone"`
}

func (Company) ConvertTimezone added in v0.3.3

func (this Company) ConvertTimezone() (*time.Location, error)

converts the companies timezone string into a golang location object

type CreateEstimateOption added in v1.4.0

type CreateEstimateOption struct {
	Name      string     `json:"name"`
	LineItems []LineItem `json:"line_items"`
}

type Customer

type Customer struct {
	Id            string    `json:"id"`
	FirstName     string    `json:"first_name"`
	LastName      string    `json:"last_name"`
	Email         string    `json:"email"`
	Mobile        string    `json:"mobile_number"`
	Home          string    `json:"home_number"`
	Work          string    `json:"work_number"`
	Company       string    `json:"company"`
	Notifications bool      `json:"notifications_enabled"`
	Tags          []string  `json:"tags"`
	Addresses     []Address `json:"addresses"`
	LeadSource    string    `json:"lead_source,omitempty"`
	Notes         string    `json:"notes,omitempty"`
}

type DispatchedEmployee added in v0.4.0

type DispatchedEmployee struct {
	Id string `json:"employee_id"`
}

type Employee added in v0.1.2

type Employee struct {
	Id        string   `json:"id"`
	FirstName string   `json:"first_name"`
	LastName  string   `json:"last_name"`
	Email     string   `json:"email"`
	Mobile    string   `json:"mobile_number"`
	Color     string   `json:"color_hex"`
	Avatar    string   `json:"avatar_url"`
	Role      string   `json:"role"`
	Tags      []string `json:"tags"`
}

type Error

type Error struct {
	ErrMsg, Description string
	StatusCode          int
}

----- ERRORS ---------------------------------------------------------------------------------------------------------//

func (*Error) Err

func (this *Error) Err() error

func (*Error) UnmarshalJSON added in v1.12.3

func (this *Error) UnmarshalJSON(b []byte) error

type Estimate added in v1.2.0

type Estimate struct {
	Id             string     `json:"id"`
	EstimateNumber string     `json:"estimate_number"`
	WorkStatus     WorkStatus `json:"work_status"`
	// LeadSource string `json:"lead_source,omitempty"`
	Customer       Customer
	Address        Address `json:"address"`
	WorkTimestamps struct {
		OnMyWay   time.Time `json:"on_my_way_at"`
		Started   time.Time `json:"started_at"`
		Completed time.Time `json:"completed_at"`
	} `json:"work_timestamps"`
	Schedule struct {
		Start  time.Time `json:"scheduled_start"`
		End    time.Time `json:"scheduled_end"`
		Window int       `json:"arrival_window"`
	}
	AssignedEmployees []Employee `json:"assigned_employees"`
	Options           []estimateOption
}

func (*Estimate) IsPending added in v1.4.0

func (this *Estimate) IsPending() bool

returns that the job is in a state where the job is still expected to be completed in the future

type Event added in v1.5.0

type Event struct {
	Id                string     `json:"id"`
	Name              string     `json:"name"`
	Note              string     `json:"note"`
	Recurrence        string     `json:"recurrence_rule"`
	AssignedEmployees []Employee `json:"assigned_employees"`
	Schedule          struct {
		Start    time.Time `json:"start_time"`
		End      time.Time `json:"end_time"`
		TimeZone string    `json:"time_zone"`
	} `json:"schedule"`
}

func (Event) ExtractRecurrence added in v1.6.0

func (this Event) ExtractRecurrence() (events []Event, err error)

creates a list of event objects based on the recurrence schedule "FREQ=WEEKLY;INTERVAL=2;UNTIL=20221128T070000Z;BYDAY=SA"

type HouseCall

type HouseCall struct {
	// contains filtered or unexported fields
}

func NewHouseCall

func NewHouseCall(clientId, clientSecret, callbackUrl string) (*HouseCall, error)

func (*HouseCall) Company added in v0.1.5

func (this *HouseCall) Company(ctx context.Context, token string) (*Company, error)

Gets the info about our current company

func (*HouseCall) CreateCustomer added in v0.6.0

func (this *HouseCall) CreateCustomer(ctx context.Context, token string, customer *Customer) error

creates the customer and returns their id

func (*HouseCall) CreateEstimate added in v1.2.0

func (this *HouseCall) CreateEstimate(ctx context.Context, token, customerId, addressId string,
	startTime time.Time, duration, arrivalWindow time.Duration, notifyCustomer bool,
	employeeIds, tags []string, leadSource, note, message string,
	options []CreateEstimateOption) (*Estimate, error)

creates a new estimate in the system

func (*HouseCall) CreateJob added in v0.7.0

func (this *HouseCall) CreateJob(ctx context.Context, token, customerId, addressId string,
	startTime time.Time, duration, arrivalWindow time.Duration,
	employeeIds, tags []string, lineItems []LineItem, leadSource string) (*Job, error)

creates a new job in the system

func (*HouseCall) GetEstimate added in v1.2.0

func (this *HouseCall) GetEstimate(ctx context.Context, token, estId string) (*Estimate, error)

gets the info about a specific estimate

func (*HouseCall) GetJob added in v0.1.6

func (this *HouseCall) GetJob(ctx context.Context, token, jobId string) (*Job, error)

gets the info about a specific job

func (*HouseCall) GetJobAppointments added in v1.14.1

func (this *HouseCall) GetJobAppointments(ctx context.Context, token, jobId string) ([]Appointment, error)

----- APPOINTMENTS jobs can have appointments now...

func (*HouseCall) GetLineItems added in v0.8.0

func (this *HouseCall) GetLineItems(ctx context.Context, token, jobId string) ([]*LineItem, error)

returns the line items associated with the job this will include all the different "kinds"

func (*HouseCall) ListEmployees added in v0.1.4

func (this *HouseCall) ListEmployees(ctx context.Context, token string) ([]Employee, error)

Returns a list of the employees (pros) in asc by last name

func (*HouseCall) ListEstimates added in v1.2.0

func (this *HouseCall) ListEstimates(ctx context.Context, token string, employeeId string, start, finish time.Time) ([]Estimate, error)

returns a list of estimates for a specific employee over the target date range

func (*HouseCall) ListEvents added in v1.5.0

func (this *HouseCall) ListEvents(ctx context.Context, token string, start, end time.Time) ([]Event, error)

returns a list of events over the target date range this includes any event that overlaps the passed time

func (*HouseCall) ListJobs

func (this *HouseCall) ListJobs(ctx context.Context, token string, start, finish time.Time) ([]Job, error)

returns all jobs that are within our start and finish ranges

func (*HouseCall) ListJobsFromCustomer added in v1.3.0

func (this *HouseCall) ListJobsFromCustomer(ctx context.Context, token string, customerId string) ([]Job, error)

returns a list of jobs that are associated with the customer

func (*HouseCall) ListJobsFromEmployee added in v0.4.4

func (this *HouseCall) ListJobsFromEmployee(ctx context.Context, token string, employeeId string, start, finish time.Time) ([]Job, error)

returns a list of jobs for a specific employee over the target date range

func (*HouseCall) ListMissedJobs added in v1.10.0

func (this *HouseCall) ListMissedJobs(ctx context.Context, token string, start, finish time.Time) ([]Job, error)

returns all jobs that are within our start and finish ranges

func (*HouseCall) ListUnscheduledEstimates added in v1.2.0

func (this *HouseCall) ListUnscheduledEstimates(ctx context.Context, token string, pageLimit int) ([]Estimate, error)

Returns a list of the estimates that are marked as "unscheduled".

func (*HouseCall) ListUnscheduledJobs added in v0.2.0

func (this *HouseCall) ListUnscheduledJobs(ctx context.Context, token string, pageLimit int) ([]Job, error)

Returns a list of the jobs that are marked as "unscheduled".

func (*HouseCall) PageCustomers added in v1.8.0

func (this *HouseCall) PageCustomers(ctx context.Context, token string, page int) ([]Customer, error)

used to request a specific page for customers allows us to check for newly created ones as well as move back in time.

func (*HouseCall) PageUnscheduledJobs added in v1.9.0

func (this *HouseCall) PageUnscheduledJobs(ctx context.Context, token string, page int) ([]Job, error)

gets a specific page of unscheduled jobs, ordered by most recently added

func (*HouseCall) Schedule added in v0.3.3

func (this *HouseCall) Schedule(ctx context.Context, token string) (*Schedule, error)

Gets the companies schedule. The return from HCP is a little... tough to interpret this just returns time.Times for the start and end of the longest time during the day

func (*HouseCall) SearchCustomers added in v0.6.0

func (this *HouseCall) SearchCustomers(ctx context.Context, token, search string) ([]Customer, error)

Returns a list of the customers using a 'simple' searching keyword or short address part returns in order of most recently created. converted to page through the results, allows us to do an empty search for customers

func (*HouseCall) TokensFromCode

func (this *HouseCall) TokensFromCode(ctx context.Context, code string) (*OauthResponse, error)

Takes the passed code we got from the params of the redirect url and converts it to long-live token and refresh token

func (*HouseCall) TokensFromRefresh

func (this *HouseCall) TokensFromRefresh(ctx context.Context, refresh string) (*OauthResponse, error)

Gets new tokens using a previously retreived refresh token

func (*HouseCall) UpdateEstimateSchedule added in v1.13.0

func (this *HouseCall) UpdateEstimateSchedule(ctx context.Context, token, estId, optionId string, employeeIds []string, startTime time.Time,
	duration, arrivalWindow time.Duration, notifyCustomer bool) error

updates the target estimate time for an option in the estimate at least 1 employee is required for this

func (*HouseCall) UpdateJobAppointmentSchedule added in v1.13.0

func (this *HouseCall) UpdateJobAppointmentSchedule(ctx context.Context, token, jobId, apptId string, employeeIds []string, startTime time.Time,
	duration, arrivalWindow time.Duration, notifyCustomer bool) error

this is how we update the "new" setup for jobs where we have an appointment now 2023-10-18 notifications don't work with this endpoint, HCP says they're working on that

func (*HouseCall) UpdateJobDispatch added in v0.4.0

func (this *HouseCall) UpdateJobDispatch(ctx context.Context, token, jobId string, employeeIds ...string) error

sets the list of all assigned employees for a job only updates the list of employees assigned to a job

func (*HouseCall) UpdateJobSchedule added in v0.1.6

func (this *HouseCall) UpdateJobSchedule(ctx context.Context, token, jobId string, employeeIds []string, startTime time.Time,
	duration, arrivalWindow time.Duration, notifyCustomer bool) error

updates the target scheduled time for a job at least 1 employee is required for this if startTime is zero, then this will remove the scheduled time from the job

type Job

type Job struct {
	Id                string `json:"id"`
	CustomerId        string `json:"customer_id"`
	Customer          Customer
	Address           Address    `json:"address"`
	Note              string     `json:"note"`
	WorkStatus        WorkStatus `json:"work_status"`
	Invoice           string     `json:"invoice_number"`
	Balance           int64      `json:"outstanding_balance"`
	Total             int64      `json:"total_amount"`
	Tags              []string   `json:"tags"`
	Description       string     `json:"description"`
	AssignedEmployees []Employee `json:"assigned_employees"`
	Schedule          struct {
		Start  time.Time `json:"scheduled_start"`
		End    time.Time `json:"scheduled_end"`
		Window int       `json:"arrival_window"`
	}
	Appointments   []Appointment `json:"appointments"`
	WorkTimestamps struct {
		OnMyWay   time.Time `json:"on_my_way_at"`
		Started   time.Time `json:"started_at"`
		Completed time.Time `json:"completed_at"`
	} `json:"work_timestamps"`
	LeadSource string `json:"lead_source,omitempty"`
}

func (*Job) IsActive added in v0.3.0

func (this *Job) IsActive() bool

returns that the job is in a state where everything is still a "go". Either it hasn't happened yet, it's happening now, or it will in the future

func (*Job) IsPending added in v0.1.5

func (this *Job) IsPending() bool

returns that the job is in a state where the job is still expected to be completed in the future

type JobDispatch added in v0.4.0

type JobDispatch struct {
	DispatchedEmployees []DispatchedEmployee `json:"dispatched_employees"`
}

type JobSchedule added in v0.1.6

type JobSchedule struct {
	Start               time.Time            `json:"start_time"`
	End                 time.Time            `json:"end_time"`
	Window              int                  `json:"arrival_window_in_minutes"`
	Notify              bool                 `json:"notify"`
	NotifyPro           bool                 `json:"notify_pro"`
	DispatchedEmployees []DispatchedEmployee `json:"dispatched_employees"`
}

type LineItem added in v0.7.1

type LineItem struct {
	Name        string      `json:"name"`
	Description string      `json:"description"`
	UnitPrice   int         `json:"unit_price"`
	Quantity    json.Number `json:"quantity"`
	UnitCost    int         `json:"unit_cost"`
	Kind        string      `json:"kind"`
}

type OauthResponse added in v1.11.0

type OauthResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	Expires      int64  `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	Scope        string `json:"scope"`
	Created      int64  `json:"created_at"`
}

func (*OauthResponse) ExpiresAt added in v1.11.0

func (this *OauthResponse) ExpiresAt() time.Time

returns a time object of when this oauth will expire

type Schedule added in v0.3.3

type Schedule struct {
	DailyAvailabilities struct {
		Data []struct {
			DayName         string `json:"day_name"`
			ScheduleWindows struct {
				Data []struct {
					StartTime scheduleTime `json:"start_time"`
					EndTime   scheduleTime `json:"end_time"`
				} `json:"data"`
			} `json:"schedule_windows"`
		} `json:"data"`
	} `json:"daily_availabilities"`
}

func (*Schedule) DaySchedules added in v0.3.3

func (this *Schedule) DaySchedules(loc *time.Location) ([]daySchedule, error)

goes through all the days and returns the earliest start and end for each leaves Start and End as IsZero if there's no schedules for that day this always returns 7 items, 1 for each day of the week loc is the local timezone for this schedule, HCP has the times as a local string when returned it converts it to UTC time if the schedule seems off I'll add more time to either side depending on how close to noon the times are

type WorkStatus added in v0.3.1

type WorkStatus string
const (
	WorkStatus_needsScheduling WorkStatus = "needs scheduling"
	WorkStatus_scheduled       WorkStatus = "scheduled"
	WorkStatus_inProgress      WorkStatus = "in progress"
	WorkStatus_completeUnrated WorkStatus = "complete unrated"
	WorkStatus_completeRated   WorkStatus = "complete rated"
	WorkStatus_userCanceled    WorkStatus = "user canceled"
	WorkStatus_proCanceled     WorkStatus = "pro canceled"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL