Skip to content

Commit e704bcf

Browse files
committed
feat: add mortgage list id filters
1 parent 7b112d3 commit e704bcf

File tree

6 files changed

+414
-1
lines changed

6 files changed

+414
-1
lines changed
File renamed without changes.
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
"log"
8+
"math"
9+
"sync"
10+
"time"
11+
12+
"lwebco.de/go-capis"
13+
)
14+
15+
var (
16+
username = flag.String("username", "", "comparisonapis.com username")
17+
password = flag.String("password", "", "comparisonapis.com password")
18+
token = flag.String("token", "", "comparisonapis.com token")
19+
20+
groupName = flag.String("group-name", "", "product group name")
21+
)
22+
23+
type (
24+
mortgageProductsRemote interface {
25+
ListMortgages(ctx context.Context, filters *capis.MortgageProductFilters) (*capis.ListMortgagesResponse, error)
26+
}
27+
28+
groupsRemote interface {
29+
FindGroup(ctx context.Context, name string) (*capis.FindGroupResponse, error)
30+
}
31+
32+
mortgageProductsRepository struct {
33+
sync.RWMutex
34+
35+
gr groupsRemote
36+
mpr mortgageProductsRemote
37+
groupName string
38+
products []*capis.Mortgage
39+
}
40+
)
41+
42+
func (r *mortgageProductsRepository) SyncEvery(ctx context.Context, t *time.Ticker) {
43+
for range t.C {
44+
if err := r.Sync(ctx); err != nil {
45+
log.Println("unable to sync products", err)
46+
}
47+
}
48+
}
49+
50+
func (r *mortgageProductsRepository) Sync(ctx context.Context) error {
51+
r.RWMutex.Lock()
52+
defer r.RWMutex.Unlock()
53+
54+
grp, err := r.gr.FindGroup(ctx, r.groupName)
55+
if err != nil {
56+
return fmt.Errorf("unable to get group %w", err)
57+
}
58+
59+
resp, err := r.mpr.ListMortgages(ctx, &capis.MortgageProductFilters{
60+
ID: grp.Data.Products,
61+
})
62+
if err != nil {
63+
return fmt.Errorf("unable to get products list %w", err)
64+
}
65+
66+
r.products = resp.Data
67+
68+
return nil
69+
}
70+
71+
func (r *mortgageProductsRepository) All() []*capis.Mortgage {
72+
r.RWMutex.RLock()
73+
defer r.RWMutex.RUnlock()
74+
75+
return r.products
76+
}
77+
78+
func getCapisClient() *capis.Client {
79+
var auth capis.AuthProvider
80+
81+
if *token != "" {
82+
auth = capis.StaticToken(*token)
83+
} else {
84+
auth = &capis.PasswordAuthentication{
85+
Username: *username,
86+
Password: *password,
87+
}
88+
}
89+
90+
client, err := capis.New(capis.WithAuthProvider(auth))
91+
if err != nil {
92+
log.Fatalf("error initialising client %v\n", err)
93+
}
94+
95+
return client
96+
}
97+
98+
func repositoryFromClient(c *capis.Client, groupName string) *mortgageProductsRepository {
99+
return &mortgageProductsRepository{
100+
gr: c,
101+
mpr: c.Products(),
102+
groupName: groupName,
103+
products: make([]*capis.Mortgage, 0),
104+
}
105+
}
106+
107+
type sourcingRun struct {
108+
// request loan amount
109+
loanAmount int
110+
111+
// maximum cost of loan in whole pounds
112+
maxCost int
113+
}
114+
115+
func getFeeCost(loanAmount int, fee capis.Fee) int {
116+
if fee.Fixed != nil {
117+
return int(fee.Fixed.Amount)
118+
}
119+
120+
costF := (float64(loanAmount) / 100) * fee.Variable
121+
return int(math.Ceil(costF))
122+
}
123+
124+
func (f sourcingRun) match(mortgage *capis.Mortgage) bool {
125+
if f.maxCost > 0 && getFeeCost(f.loanAmount, mortgage.Fee) > f.maxCost {
126+
return false
127+
}
128+
129+
return true
130+
}
131+
132+
func findMatching(repo *mortgageProductsRepository, matchFunc func(mortgage *capis.Mortgage) bool) (out []capis.Mortgage) {
133+
items := repo.All()
134+
out = make([]capis.Mortgage, 0, len(items))
135+
136+
for _, item := range items {
137+
if matchFunc(item) {
138+
out = append(out, *item)
139+
}
140+
}
141+
142+
return
143+
}
144+
145+
func main() {
146+
flag.Parse()
147+
148+
ctx := context.Background()
149+
client := getCapisClient()
150+
151+
repo := repositoryFromClient(client, *groupName)
152+
153+
if err := repo.Sync(ctx); err != nil {
154+
log.Fatalf("initial sync failied %v", err)
155+
}
156+
tick := time.NewTicker(time.Minute)
157+
defer tick.Stop()
158+
go repo.SyncEvery(ctx, tick)
159+
160+
params := sourcingRun{
161+
loanAmount: 200000,
162+
maxCost: 10000,
163+
}
164+
165+
products := findMatching(repo, params.match)
166+
167+
if len(products) == 0 {
168+
fmt.Println("sorry, no products matched the criteria")
169+
return
170+
}
171+
172+
fmt.Printf("%d products where found:\n")
173+
fmt.Println("===========")
174+
175+
for _, p := range products {
176+
fmt.Printf(
177+
"\t - [%s] %s (%.2f for %d months) + £%d in fees\n",
178+
p.ID,
179+
p.Name,
180+
p.OfferInterestRate.Rate.Value,
181+
p.OfferInterestRate.Period.Value,
182+
getFeeCost(params.loanAmount, p.Fee),
183+
)
184+
}
185+
186+
fmt.Println()
187+
}

0 commit comments

Comments
 (0)