rconomic 0.2.1 → 0.3
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.
- data/.travis.yml +1 -0
- data/Gemfile +8 -1
- data/Gemfile.lock +8 -1
- data/Guardfile +6 -0
- data/README.md +39 -14
- data/lib/economic/account.rb +25 -0
- data/lib/economic/cash_book.rb +39 -0
- data/lib/economic/cash_book_entry.rb +111 -0
- data/lib/economic/current_invoice.rb +33 -2
- data/lib/economic/current_invoice_line.rb +1 -1
- data/lib/economic/debtor.rb +2 -1
- data/lib/economic/debtor_contact.rb +1 -1
- data/lib/economic/entity/handle.rb +66 -0
- data/lib/economic/entity.rb +39 -36
- data/lib/economic/invoice.rb +58 -0
- data/lib/economic/proxies/account_proxy.rb +22 -0
- data/lib/economic/proxies/cash_book_entry_proxy.rb +53 -0
- data/lib/economic/proxies/cash_book_proxy.rb +47 -0
- data/lib/economic/proxies/current_invoice_line_proxy.rb +7 -1
- data/lib/economic/proxies/current_invoice_proxy.rb +18 -1
- data/lib/economic/proxies/debtor_contact_proxy.rb +36 -10
- data/lib/economic/proxies/debtor_proxy.rb +32 -1
- data/lib/economic/proxies/entity_proxy.rb +30 -3
- data/lib/economic/proxies/invoice_proxy.rb +31 -0
- data/lib/economic/session.rb +18 -1
- data/lib/economic/support/string.rb +19 -0
- data/lib/rconomic/version.rb +1 -1
- data/lib/rconomic.rb +10 -2
- data/spec/economic/cash_book_entry_spec.rb +20 -0
- data/spec/economic/cash_book_spec.rb +34 -0
- data/spec/economic/current_invoice_spec.rb +44 -1
- data/spec/economic/debtor_contact_spec.rb +2 -2
- data/spec/economic/debtor_spec.rb +6 -0
- data/spec/economic/entity/handle_spec.rb +116 -0
- data/spec/economic/entity_spec.rb +26 -22
- data/spec/economic/invoice_spec.rb +68 -0
- data/spec/economic/proxies/cash_book_entry_proxy_spec.rb +62 -0
- data/spec/economic/proxies/cash_book_proxy_spec.rb +54 -0
- data/spec/economic/proxies/current_invoice_line_proxy_spec.rb +1 -1
- data/spec/economic/proxies/current_invoice_proxy_spec.rb +66 -2
- data/spec/economic/proxies/debtor_proxy_spec.rb +39 -1
- data/spec/economic/proxies/invoice_proxy_spec.rb +75 -0
- data/spec/economic/session_spec.rb +11 -1
- data/spec/fixtures/cash_book_book/success.xml +10 -0
- data/spec/fixtures/cash_book_entry_create_debtor_payment/success.xml +11 -0
- data/spec/fixtures/cash_book_entry_create_finance_voucher/success.xml +11 -0
- data/spec/fixtures/cash_book_entry_create_from_data/success.xml +11 -0
- data/spec/fixtures/cash_book_entry_get_data/success.xml +73 -0
- data/spec/fixtures/cash_book_get_all/multiple.xml +15 -0
- data/spec/fixtures/cash_book_get_entries/success.xml +17 -0
- data/spec/fixtures/cash_book_get_name/success.xml +8 -0
- data/spec/fixtures/current_invoice_book/success.xml +10 -0
- data/spec/fixtures/current_invoice_find_by_date_interval/many.xml +15 -0
- data/spec/fixtures/current_invoice_find_by_date_interval/none.xml +8 -0
- data/spec/fixtures/current_invoice_find_by_date_interval/single.xml +12 -0
- data/spec/fixtures/current_invoice_get_all/multiple.xml +15 -0
- data/spec/fixtures/current_invoice_get_all/none.xml +8 -0
- data/spec/fixtures/current_invoice_get_all/single.xml +12 -0
- data/spec/fixtures/current_invoice_get_data_array/multiple.xml +141 -0
- data/spec/fixtures/current_invoice_get_data_array/single.xml +75 -0
- data/spec/fixtures/debtor_find_by_number/found.xml +10 -0
- data/spec/fixtures/debtor_find_by_number/not_found.xml +7 -0
- data/spec/fixtures/debtor_get_all/multiple.xml +15 -0
- data/spec/fixtures/debtor_get_all/single.xml +12 -0
- data/spec/fixtures/debtor_get_data_array/multiple.xml +103 -0
- data/spec/fixtures/invoice_find_by_date_interval/many.xml +15 -0
- data/spec/fixtures/invoice_find_by_date_interval/none.xml +9 -0
- data/spec/fixtures/invoice_find_by_date_interval/single.xml +12 -0
- data/spec/fixtures/invoice_get_data/success.xml +74 -0
- data/spec/fixtures/invoice_get_pdf/success.xml +8 -0
- data/spec/fixtures/invoice_get_remainder/success.xml +8 -0
- data/spec/fixtures/spec_entity_delete/success.xml +6 -0
- metadata +54 -6
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rconomic (0.
|
4
|
+
rconomic (0.3)
|
5
5
|
activesupport (~> 3.0)
|
6
6
|
savon (= 0.9.5)
|
7
7
|
|
@@ -13,6 +13,10 @@ GEM
|
|
13
13
|
gyoku (>= 0.4.0)
|
14
14
|
builder (3.0.0)
|
15
15
|
diff-lcs (1.1.2)
|
16
|
+
guard (0.8.8)
|
17
|
+
thor (~> 0.14.6)
|
18
|
+
guard-rspec (0.5.0)
|
19
|
+
guard (>= 0.8.4)
|
16
20
|
gyoku (0.4.4)
|
17
21
|
builder (>= 2.1.2)
|
18
22
|
httpi (0.9.5)
|
@@ -42,6 +46,7 @@ GEM
|
|
42
46
|
mocha (>= 0.9.8)
|
43
47
|
rspec (>= 2.0.0)
|
44
48
|
savon (>= 0.8.0)
|
49
|
+
thor (0.14.6)
|
45
50
|
wasabi (1.0.0)
|
46
51
|
nokogiri (>= 1.4.0)
|
47
52
|
|
@@ -49,6 +54,8 @@ PLATFORMS
|
|
49
54
|
ruby
|
50
55
|
|
51
56
|
DEPENDENCIES
|
57
|
+
guard
|
58
|
+
guard-rspec
|
52
59
|
rake
|
53
60
|
rconomic!
|
54
61
|
savon_spec (= 0.1.6)
|
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -31,11 +31,11 @@ Usage example
|
|
31
31
|
debtor.save
|
32
32
|
|
33
33
|
# Create invoice for debtor:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
current_invoice = economic.current_invoices.build
|
35
|
+
current_invoice.date = Time.now
|
36
|
+
current_invoice.due_date = Time.now + 15
|
37
|
+
current_invoice.exchange_rate = 100
|
38
|
+
current_invoice.is_vat_included = false
|
39
39
|
|
40
40
|
invoice_line = Economic::CurrentInvoiceLine.new
|
41
41
|
invoice_line.description = 'Line on invoice'
|
@@ -43,9 +43,31 @@ Usage example
|
|
43
43
|
invoice_line.product_handle = { :number => 101 }
|
44
44
|
invoice_line.quantity = 12
|
45
45
|
invoice_line.unit_net_price = 19.95
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
current_invoice.lines << invoice_line
|
47
|
+
|
48
|
+
current_invoice.save
|
49
|
+
|
50
|
+
# You can delete it by doing:
|
51
|
+
# current_invoice.destroy
|
52
|
+
|
53
|
+
invoice = current_invoice.book
|
54
|
+
|
55
|
+
# Create a debtor payment
|
56
|
+
|
57
|
+
cash_book = economic.cash_books.all.last # Or find it by its number
|
58
|
+
|
59
|
+
# The reason debtor payments are done this way is because we don't want to specify the voucher number. If we build the cash book entry ourselves,
|
60
|
+
# without specifying the voucher number, the API will complain. This way, E-Conomics will assign a voucher number for us.
|
61
|
+
|
62
|
+
cash_book_entry = cash_book.entries.create_debtor_payment(:debtor_handle => debtor.handle, :contra_account_handle => { :number => '1920' })
|
63
|
+
cash_book_entry.cash_book_entry_type = "DebtorPayment" # For some reason, we need to specify this.
|
64
|
+
cash_book_entry.amount = -123.45
|
65
|
+
cash_book_entry.currency_handle = { "Code" => "DKK" }
|
66
|
+
cash_book_entry.debtor_invoice_number = invoice.number
|
67
|
+
cash_book_entry.text = "Payment, invoice #{ invoice.number }"
|
68
|
+
cash_book_entry.save
|
69
|
+
|
70
|
+
cash_book.book
|
49
71
|
|
50
72
|
|
51
73
|
How to enable e-conomic API access
|
@@ -61,12 +83,15 @@ It doesn't do everything
|
|
61
83
|
|
62
84
|
Not even remotely... For now, limited to a small subset of all the [available operations](https://www.e-conomic.com/secure/api1/EconomicWebService.asmx):
|
63
85
|
|
64
|
-
| Create | Read | Update
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
86
|
+
| Create | Read | Update | Delete
|
87
|
+
-------------------+--------+------+--------+-------
|
88
|
+
CashBook | X | X | X | X
|
89
|
+
CashBookEntry | X | X | X | X
|
90
|
+
CurrentInvoice | X | X | X | X
|
91
|
+
CurrentInvoiceLine | X | X | X | X
|
92
|
+
Debtor | X | X | X | X
|
93
|
+
DebtorContact | X | X | X | X
|
94
|
+
Invoice | X | X | |
|
70
95
|
|
71
96
|
|
72
97
|
Credits
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'economic/entity'
|
2
|
+
|
3
|
+
module Economic
|
4
|
+
class Account < Entity
|
5
|
+
has_properties :name, :number, :balance, :block_direct_entries, :contra_account, :debit_credit, :department, :distribution_key, :is_accessible, :opening_account, :total_from, :type, :vat_account
|
6
|
+
|
7
|
+
|
8
|
+
def handle
|
9
|
+
Handle.new({:name => @name})
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def build_soap_data
|
16
|
+
data = ActiveSupport::OrderedHash.new
|
17
|
+
|
18
|
+
data['Handle'] = handle.to_hash
|
19
|
+
data['Name'] = handle.number
|
20
|
+
data['Number'] = number
|
21
|
+
|
22
|
+
return data
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'economic/entity'
|
2
|
+
|
3
|
+
module Economic
|
4
|
+
|
5
|
+
# Represents a cash book in E-conomic.
|
6
|
+
#
|
7
|
+
# API documentation: http://www.e-conomic.com/apidocs/Documentation/T_Economic_Api_ICashBook.html
|
8
|
+
class CashBook < Entity
|
9
|
+
has_properties :name, :number
|
10
|
+
|
11
|
+
def handle
|
12
|
+
Handle.new({:number => @number})
|
13
|
+
end
|
14
|
+
|
15
|
+
def entries
|
16
|
+
CashBookEntryProxy.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Books all entries in the cashbook. Returns book result.
|
20
|
+
def book
|
21
|
+
response = session.request(soap_action(:book)) do
|
22
|
+
soap.body = { "cashBookHandle" => handle.to_hash }
|
23
|
+
end
|
24
|
+
response[:number].to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def build_soap_data
|
30
|
+
data = ActiveSupport::OrderedHash.new
|
31
|
+
|
32
|
+
data['Handle'] = handle.to_hash
|
33
|
+
data['Name'] = name
|
34
|
+
data['Number'] = number
|
35
|
+
|
36
|
+
return data
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'economic/entity'
|
2
|
+
|
3
|
+
module Economic
|
4
|
+
|
5
|
+
# Represents a cash book in E-conomic.
|
6
|
+
#
|
7
|
+
# API documentation: http://www.e-conomic.com/apidocs/Documentation/T_Economic_Api_ICashBook.html
|
8
|
+
class CashBookEntry < Entity
|
9
|
+
has_properties :id1,
|
10
|
+
:id2,
|
11
|
+
:account_handle,
|
12
|
+
:amount,
|
13
|
+
:amount_default_currency,
|
14
|
+
:bank_payment_creditor_id,
|
15
|
+
:bank_payment_creditor_invoice_id,
|
16
|
+
:bank_payment_type_handle,
|
17
|
+
:capitalise_handle,
|
18
|
+
:cash_book_handle,
|
19
|
+
:contra_account_handle,
|
20
|
+
:contra_vat_account_handle,
|
21
|
+
:cost_type_handle,
|
22
|
+
:creditor_handle,
|
23
|
+
:creditor_invoice_number,
|
24
|
+
:currency_handle,
|
25
|
+
:date,
|
26
|
+
:debtor_handle,
|
27
|
+
:debtor_invoice_number,
|
28
|
+
:department_handle,
|
29
|
+
:distribution_key_handle,
|
30
|
+
:due_date,
|
31
|
+
:employee_handle,
|
32
|
+
:end_date,
|
33
|
+
:project_handle,
|
34
|
+
:start_date,
|
35
|
+
:text,
|
36
|
+
:cash_book_entry_type,
|
37
|
+
:vat_account_handle,
|
38
|
+
:voucher_number
|
39
|
+
|
40
|
+
def initialize_defaults
|
41
|
+
self.account_handle = nil
|
42
|
+
self.amount = 0
|
43
|
+
self.amount_default_currency = 0
|
44
|
+
self.bank_payment_creditor_id = 0
|
45
|
+
self.bank_payment_creditor_invoice_id = 0
|
46
|
+
self.bank_payment_type_handle = nil
|
47
|
+
self.capitalise_handle = nil
|
48
|
+
self.cash_book_handle = nil
|
49
|
+
self.contra_account_handle = nil
|
50
|
+
self.contra_vat_account_handle = nil
|
51
|
+
self.cost_type_handle = nil
|
52
|
+
self.creditor_handle = nil
|
53
|
+
self.creditor_invoice_number = nil
|
54
|
+
self.currency_handle = nil
|
55
|
+
self.date = Time.now
|
56
|
+
self.debtor_handle = nil
|
57
|
+
self.debtor_invoice_number = nil
|
58
|
+
self.department_handle = nil
|
59
|
+
self.distribution_key_handle = nil
|
60
|
+
self.due_date = nil
|
61
|
+
self.employee_handle = nil
|
62
|
+
self.end_date = nil
|
63
|
+
self.project_handle = nil
|
64
|
+
self.start_date = Time.now
|
65
|
+
self.text = ""
|
66
|
+
self.cash_book_entry_type = ""
|
67
|
+
self.vat_account_handle = nil
|
68
|
+
self.voucher_number = 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def handle
|
72
|
+
Handle.new(:id1 => @id1, :id2 => @id2)
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_soap_data
|
76
|
+
data = ActiveSupport::OrderedHash.new
|
77
|
+
|
78
|
+
data['Handle'] = handle.to_hash
|
79
|
+
data['Type'] = cash_book_entry_type unless cash_book_entry_type.blank?
|
80
|
+
data['CashBookHandle'] = { 'Number' => cash_book_handle[:number] } unless cash_book_handle.blank?
|
81
|
+
data['DebtorHandle'] = { 'Number' => debtor_handle[:number] } unless debtor_handle.blank?
|
82
|
+
data['CreditorHandle'] = { 'Number' => creditor_handle[:number] } unless creditor_handle.blank?
|
83
|
+
data['AccountHandle'] = { 'Number' => account_handle[:number] } unless account_handle.blank?
|
84
|
+
data['ContraAccountHandle'] = { 'Number' => contra_account_handle[:number] } unless contra_account_handle.blank?
|
85
|
+
data['Date'] = date
|
86
|
+
data['VoucherNumber'] = voucher_number
|
87
|
+
data['Text'] = text
|
88
|
+
data['AmountDefaultCurrency'] = amount_default_currency
|
89
|
+
data['CurrencyHandle'] = { 'Code' => currency_handle[:code] } unless currency_handle.blank?
|
90
|
+
data['Amount'] = amount
|
91
|
+
data['VatAccountHandle'] = { 'Number' => vat_account_handle[:number] } unless vat_account_handle.blank?
|
92
|
+
data['ContraVatAccountHandle'] = { 'Number' => contra_vat_account_handle[:number] } unless contra_vat_account_handle.blank?
|
93
|
+
data['DebtorInvoiceNumber'] = debtor_invoice_number unless debtor_invoice_number.blank?
|
94
|
+
data['CreditorInvoiceNumber'] = creditor_invoice_number unless creditor_invoice_number.blank?
|
95
|
+
data['DueDate'] = due_date
|
96
|
+
data['DepartmentHandle'] = { 'Number' => department_handle[:number] } unless department_handle.blank?
|
97
|
+
data['DistributionKeyHandle'] = { 'Number' => distribution_key_handle[:number] } unless distribution_key_handle.blank?
|
98
|
+
data['ProjectHandle'] = { 'Number' => project_handle[:number] } unless project_handle.blank?
|
99
|
+
data['CostTypeHandle'] = { 'Number' => cost_type_handle[:number] } unless cost_type_handle.blank?
|
100
|
+
data['BankPaymentTypeHandle'] = { 'Number' => bank_payment_type_handle[:number] } unless bank_payment_type_handle.blank?
|
101
|
+
data['BankPaymentCreditorId'] = bank_payment_creditor_id
|
102
|
+
data['BankPaymentCreditorInvoiceId'] = bank_payment_creditor_invoice_id
|
103
|
+
data['CapitaliseHandle'] = { 'Number' => capitalise_handle[:number] } unless capitalise_handle.blank?
|
104
|
+
data['StartDate'] = start_date
|
105
|
+
data['EndDate'] = end_date
|
106
|
+
data['EmployeeHandle'] = { 'Number' => employee_handle[:number] } unless employee_handle.blank?
|
107
|
+
|
108
|
+
return data
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -26,12 +26,40 @@ module Economic
|
|
26
26
|
#
|
27
27
|
# invoice.save
|
28
28
|
class CurrentInvoice < Entity
|
29
|
-
has_properties :id, :debtor_handle, :debtor_name, :debtor_address, :debtor_postal_code, :debtor_city, :debtor_country, :date, :term_of_payment_handle, :due_date, :currency_handle, :exchange_rate, :is_vat_included, :layout_handle, :delivery_date, :net_amount, :vat_amount, :gross_amount, :margin, :margin_as_percent
|
29
|
+
has_properties :id, :debtor_handle, :debtor_name, :debtor_address, :debtor_postal_code, :debtor_city, :debtor_country, :attention_handle, :date, :term_of_payment_handle, :due_date, :currency_handle, :exchange_rate, :is_vat_included, :layout_handle, :delivery_date, :net_amount, :vat_amount, :gross_amount, :margin, :margin_as_percent, :heading
|
30
30
|
|
31
31
|
def initialize(properties = {})
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
+
def attention
|
36
|
+
return nil if attention_handle.blank?
|
37
|
+
@attention ||= session.contacts.find(attention_handle)
|
38
|
+
end
|
39
|
+
|
40
|
+
def attention=(contact)
|
41
|
+
self.attention_handle = contact.handle
|
42
|
+
@attention = contact
|
43
|
+
end
|
44
|
+
|
45
|
+
def attention_handle=(handle)
|
46
|
+
@attention = nil unless handle == @attention_handle
|
47
|
+
@attention_handle = handle
|
48
|
+
end
|
49
|
+
|
50
|
+
# Books a current invoice. An invoice number greater than all other invoice numbers will be
|
51
|
+
# assigned to the resulting Economic::Invoice.
|
52
|
+
#
|
53
|
+
# Returns the resulting Economic::Invoice object
|
54
|
+
def book
|
55
|
+
response = session.request soap_action(:book) do
|
56
|
+
soap.body = { "currentInvoiceHandle" => handle.to_hash }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Find the created Invoice
|
60
|
+
session.invoices.find(response[:number])
|
61
|
+
end
|
62
|
+
|
35
63
|
def debtor
|
36
64
|
return nil if debtor_handle.blank?
|
37
65
|
@debtor ||= session.debtors.find(debtor_handle)
|
@@ -66,6 +94,7 @@ module Economic
|
|
66
94
|
self.is_vat_included = nil
|
67
95
|
self.layout_handle = nil
|
68
96
|
self.delivery_date = nil
|
97
|
+
self.heading = nil
|
69
98
|
self.net_amount = 0
|
70
99
|
self.vat_amount = 0
|
71
100
|
self.gross_amount = 0
|
@@ -85,6 +114,7 @@ module Economic
|
|
85
114
|
data['DebtorPostalCode'] = debtor_postal_code unless debtor_postal_code.blank?
|
86
115
|
data['DebtorCity'] = debtor_city unless debtor_city.blank?
|
87
116
|
data['DebtorCountry'] = debtor_country unless debtor_country.blank?
|
117
|
+
data['AttentionHandle'] = { 'Id' => attention_handle[:id] } unless attention_handle.blank?
|
88
118
|
data['Date'] = date.iso8601 unless date.blank?
|
89
119
|
data['TermOfPaymentHandle'] = { 'Id' => term_of_payment_handle[:id] } unless term_of_payment_handle.blank?
|
90
120
|
data['DueDate'] = (due_date.blank? ? nil : due_date.iso8601)
|
@@ -93,6 +123,7 @@ module Economic
|
|
93
123
|
data['IsVatIncluded'] = is_vat_included
|
94
124
|
data['LayoutHandle'] = { 'Id' => layout_handle[:id] } unless layout_handle.blank?
|
95
125
|
data['DeliveryDate'] = delivery_date ? delivery_date.iso8601 : nil
|
126
|
+
data['Heading'] = heading unless heading.blank?
|
96
127
|
data['NetAmount'] = net_amount
|
97
128
|
data['VatAmount'] = vat_amount
|
98
129
|
data['GrossAmount'] = gross_amount
|
@@ -114,4 +145,4 @@ module Economic
|
|
114
145
|
end
|
115
146
|
end
|
116
147
|
|
117
|
-
end
|
148
|
+
end
|
data/lib/economic/debtor.rb
CHANGED
@@ -31,11 +31,12 @@ module Economic
|
|
31
31
|
Handle.new({:number => @number})
|
32
32
|
end
|
33
33
|
|
34
|
+
# Returns the Debtors contacts
|
34
35
|
def contacts
|
35
36
|
@contacts ||= DebtorContactProxy.new(self)
|
36
37
|
end
|
37
38
|
|
38
|
-
# Provides access to the current invoices - ie invoices that haven't yet been booked
|
39
|
+
# Provides access to the current invoices for Debtor - ie invoices that haven't yet been booked
|
39
40
|
def current_invoices
|
40
41
|
@current_invoices ||= CurrentInvoiceProxy.new(self)
|
41
42
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Economic::Entity
|
2
|
+
class Handle
|
3
|
+
attr_accessor :id, :id1, :id2, :number
|
4
|
+
|
5
|
+
def initialize(hash)
|
6
|
+
verify_sanity_of_arguments!(hash)
|
7
|
+
hash = prepare_hash_argument(hash) unless hash.is_a?(self.class)
|
8
|
+
|
9
|
+
@id = hash[:id].to_i if hash[:id]
|
10
|
+
@id1 = hash[:id1].to_i if hash[:id1]
|
11
|
+
@id2 = hash[:id2].to_i if hash[:id2]
|
12
|
+
@number = hash[:number].to_i if hash[:number]
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
hash = {}
|
17
|
+
hash['Id'] = id unless id.blank?
|
18
|
+
hash['Id1'] = id1 unless id1.blank?
|
19
|
+
hash['Id2'] = id2 unless id2.blank?
|
20
|
+
hash['Number'] = number unless number.blank?
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
{:id => @id, :id1 => @id1, :id2 => @id2, :number => @number}[key]
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
return false if other.nil?
|
30
|
+
return false unless other.respond_to?(:id) && other.respond_to?(:number)
|
31
|
+
self.id == other.id && self.number == other.number
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Raises exceptions if hash doesn't contain values we can use to construct a new handle
|
37
|
+
def verify_sanity_of_arguments!(hash)
|
38
|
+
return if hash.is_a?(self.class)
|
39
|
+
|
40
|
+
if hash.nil? || (!hash.respond_to?(:to_i) && (!hash.respond_to?(:keys) && !hash.respond_to?(:values)))
|
41
|
+
raise ArgumentError.new("Expected Number, Hash or Economic::Entity::Handle - got #{hash.inspect}")
|
42
|
+
end
|
43
|
+
|
44
|
+
if hash.respond_to?(:keys)
|
45
|
+
unknown_keys = hash.keys - [:id, :id1, :id2, :number, "Number", "Id", "Id1", "Id2"]
|
46
|
+
raise ArgumentError.new("Unknown keys in handle: #{unknown_keys.inspect}") unless unknown_keys.empty?
|
47
|
+
|
48
|
+
not_to_iable = hash.select { |k, v| !v.respond_to?(:to_i) }
|
49
|
+
raise ArgumentError.new("All values must respond to to_i. #{not_to_iable.inspect} didn't") unless not_to_iable.empty?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Examples
|
54
|
+
#
|
55
|
+
# prepare_hash_argument(12) #=> {:id => 12}
|
56
|
+
# prepare_hash_argument(:id => 12) #=> {:id => 12}
|
57
|
+
# prepare_hash_argument('Id' => 12) #=> {:id => 12}
|
58
|
+
# prepare_hash_argument('Id' => 12, 'Number' => 13) #=> {:id => 12, :number => 13}
|
59
|
+
def prepare_hash_argument(hash)
|
60
|
+
hash = {:id => hash.to_i} if hash.respond_to?(:to_i) unless hash.blank?
|
61
|
+
hash[:id] ||= hash['Id']
|
62
|
+
hash[:number] ||= hash['Number']
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/economic/entity.rb
CHANGED
@@ -1,31 +1,7 @@
|
|
1
|
+
require 'economic/entity/handle'
|
2
|
+
|
1
3
|
module Economic
|
2
4
|
class Entity
|
3
|
-
class Handle
|
4
|
-
attr_accessor :id, :number
|
5
|
-
|
6
|
-
def initialize(hash)
|
7
|
-
@id = hash[:id]
|
8
|
-
@number = hash[:number]
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_hash
|
12
|
-
hash = {}
|
13
|
-
hash['Id'] = id unless id.blank?
|
14
|
-
hash['Number'] = number unless number.blank?
|
15
|
-
hash
|
16
|
-
end
|
17
|
-
|
18
|
-
def [](key)
|
19
|
-
{:id => @id, :number => @number}[key]
|
20
|
-
end
|
21
|
-
|
22
|
-
def ==(other)
|
23
|
-
return false if other.nil?
|
24
|
-
return false unless other.respond_to?(:id) && other.respond_to?(:number)
|
25
|
-
self.id == other.id && self.number == other.number
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
5
|
# Internal accessors
|
30
6
|
attr_accessor :persisted, :session, :partial
|
31
7
|
|
@@ -71,6 +47,17 @@ module Economic
|
|
71
47
|
class_name_without_modules = class_name.split('::').last
|
72
48
|
"#{class_name_without_modules.snakecase}_#{action.to_s.snakecase}".intern
|
73
49
|
end
|
50
|
+
|
51
|
+
# Returns a symbol based on the name of the entity. Used to request and read data responses.
|
52
|
+
#
|
53
|
+
# Entity.key #=> :entity
|
54
|
+
# CurrentInvoice.key #=> :current_invoice
|
55
|
+
def key
|
56
|
+
key = self.name
|
57
|
+
key = Economic::Support::String.demodulize(key)
|
58
|
+
key = Economic::Support::String.underscore(key)
|
59
|
+
key.intern
|
60
|
+
end
|
74
61
|
end
|
75
62
|
|
76
63
|
def handle
|
@@ -90,12 +77,12 @@ module Economic
|
|
90
77
|
|
91
78
|
# Updates Entity with its data from the API
|
92
79
|
def get_data
|
93
|
-
response = proxy.get_data(
|
80
|
+
response = proxy.get_data(handle)
|
94
81
|
self.update_properties(response)
|
95
82
|
self.partial = false
|
96
83
|
self.persisted = true
|
97
84
|
end
|
98
|
-
|
85
|
+
|
99
86
|
# Returns the number of Entity. This does not trigger a load from the API even if Entity is partial
|
100
87
|
def number
|
101
88
|
@number
|
@@ -106,13 +93,6 @@ module Economic
|
|
106
93
|
@id
|
107
94
|
end
|
108
95
|
|
109
|
-
def handle
|
110
|
-
handle = {}
|
111
|
-
handle[:id] = id unless id.blank?
|
112
|
-
handle[:number] = number unless number.blank?
|
113
|
-
handle
|
114
|
-
end
|
115
|
-
|
116
96
|
# Returns true if CurrentInvoiceLine has been persisted in e-conomic
|
117
97
|
def persisted?
|
118
98
|
!!@persisted
|
@@ -141,6 +121,19 @@ module Economic
|
|
141
121
|
create_or_update
|
142
122
|
end
|
143
123
|
|
124
|
+
# Deletes entity permanently from E-conomic.
|
125
|
+
def destroy
|
126
|
+
handleKey = "#{camel_back(class_name)}Handle"
|
127
|
+
response = session.request soap_action(:delete) do
|
128
|
+
soap.body = { handleKey => handle.to_hash }
|
129
|
+
end
|
130
|
+
|
131
|
+
@persisted = false
|
132
|
+
@partial = true
|
133
|
+
|
134
|
+
response
|
135
|
+
end
|
136
|
+
|
144
137
|
# Updates properties of Entity with the values from hash
|
145
138
|
def update_properties(hash)
|
146
139
|
hash.each do |key, value|
|
@@ -169,6 +162,8 @@ module Economic
|
|
169
162
|
if response
|
170
163
|
@number = response[:number]
|
171
164
|
@id = response[:id]
|
165
|
+
@id1 = response[:id1]
|
166
|
+
@id2 = response[:id2]
|
172
167
|
end
|
173
168
|
|
174
169
|
@persisted = true
|
@@ -196,6 +191,14 @@ module Economic
|
|
196
191
|
self.class.soap_action(action)
|
197
192
|
end
|
198
193
|
|
194
|
+
def class_name
|
195
|
+
self.class.to_s.split("::").last
|
196
|
+
end
|
197
|
+
|
198
|
+
def camel_back(name)
|
199
|
+
name[0,1].downcase + name[1..-1]
|
200
|
+
end
|
201
|
+
|
199
202
|
end
|
200
203
|
|
201
|
-
end
|
204
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'economic/entity'
|
2
|
+
|
3
|
+
module Economic
|
4
|
+
class Invoice < Entity
|
5
|
+
has_properties :number, :net_amount, :vat_amount, :due_date, :debtor_handle, :debtor_name, :debtor_name, :debtor_address, :debtor_postal_code, :debtor_city, :debtor_country, :debtor_ean, :attention_handle, :heading
|
6
|
+
|
7
|
+
def attention
|
8
|
+
return nil if attention_handle.blank?
|
9
|
+
@attention ||= session.contacts.find(attention_handle)
|
10
|
+
end
|
11
|
+
|
12
|
+
def attention=(contact)
|
13
|
+
self.attention_handle = contact.handle
|
14
|
+
@attention = contact
|
15
|
+
end
|
16
|
+
|
17
|
+
def attention_handle=(handle)
|
18
|
+
@attention = nil unless handle == @attention_handle
|
19
|
+
@attention_handle = handle
|
20
|
+
end
|
21
|
+
|
22
|
+
def debtor
|
23
|
+
return nil if debtor_handle.blank?
|
24
|
+
@debtor ||= session.debtors.find(debtor_handle)
|
25
|
+
end
|
26
|
+
|
27
|
+
def debtor=(debtor)
|
28
|
+
self.debtor_handle = debtor.handle
|
29
|
+
@debtor = debtor
|
30
|
+
end
|
31
|
+
|
32
|
+
def debtor_handle=(handle)
|
33
|
+
@debtor = nil unless handle == @debtor_handle
|
34
|
+
@debtor_handle = handle
|
35
|
+
end
|
36
|
+
|
37
|
+
def remainder
|
38
|
+
session.request(soap_action(:get_remainder)) do
|
39
|
+
soap.body = { "invoiceHandle" => handle.to_hash }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the PDF version of Invoice as a String.
|
44
|
+
#
|
45
|
+
# To get it as a file you can do:
|
46
|
+
#
|
47
|
+
# File.open("invoice.pdf", 'wb') do |file|
|
48
|
+
# file << invoice.pdf
|
49
|
+
# end
|
50
|
+
def pdf
|
51
|
+
response = session.request soap_action(:get_pdf) do
|
52
|
+
soap.body = { "invoiceHandle" => handle.to_hash }
|
53
|
+
end
|
54
|
+
|
55
|
+
Base64.decode64(response)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|