rconomic 0.2.1 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|