klarna 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -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 +175 -0
- data/lib/klarna/api.rb +170 -0
- data/lib/klarna/api/client.rb +128 -0
- data/lib/klarna/api/constants.rb +638 -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 +149 -0
- data/lib/klarna/api/methods/standard.rb +123 -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 +272 -0
- data/test/klarna/api/errors_test.rb +46 -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 +137 -0
- data/test/klarna_test.rb +204 -0
- data/test/support/assertions_helper.rb +40 -0
- data/test/test_helper.rb +55 -0
- metadata +312 -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
|