Skip to content

Commit 3f00233

Browse files
committed
Add VisitNoteServicer.Find and return ErrBillExist on create if one already exists for a visit note
1 parent 03979df commit 3f00233

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-0
lines changed

bill.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@ package elation
22

33
import (
44
"context"
5+
"encoding/json"
6+
"errors"
57
"fmt"
68
"net/http"
9+
"slices"
710
"time"
811

912
"go.opentelemetry.io/otel/codes"
1013
"go.opentelemetry.io/otel/trace"
1114
)
1215

16+
const billExistError = "The visit note provided already has a bill associated with it."
17+
18+
var ErrBillExist = errors.New("bill already exists for visit note")
19+
1320
type BillServicer interface {
1421
Create(ctx context.Context, create *BillCreate) (*Bill, *http.Response, error)
1522
}
@@ -115,6 +122,20 @@ func (b *BillService) Create(ctx context.Context, create *BillCreate) (*Bill, *h
115122
if err != nil {
116123
span.RecordError(err)
117124
span.SetStatus(codes.Error, "error making request")
125+
126+
var clientErr *Error
127+
if errors.As(err, &clientErr) && clientErr.StatusCode == http.StatusBadRequest {
128+
errorRes := map[string][]string{}
129+
err := json.Unmarshal([]byte(clientErr.Body), &errorRes)
130+
if err != nil {
131+
return nil, res, fmt.Errorf("unmarshaling response body to error response: %w", err)
132+
}
133+
134+
if len(errorRes["visit_note"]) > 0 && slices.Contains(errorRes["visit_note"], billExistError) {
135+
return nil, res, ErrBillExist
136+
}
137+
}
138+
118139
return nil, res, fmt.Errorf("making request: %w", err)
119140
}
120141

bill_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,53 @@ func TestBillService_Create(t *testing.T) {
100100
})
101101
}
102102
}
103+
104+
func TestBillService_Create_already_exists(t *testing.T) {
105+
assert := assert.New(t)
106+
107+
billCreate := &BillCreate{
108+
ServiceLocation: 10,
109+
VisitNote: 64409108504,
110+
Patient: 64901939201,
111+
Practice: 65540,
112+
Physician: 64811630594,
113+
}
114+
115+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
116+
if tokenRequest(w, r) {
117+
return
118+
}
119+
120+
assert.Equal(http.MethodPost, r.Method)
121+
assert.Equal("/bills", r.URL.Path)
122+
123+
body, err := io.ReadAll(r.Body)
124+
assert.NoError(err)
125+
126+
actualBillCreate := &BillCreate{}
127+
err = json.Unmarshal(body, actualBillCreate)
128+
assert.NoError(err)
129+
130+
assert.Equal(billCreate, actualBillCreate)
131+
132+
errorRes := map[string][]string{
133+
"visit_note": {billExistError},
134+
}
135+
b, err := json.Marshal(errorRes)
136+
assert.NoError(err)
137+
138+
w.Header().Set("Content-Type", "application/json")
139+
w.WriteHeader(http.StatusBadRequest)
140+
//nolint
141+
w.Write(b)
142+
}))
143+
defer srv.Close()
144+
145+
client := NewHTTPClient(srv.Client(), srv.URL+"/token", "", "", srv.URL)
146+
svc := BillService{client}
147+
148+
created, res, err := svc.Create(context.Background(), billCreate)
149+
assert.Nil(created)
150+
assert.NotNil(res)
151+
assert.ErrorIs(err, ErrBillExist)
152+
}

visit_note.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
type VisitNoteServicer interface {
1414
Create(ctx context.Context, create *VisitNoteCreate) (*VisitNote, *http.Response, error)
15+
Find(ctx context.Context, opts *FindVisitNotesOptions) (*Response[[]*VisitNote], *http.Response, error)
1516
}
1617

1718
var _ VisitNoteServicer = (*VisitNoteService)(nil)
@@ -178,3 +179,36 @@ func (v *VisitNoteService) Create(ctx context.Context, create *VisitNoteCreate)
178179

179180
return vn, res, nil
180181
}
182+
183+
type FindVisitNotesOptions struct {
184+
*Pagination
185+
186+
Patient int64 `url:"patient,omitempty"`
187+
Physician int64 `url:"physician,omitempty"`
188+
Practice int64 `url:"practice,omitempty"`
189+
190+
LastModifiedGT time.Time `url:"last_modified_gt,omitempty"`
191+
LastModifiedGTE time.Time `url:"last_modified_gte,omitempty"`
192+
LastModifiedLT time.Time `url:"last_modified_lt,omitempty"`
193+
LastModifiedLTE time.Time `url:"last_modified_lte,omitempty"`
194+
195+
FromSignedDate time.Time `url:"from_signed_date,omitempty"`
196+
ToSignedDate time.Time `url:"to_signed_date,omitempty"`
197+
Unsigned bool `url:"unsigned,omitempty"`
198+
}
199+
200+
func (v *VisitNoteService) Find(ctx context.Context, opts *FindVisitNotesOptions) (*Response[[]*VisitNote], *http.Response, error) {
201+
ctx, span := v.client.tracer.Start(ctx, "find visit notes", trace.WithSpanKind(trace.SpanKindClient))
202+
defer span.End()
203+
204+
out := &Response[[]*VisitNote]{}
205+
206+
res, err := v.client.request(ctx, http.MethodGet, "/visit_notes", opts, nil, &out)
207+
if err != nil {
208+
span.RecordError(err)
209+
span.SetStatus(codes.Error, "error making request")
210+
return nil, res, fmt.Errorf("making request: %w", err)
211+
}
212+
213+
return out, res, nil
214+
}

visit_note_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,95 @@ func TestVisitNoteService_Create(t *testing.T) {
105105
})
106106
}
107107
}
108+
109+
func TestVisitNoteService_Find(t *testing.T) {
110+
assert := assert.New(t)
111+
112+
opts := &FindVisitNotesOptions{
113+
Patient: 123,
114+
Physician: 456,
115+
Practice: 789,
116+
LastModifiedGT: time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC),
117+
LastModifiedGTE: time.Date(2022, 1, 2, 0, 0, 0, 0, time.UTC),
118+
LastModifiedLT: time.Date(2022, 1, 3, 0, 0, 0, 0, time.UTC),
119+
LastModifiedLTE: time.Date(2022, 1, 4, 0, 0, 0, 0, time.UTC),
120+
FromSignedDate: time.Date(2022, 1, 5, 0, 0, 0, 0, time.UTC),
121+
ToSignedDate: time.Date(2022, 1, 6, 0, 0, 0, 0, time.UTC),
122+
Unsigned: true,
123+
}
124+
125+
visitNotes := []*VisitNote{
126+
{
127+
ID: 1,
128+
},
129+
{
130+
ID: 2,
131+
},
132+
}
133+
134+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
135+
if tokenRequest(w, r) {
136+
return
137+
}
138+
139+
assert.Equal(http.MethodGet, r.Method)
140+
assert.Equal("/visit_notes", r.URL.Path)
141+
142+
actualPatient := r.URL.Query().Get("patient")
143+
assert.Equal(opts.Patient, strToInt64(actualPatient))
144+
145+
actualPhysician := r.URL.Query().Get("physician")
146+
assert.Equal(opts.Physician, strToInt64(actualPhysician))
147+
148+
actualPractice := r.URL.Query().Get("practice")
149+
assert.Equal(opts.Practice, strToInt64(actualPractice))
150+
151+
actualLastModifiedGT := r.URL.Query().Get("last_modified_gt")
152+
assert.Equal(opts.LastModifiedGT.Format(time.RFC3339), actualLastModifiedGT)
153+
154+
actualLastModifiedGTE := r.URL.Query().Get("last_modified_gte")
155+
assert.Equal(opts.LastModifiedGTE.Format(time.RFC3339), actualLastModifiedGTE)
156+
157+
actualLastModifiedLT := r.URL.Query().Get("last_modified_lt")
158+
assert.Equal(opts.LastModifiedLT.Format(time.RFC3339), actualLastModifiedLT)
159+
160+
actualLastModifiedLTE := r.URL.Query().Get("last_modified_lte")
161+
assert.Equal(opts.LastModifiedLTE.Format(time.RFC3339), actualLastModifiedLTE)
162+
163+
actualFromSignedDate := r.URL.Query().Get("from_signed_date")
164+
assert.Equal(opts.FromSignedDate.Format(time.RFC3339), actualFromSignedDate)
165+
166+
actualToSignedDate := r.URL.Query().Get("to_signed_date")
167+
assert.Equal(opts.ToSignedDate.Format(time.RFC3339), actualToSignedDate)
168+
169+
actualUnsigned := r.URL.Query().Get("unsigned")
170+
assert.Equal(opts.Unsigned, strToBool(actualUnsigned))
171+
172+
b, err := json.Marshal(Response[[]*VisitNote]{
173+
Results: []*VisitNote{
174+
{
175+
ID: 1,
176+
},
177+
{
178+
ID: 2,
179+
},
180+
},
181+
})
182+
assert.NoError(err)
183+
184+
w.Header().Set("Content-Type", "application/json")
185+
//nolint
186+
w.Write(b)
187+
}))
188+
defer srv.Close()
189+
190+
client := NewHTTPClient(srv.Client(), srv.URL+"/token", "", "", srv.URL)
191+
svc := VisitNoteService{client}
192+
193+
visitNotesRes, res, err := svc.Find(context.Background(), opts)
194+
assert.NotEmpty(visitNotesRes)
195+
assert.NotNil(res)
196+
assert.NoError(err)
197+
198+
assert.Equal(visitNotes, visitNotesRes.Results)
199+
}

0 commit comments

Comments
 (0)