daisybill_api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +20 -0
- data/lib/daisybill_api.rb +53 -0
- data/lib/daisybill_api/configuration.rb +46 -0
- data/lib/daisybill_api/data.rb +7 -0
- data/lib/daisybill_api/data/client.rb +66 -0
- data/lib/daisybill_api/data/rest_client/payload.rb +30 -0
- data/lib/daisybill_api/data/url.rb +26 -0
- data/lib/daisybill_api/ext.rb +20 -0
- data/lib/daisybill_api/ext/associations.rb +39 -0
- data/lib/daisybill_api/ext/attributes.rb +103 -0
- data/lib/daisybill_api/ext/attributes/attribute.rb +60 -0
- data/lib/daisybill_api/ext/attributes/type_castings.rb +78 -0
- data/lib/daisybill_api/ext/crud.rb +147 -0
- data/lib/daisybill_api/ext/crud/create.rb +107 -0
- data/lib/daisybill_api/ext/crud/destroy.rb +28 -0
- data/lib/daisybill_api/ext/crud/index.rb +41 -0
- data/lib/daisybill_api/ext/crud/show.rb +22 -0
- data/lib/daisybill_api/ext/crud/update.rb +37 -0
- data/lib/daisybill_api/ext/links.rb +65 -0
- data/lib/daisybill_api/ext/links/link.rb +35 -0
- data/lib/daisybill_api/ext/pageable_collection.rb +124 -0
- data/lib/daisybill_api/models.rb +22 -0
- data/lib/daisybill_api/models/address.rb +16 -0
- data/lib/daisybill_api/models/attachment.rb +22 -0
- data/lib/daisybill_api/models/base.rb +29 -0
- data/lib/daisybill_api/models/bill.rb +42 -0
- data/lib/daisybill_api/models/bill_payment.rb +22 -0
- data/lib/daisybill_api/models/bill_submission.rb +18 -0
- data/lib/daisybill_api/models/billing_provider.rb +25 -0
- data/lib/daisybill_api/models/claims_administrator.rb +13 -0
- data/lib/daisybill_api/models/contact.rb +19 -0
- data/lib/daisybill_api/models/employer.rb +13 -0
- data/lib/daisybill_api/models/injury.rb +30 -0
- data/lib/daisybill_api/models/patient.rb +32 -0
- data/lib/daisybill_api/models/place_of_service.rb +29 -0
- data/lib/daisybill_api/models/referring_provider.rb +21 -0
- data/lib/daisybill_api/models/rendering_provider.rb +23 -0
- data/lib/daisybill_api/models/service_line_item.rb +27 -0
- data/lib/daisybill_api/version.rb +3 -0
- data/spec/daisybill_api/configuration_spec.rb +16 -0
- data/spec/daisybill_api/data/client_spec.rb +47 -0
- data/spec/daisybill_api/data/rest_client/payload_spec.rb +17 -0
- data/spec/daisybill_api/data/url_spec.rb +13 -0
- data/spec/daisybill_api/ext/attributes/attribute_spec.rb +120 -0
- data/spec/daisybill_api/ext/attributes/type_castings_spec.rb +50 -0
- data/spec/daisybill_api/ext/links/link_spec.rb +50 -0
- data/spec/daisybill_api/ext/pageable_collection_spec.rb +145 -0
- data/spec/daisybill_api/models/address_spec.rb +7 -0
- data/spec/daisybill_api/models/attachment_spec.rb +9 -0
- data/spec/daisybill_api/models/bill_payment_spec.rb +11 -0
- data/spec/daisybill_api/models/bill_spec.rb +22 -0
- data/spec/daisybill_api/models/bill_submission_spec.rb +9 -0
- data/spec/daisybill_api/models/billing_provider_spec.rb +13 -0
- data/spec/daisybill_api/models/claims_administrator_spec.rb +7 -0
- data/spec/daisybill_api/models/contact_spec.rb +6 -0
- data/spec/daisybill_api/models/employer_spec.rb +7 -0
- data/spec/daisybill_api/models/injury_spec.rb +13 -0
- data/spec/daisybill_api/models/patient_spec.rb +14 -0
- data/spec/daisybill_api/models/place_of_service_spec.rb +14 -0
- data/spec/daisybill_api/models/referring_provider_spec.rb +11 -0
- data/spec/daisybill_api/models/rendering_provider_spec.rb +12 -0
- data/spec/daisybill_api/models/service_line_item_spec.rb +11 -0
- data/spec/daisybill_api_spec.rb +35 -0
- metadata +289 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
module DaisybillApi
|
2
|
+
module Ext
|
3
|
+
# @private
|
4
|
+
module Attributes
|
5
|
+
class Attribute
|
6
|
+
attr_accessor :name, :type, :options
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
def initialize(name, type, options = {})
|
10
|
+
@name = name.to_s
|
11
|
+
@type = type
|
12
|
+
@options = options
|
13
|
+
@value = [] if collection?
|
14
|
+
end
|
15
|
+
|
16
|
+
def value=(value)
|
17
|
+
@value = TypeCastings.convert_to(value, type)
|
18
|
+
end
|
19
|
+
|
20
|
+
def readonly?
|
21
|
+
!!options[:readonly]
|
22
|
+
end
|
23
|
+
|
24
|
+
def param_name
|
25
|
+
if collection?
|
26
|
+
simple_collection? ? name : "#{name}_attributes"
|
27
|
+
else
|
28
|
+
simple_type? ? name : "#{name}_attributes"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def param_value
|
33
|
+
if collection?
|
34
|
+
simple_collection? ? value : value.map(&:to_params)
|
35
|
+
else
|
36
|
+
simple_type? ? value : (value && value.to_params)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_param
|
41
|
+
readonly? ? {} : { param_name => param_value }
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def simple_type?
|
47
|
+
type.is_a? Symbol
|
48
|
+
end
|
49
|
+
|
50
|
+
def collection?
|
51
|
+
type.is_a? Array
|
52
|
+
end
|
53
|
+
|
54
|
+
def simple_collection?
|
55
|
+
collection? && type.first.is_a?(Symbol)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module DaisybillApi
|
4
|
+
module Ext
|
5
|
+
module Attributes
|
6
|
+
module TypeCastings
|
7
|
+
class << self
|
8
|
+
def convert_to(value, type)
|
9
|
+
return to_array(value, type.first) if type.is_a? Array
|
10
|
+
return if value.nil? || (value.is_a?(String) && value.strip.empty?)
|
11
|
+
return to_class(value, type) if type.is_a? Class
|
12
|
+
case type
|
13
|
+
when :integer
|
14
|
+
to_integer(value)
|
15
|
+
when :string
|
16
|
+
to_string(value)
|
17
|
+
when :date
|
18
|
+
to_date(value)
|
19
|
+
when :datetime
|
20
|
+
to_datetime(value)
|
21
|
+
when :boolean
|
22
|
+
to_boolean(value)
|
23
|
+
when :attachment
|
24
|
+
to_attachment(value)
|
25
|
+
when :float
|
26
|
+
to_float(value)
|
27
|
+
else
|
28
|
+
raise 'Unknown Type'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def to_date(value)
|
35
|
+
return value.to_date if value.respond_to? :to_date
|
36
|
+
Date.parse value rescue nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_datetime(value)
|
40
|
+
return value.to_datetime if value.respond_to? :to_datetime
|
41
|
+
DateTime.iso8601 value rescue nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_integer(value)
|
45
|
+
value.to_i rescue nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_string(value)
|
49
|
+
value.to_s rescue nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_boolean(value)
|
53
|
+
!!value
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_float(value)
|
57
|
+
value.to_f rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_class(attributes, type)
|
61
|
+
return attributes if attributes.is_a? type
|
62
|
+
type.new attributes rescue nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_array(values, type)
|
66
|
+
return [] if values.nil?
|
67
|
+
values.map { |value| convert_to value, type }
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_attachment(value)
|
71
|
+
return open(value) if value.is_a? String
|
72
|
+
value if value.is_a?(StringIO) || value.kind_of?(IO)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'daisybill_api/ext/crud/index'
|
2
|
+
require 'daisybill_api/ext/crud/create'
|
3
|
+
require 'daisybill_api/ext/crud/show'
|
4
|
+
require 'daisybill_api/ext/crud/update'
|
5
|
+
require 'daisybill_api/ext/crud/destroy'
|
6
|
+
|
7
|
+
module DaisybillApi
|
8
|
+
module Ext
|
9
|
+
module CRUD
|
10
|
+
# @private
|
11
|
+
module ClassMethods
|
12
|
+
def rest_actions(*actions)
|
13
|
+
actions.each { |action|
|
14
|
+
name = action.capitalize
|
15
|
+
extend "DaisybillApi::Ext::CRUD::#{name}::ClassMethods".constantize
|
16
|
+
include "DaisybillApi::Ext::CRUD::#{name}::InstanceMethods".constantize
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def path=(value)
|
21
|
+
@path = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def path
|
25
|
+
@path ||= "/#{plural_key}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def path_prefix(path, property)
|
29
|
+
@prefix_path = path
|
30
|
+
@prefix_property = property
|
31
|
+
attribute property, :integer, readonly: true
|
32
|
+
validates property, presence: true, if: :new_record?
|
33
|
+
end
|
34
|
+
|
35
|
+
def path_prefix?
|
36
|
+
!!(@prefix_path && @prefix_property)
|
37
|
+
end
|
38
|
+
|
39
|
+
def prefix_path
|
40
|
+
@prefix_path
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefix_property
|
44
|
+
@prefix_property
|
45
|
+
end
|
46
|
+
|
47
|
+
def plural_key
|
48
|
+
@plural_key ||= demodulize self.model_name.plural
|
49
|
+
end
|
50
|
+
|
51
|
+
def singular_key
|
52
|
+
@singular_key ||= demodulize self.model_name.singular
|
53
|
+
end
|
54
|
+
|
55
|
+
def show_path(id)
|
56
|
+
"#{path}/#{id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def index_path(prefix_id)
|
60
|
+
if path_prefix?
|
61
|
+
index_path_with_prefix(prefix_id)
|
62
|
+
else
|
63
|
+
index_path_without_prefix
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def client(method, path, params = {})
|
68
|
+
DaisybillApi::Data::Client.build method, path, params
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
PREFIX_LENGTH = 'daisybill_api_models_'.length
|
74
|
+
|
75
|
+
def demodulize(name)
|
76
|
+
name[PREFIX_LENGTH..name.length]
|
77
|
+
end
|
78
|
+
|
79
|
+
def index_path_with_prefix(prefix_id)
|
80
|
+
"#{prefix_path}/#{prefix_id}#{path}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def index_path_without_prefix
|
84
|
+
path
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# @private
|
89
|
+
module InstanceMethods
|
90
|
+
def new_record?
|
91
|
+
id.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
def destroyed?
|
95
|
+
!!@destroyed
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
def index_path
|
101
|
+
params = self.class.path_prefix? ? [self.send(self.class.prefix_property)] : []
|
102
|
+
self.class.index_path *params
|
103
|
+
end
|
104
|
+
|
105
|
+
def show_path
|
106
|
+
self.class.show_path(id)
|
107
|
+
end
|
108
|
+
|
109
|
+
def data
|
110
|
+
{ self.class.singular_key => to_params }
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def client(method, path, params = {})
|
116
|
+
self.class.client method, path, params
|
117
|
+
end
|
118
|
+
|
119
|
+
def send_data(method, url)
|
120
|
+
self.external_errors = nil
|
121
|
+
valid? && process_response(client method, url, data)
|
122
|
+
end
|
123
|
+
|
124
|
+
def process_response(client)
|
125
|
+
if client.success?
|
126
|
+
response = client.response.clone
|
127
|
+
self.links = response.delete 'links'
|
128
|
+
self.attributes = response
|
129
|
+
true
|
130
|
+
elsif client.bad_request?
|
131
|
+
self.external_errors = client.response['errors']
|
132
|
+
self.valid?
|
133
|
+
else
|
134
|
+
false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.included(base)
|
140
|
+
base.class_eval do
|
141
|
+
include DaisybillApi::Ext::CRUD::InstanceMethods
|
142
|
+
extend DaisybillApi::Ext::CRUD::ClassMethods
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module DaisybillApi
|
2
|
+
module Ext
|
3
|
+
module CRUD
|
4
|
+
module Create
|
5
|
+
module ClassMethods
|
6
|
+
# === Creating a record
|
7
|
+
#
|
8
|
+
# DaisybillApi::Models::Patient.create(
|
9
|
+
# first_name: "Johnny",
|
10
|
+
# last_name: "Smith",
|
11
|
+
# billing_provider_id: 14
|
12
|
+
# )
|
13
|
+
# # => <DaisybillApi::Models::Patient billing_provider_id: 14 ...>
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# === Creating a Bill
|
17
|
+
#
|
18
|
+
# bp = DaisybillApi::Models::BillingProvider.find(14)
|
19
|
+
# # => <DaisybillApi::Models::BillingProvider id: 14...>
|
20
|
+
# pos = bp.places_of_service.first
|
21
|
+
# # => <DaisybillApi::Models::PlaceOfService billing_provider_id: 14...>
|
22
|
+
# rp = bp.rendering_providers.first
|
23
|
+
# # => <DaisybillApi::Models::RenderingProvider billing_provider_id: 14...>
|
24
|
+
#
|
25
|
+
# sli = DaisybillApi::Models::ServiceLineItem.new(
|
26
|
+
# procedure_code: "S9981",
|
27
|
+
# units: 1,
|
28
|
+
# modifier_codes: ["93", "17"],
|
29
|
+
# diagnosis_code_1: "72700",
|
30
|
+
# custom_unit_charge_cents: 12345
|
31
|
+
# )
|
32
|
+
# # => <DaisybillApi::Models::ServiceLineItem...>
|
33
|
+
#
|
34
|
+
# bill = DaisybillApi::Models::Bill.new(
|
35
|
+
# injury_id: 345,
|
36
|
+
# date_of_service: '2015-01-01',
|
37
|
+
# rendering_provider_id: rp.id,
|
38
|
+
# place_of_service_id: pos.id,
|
39
|
+
# diagnosis_codes: ["72700"],
|
40
|
+
# diagnosis_type: "Icd10",
|
41
|
+
# service_line_items: [sli]
|
42
|
+
# )
|
43
|
+
# # => <DaisybillApi::Models::Bill...>
|
44
|
+
#
|
45
|
+
# bill.save
|
46
|
+
# # => true
|
47
|
+
#
|
48
|
+
# @param attributes [Hash]
|
49
|
+
# @return [Object]
|
50
|
+
def create(attributes = {})
|
51
|
+
instance = new(attributes)
|
52
|
+
instance.create
|
53
|
+
instance
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module InstanceMethods
|
58
|
+
# == Creating or Updating a record
|
59
|
+
#
|
60
|
+
# === Creating a record
|
61
|
+
#
|
62
|
+
# pt = DaisyBillApi::Models::Patient.new(
|
63
|
+
# billing_provider_id: 14,
|
64
|
+
# first_name: "Johnny",
|
65
|
+
# last_name: "Smith",
|
66
|
+
# ssn: "123456789",
|
67
|
+
# gender: "Male"
|
68
|
+
# )
|
69
|
+
#
|
70
|
+
# pt.save # => true
|
71
|
+
#
|
72
|
+
# === Updating a record
|
73
|
+
#
|
74
|
+
# pt = DaisybillApi::Models::Patient.find(12) # => <DaisybillApi::Models::Patient id: 12...>
|
75
|
+
#
|
76
|
+
# pt.telephone # => "2138888888"
|
77
|
+
#
|
78
|
+
# pt.telephone = "2137777777" # => "2137777777"
|
79
|
+
#
|
80
|
+
# pt.telephone # => "2137777777"
|
81
|
+
#
|
82
|
+
# pt.save # => true
|
83
|
+
#
|
84
|
+
# === Inspecting errors
|
85
|
+
#
|
86
|
+
# pt = DaisybillApi::Models::Patient.new(billing_provider_id: 14, first_name: "Johnny")
|
87
|
+
#
|
88
|
+
# pt.save # => false
|
89
|
+
#
|
90
|
+
# pt.errors.full_messages # => ["Last name can't be blank"]
|
91
|
+
def save
|
92
|
+
return create if new_record?
|
93
|
+
return update if respond_to? :update
|
94
|
+
message = '#save method is not supported for saved record'
|
95
|
+
DaisybillApi.logger.error message
|
96
|
+
raise NotImplementedError.new message
|
97
|
+
end
|
98
|
+
|
99
|
+
# @private
|
100
|
+
def create
|
101
|
+
send_data :post, index_path
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DaisybillApi
|
2
|
+
module Ext
|
3
|
+
module CRUD
|
4
|
+
module Destroy
|
5
|
+
# @private
|
6
|
+
module ClassMethods; end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
# === Deleting records
|
10
|
+
#
|
11
|
+
# bill = DaisybillApi::Models::Bill.find(12) # => <DaisybillApi::Models::Bill id: 12>
|
12
|
+
# bill.destroy # => true
|
13
|
+
# DaisybillApi::Models::Bill.find(12) # => nil
|
14
|
+
#
|
15
|
+
# Some records will not be deletable depending on their conditions:
|
16
|
+
#
|
17
|
+
# bill = DaisybillApi::Models::Bill.find(1) # => <DaisybillApi::Models::Bill id: 1...>
|
18
|
+
# bill.status # => "done"
|
19
|
+
# bill.destroy # => false
|
20
|
+
# bill.errors.full_messages # => ["Bill is not deletable"]
|
21
|
+
def destroy
|
22
|
+
@destroyed = send_data :delete, show_path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module DaisybillApi
|
2
|
+
module Ext
|
3
|
+
module CRUD
|
4
|
+
module Index
|
5
|
+
module ClassMethods
|
6
|
+
# Retrieves a list of records
|
7
|
+
#
|
8
|
+
# @patients = DaisybillApi::Models::Patient.all(billing_provider_id: 2)
|
9
|
+
# # => #<DaisybillApi::Ext::PageableCollection>
|
10
|
+
#
|
11
|
+
# @param [Hash] options
|
12
|
+
# @return [Object] a {DaisybillApi::Ext::PageableCollection PageableCollection} that includes Enumerable
|
13
|
+
def all(options = {})
|
14
|
+
id = options[@prefix_property]
|
15
|
+
c = client(:get, index_path(id), options)
|
16
|
+
|
17
|
+
if c.success?
|
18
|
+
DaisybillApi::Ext::PageableCollection.new(
|
19
|
+
c.response[plural_key.to_s].map { |attributes|
|
20
|
+
instance = new(attributes)
|
21
|
+
instance.send("#{prefix_property}=", id) if path_prefix?
|
22
|
+
instance
|
23
|
+
},
|
24
|
+
{
|
25
|
+
headers: c.headers,
|
26
|
+
params: options,
|
27
|
+
resource_class: self
|
28
|
+
}
|
29
|
+
)
|
30
|
+
else
|
31
|
+
DaisybillApi::Ext::PageableCollection.new([])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @private
|
37
|
+
module InstanceMethods; end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|