klarna-xmlrpc 0.2.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/.travis.yml +13 -0
- data/Gemfile +14 -0
- data/Guardfile +16 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +139 -0
- data/Rakefile +22 -0
- data/TODO +30 -0
- data/examples/Gemfile +8 -0
- data/examples/config/initializer.rb +15 -0
- data/examples/console.rb +71 -0
- data/examples/public/images/klarna.png +0 -0
- data/examples/public/images/ruby.png +0 -0
- data/examples/views/_address.haml +22 -0
- data/examples/views/_articles.haml +21 -0
- data/examples/views/checkout_page_example.haml +2 -0
- data/examples/views/essential/add_transaction/_form.haml +32 -0
- data/examples/views/essential/add_transaction/result.haml +7 -0
- data/examples/views/essential/calculate_monthly_cost/_form.haml +16 -0
- data/examples/views/essential/calculate_monthly_cost/result.haml +7 -0
- data/examples/views/essential/get_addresses/_form.haml +9 -0
- data/examples/views/essential/get_addresses/result.haml +8 -0
- data/examples/views/index.haml +296 -0
- data/examples/views/layout.haml +48 -0
- data/examples/views/payment_terms_example.haml +102 -0
- data/examples/views/product_page_example.haml +2 -0
- data/examples/views/reservation/activate_reservation/_form.haml +54 -0
- data/examples/views/reservation/activate_reservation/result.haml +7 -0
- data/examples/views/reservation/cancel_reservation/_form.haml +8 -0
- data/examples/views/reservation/cancel_reservation/result.haml +7 -0
- data/examples/views/reservation/change_reservation/_form.haml +10 -0
- data/examples/views/reservation/change_reservation/result.haml +7 -0
- data/examples/views/reservation/reserve_amount/_form.haml +58 -0
- data/examples/views/reservation/reserve_amount/result.haml +7 -0
- data/examples/views/reservation/reserve_ocr_numbers/_form.haml +8 -0
- data/examples/views/reservation/reserve_ocr_numbers/result.haml +7 -0
- data/examples/views/reservation/split_reservation/_form.haml +14 -0
- data/examples/views/reservation/split_reservation/result.haml +7 -0
- data/examples/views/special/get_pclasses/_form.haml +8 -0
- data/examples/views/special/get_pclasses/result.haml +7 -0
- data/examples/views/special/invoice_address/_form.haml +8 -0
- data/examples/views/special/invoice_address/result.haml +7 -0
- data/examples/views/special/invoice_amount/_form.haml +8 -0
- data/examples/views/special/invoice_amount/result.haml +7 -0
- data/examples/views/special/is_invoice_paid/_form.haml +8 -0
- data/examples/views/special/is_invoice_paid/result.haml +7 -0
- data/examples/views/special/update_charge_amount/_form.haml +15 -0
- data/examples/views/special/update_charge_amount/result.haml +7 -0
- data/examples/views/special/update_goods_quantity/_form.haml +17 -0
- data/examples/views/special/update_goods_quantity/result.haml +7 -0
- data/examples/views/special/update_order_number/_form.haml +10 -0
- data/examples/views/special/update_order_number/result.haml +7 -0
- data/examples/views/useful/activate_invoice/_form.haml +9 -0
- data/examples/views/useful/activate_invoice/result.haml +7 -0
- data/examples/views/useful/credit_invoice/_form.haml +11 -0
- data/examples/views/useful/credit_invoice/result.haml +7 -0
- data/examples/views/useful/delete_invoice/_form.haml +9 -0
- data/examples/views/useful/delete_invoice/result.haml +7 -0
- data/examples/views/useful/email_invoice/_form.haml +9 -0
- data/examples/views/useful/email_invoice/result.haml +7 -0
- data/examples/views/useful/has_account/_form.haml +9 -0
- data/examples/views/useful/has_account/result.haml +7 -0
- data/examples/views/useful/return_amount/_form.haml +15 -0
- data/examples/views/useful/return_amount/result.haml +7 -0
- data/examples/views/useful/send_invoice/_form.haml +9 -0
- data/examples/views/useful/send_invoice/result.haml +7 -0
- data/examples/web.rb +349 -0
- data/klarna.gemspec +34 -0
- data/lib/klarna.rb +171 -0
- data/lib/klarna/api.rb +187 -0
- data/lib/klarna/api/client.rb +126 -0
- data/lib/klarna/api/constants.rb +647 -0
- data/lib/klarna/api/errors.rb +154 -0
- data/lib/klarna/api/methods.rb +16 -0
- data/lib/klarna/api/methods/cost_calculations.rb +134 -0
- data/lib/klarna/api/methods/invoicing.rb +304 -0
- data/lib/klarna/api/methods/reservation.rb +188 -0
- data/lib/klarna/api/methods/standard.rb +126 -0
- data/lib/klarna/version.rb +5 -0
- data/test/fixtures/api/companies.yml +97 -0
- data/test/fixtures/api/pclasses.yml +37 -0
- data/test/fixtures/api/persons.yml +144 -0
- data/test/fixtures/api/stores.yml +6 -0
- data/test/fixtures/klarna.yml +10 -0
- data/test/klarna/api/client_test.rb +288 -0
- data/test/klarna/api/errors_test.rb +34 -0
- data/test/klarna/api/methods/cost_calculations_test.rb +78 -0
- data/test/klarna/api/methods/invoicing_test.rb +409 -0
- data/test/klarna/api/methods/reservation_test.rb +66 -0
- data/test/klarna/api/methods/standard_test.rb +244 -0
- data/test/klarna/api_test.rb +184 -0
- data/test/klarna_test.rb +204 -0
- data/test/support/assertions_helper.rb +40 -0
- data/test/test_helper.rb +55 -0
- metadata +335 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'xmlrpc/client'
|
3
|
+
|
4
|
+
module Klarna
|
5
|
+
module API
|
6
|
+
module Errors
|
7
|
+
|
8
|
+
ERROR_CODES = {
|
9
|
+
1103 => :estore_overrun,
|
10
|
+
1104 => :estore_blacklisted,
|
11
|
+
1999 => :misc_estore_error,
|
12
|
+
2101 => :credit,
|
13
|
+
2102 => :amount,
|
14
|
+
2103 => :customer_credit_overrun,
|
15
|
+
2104 => :blocked,
|
16
|
+
2105 => :unpaid_bills,
|
17
|
+
2106 => :customer_not_accepted,
|
18
|
+
2107 => :customer_blacklisted,
|
19
|
+
2201 => :pno,
|
20
|
+
2202 => :invalid_pno,
|
21
|
+
2203 => :pno_not_real_person,
|
22
|
+
2204 => :dead,
|
23
|
+
2205 => :under_aged,
|
24
|
+
2206 => :customer_not_18,
|
25
|
+
2301 => :no_such_person,
|
26
|
+
2302 => :customer_missing,
|
27
|
+
2303 => :no_such_customer,
|
28
|
+
2304 => :unknown_customer,
|
29
|
+
2305 => :bad_customer_password,
|
30
|
+
2401 => :tno_not_found,
|
31
|
+
2402 => :pin_error,
|
32
|
+
2403 => :wrong_pin,
|
33
|
+
2404 => :no_pin,
|
34
|
+
2405 => :orgno,
|
35
|
+
2999 => :misc_customer_error,
|
36
|
+
3101 => :foreign_addr,
|
37
|
+
3102 => :bad_addr,
|
38
|
+
3103 => :bad_address,
|
39
|
+
3104 => :postno,
|
40
|
+
3105 => :bad_postno,
|
41
|
+
3106 => :bad_name,
|
42
|
+
3107 => :address,
|
43
|
+
3108 => :no_address,
|
44
|
+
3201 => :cellno,
|
45
|
+
3202 => :telno,
|
46
|
+
3203 => :email,
|
47
|
+
3204 => :country,
|
48
|
+
3205 => :city,
|
49
|
+
3206 => :postno,
|
50
|
+
3207 => :street,
|
51
|
+
3208 => :client_ip,
|
52
|
+
3209 => :proto_vsn,
|
53
|
+
3210 => :goods_list,
|
54
|
+
3211 => :artnos,
|
55
|
+
3301 => :bad_name_and_address,
|
56
|
+
3302 => :bad_last_name,
|
57
|
+
3303 => :bad_first_name,
|
58
|
+
3304 => :bad_first_name_and_last_name,
|
59
|
+
3999 => :misc_submission_error,
|
60
|
+
6101 => :orgno_pclass_not_allowed,
|
61
|
+
6102 => :sum_low_for_pclass,
|
62
|
+
6103 => :unknown_pclass,
|
63
|
+
6104 => :not_annuity_pclass,
|
64
|
+
6999 => :misc_pclass_error,
|
65
|
+
7101 => :no_such_subscription,
|
66
|
+
7102 => :not_unique_subscription_no,
|
67
|
+
7103 => :terminated,
|
68
|
+
7104 => :already_set,
|
69
|
+
7105 => :need_email_addr,
|
70
|
+
7999 => :misc_subscription_error,
|
71
|
+
8101 => :unknown_invoice,
|
72
|
+
8102 => :negative_invoice,
|
73
|
+
8103 => :invoice_not_active,
|
74
|
+
8104 => :invoice_bad_status,
|
75
|
+
8105 => :invoice_is_passive,
|
76
|
+
8106 => :invoice_is_archived,
|
77
|
+
8107 => :invoice_is_suspect,
|
78
|
+
8108 => :invoice_is_frozen,
|
79
|
+
8109 => :invoice_is_pre_pay,
|
80
|
+
8110 => :invoice_stale,
|
81
|
+
8111 => :invoice_not_passive_or_frozen,
|
82
|
+
8112 => :invoice_in_test_mode,
|
83
|
+
8113 => :invoice_not_passive,
|
84
|
+
8114 => :invno,
|
85
|
+
8999 => :misc_invoice_error,
|
86
|
+
9101 => :cno_already_in_use,
|
87
|
+
9102 => :unknown_csid,
|
88
|
+
9103 => :not_allowed_operation,
|
89
|
+
9104 => :ip_from_wrong_country,
|
90
|
+
9105 => :bad_type,
|
91
|
+
9106 => :unknown_type,
|
92
|
+
9107 => :bad_artnolist,
|
93
|
+
9108 => :unknown_artno,
|
94
|
+
9109 => :rno,
|
95
|
+
9110 => :split,
|
96
|
+
9111 => :bad_order_no,
|
97
|
+
9112 => :bad_ocr,
|
98
|
+
9113 => :unknown_estore,
|
99
|
+
9114 => :invalid_estore_secret,
|
100
|
+
9115 => :bad_module_vsn,
|
101
|
+
9116 => :pno_encoding,
|
102
|
+
9117 => :currency,
|
103
|
+
9118 => :currency_country_pnoencoding,
|
104
|
+
9119 => :timeout
|
105
|
+
}.freeze
|
106
|
+
|
107
|
+
class KlarnaStandardError < ::StandardError
|
108
|
+
def initialize(message)
|
109
|
+
::Klarna.log message, :error
|
110
|
+
super(message)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class KlarnaArgumentError < ::ArgumentError
|
115
|
+
def initialize(message)
|
116
|
+
::Klarna.log message, :error
|
117
|
+
super(message)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class KlarnaCredentialsError < KlarnaStandardError
|
122
|
+
end
|
123
|
+
|
124
|
+
class KlarnaServiceError < ::XMLRPC::FaultException
|
125
|
+
alias :error_code :faultCode
|
126
|
+
alias :error_message :faultString
|
127
|
+
|
128
|
+
def initialize(error_code, error_key)
|
129
|
+
localized_error_message = ::Klarna::API::Errors.error_message(error_key)
|
130
|
+
message = ::Klarna.mode == :test ? "#{error_key} (#{[error_code, ERROR_CODES[error_code]].compact.join(' - ')})" : localized_error_message
|
131
|
+
::Klarna.log message, :error
|
132
|
+
super(error_code, message)
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_h
|
136
|
+
{:error_code => self.error_code, :error_message => self.error_message}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class << self
|
141
|
+
|
142
|
+
# Lookup localized string value for a specified error/exception code or key.
|
143
|
+
#
|
144
|
+
def error_message(id_or_key)
|
145
|
+
key = id_or_key.is_a?(Fixnum) ? ERROR_CODES[id_or_key] : id_or_key
|
146
|
+
key
|
147
|
+
end
|
148
|
+
alias :localized_error_message :error_message
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'klarna/api/methods/standard'
|
3
|
+
require 'klarna/api/methods/invoicing'
|
4
|
+
require 'klarna/api/methods/reservation'
|
5
|
+
require 'klarna/api/methods/cost_calculations'
|
6
|
+
|
7
|
+
module Klarna
|
8
|
+
module API
|
9
|
+
module Methods
|
10
|
+
include ::Klarna::API::Methods::Standard
|
11
|
+
include ::Klarna::API::Methods::Invoicing
|
12
|
+
include ::Klarna::API::Methods::Reservation
|
13
|
+
include ::Klarna::API::Methods::CostCalculations
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Klarna
|
4
|
+
module API
|
5
|
+
module Methods
|
6
|
+
module CostCalculations
|
7
|
+
|
8
|
+
# Purpose: Obtain pclass values from Klarna.
|
9
|
+
#
|
10
|
+
# == Note:
|
11
|
+
#
|
12
|
+
# This function is only to be used to obtain pclass values for stores ONE TIME ONLY.
|
13
|
+
# It is not allowed to use this function for continuous calculation of monthly costs or
|
14
|
+
# with every purchase in the checkout. The pclass values do NOT change.
|
15
|
+
#
|
16
|
+
def fetch_pclasses(currency_code)
|
17
|
+
# params = [
|
18
|
+
# self.store_id,
|
19
|
+
# currency_code,
|
20
|
+
# self.digest(currency_code)
|
21
|
+
# ]
|
22
|
+
# self.call(:fetch_pclasses, *params)
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Calculate monthly cost "in the most proper way".
|
27
|
+
#
|
28
|
+
def calculate_monthly_cost(sum, currency, pclass_id, flags = nil)
|
29
|
+
# # TODO: OpenStruct this
|
30
|
+
# pclasses = ::Klarna.store_pclasses[currency.to_s.underscore]
|
31
|
+
# month_count = pclasses[pclass_id][:months]
|
32
|
+
# monthly_fee = pclasses[pclass_id][:invoice_fee]
|
33
|
+
# start_fee = pclasses[pclass_id][:start_fee]
|
34
|
+
# rate = pclasses[pclass_id][:interest_rate]
|
35
|
+
# type = pclasses[pclass_id][:type] # QUESTION: Where do I get this from - not in API-call.
|
36
|
+
#
|
37
|
+
# # TODO: Call Klarna and ask where I get "type" from - not with pclasses.
|
38
|
+
# case type
|
39
|
+
# when ::Klarna::API::PClassFlags::ANNUITY
|
40
|
+
# self.periodic_cost(sum, month_count, monthly_fee, start_fee, rate, currency, flags)
|
41
|
+
# when ::Klarna::API::PClassFlags::DIVISOR
|
42
|
+
# self.monthly_cost(sum, month_count, monthly_fee, start_fee, rate, currency, flags)
|
43
|
+
# else
|
44
|
+
# raise InvalidArgumentError, "Invalid Klarna campaign/pclass type: #{type.inspect}"
|
45
|
+
# end
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
|
49
|
+
# Calculate the monthly cost for goods which can be paid for by part payment.
|
50
|
+
#
|
51
|
+
def periodic_cost(sum, month_count, monthly_fee, start_fee, rate, currency, flags = nil)
|
52
|
+
# daily_rate = self.calculate_daily_rate(rate)
|
53
|
+
# monthly_payment = self.calculate_monthly_payment(sum + start_fee, daily_rate, month_count)
|
54
|
+
# monthly_cost = monthly_payment + monthly_fee
|
55
|
+
# monthly_cost.round
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
# Calculate the monthly cost for account purchases.
|
60
|
+
#
|
61
|
+
def monthly_cost(sum, month_count, monthly_fee, start_fee, rate, currency, flags = nil)
|
62
|
+
# interest_cost = self.calculate_interest_cost(sum, rate)
|
63
|
+
# period_cost = (sum + interest_cost) / month_count
|
64
|
+
# flags ||= ::Klarna::API::MonthlyCostFlags::LIMIT
|
65
|
+
#
|
66
|
+
# # TODO: Remove this line - after debugging.
|
67
|
+
# ::Klarna.log [::Klarna::API::AVERAGE_INTEREST_PERIOD, calc_rate, interest_cost, period_cost].join(', ')
|
68
|
+
#
|
69
|
+
# monthly_cost = case flags
|
70
|
+
# when ::Klarna::API::MonthlyCostFlags::LIMIT
|
71
|
+
# period_cost
|
72
|
+
# when ::Klarna::API::MonthlyCostFlags::ACTUAL
|
73
|
+
# begin
|
74
|
+
# lowest_monthly_payment = ::Klarna::API::LOWEST_PAYMENT_BY_CURRENCY[currency]
|
75
|
+
# rescue
|
76
|
+
# raise ::Klarna::API::KlarnaStandardError,
|
77
|
+
# "No such currency: #{currency.inspect}. Valid currencies: SEK:1, NOK:2, EUR:3, DKK:4"
|
78
|
+
# end
|
79
|
+
# period_cost += monthly_fee
|
80
|
+
# (period_cost < lowest_monthly_payment) ? lowest_monthly_payment : period_cost
|
81
|
+
# else
|
82
|
+
# raise ::Klarna::API::KlarnaStandardError,
|
83
|
+
# "Invalid flag: #{flags.inspect}. Valid flags: LIMIT:0, ACTUAL:1"
|
84
|
+
# end
|
85
|
+
# ::Klarna.log_result("Calculation: monthly_cost = %s") do
|
86
|
+
# self.round_up(monthly_cost, currency)
|
87
|
+
# end
|
88
|
+
raise NotImplementedError
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def calculate_interest_cost(sum, rate)
|
94
|
+
# rate *= 100.0 if rate < 100.0
|
95
|
+
# calc_rate = (rate / 10000)
|
96
|
+
# (::Klarna::API::AVERAGE_INTEREST_PERIOD / ::Klarna::API::DAYS_IN_A_YEAR) * calc_rate * sum
|
97
|
+
raise NotImplementedError
|
98
|
+
end
|
99
|
+
|
100
|
+
def calculate_monthly_payment(sum, daily_rate, month_count)
|
101
|
+
# sum = sum.to_double
|
102
|
+
# total_dates = (month_count - 1) * 30
|
103
|
+
# denominator = self.get_denominator(dailyrate, total_dates)
|
104
|
+
# total_dates += 60
|
105
|
+
# (dailyrate ** totdates) * sum / denominator
|
106
|
+
raise NotImplementedError
|
107
|
+
end
|
108
|
+
|
109
|
+
def calculate_daily_rate(rate)
|
110
|
+
# ((rate.to_decimal / 10000.0) + 1.0) ** (1 / ::Klarna::API::DAYS_IN_A_YEAR)
|
111
|
+
raise NotImplementedError
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_denominator(daily_rate, total_dates)
|
115
|
+
# start_dates = 0.0
|
116
|
+
# sum = 1.0
|
117
|
+
# while total_dates > start_dates
|
118
|
+
# start_dates += 30
|
119
|
+
# sum += total_dates ** start_dates
|
120
|
+
# end
|
121
|
+
# sum
|
122
|
+
raise NotImplementedError
|
123
|
+
end
|
124
|
+
|
125
|
+
def round_up(amount, currency)
|
126
|
+
# divisor = currency == ::Klarna::API::Currencies::EUR ? 10.0 : 100.0
|
127
|
+
# (((divisor / 2) + amount) / divisor) #.round
|
128
|
+
raise NotImplementedError
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Klarna
|
4
|
+
module API
|
5
|
+
module Methods
|
6
|
+
module Invoicing
|
7
|
+
|
8
|
+
# == TODO:
|
9
|
+
#
|
10
|
+
# * #total_credit_purchase_cost
|
11
|
+
#
|
12
|
+
|
13
|
+
# Create an invoice.
|
14
|
+
#
|
15
|
+
def add_invoice(store_user_id, order_id, articles, shipping_fee,
|
16
|
+
handling_fee, shipment_type, pno, first_name, last_name, address, client_ip,
|
17
|
+
currency, country, language, pno_encoding, pclass = nil, annual_salary = nil,
|
18
|
+
password = nil, ready_date = nil, comment = nil, rand_string = nil, new_password = nil, flags = nil)
|
19
|
+
shipment_type = ::Klarna::API.id_for(:shipment_type, shipment_type)
|
20
|
+
currency = ::Klarna::API.id_for(:currency, currency)
|
21
|
+
country = ::Klarna::API.id_for(:country, country)
|
22
|
+
language = ::Klarna::API.id_for(:language, language)
|
23
|
+
pno_encoding = ::Klarna::API.id_for(:pno_format, pno_encoding)
|
24
|
+
pclass = pclass ? ::Klarna::API.id_for(:pclass, pclass) : -1
|
25
|
+
flags = ::Klarna::API.parse_flags(:INVOICE, flags)
|
26
|
+
articles = Array.wrap(articles).compact
|
27
|
+
|
28
|
+
params = [
|
29
|
+
self.store_id,
|
30
|
+
store_user_id,
|
31
|
+
self.digest(articles.collect { |g| g[:goods][:title] }, :store_id => false),
|
32
|
+
order_id,
|
33
|
+
articles,
|
34
|
+
shipping_fee,
|
35
|
+
shipment_type,
|
36
|
+
handling_fee,
|
37
|
+
pno,
|
38
|
+
first_name,
|
39
|
+
last_name,
|
40
|
+
address,
|
41
|
+
password.to_s,
|
42
|
+
client_ip.to_s,
|
43
|
+
new_password.to_s,
|
44
|
+
flags.to_i,
|
45
|
+
comment.to_s,
|
46
|
+
ready_date.to_s,
|
47
|
+
rand_string.to_s,
|
48
|
+
currency,
|
49
|
+
country,
|
50
|
+
language,
|
51
|
+
pno_encoding,
|
52
|
+
pclass,
|
53
|
+
annual_salary.to_i
|
54
|
+
]
|
55
|
+
|
56
|
+
self.call(:add_invoice, *params)
|
57
|
+
end
|
58
|
+
alias :add_transaction :add_invoice
|
59
|
+
|
60
|
+
# Activate a passive invoice - optionally only partly.
|
61
|
+
#
|
62
|
+
# == Note:
|
63
|
+
#
|
64
|
+
# This function call cannot activate an invoice created in test mode. It is however possible
|
65
|
+
# to manually activate such an invoice.
|
66
|
+
#
|
67
|
+
# When partially activating an invoice only the articles and quantities specified by
|
68
|
+
# you will be activated. A passive invoice is created containing the articles on the
|
69
|
+
# original invoice not activated.
|
70
|
+
#
|
71
|
+
def activate_invoice(invoice_no, articles = nil)
|
72
|
+
# TODO: Parse/Validate invoice_no as :integer
|
73
|
+
# TODO: Parse/Valdiate articles as array of articles
|
74
|
+
articles = Array.wrap(articles).compact
|
75
|
+
|
76
|
+
params = [
|
77
|
+
self.store_id,
|
78
|
+
invoice_no
|
79
|
+
]
|
80
|
+
|
81
|
+
# Only partly?
|
82
|
+
if articles.present?
|
83
|
+
params << articles
|
84
|
+
params << self.digest(invoice_no, articles.collect { |a| [a[:goods][:artno], a[:qty]].join(':') }.join(':'))
|
85
|
+
method = :activate_part
|
86
|
+
else
|
87
|
+
params << self.digest(invoice_no)
|
88
|
+
method = :activate_invoice
|
89
|
+
end
|
90
|
+
|
91
|
+
self.call(method, *params)
|
92
|
+
end
|
93
|
+
alias :activate_part :activate_invoice
|
94
|
+
|
95
|
+
# Delete a passive invoice.
|
96
|
+
#
|
97
|
+
def delete_invoice(invoice_no)
|
98
|
+
# TODO: Parse/Validate invoice_no as :integer
|
99
|
+
|
100
|
+
params = [
|
101
|
+
self.store_id,
|
102
|
+
invoice_no,
|
103
|
+
self.digest(invoice_no)
|
104
|
+
]
|
105
|
+
|
106
|
+
self.call(:delete_invoice, *params)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Give discounts for invoices.
|
110
|
+
#
|
111
|
+
def return_amount(invoice_no, amount, vat)
|
112
|
+
params = [
|
113
|
+
self.store_id,
|
114
|
+
invoice_no,
|
115
|
+
amount,
|
116
|
+
vat,
|
117
|
+
self.digest(invoice_no)
|
118
|
+
]
|
119
|
+
self.call(:return_amount, *params) # raise NotImplementedError
|
120
|
+
end
|
121
|
+
|
122
|
+
# Return a invoice - optionally only partly.
|
123
|
+
#
|
124
|
+
def credit_invoice(invoice_no, credit_id, articles = nil)
|
125
|
+
articles = Array.wrap(articles).compact
|
126
|
+
|
127
|
+
params = [
|
128
|
+
self.store_id,
|
129
|
+
invoice_no,
|
130
|
+
credit_id,
|
131
|
+
]
|
132
|
+
|
133
|
+
if articles.present? # Only partly?
|
134
|
+
params << articles
|
135
|
+
params << self.digest(invoice_no, articles.collect { |a| [a[:goods][:artno], a[:qty]].join(':') }.join(':'))
|
136
|
+
method = :credit_part
|
137
|
+
else
|
138
|
+
params << self.digest(invoice_no)
|
139
|
+
method = :credit_invoice
|
140
|
+
end
|
141
|
+
|
142
|
+
self.call(method, *params)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Send an active invoice to the customer via e-mail.
|
146
|
+
#
|
147
|
+
# == Note:
|
148
|
+
#
|
149
|
+
# Regular postal service is used if the customer lacks an e-mail address.
|
150
|
+
#
|
151
|
+
def email_invoice(invoice_no)
|
152
|
+
# TODO: Parse/Validate invoice_no as integer
|
153
|
+
|
154
|
+
params = [
|
155
|
+
self.store_id,
|
156
|
+
invoice_no,
|
157
|
+
self.digest(invoice_no)
|
158
|
+
]
|
159
|
+
|
160
|
+
self.call(:email_invoice, *params)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Request a postal send-out of an active invoice to a customer by Klarna.
|
164
|
+
#
|
165
|
+
def send_invoice(invoice_no)
|
166
|
+
# TODO: Parse/Validate invoice_no as integer
|
167
|
+
|
168
|
+
params = [
|
169
|
+
self.store_id,
|
170
|
+
invoice_no,
|
171
|
+
self.digest(invoice_no)
|
172
|
+
]
|
173
|
+
|
174
|
+
self.call(:send_invoice, *params)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Create quantity and article number (i.e. the +articles+ argument for the
|
178
|
+
# +activate_part+ and +credit_part+ function).
|
179
|
+
#
|
180
|
+
def make_article(quantity, article_no)
|
181
|
+
quantity = quantity.to_i
|
182
|
+
article_no = article_no.to_s
|
183
|
+
[quantity, article_no]
|
184
|
+
end
|
185
|
+
|
186
|
+
# Change the quantity of a specific item in a passive invoice.
|
187
|
+
#
|
188
|
+
def update_goods_quantity(invoice_no, article_no, new_quantity)
|
189
|
+
# TODO: Parse/Validate invoice_no as integer
|
190
|
+
# TODO: Parse/Validate article_no as string
|
191
|
+
# TODO: Parse/Validate new_quantity as integer
|
192
|
+
|
193
|
+
params = [
|
194
|
+
self.store_id,
|
195
|
+
self.digest(invoice_no, article_no, new_quantity, :store_id => false),
|
196
|
+
invoice_no,
|
197
|
+
article_no,
|
198
|
+
new_quantity
|
199
|
+
]
|
200
|
+
|
201
|
+
self.call(:update_goods_qty, *params)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Change the amount of a fee (for example the invoice fee) in a passive invoice.
|
205
|
+
#
|
206
|
+
def update_charge_amount(invoice_no, charge_type, new_amount)
|
207
|
+
# TODO: Parse/Validate invoice_no as integer
|
208
|
+
# TODO: Parse/Validate charge_type as integer/charge-type
|
209
|
+
# TODO: Parse/Validate new_amount as integer (or parse from decimal)
|
210
|
+
|
211
|
+
params = [
|
212
|
+
self.store_id,
|
213
|
+
self.digest(invoice_no, charge_type, new_amount),
|
214
|
+
invoice_no,
|
215
|
+
charge_type,
|
216
|
+
new_amount
|
217
|
+
]
|
218
|
+
|
219
|
+
self.call(:update_charge_amount, *params)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Change the store’s order number for a specific invoice.
|
223
|
+
#
|
224
|
+
def update_order_no(invoice_no, new_order_no)
|
225
|
+
# TODO: Parse/Validate invoice_no as integer
|
226
|
+
# TODO: Parse/Validate new_order_no as integer
|
227
|
+
|
228
|
+
params = [
|
229
|
+
self.store_id,
|
230
|
+
invoice_no,
|
231
|
+
self.digest(invoice_no, new_order_no),
|
232
|
+
new_order_no
|
233
|
+
]
|
234
|
+
|
235
|
+
self.call(:update_orderno, *params)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Retrieve the address for an invoice.
|
239
|
+
#
|
240
|
+
def invoice_address(invoice_no)
|
241
|
+
# TODO: Parse/Validate invoice_no as integer
|
242
|
+
|
243
|
+
params = [
|
244
|
+
self.store_id,
|
245
|
+
invoice_no,
|
246
|
+
self.digest(invoice_no)
|
247
|
+
]
|
248
|
+
|
249
|
+
self.call(:invoice_address, *params).tap do |result|
|
250
|
+
result[5] = result[5].to_s.upcase
|
251
|
+
end
|
252
|
+
end
|
253
|
+
alias :get_invoice_address :invoice_address
|
254
|
+
|
255
|
+
# Retrieve the total amount of an invoice - optionally only partly.
|
256
|
+
#
|
257
|
+
def invoice_amount(invoice_no, articles = nil)
|
258
|
+
# TODO: Parse/Validate invoice_no as integer
|
259
|
+
articles = Array.wrap(articles).compact
|
260
|
+
artnos =
|
261
|
+
if articles.first.respond_to?(:key?) && articles.first.key?(:qty) && articles.first.key?(:artno)
|
262
|
+
articles
|
263
|
+
else
|
264
|
+
articles.collect { |a| {:artno => a[:goods][:artno], :qty => a[:qty]} }
|
265
|
+
end
|
266
|
+
|
267
|
+
params = [
|
268
|
+
self.store_id,
|
269
|
+
invoice_no
|
270
|
+
]
|
271
|
+
|
272
|
+
# Only partly?
|
273
|
+
if articles.present?
|
274
|
+
params << artnos
|
275
|
+
params << self.digest(invoice_no, artnos.collect { |an| [an[:artno], an[:qty]].join(':') }.join(':'))
|
276
|
+
method = :invoice_part_amount
|
277
|
+
else
|
278
|
+
params << self.digest(invoice_no)
|
279
|
+
method = :invoice_amount
|
280
|
+
end
|
281
|
+
|
282
|
+
self.call(method, *params)
|
283
|
+
end
|
284
|
+
alias :get_invoice_amount :invoice_amount
|
285
|
+
|
286
|
+
# Check if invoice is paid.
|
287
|
+
#
|
288
|
+
def invoice_paid?(invoice_no)
|
289
|
+
# TODO: Parse/Validate invoice_no as numeric value (string)
|
290
|
+
|
291
|
+
params = [
|
292
|
+
invoice_no,
|
293
|
+
self.store_id,
|
294
|
+
self.digest(invoice_no)
|
295
|
+
]
|
296
|
+
|
297
|
+
result = self.call(:is_invoice_paid, *params)
|
298
|
+
result == 'unpaid' ? false : true
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|