From 53fbd2f50c3dae3a5c3ffe1dbb3a9343359d6229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 30 Jan 2020 17:24:07 +0200 Subject: [PATCH 01/17] Implement partial payment logging for EveryPay / Bank links --- .../registrar/payments_controller.rb | 63 ++- app/models/invoice.rb | 3 +- app/models/payment_order.rb | 57 +++ app/models/payment_orders.rb | 15 - app/models/payment_orders/bank_link.rb | 87 ++-- app/models/payment_orders/base.rb | 33 -- app/models/payment_orders/every_pay.rb | 46 +- app/models/payment_orders/lhv.rb | 7 + app/models/payment_orders/seb.rb | 7 + app/models/payment_orders/swed.rb | 7 + app/views/registrar/invoices/show.haml | 2 +- app/views/registrar/payments/pay.html.haml | 4 +- .../20200130092113_create_payment_orders.rb | 13 + db/structure.sql | 471 ++++++++++-------- 14 files changed, 470 insertions(+), 345 deletions(-) create mode 100644 app/models/payment_order.rb delete mode 100644 app/models/payment_orders.rb delete mode 100644 app/models/payment_orders/base.rb create mode 100644 app/models/payment_orders/lhv.rb create mode 100644 app/models/payment_orders/seb.rb create mode 100644 app/models/payment_orders/swed.rb create mode 100644 db/migrate/20200130092113_create_payment_orders.rb diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 5be0d6562..98b9e1d7d 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -9,27 +9,37 @@ class Registrar def pay invoice = Invoice.find(params[:invoice_id]) - bank = params[:bank] - opts = { - return_url: registrar_return_payment_with_url( - bank, invoice_id: invoice - ), - response_url: registrar_response_payment_with_url( - bank, invoice_id: invoice - ) - } - @payment = ::PaymentOrders.create_with_type(bank, invoice, opts) - @payment.create_transaction + payment_type = params[:bank] + + channel = if payment_type == 'every_pay' + 'PaymentOrders::EveryPay' + elsif payment_type == 'seb' + 'PaymentOrders::SEB' + elsif payment_type == 'swed' + 'PaymentOrders::Swed' + elsif payment_type == 'lhv' + 'PaymentOrders::LHV' + end + + @payment_order = PaymentOrder.new(type: channel, invoice: invoice) + @payment_order.save && @payment_order.reload + + @payment_order.return_url = registrar_return_payment_with_url(@payment_order) + @payment_order.response_url = registrar_response_payment_with_url(@payment_order) + + @payment_order.save && @payment_order.reload end def back - invoice = Invoice.find(params[:invoice_id]) - opts = { response: params } - @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) - if @payment.valid_response_from_intermediary? && @payment.settled_payment? - @payment.complete_transaction + puts params - if invoice.paid? + @payment_order = PaymentOrder.find_by!(id: params[:bank]) + @payment_order.update!(response: params.to_unsafe_h) + + if @payment_order.valid_response_from_intermediary? && @payment_order.settled_payment? + @payment_order.complete_transaction + + if @payment_order.invoice.paid? flash[:notice] = t(:pending_applied) else flash[:alert] = t(:something_wrong) @@ -37,16 +47,15 @@ class Registrar else flash[:alert] = t(:something_wrong) end - redirect_to registrar_invoice_path(invoice) + redirect_to registrar_invoice_path(@payment_order.invoice) end def callback - invoice = Invoice.find(params[:invoice_id]) - opts = { response: params } - @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) + @payment_order = PaymentOrder.find_by!(id: params[:bank]) + @payment_order.update!(response: params.to_unsafe_h) - if @payment.valid_response_from_intermediary? && @payment.settled_payment? - @payment.complete_transaction + if @payment_order.valid_response_from_intermediary? && @payment_order.settled_payment? + @payment_order.complete_transaction end render status: 200, json: { status: 'ok' } @@ -56,12 +65,14 @@ class Registrar def check_supported_payment_method return if supported_payment_method? - raise StandardError.new("Not supported payment method") + + raise StandardError.new('Not supported payment method') end - def supported_payment_method? - PaymentOrders::PAYMENT_METHODS.include?(params[:bank]) + puts "Payment method param is #{params[:bank]}" + # PaymentOrder::PAYMENT_METHODS.include?(params[:bank]) + true end end end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 7f1dea825..3aa2a5c3c 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -7,6 +7,7 @@ class Invoice < ApplicationRecord has_one :account_activity has_many :items, class_name: 'InvoiceItem', dependent: :destroy has_many :directo_records, as: :item, class_name: 'Directo' + has_many :payment_orders accepts_nested_attributes_for :items @@ -111,4 +112,4 @@ class Invoice < ApplicationRecord def calculate_total self.total = subtotal + vat_amount end -end \ No newline at end of file +end diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb new file mode 100644 index 000000000..228c4021d --- /dev/null +++ b/app/models/payment_order.rb @@ -0,0 +1,57 @@ +class PaymentOrder < ApplicationRecord + #include Versions + include ActionView::Helpers::NumberHelper + + PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze + PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze + PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze + + belongs_to :invoice, optional: false + + validate :invoice_cannot_be_already_paid, on: :create + # validates :type, inclusion: { in: PAYMENT_METHODS } + + enum status: { issued: 'issued', paid: 'paid', cancelled: 'cancelled' } + + attr_accessor :return_url, :response_url + + # Name of configuration namespace + def self.config_namespace_name; end + + def invoice_cannot_be_already_paid + return unless invoice&.paid? + + errors.add(:invoice, 'is already paid') + end + + def self.supported_method?(some_class) + raise ArgumentError unless some_class < PaymentOrder + + if PAYMENT_METHODS.include?(some_class.name) + true + else + false + end + end + + def self.supported_methods + enabled = [] + + ENABLED_METHODS.each do |method| + class_name = method.constantize + raise(Errors::ExpectedPaymentOrder, class_name) unless class_name < PaymentOrder + + enabled << class_name + end + + enabled + end + + def channel + type.gsub('PaymentOrders::', '') + end + + def form_url + ENV["payments_#{self.class.config_namespace_name}_url"] + end +end diff --git a/app/models/payment_orders.rb b/app/models/payment_orders.rb deleted file mode 100644 index 921af0cd4..000000000 --- a/app/models/payment_orders.rb +++ /dev/null @@ -1,15 +0,0 @@ -module PaymentOrders - PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze - PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze - PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze - - def self.create_with_type(type, invoice, opts = {}) - raise ArgumentError unless PAYMENT_METHODS.include?(type) - - if PAYMENT_BANKLINK_BANKS.include?(type) - BankLink.new(type, invoice, opts) - elsif type == 'every_pay' - EveryPay.new(type, invoice, opts) - end - end -end diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb index e568da0df..0cdedbd85 100644 --- a/app/models/payment_orders/bank_link.rb +++ b/app/models/payment_orders/bank_link.rb @@ -1,44 +1,44 @@ module PaymentOrders - class BankLink < Base - BANK_LINK_VERSION = '008' + class BankLink < PaymentOrder + BANK_LINK_VERSION = '008'.freeze - NEW_TRANSACTION_SERVICE_NUMBER = '1012' - SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111' - CANCELLED_PAYMENT_SERVICE_NUMBER = '1911' + NEW_TRANSACTION_SERVICE_NUMBER = '1012'.freeze + SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111'.freeze + CANCELLED_PAYMENT_SERVICE_NUMBER = '1911'.freeze - NEW_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT + NEW_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF VK_MSG VK_RETURN VK_CANCEL - VK_DATETIME).freeze - SUCCESS_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_DATETIME].freeze + SUCCESS_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG - VK_T_DATETIME).freeze - CANCEL_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP - VK_REF VK_MSG).freeze + VK_T_DATETIME].freeze + CANCEL_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_REF VK_MSG].freeze def form_fields hash = {} - hash["VK_SERVICE"] = NEW_TRANSACTION_SERVICE_NUMBER - hash["VK_VERSION"] = BANK_LINK_VERSION - hash["VK_SND_ID"] = seller_account - hash["VK_STAMP"] = invoice.number - hash["VK_AMOUNT"] = number_with_precision(invoice.total, precision: 2, separator: ".") - hash["VK_CURR"] = invoice.currency - hash["VK_REF"] = "" - hash["VK_MSG"] = invoice.order - hash["VK_RETURN"] = return_url - hash["VK_CANCEL"] = return_url - hash["VK_DATETIME"] = Time.zone.now.strftime("%Y-%m-%dT%H:%M:%S%z") - hash["VK_MAC"] = calc_mac(hash) - hash["VK_ENCODING"] = "UTF-8" - hash["VK_LANG"] = "ENG" + hash['VK_SERVICE'] = NEW_TRANSACTION_SERVICE_NUMBER + hash['VK_VERSION'] = BANK_LINK_VERSION + hash['VK_SND_ID'] = seller_account + hash['VK_STAMP'] = invoice.number + hash['VK_AMOUNT'] = number_with_precision(invoice.total, precision: 2, separator: ".") + hash['VK_CURR'] = invoice.currency + hash['VK_REF'] = '' + hash['VK_MSG'] = invoice.order + hash['VK_RETURN'] = return_url + hash['VK_CANCEL'] = return_url + hash['VK_DATETIME'] = Time.zone.now.strftime('%Y-%m-%dT%H:%M:%S%z') + hash['VK_MAC'] = calc_mac(hash) + hash['VK_ENCODING'] = 'UTF-8' + hash['VK_LANG'] = 'ENG' hash end def valid_response_from_intermediary? return false unless response - case response["VK_SERVICE"] + case response['VK_SERVICE'] when SUCCESSFUL_PAYMENT_SERVICE_NUMBER valid_successful_transaction? when CANCELLED_PAYMENT_SERVICE_NUMBER @@ -49,30 +49,31 @@ module PaymentOrders end def complete_transaction - return unless valid_successful_transaction? + return unless valid_response_from_intermediary? && settled_payment? - transaction = BankTransaction.find_by( + transaction = BankTransaction.where(description: invoice.order).first_or_initialize( description: invoice.order, + reference_no: invoice.reference_no, currency: invoice.currency, iban: invoice.seller_iban ) transaction.sum = response['VK_AMOUNT'] transaction.bank_reference = response['VK_T_NO'] - transaction.buyer_bank_code = response["VK_SND_ID"] - transaction.buyer_iban = response["VK_SND_ACC"] - transaction.buyer_name = response["VK_SND_NAME"] - transaction.paid_at = Time.parse(response["VK_T_DATETIME"]) + transaction.buyer_bank_code = response['VK_SND_ID'] + transaction.buyer_iban = response['VK_SND_ACC'] + transaction.buyer_name = response['VK_SND_NAME'] + transaction.paid_at = Time.parse(response['VK_T_DATETIME']) transaction.save! transaction.autobind_invoice end def settled_payment? - response["VK_SERVICE"] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER + response['VK_SERVICE'] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER end - private + # private def valid_successful_transaction? valid_success_notice? && valid_amount? && valid_currency? @@ -88,17 +89,17 @@ module PaymentOrders def valid_amount? source = number_with_precision( - BigDecimal.new(response["VK_AMOUNT"]), precision: 2, separator: "." + BigDecimal(response['VK_AMOUNT']), precision: 2, separator: '.' ) target = number_with_precision( - invoice.total, precision: 2, separator: "." + invoice.total, precision: 2, separator: '.' ) source == target end def valid_currency? - invoice.currency == response["VK_CURR"] + invoice.currency == response['VK_CURR'] end def sign(data) @@ -116,7 +117,7 @@ module PaymentOrders def valid_mac?(hash, keys) data = keys.map { |element| prepend_size(hash[element]) }.join - verify_mac(data, hash["VK_MAC"]) + verify_mac(data, hash['VK_MAC']) end def verify_mac(data, mac) @@ -125,22 +126,22 @@ module PaymentOrders end def prepend_size(value) - value = (value || "").to_s.strip - string = "" + value = (value || '').to_s.strip + string = '' string << format("%03i", value.size) string << value end def seller_account - ENV["payments_#{type}_seller_account"] + ENV["payments_#{self.class.config_namespace_name}_seller_account"] end def seller_certificate - ENV["payments_#{type}_seller_private"] + ENV["payments_#{self.class.config_namespace_name}_seller_private"] end def bank_certificate - ENV["payments_#{type}_bank_certificate"] + ENV["payments_#{self.class.config_namespace_name}_bank_certificate"] end end end diff --git a/app/models/payment_orders/base.rb b/app/models/payment_orders/base.rb deleted file mode 100644 index cf0293025..000000000 --- a/app/models/payment_orders/base.rb +++ /dev/null @@ -1,33 +0,0 @@ -module PaymentOrders - class Base - include ActionView::Helpers::NumberHelper - - attr_reader :type, - :invoice, - :return_url, - :response_url, - :response - - def initialize(type, invoice, opts = {}) - @type = type - @invoice = invoice - @return_url = opts[:return_url] - @response_url = opts[:response_url] - @response = opts[:response] - end - - def create_transaction - transaction = BankTransaction.where(description: invoice.order).first_or_initialize( - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) - - transaction.save! - end - - def form_url - ENV["payments_#{type}_url"] - end - end -end diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb index b4ddcdf29..ae84aacca 100644 --- a/app/models/payment_orders/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -1,9 +1,15 @@ module PaymentOrders - class EveryPay < Base - USER = ENV['payments_every_pay_api_user'].freeze - KEY = ENV['payments_every_pay_api_key'].freeze - ACCOUNT_ID = ENV['payments_every_pay_seller_account'].freeze - SUCCESSFUL_PAYMENT = %w(settled authorized).freeze + class EveryPay < PaymentOrder + USER = ENV['payments_every_pay_api_user'] + KEY = ENV['payments_every_pay_api_key'] + ACCOUNT_ID = ENV['payments_every_pay_seller_account'] + SUCCESSFUL_PAYMENT = %w[settled authorized].freeze + + CONFIG_NAMESPACE = 'every_pay' + + def self.config_namespace_name + CONFIG_NAMESPACE + end def form_fields base_json = base_params @@ -20,32 +26,31 @@ module PaymentOrders def valid_response_from_intermediary? return false unless response + valid_hmac? && valid_amount? && valid_account? end def settled_payment? - SUCCESSFUL_PAYMENT.include?(response[:payment_state]) + SUCCESSFUL_PAYMENT.include?(response['payment_state']) end def complete_transaction return unless valid_response_from_intermediary? && settled_payment? - transaction = BankTransaction.find_by( + transaction = BankTransaction.where(description: invoice.order).first_or_initialize( description: invoice.order, - currency: invoice.currency, - iban: invoice.seller_iban + reference_no: invoice.reference_no, + currency: invoice.currency, + iban: invoice.seller_iban ) - transaction.sum = response[:amount] - transaction.paid_at = Date.strptime(response[:timestamp], '%s') - transaction.buyer_name = response[:cc_holder_name] + transaction.sum = response['amount'] + transaction.paid_at = Date.strptime(response['timestamp'], '%s') + transaction.buyer_name = response['cc_holder_name'] - transaction.save! transaction.autobind_invoice end - private - def base_params { api_username: USER, @@ -61,24 +66,23 @@ module PaymentOrders end def valid_hmac? - hmac_fields = response[:hmac_fields].split(',') + hmac_fields = response['hmac_fields'].split(',') hmac_hash = {} hmac_fields.map do |field| - symbol = field.to_sym - hmac_hash[symbol] = response[symbol] + hmac_hash[field] = response[field] end hmac_string = hmac_hash.map { |key, _v| "#{key}=#{hmac_hash[key]}" }.join('&') expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) - expected_hmac == response[:hmac] + expected_hmac == response['hmac'] end def valid_amount? - invoice.total == BigDecimal.new(response[:amount]) + invoice.total == BigDecimal(response['amount']) end def valid_account? - response[:account_id] == ACCOUNT_ID + response['account_id'] == ACCOUNT_ID end end end diff --git a/app/models/payment_orders/lhv.rb b/app/models/payment_orders/lhv.rb new file mode 100644 index 000000000..7443f85d3 --- /dev/null +++ b/app/models/payment_orders/lhv.rb @@ -0,0 +1,7 @@ +module PaymentOrders + class LHV < BankLink + def self.config_namespace_name + 'lhv' + end + end +end diff --git a/app/models/payment_orders/seb.rb b/app/models/payment_orders/seb.rb new file mode 100644 index 000000000..50fb24ced --- /dev/null +++ b/app/models/payment_orders/seb.rb @@ -0,0 +1,7 @@ +module PaymentOrders + class SEB < BankLink + def self.config_namespace_name + 'seb' + end + end +end diff --git a/app/models/payment_orders/swed.rb b/app/models/payment_orders/swed.rb new file mode 100644 index 000000000..ff3aca3d1 --- /dev/null +++ b/app/models/payment_orders/swed.rb @@ -0,0 +1,7 @@ +module PaymentOrders + class Swed < BankLink + def self.config_namespace_name + 'swed' + end + end +end diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml index 66a025eaf..d987241b1 100644 --- a/app/views/registrar/invoices/show.haml +++ b/app/views/registrar/invoices/show.haml @@ -17,4 +17,4 @@ - if @invoice.payable? .row.semifooter - .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrders::PAYMENT_METHODS } + .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrder::PAYMENT_METHODS } diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml index 8e759f9ea..dd3fc982f 100644 --- a/app/views/registrar/payments/pay.html.haml +++ b/app/views/registrar/payments/pay.html.haml @@ -2,8 +2,8 @@ = t('registrar.invoices.redirected_to_intermediary') .payment-form - = form_tag @payment.form_url, method: :post do - - @payment.form_fields.each do |k, v| + = form_tag @payment_order.form_url, method: :post do + - @payment_order.form_fields.each do |k, v| = hidden_field_tag k, v = submit_tag t('registrar.invoices.go_to_intermediary') diff --git a/db/migrate/20200130092113_create_payment_orders.rb b/db/migrate/20200130092113_create_payment_orders.rb new file mode 100644 index 000000000..0b0594e56 --- /dev/null +++ b/db/migrate/20200130092113_create_payment_orders.rb @@ -0,0 +1,13 @@ +class CreatePaymentOrders < ActiveRecord::Migration[5.0] + def change + create_table :payment_orders do |t| + t.string :type, null: false + t.string :status, default: 0, null: false + t.belongs_to :invoice, foreign_key: true + t.jsonb :response, null: true + t.string :notes, null: true + + t.timestamps + end + end +end diff --git a/db/structure.sql b/db/structure.sql index a23623bae..c664522bb 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -196,7 +196,7 @@ SET default_tablespace = ''; SET default_with_oids = false; -- --- Name: account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.account_activities ( @@ -236,7 +236,7 @@ ALTER SEQUENCE public.account_activities_id_seq OWNED BY public.account_activiti -- --- Name: accounts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: accounts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.accounts ( @@ -272,7 +272,7 @@ ALTER SEQUENCE public.accounts_id_seq OWNED BY public.accounts.id; -- --- Name: actions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: actions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.actions ( @@ -304,7 +304,7 @@ ALTER SEQUENCE public.actions_id_seq OWNED BY public.actions.id; -- --- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.ar_internal_metadata ( @@ -316,7 +316,7 @@ CREATE TABLE public.ar_internal_metadata ( -- --- Name: auctions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: auctions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.auctions ( @@ -349,7 +349,7 @@ ALTER SEQUENCE public.auctions_id_seq OWNED BY public.auctions.id; -- --- Name: bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.bank_statements ( @@ -385,7 +385,7 @@ ALTER SEQUENCE public.bank_statements_id_seq OWNED BY public.bank_statements.id; -- --- Name: bank_transactions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: bank_transactions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.bank_transactions ( @@ -429,7 +429,7 @@ ALTER SEQUENCE public.bank_transactions_id_seq OWNED BY public.bank_transactions -- --- Name: blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.blocked_domains ( @@ -462,7 +462,7 @@ ALTER SEQUENCE public.blocked_domains_id_seq OWNED BY public.blocked_domains.id; -- --- Name: certificates; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: certificates; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.certificates ( @@ -500,7 +500,7 @@ ALTER SEQUENCE public.certificates_id_seq OWNED BY public.certificates.id; -- --- Name: contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.contacts ( @@ -558,7 +558,7 @@ ALTER SEQUENCE public.contacts_id_seq OWNED BY public.contacts.id; -- --- Name: directos; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: directos; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.directos ( @@ -593,7 +593,7 @@ ALTER SEQUENCE public.directos_id_seq OWNED BY public.directos.id; -- --- Name: dnskeys; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: dnskeys; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.dnskeys ( @@ -634,7 +634,7 @@ ALTER SEQUENCE public.dnskeys_id_seq OWNED BY public.dnskeys.id; -- --- Name: domain_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: domain_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.domain_contacts ( @@ -672,7 +672,7 @@ ALTER SEQUENCE public.domain_contacts_id_seq OWNED BY public.domain_contacts.id; -- --- Name: domain_transfers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: domain_transfers; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.domain_transfers ( @@ -709,7 +709,7 @@ ALTER SEQUENCE public.domain_transfers_id_seq OWNED BY public.domain_transfers.i -- --- Name: domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.domains ( @@ -746,7 +746,6 @@ CREATE TABLE public.domains ( locked_by_registrant_at timestamp without time zone, force_delete_start timestamp without time zone, force_delete_data public.hstore - ); @@ -770,7 +769,7 @@ ALTER SEQUENCE public.domains_id_seq OWNED BY public.domains.id; -- --- Name: epp_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: epp_sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.epp_sessions ( @@ -802,7 +801,7 @@ ALTER SEQUENCE public.epp_sessions_id_seq OWNED BY public.epp_sessions.id; -- --- Name: invoice_items; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: invoice_items; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.invoice_items ( @@ -840,7 +839,7 @@ ALTER SEQUENCE public.invoice_items_id_seq OWNED BY public.invoice_items.id; -- --- Name: invoices; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: invoices; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.invoices ( @@ -910,7 +909,7 @@ ALTER SEQUENCE public.invoices_id_seq OWNED BY public.invoices.id; -- --- Name: legal_documents; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: legal_documents; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.legal_documents ( @@ -945,7 +944,7 @@ ALTER SEQUENCE public.legal_documents_id_seq OWNED BY public.legal_documents.id; -- --- Name: log_account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_account_activities ( @@ -983,7 +982,7 @@ ALTER SEQUENCE public.log_account_activities_id_seq OWNED BY public.log_account_ -- --- Name: log_accounts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_accounts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_accounts ( @@ -1021,7 +1020,7 @@ ALTER SEQUENCE public.log_accounts_id_seq OWNED BY public.log_accounts.id; -- --- Name: log_actions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_actions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_actions ( @@ -1059,7 +1058,7 @@ ALTER SEQUENCE public.log_actions_id_seq OWNED BY public.log_actions.id; -- --- Name: log_bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_bank_statements ( @@ -1097,7 +1096,7 @@ ALTER SEQUENCE public.log_bank_statements_id_seq OWNED BY public.log_bank_statem -- --- Name: log_bank_transactions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_bank_transactions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_bank_transactions ( @@ -1135,7 +1134,7 @@ ALTER SEQUENCE public.log_bank_transactions_id_seq OWNED BY public.log_bank_tran -- --- Name: log_blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_blocked_domains ( @@ -1173,7 +1172,7 @@ ALTER SEQUENCE public.log_blocked_domains_id_seq OWNED BY public.log_blocked_dom -- --- Name: log_certificates; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_certificates; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_certificates ( @@ -1211,7 +1210,7 @@ ALTER SEQUENCE public.log_certificates_id_seq OWNED BY public.log_certificates.i -- --- Name: log_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_contacts ( @@ -1250,7 +1249,7 @@ ALTER SEQUENCE public.log_contacts_id_seq OWNED BY public.log_contacts.id; -- --- Name: log_dnskeys; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_dnskeys; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_dnskeys ( @@ -1288,7 +1287,7 @@ ALTER SEQUENCE public.log_dnskeys_id_seq OWNED BY public.log_dnskeys.id; -- --- Name: log_domain_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_domain_contacts; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_domain_contacts ( @@ -1326,7 +1325,7 @@ ALTER SEQUENCE public.log_domain_contacts_id_seq OWNED BY public.log_domain_cont -- --- Name: log_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_domains ( @@ -1364,7 +1363,7 @@ ALTER SEQUENCE public.log_domains_id_seq OWNED BY public.log_domains.id; -- --- Name: log_invoice_items; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_invoice_items; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_invoice_items ( @@ -1402,7 +1401,7 @@ ALTER SEQUENCE public.log_invoice_items_id_seq OWNED BY public.log_invoice_items -- --- Name: log_invoices; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_invoices; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_invoices ( @@ -1440,7 +1439,7 @@ ALTER SEQUENCE public.log_invoices_id_seq OWNED BY public.log_invoices.id; -- --- Name: log_nameservers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_nameservers; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_nameservers ( @@ -1478,7 +1477,7 @@ ALTER SEQUENCE public.log_nameservers_id_seq OWNED BY public.log_nameservers.id; -- --- Name: log_notifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_notifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_notifications ( @@ -1516,7 +1515,7 @@ ALTER SEQUENCE public.log_notifications_id_seq OWNED BY public.log_notifications -- --- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_registrant_verifications ( @@ -1553,7 +1552,7 @@ ALTER SEQUENCE public.log_registrant_verifications_id_seq OWNED BY public.log_re -- --- Name: log_registrars; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_registrars; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_registrars ( @@ -1591,7 +1590,7 @@ ALTER SEQUENCE public.log_registrars_id_seq OWNED BY public.log_registrars.id; -- --- Name: log_reserved_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_reserved_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_reserved_domains ( @@ -1629,7 +1628,7 @@ ALTER SEQUENCE public.log_reserved_domains_id_seq OWNED BY public.log_reserved_d -- --- Name: log_settings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_settings; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_settings ( @@ -1667,7 +1666,7 @@ ALTER SEQUENCE public.log_settings_id_seq OWNED BY public.log_settings.id; -- --- Name: log_users; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_users; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_users ( @@ -1705,7 +1704,7 @@ ALTER SEQUENCE public.log_users_id_seq OWNED BY public.log_users.id; -- --- Name: log_white_ips; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_white_ips; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.log_white_ips ( @@ -1743,7 +1742,7 @@ ALTER SEQUENCE public.log_white_ips_id_seq OWNED BY public.log_white_ips.id; -- --- Name: nameservers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: nameservers; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.nameservers ( @@ -1781,7 +1780,7 @@ ALTER SEQUENCE public.nameservers_id_seq OWNED BY public.nameservers.id; -- --- Name: notifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: notifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.notifications ( @@ -1819,7 +1818,42 @@ ALTER SEQUENCE public.notifications_id_seq OWNED BY public.notifications.id; -- --- Name: prices; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: payment_orders; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.payment_orders ( + id integer NOT NULL, + type character varying NOT NULL, + status character varying DEFAULT '0'::character varying NOT NULL, + invoice_id integer, + response jsonb, + notes character varying, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- +-- Name: payment_orders_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.payment_orders_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: payment_orders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.payment_orders_id_seq OWNED BY public.payment_orders.id; + + +-- +-- Name: prices; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.prices ( @@ -1857,7 +1891,7 @@ ALTER SEQUENCE public.prices_id_seq OWNED BY public.prices.id; -- --- Name: que_jobs; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: que_jobs; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.que_jobs ( @@ -1899,7 +1933,7 @@ ALTER SEQUENCE public.que_jobs_job_id_seq OWNED BY public.que_jobs.job_id; -- --- Name: registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.registrant_verifications ( @@ -1935,7 +1969,7 @@ ALTER SEQUENCE public.registrant_verifications_id_seq OWNED BY public.registrant -- --- Name: registrars; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: registrars; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.registrars ( @@ -1988,7 +2022,7 @@ ALTER SEQUENCE public.registrars_id_seq OWNED BY public.registrars.id; -- --- Name: reserved_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: reserved_domains; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.reserved_domains ( @@ -2023,7 +2057,7 @@ ALTER SEQUENCE public.reserved_domains_id_seq OWNED BY public.reserved_domains.i -- --- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.schema_migrations ( @@ -2032,7 +2066,7 @@ CREATE TABLE public.schema_migrations ( -- --- Name: settings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: settings; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.settings ( @@ -2068,7 +2102,7 @@ ALTER SEQUENCE public.settings_id_seq OWNED BY public.settings.id; -- --- Name: users; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: users; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.users ( @@ -2120,7 +2154,7 @@ ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; -- --- Name: versions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: versions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.versions ( @@ -2155,7 +2189,7 @@ ALTER SEQUENCE public.versions_id_seq OWNED BY public.versions.id; -- --- Name: white_ips; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: white_ips; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.white_ips ( @@ -2191,7 +2225,7 @@ ALTER SEQUENCE public.white_ips_id_seq OWNED BY public.white_ips.id; -- --- Name: whois_records; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: whois_records; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.whois_records ( @@ -2226,7 +2260,7 @@ ALTER SEQUENCE public.whois_records_id_seq OWNED BY public.whois_records.id; -- --- Name: zones; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: zones; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.zones ( @@ -2555,6 +2589,13 @@ ALTER TABLE ONLY public.nameservers ALTER COLUMN id SET DEFAULT nextval('public. ALTER TABLE ONLY public.notifications ALTER COLUMN id SET DEFAULT nextval('public.notifications_id_seq'::regclass); +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.payment_orders ALTER COLUMN id SET DEFAULT nextval('public.payment_orders_id_seq'::regclass); + + -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2633,7 +2674,7 @@ ALTER TABLE ONLY public.zones ALTER COLUMN id SET DEFAULT nextval('public.zones_ -- --- Name: account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.account_activities @@ -2641,7 +2682,7 @@ ALTER TABLE ONLY public.account_activities -- --- Name: accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.accounts @@ -2649,7 +2690,7 @@ ALTER TABLE ONLY public.accounts -- --- Name: actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.actions @@ -2657,7 +2698,7 @@ ALTER TABLE ONLY public.actions -- --- Name: ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.ar_internal_metadata @@ -2665,7 +2706,7 @@ ALTER TABLE ONLY public.ar_internal_metadata -- --- Name: auctions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: auctions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.auctions @@ -2673,7 +2714,7 @@ ALTER TABLE ONLY public.auctions -- --- Name: bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.bank_statements @@ -2681,7 +2722,7 @@ ALTER TABLE ONLY public.bank_statements -- --- Name: bank_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: bank_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.bank_transactions @@ -2689,7 +2730,7 @@ ALTER TABLE ONLY public.bank_transactions -- --- Name: blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.blocked_domains @@ -2697,7 +2738,7 @@ ALTER TABLE ONLY public.blocked_domains -- --- Name: certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.certificates @@ -2705,7 +2746,7 @@ ALTER TABLE ONLY public.certificates -- --- Name: contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.contacts @@ -2713,7 +2754,7 @@ ALTER TABLE ONLY public.contacts -- --- Name: directos_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: directos_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.directos @@ -2721,7 +2762,7 @@ ALTER TABLE ONLY public.directos -- --- Name: dnskeys_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: dnskeys_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.dnskeys @@ -2729,7 +2770,7 @@ ALTER TABLE ONLY public.dnskeys -- --- Name: domain_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: domain_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.domain_contacts @@ -2737,7 +2778,7 @@ ALTER TABLE ONLY public.domain_contacts -- --- Name: domain_transfers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: domain_transfers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.domain_transfers @@ -2745,7 +2786,7 @@ ALTER TABLE ONLY public.domain_transfers -- --- Name: domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.domains @@ -2753,7 +2794,7 @@ ALTER TABLE ONLY public.domains -- --- Name: epp_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: epp_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.epp_sessions @@ -2761,7 +2802,7 @@ ALTER TABLE ONLY public.epp_sessions -- --- Name: invoice_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: invoice_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.invoice_items @@ -2769,7 +2810,7 @@ ALTER TABLE ONLY public.invoice_items -- --- Name: invoices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: invoices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.invoices @@ -2777,7 +2818,7 @@ ALTER TABLE ONLY public.invoices -- --- Name: legal_documents_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: legal_documents_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.legal_documents @@ -2785,7 +2826,7 @@ ALTER TABLE ONLY public.legal_documents -- --- Name: log_account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_account_activities @@ -2793,7 +2834,7 @@ ALTER TABLE ONLY public.log_account_activities -- --- Name: log_accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_accounts @@ -2801,7 +2842,7 @@ ALTER TABLE ONLY public.log_accounts -- --- Name: log_actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_actions @@ -2809,7 +2850,7 @@ ALTER TABLE ONLY public.log_actions -- --- Name: log_bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_bank_statements @@ -2817,7 +2858,7 @@ ALTER TABLE ONLY public.log_bank_statements -- --- Name: log_bank_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_bank_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_bank_transactions @@ -2825,7 +2866,7 @@ ALTER TABLE ONLY public.log_bank_transactions -- --- Name: log_blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_blocked_domains @@ -2833,7 +2874,7 @@ ALTER TABLE ONLY public.log_blocked_domains -- --- Name: log_certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_certificates @@ -2841,7 +2882,7 @@ ALTER TABLE ONLY public.log_certificates -- --- Name: log_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_contacts @@ -2849,7 +2890,7 @@ ALTER TABLE ONLY public.log_contacts -- --- Name: log_dnskeys_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_dnskeys_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_dnskeys @@ -2857,7 +2898,7 @@ ALTER TABLE ONLY public.log_dnskeys -- --- Name: log_domain_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_domain_contacts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_domain_contacts @@ -2865,7 +2906,7 @@ ALTER TABLE ONLY public.log_domain_contacts -- --- Name: log_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_domains @@ -2873,7 +2914,7 @@ ALTER TABLE ONLY public.log_domains -- --- Name: log_invoice_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_invoice_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_invoice_items @@ -2881,7 +2922,7 @@ ALTER TABLE ONLY public.log_invoice_items -- --- Name: log_invoices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_invoices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_invoices @@ -2889,7 +2930,7 @@ ALTER TABLE ONLY public.log_invoices -- --- Name: log_nameservers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_nameservers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_nameservers @@ -2897,7 +2938,7 @@ ALTER TABLE ONLY public.log_nameservers -- --- Name: log_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_notifications @@ -2905,7 +2946,7 @@ ALTER TABLE ONLY public.log_notifications -- --- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_registrant_verifications @@ -2913,7 +2954,7 @@ ALTER TABLE ONLY public.log_registrant_verifications -- --- Name: log_registrars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_registrars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_registrars @@ -2921,7 +2962,7 @@ ALTER TABLE ONLY public.log_registrars -- --- Name: log_reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_reserved_domains @@ -2929,7 +2970,7 @@ ALTER TABLE ONLY public.log_reserved_domains -- --- Name: log_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_settings @@ -2937,7 +2978,7 @@ ALTER TABLE ONLY public.log_settings -- --- Name: log_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_users @@ -2945,7 +2986,7 @@ ALTER TABLE ONLY public.log_users -- --- Name: log_white_ips_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_white_ips_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.log_white_ips @@ -2953,7 +2994,7 @@ ALTER TABLE ONLY public.log_white_ips -- --- Name: nameservers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: nameservers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.nameservers @@ -2961,7 +3002,7 @@ ALTER TABLE ONLY public.nameservers -- --- Name: notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.notifications @@ -2969,7 +3010,15 @@ ALTER TABLE ONLY public.notifications -- --- Name: prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: payment_orders_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.payment_orders + ADD CONSTRAINT payment_orders_pkey PRIMARY KEY (id); + + +-- +-- Name: prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.prices @@ -2977,7 +3026,7 @@ ALTER TABLE ONLY public.prices -- --- Name: que_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: que_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.que_jobs @@ -2985,7 +3034,7 @@ ALTER TABLE ONLY public.que_jobs -- --- Name: registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.registrant_verifications @@ -2993,7 +3042,7 @@ ALTER TABLE ONLY public.registrant_verifications -- --- Name: registrars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: registrars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.registrars @@ -3001,7 +3050,7 @@ ALTER TABLE ONLY public.registrars -- --- Name: reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.reserved_domains @@ -3009,7 +3058,7 @@ ALTER TABLE ONLY public.reserved_domains -- --- Name: settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.settings @@ -3017,7 +3066,7 @@ ALTER TABLE ONLY public.settings -- --- Name: uniq_blocked_domains_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: uniq_blocked_domains_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.blocked_domains @@ -3025,7 +3074,7 @@ ALTER TABLE ONLY public.blocked_domains -- --- Name: uniq_contact_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: uniq_contact_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.contacts @@ -3033,7 +3082,7 @@ ALTER TABLE ONLY public.contacts -- --- Name: uniq_domain_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: uniq_domain_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.domains @@ -3041,7 +3090,7 @@ ALTER TABLE ONLY public.domains -- --- Name: uniq_reserved_domains_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: uniq_reserved_domains_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.reserved_domains @@ -3049,7 +3098,7 @@ ALTER TABLE ONLY public.reserved_domains -- --- Name: uniq_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: uniq_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.auctions @@ -3057,7 +3106,7 @@ ALTER TABLE ONLY public.auctions -- --- Name: unique_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.registrars @@ -3065,7 +3114,7 @@ ALTER TABLE ONLY public.registrars -- --- Name: unique_contact_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_contact_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.contacts @@ -3073,7 +3122,7 @@ ALTER TABLE ONLY public.contacts -- --- Name: unique_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_name; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.registrars @@ -3081,7 +3130,7 @@ ALTER TABLE ONLY public.registrars -- --- Name: unique_number; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_number; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.invoices @@ -3089,7 +3138,7 @@ ALTER TABLE ONLY public.invoices -- --- Name: unique_reference_no; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_reference_no; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.registrars @@ -3097,7 +3146,7 @@ ALTER TABLE ONLY public.registrars -- --- Name: unique_registration_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_registration_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.auctions @@ -3105,7 +3154,7 @@ ALTER TABLE ONLY public.auctions -- --- Name: unique_session_id; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_session_id; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.epp_sessions @@ -3113,7 +3162,7 @@ ALTER TABLE ONLY public.epp_sessions -- --- Name: unique_zone_origin; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: unique_zone_origin; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.zones @@ -3121,7 +3170,7 @@ ALTER TABLE ONLY public.zones -- --- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.users @@ -3129,7 +3178,7 @@ ALTER TABLE ONLY public.users -- --- Name: versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.versions @@ -3137,7 +3186,7 @@ ALTER TABLE ONLY public.versions -- --- Name: white_ips_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: white_ips_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.white_ips @@ -3145,7 +3194,7 @@ ALTER TABLE ONLY public.white_ips -- --- Name: whois_records_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: whois_records_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.whois_records @@ -3153,7 +3202,7 @@ ALTER TABLE ONLY public.whois_records -- --- Name: zones_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: zones_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.zones @@ -3161,567 +3210,574 @@ ALTER TABLE ONLY public.zones -- --- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_account_activities_on_account_id ON public.account_activities USING btree (account_id); -- --- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_account_activities_on_bank_transaction_id ON public.account_activities USING btree (bank_transaction_id); -- --- Name: index_account_activities_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_account_activities_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_account_activities_on_invoice_id ON public.account_activities USING btree (invoice_id); -- --- Name: index_accounts_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_accounts_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_accounts_on_registrar_id ON public.accounts USING btree (registrar_id); -- --- Name: index_certificates_on_api_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_certificates_on_api_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_certificates_on_api_user_id ON public.certificates USING btree (api_user_id); -- --- Name: index_contacts_on_code; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_contacts_on_code; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_contacts_on_code ON public.contacts USING btree (code); -- --- Name: index_contacts_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_contacts_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_contacts_on_registrar_id ON public.contacts USING btree (registrar_id); -- --- Name: index_contacts_on_registrar_id_and_ident_type; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_contacts_on_registrar_id_and_ident_type; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_contacts_on_registrar_id_and_ident_type ON public.contacts USING btree (registrar_id, ident_type); -- --- Name: index_directos_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_directos_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_directos_on_item_type_and_item_id ON public.directos USING btree (item_type, item_id); -- --- Name: index_dnskeys_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_dnskeys_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_dnskeys_on_domain_id ON public.dnskeys USING btree (domain_id); -- --- Name: index_dnskeys_on_legacy_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_dnskeys_on_legacy_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_dnskeys_on_legacy_domain_id ON public.dnskeys USING btree (legacy_domain_id); -- --- Name: index_domain_contacts_on_contact_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domain_contacts_on_contact_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domain_contacts_on_contact_id ON public.domain_contacts USING btree (contact_id); -- --- Name: index_domain_contacts_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domain_contacts_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domain_contacts_on_domain_id ON public.domain_contacts USING btree (domain_id); -- --- Name: index_domain_transfers_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domain_transfers_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domain_transfers_on_domain_id ON public.domain_transfers USING btree (domain_id); -- --- Name: index_domains_on_delete_date; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_delete_date; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_delete_date ON public.domains USING btree (delete_date); -- --- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE UNIQUE INDEX index_domains_on_name ON public.domains USING btree (name); -- --- Name: index_domains_on_outzone_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_outzone_at; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_outzone_at ON public.domains USING btree (outzone_at); -- --- Name: index_domains_on_registrant_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_registrant_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_registrant_id ON public.domains USING btree (registrant_id); -- --- Name: index_domains_on_registrant_verification_asked_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_registrant_verification_asked_at; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_registrant_verification_asked_at ON public.domains USING btree (registrant_verification_asked_at); -- --- Name: index_domains_on_registrant_verification_token; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_registrant_verification_token; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_registrant_verification_token ON public.domains USING btree (registrant_verification_token); -- --- Name: index_domains_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_registrar_id ON public.domains USING btree (registrar_id); -- --- Name: index_domains_on_statuses; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_domains_on_statuses; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_domains_on_statuses ON public.domains USING gin (statuses); -- --- Name: index_epp_sessions_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_epp_sessions_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_epp_sessions_on_updated_at ON public.epp_sessions USING btree (updated_at); -- --- Name: index_invoice_items_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_invoice_items_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_invoice_items_on_invoice_id ON public.invoice_items USING btree (invoice_id); -- --- Name: index_invoices_on_buyer_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_invoices_on_buyer_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_invoices_on_buyer_id ON public.invoices USING btree (buyer_id); -- --- Name: index_legal_documents_on_checksum; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_legal_documents_on_checksum; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_legal_documents_on_checksum ON public.legal_documents USING btree (checksum); -- --- Name: index_legal_documents_on_documentable_type_and_documentable_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_legal_documents_on_documentable_type_and_documentable_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_legal_documents_on_documentable_type_and_documentable_id ON public.legal_documents USING btree (documentable_type, documentable_id); -- --- Name: index_log_account_activities_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_account_activities_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_account_activities_on_item_type_and_item_id ON public.log_account_activities USING btree (item_type, item_id); -- --- Name: index_log_account_activities_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_account_activities_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_account_activities_on_whodunnit ON public.log_account_activities USING btree (whodunnit); -- --- Name: index_log_accounts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_accounts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_accounts_on_item_type_and_item_id ON public.log_accounts USING btree (item_type, item_id); -- --- Name: index_log_accounts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_accounts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_accounts_on_whodunnit ON public.log_accounts USING btree (whodunnit); -- --- Name: index_log_bank_statements_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_bank_statements_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_bank_statements_on_item_type_and_item_id ON public.log_bank_statements USING btree (item_type, item_id); -- --- Name: index_log_bank_statements_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_bank_statements_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_bank_statements_on_whodunnit ON public.log_bank_statements USING btree (whodunnit); -- --- Name: index_log_bank_transactions_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_bank_transactions_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_bank_transactions_on_item_type_and_item_id ON public.log_bank_transactions USING btree (item_type, item_id); -- --- Name: index_log_bank_transactions_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_bank_transactions_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_bank_transactions_on_whodunnit ON public.log_bank_transactions USING btree (whodunnit); -- --- Name: index_log_blocked_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_blocked_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_blocked_domains_on_item_type_and_item_id ON public.log_blocked_domains USING btree (item_type, item_id); -- --- Name: index_log_blocked_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_blocked_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_blocked_domains_on_whodunnit ON public.log_blocked_domains USING btree (whodunnit); -- --- Name: index_log_certificates_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_certificates_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_certificates_on_item_type_and_item_id ON public.log_certificates USING btree (item_type, item_id); -- --- Name: index_log_certificates_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_certificates_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_certificates_on_whodunnit ON public.log_certificates USING btree (whodunnit); -- --- Name: index_log_contacts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_contacts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_contacts_on_item_type_and_item_id ON public.log_contacts USING btree (item_type, item_id); -- --- Name: index_log_contacts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_contacts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_contacts_on_whodunnit ON public.log_contacts USING btree (whodunnit); -- --- Name: index_log_dnskeys_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_dnskeys_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_dnskeys_on_item_type_and_item_id ON public.log_dnskeys USING btree (item_type, item_id); -- --- Name: index_log_dnskeys_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_dnskeys_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_dnskeys_on_whodunnit ON public.log_dnskeys USING btree (whodunnit); -- --- Name: index_log_domain_contacts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_domain_contacts_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_domain_contacts_on_item_type_and_item_id ON public.log_domain_contacts USING btree (item_type, item_id); -- --- Name: index_log_domain_contacts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_domain_contacts_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_domain_contacts_on_whodunnit ON public.log_domain_contacts USING btree (whodunnit); -- --- Name: index_log_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_domains_on_item_type_and_item_id ON public.log_domains USING btree (item_type, item_id); -- --- Name: index_log_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_domains_on_whodunnit ON public.log_domains USING btree (whodunnit); -- --- Name: index_log_invoice_items_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_invoice_items_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_invoice_items_on_item_type_and_item_id ON public.log_invoice_items USING btree (item_type, item_id); -- --- Name: index_log_invoice_items_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_invoice_items_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_invoice_items_on_whodunnit ON public.log_invoice_items USING btree (whodunnit); -- --- Name: index_log_invoices_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_invoices_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_invoices_on_item_type_and_item_id ON public.log_invoices USING btree (item_type, item_id); -- --- Name: index_log_invoices_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_invoices_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_invoices_on_whodunnit ON public.log_invoices USING btree (whodunnit); -- --- Name: index_log_nameservers_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_nameservers_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_nameservers_on_item_type_and_item_id ON public.log_nameservers USING btree (item_type, item_id); -- --- Name: index_log_nameservers_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_nameservers_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_nameservers_on_whodunnit ON public.log_nameservers USING btree (whodunnit); -- --- Name: index_log_notifications_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_notifications_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_notifications_on_item_type_and_item_id ON public.log_notifications USING btree (item_type, item_id); -- --- Name: index_log_notifications_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_notifications_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_notifications_on_whodunnit ON public.log_notifications USING btree (whodunnit); -- --- Name: index_log_registrant_verifications_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_registrant_verifications_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_registrant_verifications_on_item_type_and_item_id ON public.log_registrant_verifications USING btree (item_type, item_id); -- --- Name: index_log_registrant_verifications_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_registrant_verifications_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_registrant_verifications_on_whodunnit ON public.log_registrant_verifications USING btree (whodunnit); -- --- Name: index_log_registrars_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_registrars_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_registrars_on_item_type_and_item_id ON public.log_registrars USING btree (item_type, item_id); -- --- Name: index_log_registrars_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_registrars_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_registrars_on_whodunnit ON public.log_registrars USING btree (whodunnit); -- --- Name: index_log_reserved_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_reserved_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_reserved_domains_on_item_type_and_item_id ON public.log_reserved_domains USING btree (item_type, item_id); -- --- Name: index_log_reserved_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_reserved_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_reserved_domains_on_whodunnit ON public.log_reserved_domains USING btree (whodunnit); -- --- Name: index_log_settings_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_settings_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_settings_on_item_type_and_item_id ON public.log_settings USING btree (item_type, item_id); -- --- Name: index_log_settings_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_settings_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_settings_on_whodunnit ON public.log_settings USING btree (whodunnit); -- --- Name: index_log_users_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_users_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_users_on_item_type_and_item_id ON public.log_users USING btree (item_type, item_id); -- --- Name: index_log_users_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_log_users_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_log_users_on_whodunnit ON public.log_users USING btree (whodunnit); -- --- Name: index_nameservers_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_nameservers_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_nameservers_on_domain_id ON public.nameservers USING btree (domain_id); -- --- Name: index_notifications_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_notifications_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_notifications_on_registrar_id ON public.notifications USING btree (registrar_id); -- --- Name: index_prices_on_zone_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_payment_orders_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_payment_orders_on_invoice_id ON public.payment_orders USING btree (invoice_id); + + +-- +-- Name: index_prices_on_zone_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_prices_on_zone_id ON public.prices USING btree (zone_id); -- --- Name: index_registrant_verifications_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_registrant_verifications_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_registrant_verifications_on_created_at ON public.registrant_verifications USING btree (created_at); -- --- Name: index_registrant_verifications_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_registrant_verifications_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_registrant_verifications_on_domain_id ON public.registrant_verifications USING btree (domain_id); -- --- Name: index_settings_on_thing_type_and_thing_id_and_var; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_settings_on_thing_type_and_thing_id_and_var; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE UNIQUE INDEX index_settings_on_thing_type_and_thing_id_and_var ON public.settings USING btree (thing_type, thing_id, var); -- --- Name: index_users_on_identity_code; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_users_on_identity_code; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_users_on_identity_code ON public.users USING btree (identity_code); -- --- Name: index_users_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_users_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_users_on_registrar_id ON public.users USING btree (registrar_id); -- --- Name: index_versions_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_versions_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_versions_on_item_type_and_item_id ON public.versions USING btree (item_type, item_id); -- --- Name: index_whois_records_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_whois_records_on_domain_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_whois_records_on_domain_id ON public.whois_records USING btree (domain_id); -- --- Name: index_whois_records_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_whois_records_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_whois_records_on_registrar_id ON public.whois_records USING btree (registrar_id); -- --- Name: log_contacts_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: log_contacts_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX log_contacts_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_id'::text))::integer)); -- --- Name: log_dnskeys_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: log_dnskeys_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX log_dnskeys_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer)); -- --- Name: log_domains_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: log_domains_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX log_domains_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_id'::text))::integer)); -- --- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX log_nameservers_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer)); -- --- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version); @@ -3895,6 +3951,14 @@ ALTER TABLE ONLY public.registrant_verifications ADD CONSTRAINT fk_rails_f41617a0e9 FOREIGN KEY (domain_id) REFERENCES public.domains(id); +-- +-- Name: fk_rails_f9dc5857c3; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.payment_orders + ADD CONSTRAINT fk_rails_f9dc5857c3 FOREIGN KEY (invoice_id) REFERENCES public.invoices(id); + + -- -- Name: invoice_items_invoice_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -4339,6 +4403,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20191212133136'), ('20191227110904'), ('20200113091254'), -('20200115102202'); +('20200115102202'), +('20200130092113'); From 7033d912272565ea1c4fe57f84126f9cf2741bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 30 Jan 2020 18:31:39 +0200 Subject: [PATCH 02/17] EveryPay/BankLink: Select specific Invoice to mark as paid --- app/models/bank_transaction.rb | 15 ++++++++++----- app/models/payment_orders/bank_link.rb | 3 ++- app/models/payment_orders/every_pay.rb | 4 +++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index 6612a4dbd..174aae06c 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -24,15 +24,20 @@ class BankTransaction < ApplicationRecord @registrar ||= Invoice.find_by(reference_no: parsed_ref_number)&.buyer end - # For successful binding, reference number, invoice id and sum must match with the invoice - def autobind_invoice + def autobind_invoice(invoice_no: nil) return if binded? return unless registrar - return unless invoice - return unless invoice.payable? - create_activity(registrar, invoice) + inv = if invoice_no.nil? + invoice + else + Invoice.find_by(number: invoice_no) + end + return unless inv + return unless inv.payable? + + create_activity(registrar, inv) end def bind_invoice(invoice_no) diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb index 0cdedbd85..be78973ed 100644 --- a/app/models/payment_orders/bank_link.rb +++ b/app/models/payment_orders/bank_link.rb @@ -51,6 +51,7 @@ module PaymentOrders def complete_transaction return unless valid_response_from_intermediary? && settled_payment? + self.status = 'paid' transaction = BankTransaction.where(description: invoice.order).first_or_initialize( description: invoice.order, reference_no: invoice.reference_no, @@ -66,7 +67,7 @@ module PaymentOrders transaction.paid_at = Time.parse(response['VK_T_DATETIME']) transaction.save! - transaction.autobind_invoice + transaction.autobind_invoice(invoice_no: invoice.number) end def settled_payment? diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb index ae84aacca..66c34c3fa 100644 --- a/app/models/payment_orders/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -36,6 +36,7 @@ module PaymentOrders def complete_transaction return unless valid_response_from_intermediary? && settled_payment? + self.status = 'paid' transaction = BankTransaction.where(description: invoice.order).first_or_initialize( description: invoice.order, @@ -48,7 +49,8 @@ module PaymentOrders transaction.paid_at = Date.strptime(response['timestamp'], '%s') transaction.buyer_name = response['cc_holder_name'] - transaction.autobind_invoice + transaction.save! + transaction.autobind_invoice(invoice_no: invoice.number) end def base_params From 32d4fc3c8332a413c01d3d76f7510bfb2e73898c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 30 Jan 2020 21:01:15 +0200 Subject: [PATCH 03/17] Refactor EveryPay / Banklink processing --- .../registrar/payments_controller.rb | 14 +++++++------ app/models/bank_transaction.rb | 14 ++++--------- app/models/payment_order.rb | 19 +++++++++++++++++- app/models/payment_orders/bank_link.rb | 16 ++++++++++----- app/models/payment_orders/every_pay.rb | 20 +++++++++++++------ 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 98b9e1d7d..aaa742be5 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -31,20 +31,20 @@ class Registrar end def back - puts params - @payment_order = PaymentOrder.find_by!(id: params[:bank]) @payment_order.update!(response: params.to_unsafe_h) - if @payment_order.valid_response_from_intermediary? && @payment_order.settled_payment? - @payment_order.complete_transaction + if @payment_order.payment_received? + @payment_order.complete_transaction(@payment_order.composed_transaction) if @payment_order.invoice.paid? flash[:notice] = t(:pending_applied) else - flash[:alert] = t(:something_wrong) + # flash[:alert] = t(:something_wrong) + flash[:alert] = 'We fucked up' end else + @payment_order.create_failure_report flash[:alert] = t(:something_wrong) end redirect_to registrar_invoice_path(@payment_order.invoice) @@ -54,8 +54,10 @@ class Registrar @payment_order = PaymentOrder.find_by!(id: params[:bank]) @payment_order.update!(response: params.to_unsafe_h) - if @payment_order.valid_response_from_intermediary? && @payment_order.settled_payment? + if @payment_order.payment_received? @payment_order.complete_transaction + else + @payment_order.create_failure_report end render status: 200, json: { status: 'ok' } diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index 0cc9500cc..792a32484 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -31,19 +31,13 @@ class BankTransaction < ApplicationRecord end # For successful binding, reference number, invoice id and sum must match with the invoice - def autobind_invoice(invoice_no: nil) + def autobind_invoice return if binded? return unless registrar + return unless invoice + return unless invoice.payable? - inv = if invoice_no.nil? - invoice - else - Invoice.find_by(number: invoice_no) - end - return unless inv - return unless inv.payable? - - create_activity(registrar, inv) + create_activity(registrar, invoice) end def bind_invoice(invoice_no) diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index 228c4021d..a0d3da254 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -11,7 +11,8 @@ class PaymentOrder < ApplicationRecord validate :invoice_cannot_be_already_paid, on: :create # validates :type, inclusion: { in: PAYMENT_METHODS } - enum status: { issued: 'issued', paid: 'paid', cancelled: 'cancelled' } + enum status: { issued: 'issued', paid: 'paid', cancelled: 'cancelled', + failed: 'failed' } attr_accessor :return_url, :response_url @@ -34,6 +35,22 @@ class PaymentOrder < ApplicationRecord end end + def complete_transaction(transaction) + paid! + + transaction.save! + transaction.bind_invoice(invoice.number) + + return unless transaction.errors.any? + + worded_errors = 'Failed to bind. ' + transaction.errors.full_messages.each do |err| + worded_errors << "#{err}, " + end + + update!(notes: worded_errors) + end + def self.supported_methods enabled = [] diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb index be78973ed..c5a8bc54e 100644 --- a/app/models/payment_orders/bank_link.rb +++ b/app/models/payment_orders/bank_link.rb @@ -48,10 +48,17 @@ module PaymentOrders end end - def complete_transaction - return unless valid_response_from_intermediary? && settled_payment? + def payment_received? + valid_response_from_intermediary? && settled_payment? + end - self.status = 'paid' + def create_failure_report + notes = "User failed to make valid payment. Bank responded with code #{response['VK_SERVICE']}" + status = 'cancelled' + update!(notes: notes, status: status) + end + + def composed_transaction transaction = BankTransaction.where(description: invoice.order).first_or_initialize( description: invoice.order, reference_no: invoice.reference_no, @@ -66,8 +73,7 @@ module PaymentOrders transaction.buyer_name = response['VK_SND_NAME'] transaction.paid_at = Time.parse(response['VK_T_DATETIME']) - transaction.save! - transaction.autobind_invoice(invoice_no: invoice.number) + transaction end def settled_payment? diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb index 66c34c3fa..53705d1a6 100644 --- a/app/models/payment_orders/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -34,11 +34,12 @@ module PaymentOrders SUCCESSFUL_PAYMENT.include?(response['payment_state']) end - def complete_transaction - return unless valid_response_from_intermediary? && settled_payment? - self.status = 'paid' + def payment_received? + valid_response_from_intermediary? && settled_payment? + end - transaction = BankTransaction.where(description: invoice.order).first_or_initialize( + def composed_transaction + transaction = BankTransaction.new( description: invoice.order, reference_no: invoice.reference_no, currency: invoice.currency, @@ -49,8 +50,13 @@ module PaymentOrders transaction.paid_at = Date.strptime(response['timestamp'], '%s') transaction.buyer_name = response['cc_holder_name'] - transaction.save! - transaction.autobind_invoice(invoice_no: invoice.number) + transaction + end + + def create_failure_report + notes = "User failed to make valid payment. Payment state: #{response['payment_state']}" + status = 'cancelled' + update!(notes: notes, status: status) end def base_params @@ -80,6 +86,8 @@ module PaymentOrders end def valid_amount? + return false unless response.key? 'amount' + invoice.total == BigDecimal(response['amount']) end From 347249df39af1886fb2c999617787b5e7e70a8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 30 Jan 2020 21:02:07 +0200 Subject: [PATCH 04/17] Introduce Payment Orders to views --- app/views/admin/invoices/show.haml | 2 ++ .../invoices/partials/_payment_orders.haml | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 app/views/registrar/invoices/partials/_payment_orders.haml diff --git a/app/views/admin/invoices/show.haml b/app/views/admin/invoices/show.haml index e3627c158..d0450469f 100644 --- a/app/views/admin/invoices/show.haml +++ b/app/views/admin/invoices/show.haml @@ -21,3 +21,5 @@ .col-md-6= render 'registrar/invoices/partials/buyer' .row .col-md-12= render 'registrar/invoices/partials/items' +.row + .col-md-12= render 'registrar/invoices/partials/payment_orders' diff --git a/app/views/registrar/invoices/partials/_payment_orders.haml b/app/views/registrar/invoices/partials/_payment_orders.haml new file mode 100644 index 000000000..d418ea1ac --- /dev/null +++ b/app/views/registrar/invoices/partials/_payment_orders.haml @@ -0,0 +1,19 @@ +%h4= "Payment Orders" +%hr +.table-responsive + %table.table.table-hover.table-condensed + %thead + %tr + %th{class: 'col-xs-1'}= "#" + %th{class: 'col-xs-1'}= "Channel" + %th{class: 'col-xs-2'}= "Status" + %th{class: 'col-xs-3'}= "Initiated" + %th{class: 'col-xs-4'}= "Notes" + %tbody + - @invoice.payment_orders.each do |payment_order| + %tr + %td= payment_order.id + %td= payment_order.channel + %td= payment_order.status + %td= payment_order.created_at + %td= payment_order.notes From 03b031abeb3e5b60d304bcfcd6a97ee86c98002c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 30 Jan 2020 21:02:43 +0200 Subject: [PATCH 05/17] Make PaymentOrder default status 'issued' --- db/migrate/20200130092113_create_payment_orders.rb | 2 +- db/structure.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/migrate/20200130092113_create_payment_orders.rb b/db/migrate/20200130092113_create_payment_orders.rb index 0b0594e56..d3320ee9b 100644 --- a/db/migrate/20200130092113_create_payment_orders.rb +++ b/db/migrate/20200130092113_create_payment_orders.rb @@ -2,7 +2,7 @@ class CreatePaymentOrders < ActiveRecord::Migration[5.0] def change create_table :payment_orders do |t| t.string :type, null: false - t.string :status, default: 0, null: false + t.string :status, default: 'issued', null: false t.belongs_to :invoice, foreign_key: true t.jsonb :response, null: true t.string :notes, null: true diff --git a/db/structure.sql b/db/structure.sql index c664522bb..edf53fe6f 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1824,7 +1824,7 @@ ALTER SEQUENCE public.notifications_id_seq OWNED BY public.notifications.id; CREATE TABLE public.payment_orders ( id integer NOT NULL, type character varying NOT NULL, - status character varying DEFAULT '0'::character varying NOT NULL, + status character varying DEFAULT 'issued'::character varying NOT NULL, invoice_id integer, response jsonb, notes character varying, From 3f5b5962d1797abcc81ab27655621894e4ae741d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 3 Feb 2020 14:14:31 +0200 Subject: [PATCH 06/17] Make sure that Payment method is functional prior to paying --- .../registrar/payments_controller.rb | 23 +++++----------- app/models/payment_order.rb | 26 +++++++++---------- app/models/payment_orders/lhv.rb | 2 +- app/models/payment_orders/seb.rb | 2 +- config/routes.rb | 10 +++---- 5 files changed, 27 insertions(+), 36 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index aaa742be5..00b10f34e 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -5,21 +5,14 @@ class Registrar skip_authorization_check # actually anyone can pay, no problems at all skip_before_action :authenticate_registrar_user!, :check_ip_restriction, only: [:back, :callback] - before_action :check_supported_payment_method + + before_action :check_supported_payment_method, only: [:pay] def pay invoice = Invoice.find(params[:invoice_id]) payment_type = params[:bank] - channel = if payment_type == 'every_pay' - 'PaymentOrders::EveryPay' - elsif payment_type == 'seb' - 'PaymentOrders::SEB' - elsif payment_type == 'swed' - 'PaymentOrders::Swed' - elsif payment_type == 'lhv' - 'PaymentOrders::LHV' - end + channel = PaymentOrder.type_from_shortname(payment_type) @payment_order = PaymentOrder.new(type: channel, invoice: invoice) @payment_order.save && @payment_order.reload @@ -31,7 +24,7 @@ class Registrar end def back - @payment_order = PaymentOrder.find_by!(id: params[:bank]) + @payment_order = PaymentOrder.find_by!(id: params[:payment_order]) @payment_order.update!(response: params.to_unsafe_h) if @payment_order.payment_received? @@ -51,7 +44,7 @@ class Registrar end def callback - @payment_order = PaymentOrder.find_by!(id: params[:bank]) + @payment_order = PaymentOrder.find_by!(id: params[:payment_order]) @payment_order.update!(response: params.to_unsafe_h) if @payment_order.payment_received? @@ -68,13 +61,11 @@ class Registrar def check_supported_payment_method return if supported_payment_method? - raise StandardError.new('Not supported payment method') + raise(StandardError, 'Not supported payment method') end def supported_payment_method? - puts "Payment method param is #{params[:bank]}" - # PaymentOrder::PAYMENT_METHODS.include?(params[:bank]) - true + PaymentOrder.supported_method?(params[:bank]) end end end diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index a0d3da254..4ce67d887 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -25,14 +25,14 @@ class PaymentOrder < ApplicationRecord errors.add(:invoice, 'is already paid') end - def self.supported_method?(some_class) - raise ArgumentError unless some_class < PaymentOrder + def self.type_from_shortname(shortname) + ('PaymentOrders::' + shortname.camelize).constantize + end - if PAYMENT_METHODS.include?(some_class.name) - true - else - false - end + def self.supported_method?(some_class) + supported_methods.include? type_from_shortname(some_class) + rescue NameError + false end def complete_transaction(transaction) @@ -52,16 +52,16 @@ class PaymentOrder < ApplicationRecord end def self.supported_methods - enabled = [] + supported = [] - ENABLED_METHODS.each do |method| - class_name = method.constantize - raise(Errors::ExpectedPaymentOrder, class_name) unless class_name < PaymentOrder + PAYMENT_METHODS.each do |method| + class_name = ('PaymentOrders::' + method.camelize).constantize + raise(NoMethodError, class_name) unless class_name < PaymentOrder - enabled << class_name + supported << class_name end - enabled + supported end def channel diff --git a/app/models/payment_orders/lhv.rb b/app/models/payment_orders/lhv.rb index 7443f85d3..4c9f59c4a 100644 --- a/app/models/payment_orders/lhv.rb +++ b/app/models/payment_orders/lhv.rb @@ -1,5 +1,5 @@ module PaymentOrders - class LHV < BankLink + class Lhv < BankLink def self.config_namespace_name 'lhv' end diff --git a/app/models/payment_orders/seb.rb b/app/models/payment_orders/seb.rb index 50fb24ced..878d877a7 100644 --- a/app/models/payment_orders/seb.rb +++ b/app/models/payment_orders/seb.rb @@ -1,5 +1,5 @@ module PaymentOrders - class SEB < BankLink + class Seb < BankLink def self.config_namespace_name 'seb' end diff --git a/config/routes.rb b/config/routes.rb index 135fe8eb0..f77529e4f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -127,11 +127,11 @@ Rails.application.routes.draw do end end - get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' - post 'pay/return/:bank' => 'payments#back' - put 'pay/return/:bank' => 'payments#back' - post 'pay/callback/:bank' => 'payments#callback', as: 'response_payment_with' - get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' + get 'pay/return/:payment_order' => 'payments#back', as: 'return_payment_with' + post 'pay/return/:payment_order' => 'payments#back' + put 'pay/return/:payment_order' => 'payments#back' + post 'pay/callback/:payment_order' => 'payments#callback', as: 'response_payment_with' + get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' namespace :settings do resource :balance_auto_reload, controller: :balance_auto_reload, only: %i[edit update destroy] From ec5ff5dc8cff26e02e1d03669542fc2a7472b3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 3 Feb 2020 15:52:02 +0200 Subject: [PATCH 07/17] Validate inclusion of payment method when saving PaymentOrder --- .../registrar/payments_controller.rb | 5 +- app/models/payment_order.rb | 90 +++++++++++-------- app/models/payment_orders/bank_link.rb | 21 ++--- app/models/payment_orders/every_pay.rb | 19 ++-- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 00b10f34e..736cfe01c 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -28,7 +28,7 @@ class Registrar @payment_order.update!(response: params.to_unsafe_h) if @payment_order.payment_received? - @payment_order.complete_transaction(@payment_order.composed_transaction) + @payment_order.complete_transaction if @payment_order.invoice.paid? flash[:notice] = t(:pending_applied) @@ -65,7 +65,8 @@ class Registrar end def supported_payment_method? - PaymentOrder.supported_method?(params[:bank]) + method_name = PaymentOrder.type_from_shortname(params[:bank]) + PaymentOrder.supported_method?(method_name) end end end diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index 4ce67d887..e204ec5dc 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -9,48 +9,13 @@ class PaymentOrder < ApplicationRecord belongs_to :invoice, optional: false validate :invoice_cannot_be_already_paid, on: :create - # validates :type, inclusion: { in: PAYMENT_METHODS } + validate :supported_payment_method enum status: { issued: 'issued', paid: 'paid', cancelled: 'cancelled', failed: 'failed' } attr_accessor :return_url, :response_url - # Name of configuration namespace - def self.config_namespace_name; end - - def invoice_cannot_be_already_paid - return unless invoice&.paid? - - errors.add(:invoice, 'is already paid') - end - - def self.type_from_shortname(shortname) - ('PaymentOrders::' + shortname.camelize).constantize - end - - def self.supported_method?(some_class) - supported_methods.include? type_from_shortname(some_class) - rescue NameError - false - end - - def complete_transaction(transaction) - paid! - - transaction.save! - transaction.bind_invoice(invoice.number) - - return unless transaction.errors.any? - - worded_errors = 'Failed to bind. ' - transaction.errors.full_messages.each do |err| - worded_errors << "#{err}, " - end - - update!(notes: worded_errors) - end - def self.supported_methods supported = [] @@ -64,6 +29,59 @@ class PaymentOrder < ApplicationRecord supported end + # Name of configuration namespace + def self.config_namespace_name; end + + def supported_payment_method + return if PaymentOrder.supported_method? type.constantize + + errors.add(:type, 'is not supported') + end + + def invoice_cannot_be_already_paid + return unless invoice&.paid? + + errors.add(:invoice, 'is already paid') + end + + def self.type_from_shortname(shortname) + ('PaymentOrders::' + shortname.camelize).constantize + end + + def self.supported_method?(some_class) + supported_methods.include? some_class + rescue NameError + false + end + + def base_transaction(sum:, paid_at:, buyer_name:) + BankTransaction.new( + description: invoice.order, + reference_no: invoice.reference_no, + currency: invoice.currency, + iban: invoice.seller_iban, + sum: sum, + paid_at: paid_at, + buyer_name: buyer_name + ) + end + + def complete_transaction + paid! + transaction = composed_transaction + transaction.save! + transaction.bind_invoice(invoice.number) + + return unless transaction.errors.any? + + worded_errors = 'Failed to bind. ' + transaction.errors.full_messages.each do |err| + worded_errors << "#{err}, " + end + + update!(notes: worded_errors) + end + def channel type.gsub('PaymentOrders::', '') end diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb index c5a8bc54e..5bfd02c48 100644 --- a/app/models/payment_orders/bank_link.rb +++ b/app/models/payment_orders/bank_link.rb @@ -53,25 +53,20 @@ module PaymentOrders end def create_failure_report - notes = "User failed to make valid payment. Bank responded with code #{response['VK_SERVICE']}" + notes = "User failed to make payment. Bank responded with code #{response['VK_SERVICE']}" status = 'cancelled' update!(notes: notes, status: status) end def composed_transaction - transaction = BankTransaction.where(description: invoice.order).first_or_initialize( - description: invoice.order, - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) + paid_at = Time.parse(response['VK_T_DATETIME']) + transaction = base_transaction(sum: response['VK_AMOUNT'], + paid_at: paid_at, + buyer_name: response['VK_SND_NAME']) - transaction.sum = response['VK_AMOUNT'] - transaction.bank_reference = response['VK_T_NO'] + transaction.bank_reference = response['VK_T_NO'] transaction.buyer_bank_code = response['VK_SND_ID'] - transaction.buyer_iban = response['VK_SND_ACC'] - transaction.buyer_name = response['VK_SND_NAME'] - transaction.paid_at = Time.parse(response['VK_T_DATETIME']) + transaction.buyer_iban = response['VK_SND_ACC'] transaction end @@ -80,7 +75,7 @@ module PaymentOrders response['VK_SERVICE'] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER end - # private + private def valid_successful_transaction? valid_success_notice? && valid_amount? && valid_currency? diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb index 53705d1a6..2f848fa82 100644 --- a/app/models/payment_orders/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -5,7 +5,7 @@ module PaymentOrders ACCOUNT_ID = ENV['payments_every_pay_seller_account'] SUCCESSFUL_PAYMENT = %w[settled authorized].freeze - CONFIG_NAMESPACE = 'every_pay' + CONFIG_NAMESPACE = 'every_pay'.freeze def self.config_namespace_name CONFIG_NAMESPACE @@ -39,18 +39,9 @@ module PaymentOrders end def composed_transaction - transaction = BankTransaction.new( - description: invoice.order, - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) - - transaction.sum = response['amount'] - transaction.paid_at = Date.strptime(response['timestamp'], '%s') - transaction.buyer_name = response['cc_holder_name'] - - transaction + base_transaction(sum: response['amount'], + paid_at: Date.strptime(response['timestamp'], '%s'), + buyer_name: response['cc_holder_name']) end def create_failure_report @@ -59,6 +50,8 @@ module PaymentOrders update!(notes: notes, status: status) end + private + def base_params { api_username: USER, From fa1687baf0c27b1dc9b99af6a59b234cb8c5f4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 3 Feb 2020 16:47:04 +0200 Subject: [PATCH 08/17] Add PaperTrail history to PaymentOrders --- app/models/payment_order.rb | 2 +- app/models/version/payment_order_version.rb | 4 ++ .../20200130092113_create_payment_orders.rb | 2 + ...203143458_create_payment_order_versions.rb | 16 +++++ db/structure.sql | 58 ++++++++++++++++++- 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 app/models/version/payment_order_version.rb create mode 100644 db/migrate/20200203143458_create_payment_order_versions.rb diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index e204ec5dc..5449262ba 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -1,5 +1,5 @@ class PaymentOrder < ApplicationRecord - #include Versions + include Versions include ActionView::Helpers::NumberHelper PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze diff --git a/app/models/version/payment_order_version.rb b/app/models/version/payment_order_version.rb new file mode 100644 index 000000000..e556f1021 --- /dev/null +++ b/app/models/version/payment_order_version.rb @@ -0,0 +1,4 @@ +class PaymentOrderVersion < PaperTrail::Version + self.table_name = :log_payment_orders + self.sequence_name = :log_payment_orders_id_seq +end diff --git a/db/migrate/20200130092113_create_payment_orders.rb b/db/migrate/20200130092113_create_payment_orders.rb index d3320ee9b..97d86a034 100644 --- a/db/migrate/20200130092113_create_payment_orders.rb +++ b/db/migrate/20200130092113_create_payment_orders.rb @@ -6,6 +6,8 @@ class CreatePaymentOrders < ActiveRecord::Migration[5.0] t.belongs_to :invoice, foreign_key: true t.jsonb :response, null: true t.string :notes, null: true + t.string :creator_str + t.string :updator_str t.timestamps end diff --git a/db/migrate/20200203143458_create_payment_order_versions.rb b/db/migrate/20200203143458_create_payment_order_versions.rb new file mode 100644 index 000000000..d02b300e1 --- /dev/null +++ b/db/migrate/20200203143458_create_payment_order_versions.rb @@ -0,0 +1,16 @@ +class CreatePaymentOrderVersions < ActiveRecord::Migration[5.0] + def change + create_table :log_payment_orders do |t| + t.string :item_type, null: false + t.integer :item_id, null: false + t.string :event, null: false + t.string :whodunnit + t.jsonb :object + t.jsonb :object_changes + t.datetime :created_at + t.string :session + t.jsonb :children + t.string :uuid + end + end +end diff --git a/db/structure.sql b/db/structure.sql index edf53fe6f..d694da536 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1514,6 +1514,44 @@ CREATE SEQUENCE public.log_notifications_id_seq ALTER SEQUENCE public.log_notifications_id_seq OWNED BY public.log_notifications.id; +-- +-- Name: log_payment_orders; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.log_payment_orders ( + id integer NOT NULL, + item_type character varying NOT NULL, + item_id integer NOT NULL, + event character varying NOT NULL, + whodunnit character varying, + object jsonb, + object_changes jsonb, + created_at timestamp without time zone, + session character varying, + children jsonb, + uuid character varying +); + + +-- +-- Name: log_payment_orders_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.log_payment_orders_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: log_payment_orders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.log_payment_orders_id_seq OWNED BY public.log_payment_orders.id; + + -- -- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: -- @@ -1828,6 +1866,8 @@ CREATE TABLE public.payment_orders ( invoice_id integer, response jsonb, notes character varying, + creator_str character varying, + updator_str character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL ); @@ -2533,6 +2573,13 @@ ALTER TABLE ONLY public.log_nameservers ALTER COLUMN id SET DEFAULT nextval('pub ALTER TABLE ONLY public.log_notifications ALTER COLUMN id SET DEFAULT nextval('public.log_notifications_id_seq'::regclass); +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.log_payment_orders ALTER COLUMN id SET DEFAULT nextval('public.log_payment_orders_id_seq'::regclass); + + -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2945,6 +2992,14 @@ ALTER TABLE ONLY public.log_notifications ADD CONSTRAINT log_notifications_pkey PRIMARY KEY (id); +-- +-- Name: log_payment_orders_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.log_payment_orders + ADD CONSTRAINT log_payment_orders_pkey PRIMARY KEY (id); + + -- -- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -4404,6 +4459,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20191227110904'), ('20200113091254'), ('20200115102202'), -('20200130092113'); +('20200130092113'), +('20200203143458'); From b6469f3dfe63761a1e31dea6a7bb246372a5bc66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 3 Feb 2020 19:57:52 +0200 Subject: [PATCH 09/17] Move payment method fetching logic to Model, rewrite tests for EveryPay component --- .../registrar/payments_controller.rb | 6 +- app/models/payment_order.rb | 12 ++- app/models/payment_orders/every_pay.rb | 2 + test/fixtures/invoice_items.yml | 7 ++ test/fixtures/invoices.yml | 27 ++++++ test/fixtures/payment_orders.yml | 20 ++++ .../invoices/payment_callback_test.rb | 2 +- test/models/payment_orders/bank_link_test.rb | 20 ++-- test/models/payment_orders/every_pay_test.rb | 96 ++++++++++--------- test/models/payment_orders_test.rb | 24 +++-- 10 files changed, 139 insertions(+), 77 deletions(-) create mode 100644 test/fixtures/payment_orders.yml diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 736cfe01c..a988dc57e 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -10,11 +10,9 @@ class Registrar def pay invoice = Invoice.find(params[:invoice_id]) - payment_type = params[:bank] + channel = params[:bank] - channel = PaymentOrder.type_from_shortname(payment_type) - - @payment_order = PaymentOrder.new(type: channel, invoice: invoice) + @payment_order = PaymentOrder.create_with_type(type: channel, invoice: invoice) @payment_order.save && @payment_order.reload @payment_order.return_url = registrar_return_payment_with_url(@payment_order) diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index 5449262ba..bc10528fc 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -29,6 +29,12 @@ class PaymentOrder < ApplicationRecord supported end + def self.create_with_type(type:, invoice:) + channel = PaymentOrder.type_from_shortname(type) + + PaymentOrder.new(type: channel, invoice: invoice) + end + # Name of configuration namespace def self.config_namespace_name; end @@ -67,11 +73,11 @@ class PaymentOrder < ApplicationRecord end def complete_transaction + return NoMethodError unless payment_received? + paid! transaction = composed_transaction - transaction.save! - transaction.bind_invoice(invoice.number) - + transaction.save! && transaction.bind_invoice(invoice.number) return unless transaction.errors.any? worded_errors = 'Failed to bind. ' diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb index 2f848fa82..2695c20e0 100644 --- a/app/models/payment_orders/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -76,6 +76,8 @@ module PaymentOrders hmac_string = hmac_hash.map { |key, _v| "#{key}=#{hmac_hash[key]}" }.join('&') expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) expected_hmac == response['hmac'] + rescue NoMethodError + false end def valid_amount? diff --git a/test/fixtures/invoice_items.yml b/test/fixtures/invoice_items.yml index 19409df81..a61ef4eb0 100644 --- a/test/fixtures/invoice_items.yml +++ b/test/fixtures/invoice_items.yml @@ -4,3 +4,10 @@ one: quantity: 1 unit: pc invoice: one + +two: + description: Acme services + price: 5 + quantity: 1 + unit: pc + invoice: unpaid diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index bc9fa2900..6c0dca021 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -24,3 +24,30 @@ one: reference_no: 13 number: 1 description: Order nr 1 from registrar 1234567 second number 2345678 + +unpaid: + issue_date: <%= Date.parse '2010-07-05' %> + due_date: <%= Date.parse '2010-07-06' %> + currency: EUR + seller_name: Seller Ltd + seller_reg_no: 1234 + seller_iban: US75512108001245126199 + seller_bank: Main Bank + seller_swift: swift + seller_email: info@seller.test + seller_country_code: US + seller_street: Main Street 1 + seller_city: New York + seller_contact_name: John Doe + buyer: bestnames + buyer_name: Buyer Ltd + buyer_reg_no: 12345 + buyer_email: info@buyer.test + buyer_country_code: GB + buyer_street: Main Street 2 + buyer_city: London + vat_rate: 0.1 + total: 16.50 + reference_no: 13 + number: 2 + description: Order nr 2 from registrar 1234567 second number 2345678 diff --git a/test/fixtures/payment_orders.yml b/test/fixtures/payment_orders.yml new file mode 100644 index 000000000..b39d309dc --- /dev/null +++ b/test/fixtures/payment_orders.yml @@ -0,0 +1,20 @@ +issued: + type: PaymentOrders::EveryPay + status: issued + invoice: one + response: + notes: + +paid: + type: PaymentOrders::EveryPay + status: paid + invoice: one + response: "{}" + notes: + +cancelled: + type: PaymentOrders::Seb + status: cancelled + invoice: one + response: "{}" + notes: User failed to make payment. Bank responded with code 1911 diff --git a/test/integration/registrar_area/invoices/payment_callback_test.rb b/test/integration/registrar_area/invoices/payment_callback_test.rb index 23db55e84..c26ffa8c0 100644 --- a/test/integration/registrar_area/invoices/payment_callback_test.rb +++ b/test/integration/registrar_area/invoices/payment_callback_test.rb @@ -12,7 +12,7 @@ class PaymentCallbackTest < ApplicationIntegrationTest invoice = payable_invoice assert_matching_bank_transaction_exists(invoice) - request_params = every_pay_request_params.merge(invoice_id: invoice.id) + request_params = every_pay_request_params.merge(payment_order: invoice.id) post "/registrar/pay/callback/every_pay", params: request_params assert_response :ok diff --git a/test/models/payment_orders/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb index f1069819c..775e82cf9 100644 --- a/test/models/payment_orders/bank_link_test.rb +++ b/test/models/payment_orders/bank_link_test.rb @@ -36,11 +36,11 @@ class BankLinkTest < ActiveSupport::TestCase 'VK_MAC': 'CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=', 'VK_ENCODING': 'UTF-8', 'VK_LANG': 'ENG' - }.with_indifferent_access + }.as_json - @completed_bank_link = PaymentOrders::BankLink.new( - 'seb', @invoice, { response: params } - ) + @completed_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb', + invoice: @invoice, + response: params) end def create_cancelled_bank_link @@ -55,16 +55,18 @@ class BankLinkTest < ActiveSupport::TestCase 'VK_MAC': 'PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=', 'VK_ENCODING': 'UTF-8', 'VK_LANG': 'ENG' - }.with_indifferent_access + }.as_json - @cancelled_bank_link = PaymentOrders::BankLink.new( - 'seb', @invoice, { response: params } - ) + @cancelled_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb', + invoice: @invoice, + response: params) end def create_new_bank_link params = { return_url: 'return.url', response_url: 'response.url' } - @new_bank_link = PaymentOrders::BankLink.new('seb', @invoice, params) + @new_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb', invoice: @invoice) + @new_bank_link.return_url = 'return.url' + @new_bank_link.response_url = 'response.url' end def test_response_is_not_valid_when_it_is_missing diff --git a/test/models/payment_orders/every_pay_test.rb b/test/models/payment_orders/every_pay_test.rb index 202efc1b7..1e560f32a 100644 --- a/test/models/payment_orders/every_pay_test.rb +++ b/test/models/payment_orders/every_pay_test.rb @@ -4,36 +4,38 @@ class EveryPayTest < ActiveSupport::TestCase def setup super - @invoice = invoices(:one) + @invoice = invoices(:unpaid) @invoice.update!(total: 12) - params = { - response: - { - utf8: '✓', - _method: 'put', - authenticity_token: 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==', - nonce: '392f2d7748bc8cb0d14f263ebb7b8932', - timestamp: '1524136727', - api_username: 'ca8d6336dd750ddb', - transaction_result: 'completed', - payment_reference: 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56', - payment_state: 'settled', - amount: '12.00', - order_reference: 'e468a2d59a731ccc546f2165c3b1a6', - account_id: 'EUR3D1', - cc_type: 'master_card', - cc_last_four_digits: '0487', - cc_month: '10', - cc_year: '2018', - cc_holder_name: 'John Doe', - hmac_fields: 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result', - hmac: 'efac1c732835668cd86023a7abc140506c692f0d', - invoice_id: '1', - }, - } - @every_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, params) - @other_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, {}) + response = { + "utf8": '✓', + "_method": 'put', + "authenticity_token": 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw=="', + "nonce": '392f2d7748bc8cb0d14f263ebb7b8932', + "timestamp": '1524136727', + "api_username": 'ca8d6336dd750ddb', + "transaction_result": 'completed', + "payment_reference": 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56', + "payment_state": 'settled', + "amount": '12.00', + "order_reference": 'e468a2d59a731ccc546f2165c3b1a6', + "account_id": 'EUR3D1', + "cc_type": 'master_card', + "cc_last_four_digits": '0487', + "cc_month": '10', + "cc_year": '2018', + "cc_holder_name": 'John Doe', + "hmac_fields": 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result', + "hmac": 'efac1c732835668cd86023a7abc140506c692f0d', + "invoice_id": '2' + }.as_json + + @successful_payment = PaymentOrder.new(type: 'PaymentOrders::EveryPay', + invoice: @invoice, + response: response) + + @failed_payment = @successful_payment.dup + @failed_payment.response['payment_state'] = 'cancelled' travel_to Time.zone.parse('2018-04-01 00:30:00 +0000') end @@ -47,37 +49,37 @@ class EveryPayTest < ActiveSupport::TestCase transaction_type: 'charge', hmac_fields: 'account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' } - form_fields = @every_pay.form_fields + form_fields = @successful_payment.form_fields expected_fields.each do |k, v| assert_equal(v, form_fields[k]) end end def test_valid_response_from_intermediary? - assert(@every_pay.valid_response_from_intermediary?) - refute(@other_pay.valid_response_from_intermediary?) + assert(@successful_payment.valid_response_from_intermediary?) + + @failed_payment.response = { 'what': 'definitely not valid everypay response' } + refute(@failed_payment.valid_response_from_intermediary?) + end + + def test_valid_and_successful_payment_is_determined + assert(@successful_payment.payment_received?) + refute(@failed_payment.payment_received?) end def test_settled_payment? - assert(@every_pay.settled_payment?) - other_pay = PaymentOrders::EveryPay.new( - 'every_pay', @invoice, {response: {payment_state: 'CANCELLED'}} - ) - refute(other_pay.settled_payment?) + assert(@successful_payment.settled_payment?) + refute(@failed_payment.settled_payment?) end - def test_complete_transaction_calls_methods_on_transaction - mock_transaction = MiniTest::Mock.new - mock_transaction.expect(:sum= , '12.00', ['12.00']) - mock_transaction.expect(:paid_at= , Date.strptime('1524136727', '%s'), [Date.strptime('1524136727', '%s')]) - mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) - mock_transaction.expect(:save!, true) - mock_transaction.expect(:autobind_invoice, AccountActivity.new) + def test_successful_payment_creates_bank_transaction + @successful_payment.complete_transaction - BankTransaction.stub(:find_by, mock_transaction) do - @every_pay.complete_transaction - end + transaction = BankTransaction.find_by( + sum: @successful_payment.response['amount'], + buyer_name: @successful_payment.response['cc_holder_name'] + ) - mock_transaction.verify + assert transaction.present? end end diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb index 252ba0582..3027bb60e 100644 --- a/test/models/payment_orders_test.rb +++ b/test/models/payment_orders_test.rb @@ -5,23 +5,21 @@ class PaymentOrdersTest < ActiveSupport::TestCase super @original_methods = ENV['payment_methods'] - @original_seb_URL = ENV['seb_payment_url'] - ENV['payment_methods'] = 'seb, swed, credit_card' + @original_seb_url = ENV['seb_payment_url'] + ENV['payment_methods'] = 'seb, swed, every_pay' ENV['seb_payment_url'] = nil - @not_implemented_payment = PaymentOrders::Base.new( - 'not_implemented', Invoice.new - ) + @not_implemented_payment = PaymentOrder.new(invoice: Invoice.new) end def teardown super ENV['payment_methods'] = @original_methods - ENV['seb_payment_url'] = @original_seb_URL + ENV['seb_payment_url'] = @original_seb_url end def test_variable_assignment - assert_equal 'not_implemented', @not_implemented_payment.type + assert_nil @not_implemented_payment.type assert_nil @not_implemented_payment.response_url assert_nil @not_implemented_payment.return_url assert_nil @not_implemented_payment.form_url @@ -45,14 +43,14 @@ class PaymentOrdersTest < ActiveSupport::TestCase end end - def test_that_create_with_type_raises_argument_error - assert_raise ArgumentError do - PaymentOrders.create_with_type("not_implemented", Invoice.new) + def test_can_not_create_order_with_invalid_type + assert_raise NameError do + PaymentOrder.create_with_type(type: 'not_implemented', invoice: Invoice.new) end end - def test_create_with_correct_subclass - payment = PaymentOrders.create_with_type('seb', Invoice.new) - assert_equal PaymentOrders::BankLink, payment.class + def test_can_create_with_correct_subclass + payment = PaymentOrder.create_with_type(type: 'seb', invoice: Invoice.new) + assert_equal PaymentOrders::Seb, payment.class end end From 6418924fafda1a7e1b46f1f2f4c5670b13e15d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 4 Feb 2020 09:42:26 +0200 Subject: [PATCH 10/17] Cover EveryPay / BankLink payments with tests --- .../registrar/payments_controller.rb | 7 +- app/models/payment_order.rb | 15 ++-- test/fixtures/payment_orders.yml | 13 +++- .../invoices/payment_callback_test.rb | 44 ++++++------ .../invoices/payment_return_test.rb | 68 ++++++++++++++++--- test/models/payment_orders/bank_link_test.rb | 38 ++++++----- test/models/payment_orders_test.rb | 21 ++++++ 7 files changed, 145 insertions(+), 61 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index a988dc57e..e356f7049 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -57,14 +57,9 @@ class Registrar private def check_supported_payment_method - return if supported_payment_method? + return if PaymentOrder.supported_method?(params[:bank], shortname: true) raise(StandardError, 'Not supported payment method') end - - def supported_payment_method? - method_name = PaymentOrder.type_from_shortname(params[:bank]) - PaymentOrder.supported_method?(method_name) - end end end diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index bc10528fc..b6fea65be 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -30,7 +30,7 @@ class PaymentOrder < ApplicationRecord end def self.create_with_type(type:, invoice:) - channel = PaymentOrder.type_from_shortname(type) + channel = ('PaymentOrders::' + type.camelize).constantize PaymentOrder.new(type: channel, invoice: invoice) end @@ -39,7 +39,7 @@ class PaymentOrder < ApplicationRecord def self.config_namespace_name; end def supported_payment_method - return if PaymentOrder.supported_method? type.constantize + return if PaymentOrder.supported_method?(type) errors.add(:type, 'is not supported') end @@ -50,11 +50,12 @@ class PaymentOrder < ApplicationRecord errors.add(:invoice, 'is already paid') end - def self.type_from_shortname(shortname) - ('PaymentOrders::' + shortname.camelize).constantize - end - - def self.supported_method?(some_class) + def self.supported_method?(name, shortname: false) + some_class = if shortname + ('PaymentOrders::' + name.camelize).constantize + else + name.constantize + end supported_methods.include? some_class rescue NameError false diff --git a/test/fixtures/payment_orders.yml b/test/fixtures/payment_orders.yml index b39d309dc..39289b7d1 100644 --- a/test/fixtures/payment_orders.yml +++ b/test/fixtures/payment_orders.yml @@ -1,20 +1,27 @@ -issued: +everypay_issued: type: PaymentOrders::EveryPay status: issued invoice: one response: notes: +banklink_issued: + type: PaymentOrders::Seb + status: issued + invoice: one + response: + notes: + paid: type: PaymentOrders::EveryPay status: paid - invoice: one + invoice: unpaid response: "{}" notes: cancelled: type: PaymentOrders::Seb status: cancelled - invoice: one + invoice: unpaid response: "{}" notes: User failed to make payment. Bank responded with code 1911 diff --git a/test/integration/registrar_area/invoices/payment_callback_test.rb b/test/integration/registrar_area/invoices/payment_callback_test.rb index c26ffa8c0..94ca6e373 100644 --- a/test/integration/registrar_area/invoices/payment_callback_test.rb +++ b/test/integration/registrar_area/invoices/payment_callback_test.rb @@ -6,34 +6,40 @@ class PaymentCallbackTest < ApplicationIntegrationTest @user = users(:api_bestnames) sign_in @user + + @payment_order = payment_orders(:everypay_issued) + @invoice = invoices(:one) + @invoice.update!(account_activity: nil, total: 12) end def test_every_pay_callback_returns_status_200 - invoice = payable_invoice - assert_matching_bank_transaction_exists(invoice) - - request_params = every_pay_request_params.merge(payment_order: invoice.id) - post "/registrar/pay/callback/every_pay", params: request_params + request_params = every_pay_request_params + post "/registrar/pay/callback/#{@payment_order.id}", params: request_params assert_response :ok end + def test_invoice_is_marked_as_paid + request_params = every_pay_request_params + post "/registrar/pay/callback/#{@payment_order.id}", params: request_params + + assert @payment_order.invoice.paid? + end + + def failure_log_is_created_if_unsuccessful_payment + request_params = every_pay_request_params.dup + request_params['payment_state'] = 'cancelled' + request_params['transaction_result'] = 'failed' + + post "/registrar/pay/callback/#{@payment_order.id}", params: request_params + + @payment_order.reload + assert @payment_order.cancelled? + assert_includes @payment_order.notes, 'Payment state: cancelled' + end + private - def payable_invoice - invoice = invoices(:one) - invoice.update!(account_activity: nil) - invoice - end - - def assert_matching_bank_transaction_exists(invoice) - assert BankTransaction.find_by( - description: invoice.description, - currency: invoice.currency, - iban: invoice.seller_iban - ), 'Matching bank transaction should exist' - end - def every_pay_request_params { nonce: "392f2d7748bc8cb0d14f263ebb7b8932", diff --git a/test/integration/registrar_area/invoices/payment_return_test.rb b/test/integration/registrar_area/invoices/payment_return_test.rb index de65cccb0..a4adb8160 100644 --- a/test/integration/registrar_area/invoices/payment_return_test.rb +++ b/test/integration/registrar_area/invoices/payment_return_test.rb @@ -8,6 +8,9 @@ class PaymentReturnTest < ApplicationIntegrationTest sign_in @user @invoice = invoices(:one) + @invoice.update!(account_activity: nil, total: 12) + @everypay_order = payment_orders(:everypay_issued) + @banklink_order = payment_orders(:banklink_issued) end def every_pay_request_params @@ -57,33 +60,78 @@ class PaymentReturnTest < ApplicationIntegrationTest } end - def test_every_pay_return_creates_activity_redirects_to_invoice_path - request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + def test_successful_bank_payment_marks_invoice_as_paid + @invoice.update!(account_activity: nil) + request_params = bank_link_request_params - post "/registrar/pay/return/every_pay", params: request_params + post "/registrar/pay/return/#{@banklink_order.id}", params: request_params + + @banklink_order.reload + assert @banklink_order.invoice.paid? + end + + def test_every_pay_return_creates_activity_redirects_to_invoice_path + request_params = every_pay_request_params + + post "/registrar/pay/return/#{@everypay_order.id}", params: request_params assert_equal(302, response.status) assert_redirected_to(registrar_invoice_path(@invoice)) end - def test_Every_Pay_return_raises_RecordNotFound - request_params = every_pay_request_params.merge(invoice_id: "178907") + def test_every_pay_return_raises_record_not_found + request_params = every_pay_request_params assert_raises(ActiveRecord::RecordNotFound) do - post "/registrar/pay/return/every_pay", params: request_params + post '/registrar/pay/return/123456', params: request_params end end def test_bank_link_return_redirects_to_invoice_paths - request_params = bank_link_request_params.merge(invoice_id: @invoice.id) + request_params = bank_link_request_params - post "/registrar/pay/return/seb", params: request_params + post "/registrar/pay/return/#{@banklink_order.id}", params: request_params assert_equal(302, response.status) assert_redirected_to(registrar_invoice_path(@invoice)) end def test_bank_link_return - request_params = bank_link_request_params.merge(invoice_id: "178907") + request_params = bank_link_request_params assert_raises(ActiveRecord::RecordNotFound) do - post "/registrar/pay/return/seb", params: request_params + post '/registrar/pay/return/123456', params: request_params end end + + def test_marks_as_paid_and_adds_notes_if_failed_to_bind + request_params = bank_link_request_params + + post "/registrar/pay/return/#{@banklink_order.id}", params: request_params + post "/registrar/pay/return/#{@banklink_order.id}", params: request_params + @banklink_order.reload + + assert @banklink_order.notes.present? + assert @banklink_order.paid? + assert_includes @banklink_order.notes, 'Failed to bind' + end + + def test_failed_bank_link_payment_creates_brief_error_explanation + request_params = bank_link_request_params.dup + request_params['VK_SERVICE'] = '1911' + + post "/registrar/pay/return/#{@banklink_order.id}", params: request_params + + @banklink_order.reload + + assert_includes @banklink_order.notes, 'Bank responded with code 1911' + end + + def test_failed_every_pay_payment_creates_brief_error_explanation + request_params = every_pay_request_params.dup + request_params['payment_state'] = 'cancelled' + request_params['transaction_result'] = 'failed' + + post "/registrar/pay/return/#{@everypay_order.id}", params: request_params + + @everypay_order.reload + + assert_includes @everypay_order.notes, 'Payment state: cancelled' + end end diff --git a/test/models/payment_orders/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb index 775e82cf9..7f7897f5f 100644 --- a/test/models/payment_orders/bank_link_test.rb +++ b/test/models/payment_orders/bank_link_test.rb @@ -8,7 +8,7 @@ class BankLinkTest < ActiveSupport::TestCase super @invoice = invoices(:one) - @invoice.update!(total: 12) + @invoice.update!(account_activity: nil, total: 12) travel_to '2018-04-01 00:30 +0300' create_new_bank_link @@ -63,7 +63,6 @@ class BankLinkTest < ActiveSupport::TestCase end def create_new_bank_link - params = { return_url: 'return.url', response_url: 'response.url' } @new_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb', invoice: @invoice) @new_bank_link.return_url = 'return.url' @new_bank_link.response_url = 'response.url' @@ -94,6 +93,20 @@ class BankLinkTest < ActiveSupport::TestCase assert_equal(expected_response, @new_bank_link.form_fields) end + def test_correct_channel_is_assigned + swed_link = PaymentOrder.create_with_type(type: 'swed', invoice: @invoice) + assert_equal swed_link.channel, 'Swed' + assert_equal swed_link.class.config_namespace_name, 'swed' + + seb_link = PaymentOrder.create_with_type(type: 'seb', invoice: @invoice) + assert_equal seb_link.channel, 'Seb' + assert_equal seb_link.class.config_namespace_name, 'seb' + + lhv_link = PaymentOrder.create_with_type(type: 'lhv', invoice: @invoice) + assert_equal lhv_link.channel, 'Lhv' + assert_equal lhv_link.class.config_namespace_name, 'lhv' + end + def test_valid_success_response_from_intermediary? assert(@completed_bank_link.valid_response_from_intermediary?) end @@ -107,21 +120,14 @@ class BankLinkTest < ActiveSupport::TestCase refute(@cancelled_bank_link.settled_payment?) end - def test_complete_transaction_calls_methods_on_transaction - mock_transaction = MiniTest::Mock.new - mock_transaction.expect(:sum= , '12.00', ['12.00']) - mock_transaction.expect(:bank_reference= , '1', ['1']) - mock_transaction.expect(:buyer_bank_code= , 'testvpos', ['testvpos']) - mock_transaction.expect(:buyer_iban= , '1234', ['1234']) - mock_transaction.expect(:paid_at= , Date.parse('2018-04-01 00:30:00 +0300'), [Time.parse('2018-04-01T00:30:00+0300')]) - mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) - mock_transaction.expect(:save!, true) - mock_transaction.expect(:autobind_invoice, AccountActivity.new) + def test_successful_payment_creates_bank_transaction + @completed_bank_link.complete_transaction - BankTransaction.stub(:find_by, mock_transaction) do - @completed_bank_link.complete_transaction - end + transaction = BankTransaction.find_by( + sum: @completed_bank_link.response['VK_AMOUNT'], + buyer_name: @completed_bank_link.response['VK_SND_NAME'] + ) - mock_transaction.verify + assert transaction.present? end end diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb index 3027bb60e..3f72dcf8f 100644 --- a/test/models/payment_orders_test.rb +++ b/test/models/payment_orders_test.rb @@ -43,12 +43,33 @@ class PaymentOrdersTest < ActiveSupport::TestCase end end + def test_can_not_create_order_for_paid_invoice + invoice = invoices(:one) + payment_order = PaymentOrder.create_with_type(type: 'every_pay', invoice: invoice) + assert payment_order.invalid? + assert_includes payment_order.errors[:invoice], 'is already paid' + end + + def test_order_without_channel_is_invalid + payment_order = PaymentOrder.new + assert payment_order.invalid? + assert_includes payment_order.errors[:type], 'is not supported' + end + def test_can_not_create_order_with_invalid_type assert_raise NameError do PaymentOrder.create_with_type(type: 'not_implemented', invoice: Invoice.new) end end + def test_supported_method_bool_does_not_fail + assert_not PaymentOrder.supported_method?('not_implemented', shortname: true) + assert PaymentOrder.supported_method?('every_pay', shortname: true) + + assert_not PaymentOrder.supported_method?('PaymentOrders::NonExistant') + assert PaymentOrder.supported_method?('PaymentOrders::EveryPay') + end + def test_can_create_with_correct_subclass payment = PaymentOrder.create_with_type(type: 'seb', invoice: Invoice.new) assert_equal PaymentOrders::Seb, payment.class From 2645654aefbc4c3086395110e25cc647fc0857d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 4 Feb 2020 18:36:06 +0200 Subject: [PATCH 11/17] Create System / Admin payment log --- .../admin/bank_statements_controller.rb | 2 +- .../admin/bank_transactions_controller.rb | 2 +- app/models/bank_statement.rb | 8 ++- app/models/bank_transaction.rb | 63 +++++++++++++------ app/models/payment_order.rb | 4 +- app/models/payment_orders/admin_payment.rb | 9 +++ app/models/payment_orders/system_payment.rb | 9 +++ test/models/payment_orders/bank_link_test.rb | 14 ----- test/models/payment_orders_test.rb | 26 ++++++++ test/tasks/invoices/process_payments_test.rb | 26 +++++++- 10 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 app/models/payment_orders/admin_payment.rb create mode 100644 app/models/payment_orders/system_payment.rb diff --git a/app/controllers/admin/bank_statements_controller.rb b/app/controllers/admin/bank_statements_controller.rb index a70387317..1e3b31bf5 100644 --- a/app/controllers/admin/bank_statements_controller.rb +++ b/app/controllers/admin/bank_statements_controller.rb @@ -60,7 +60,7 @@ module Admin end def bind_invoices - @bank_statement.bind_invoices + @bank_statement.bind_invoices(manual: true) flash[:notice] = t('invoices_were_fully_binded') if @bank_statement.fully_binded? flash[:warning] = t('invoices_were_partially_binded') if @bank_statement.partially_binded? diff --git a/app/controllers/admin/bank_transactions_controller.rb b/app/controllers/admin/bank_transactions_controller.rb index 1ce62b279..348cadc64 100644 --- a/app/controllers/admin/bank_transactions_controller.rb +++ b/app/controllers/admin/bank_transactions_controller.rb @@ -34,7 +34,7 @@ module Admin end def bind - if @bank_transaction.bind_invoice(params[:invoice_no]) + if @bank_transaction.bind_invoice(params[:invoice_no], manual: true) flash[:notice] = I18n.t('record_created') redirect_to [:admin, @bank_transaction] else diff --git a/app/models/bank_statement.rb b/app/models/bank_statement.rb index 8d4608f64..ace1e922d 100644 --- a/app/models/bank_statement.rb +++ b/app/models/bank_statement.rb @@ -45,7 +45,7 @@ class BankStatement < ApplicationRecord buyer_name: row[83, 35].strip, document_no: row[118, 8].strip, description: row[126, 140].strip, - sum: BigDecimal.new(row[268, 12].strip) / BigDecimal.new('100.0'), + sum: BigDecimal(row[268, 12].strip) / BigDecimal('100.0'), reference_no: row[280, 35].strip } end @@ -80,7 +80,9 @@ class BankStatement < ApplicationRecord status == FULLY_BINDED end - def bind_invoices - bank_transactions.unbinded.each(&:autobind_invoice) + def bind_invoices(manual: false) + bank_transactions.unbinded.each do |transaction| + transaction.autobind_invoice(manual: manual) + end end end diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index 792a32484..25c6b60e9 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -13,6 +13,7 @@ class BankTransaction < ApplicationRecord def binded_invoice return unless binded? + account_activity.invoice end @@ -31,28 +32,54 @@ class BankTransaction < ApplicationRecord end # For successful binding, reference number, invoice id and sum must match with the invoice - def autobind_invoice + def autobind_invoice(manual: false) return if binded? return unless registrar return unless invoice return unless invoice.payable? - create_activity(registrar, invoice) + channel = if manual + 'admin_payment' + else + 'system_payment' + end + record_system_payment(channel: channel, invoice: invoice, registrar: registrar) end - def bind_invoice(invoice_no) + def record_system_payment(channel: nil, invoice:, registrar:) + if channel.nil? + create_activity(invoice.buyer, invoice) + return + end + + payment_order = PaymentOrder.create_with_type(type: channel, invoice: invoice) + payment_order.save! + + if create_activity(registrar, invoice) + payment_order.paid! + else + payment_order.failed! + payment_order.notes = 'Failed to create activity' + payment_order.save! + end + end + + def bind_invoice(invoice_no, manual: false) if binded? errors.add(:base, I18n.t('transaction_is_already_binded')) return end invoice = Invoice.find_by(number: invoice_no) + errors.add(:base, I18n.t('invoice_was_not_found')) unless invoice + validate_invoice_data(invoice) + return if errors.any? - unless invoice - errors.add(:base, I18n.t('invoice_was_not_found')) - return - end + record_system_payment(channel: (manual ? 'admin_payment' : nil), invoice: invoice, + registrar: invoice.buyer) + end + def validate_invoice_data(invoice) if invoice.paid? errors.add(:base, I18n.t('invoice_is_already_binded')) return @@ -63,23 +90,19 @@ class BankTransaction < ApplicationRecord return end - if invoice.total != sum - errors.add(:base, I18n.t('invoice_and_transaction_sums_do_not_match')) - return - end - - create_activity(invoice.buyer, invoice) + errors.add(:base, I18n.t('invoice_and_transaction_sums_do_not_match')) if invoice.total != sum end def create_activity(registrar, invoice) - ActiveRecord::Base.transaction do - create_account_activity!(account: registrar.cash_account, - invoice: invoice, - sum: invoice.subtotal, - currency: currency, - description: description, - activity_type: AccountActivity::ADD_CREDIT) + activity = AccountActivity.new(account: registrar.cash_account, + invoice: invoice, sum: invoice.subtotal, + currency: currency, description: description, + activity_type: AccountActivity::ADD_CREDIT) + if activity.save reset_pending_registrar_balance_reload + true + else + false end end diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index b6fea65be..c2cc883a6 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -4,7 +4,9 @@ class PaymentOrder < ApplicationRecord PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze - PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze + INTERNAL_PAYMENT_METHODS = %w[admin_payment system_payment].freeze + PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS, + INTERNAL_PAYMENT_METHODS].flatten.freeze belongs_to :invoice, optional: false diff --git a/app/models/payment_orders/admin_payment.rb b/app/models/payment_orders/admin_payment.rb new file mode 100644 index 000000000..05ae061fb --- /dev/null +++ b/app/models/payment_orders/admin_payment.rb @@ -0,0 +1,9 @@ +module PaymentOrders + class AdminPayment < PaymentOrder + CONFIG_NAMESPACE = 'admin_payment'.freeze + + def self.config_namespace_name + CONFIG_NAMESPACE + end + end +end diff --git a/app/models/payment_orders/system_payment.rb b/app/models/payment_orders/system_payment.rb new file mode 100644 index 000000000..47c75ebe3 --- /dev/null +++ b/app/models/payment_orders/system_payment.rb @@ -0,0 +1,9 @@ +module PaymentOrders + class SystemPayment < PaymentOrder + CONFIG_NAMESPACE = 'system_payment'.freeze + + def self.config_namespace_name + CONFIG_NAMESPACE + end + end +end diff --git a/test/models/payment_orders/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb index 7f7897f5f..30d91cb7c 100644 --- a/test/models/payment_orders/bank_link_test.rb +++ b/test/models/payment_orders/bank_link_test.rb @@ -93,20 +93,6 @@ class BankLinkTest < ActiveSupport::TestCase assert_equal(expected_response, @new_bank_link.form_fields) end - def test_correct_channel_is_assigned - swed_link = PaymentOrder.create_with_type(type: 'swed', invoice: @invoice) - assert_equal swed_link.channel, 'Swed' - assert_equal swed_link.class.config_namespace_name, 'swed' - - seb_link = PaymentOrder.create_with_type(type: 'seb', invoice: @invoice) - assert_equal seb_link.channel, 'Seb' - assert_equal seb_link.class.config_namespace_name, 'seb' - - lhv_link = PaymentOrder.create_with_type(type: 'lhv', invoice: @invoice) - assert_equal lhv_link.channel, 'Lhv' - assert_equal lhv_link.class.config_namespace_name, 'lhv' - end - def test_valid_success_response_from_intermediary? assert(@completed_bank_link.valid_response_from_intermediary?) end diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb index 3f72dcf8f..67267fec0 100644 --- a/test/models/payment_orders_test.rb +++ b/test/models/payment_orders_test.rb @@ -43,6 +43,32 @@ class PaymentOrdersTest < ActiveSupport::TestCase end end + def test_correct_channel_is_assigned + everypay_channel = PaymentOrder.create_with_type(type: 'every_pay', invoice: @invoice) + assert_equal everypay_channel.channel, 'EveryPay' + assert_equal everypay_channel.class.config_namespace_name, 'every_pay' + + swed_channel = PaymentOrder.create_with_type(type: 'swed', invoice: @invoice) + assert_equal swed_channel.channel, 'Swed' + assert_equal swed_channel.class.config_namespace_name, 'swed' + + seb_channel = PaymentOrder.create_with_type(type: 'seb', invoice: @invoice) + assert_equal seb_channel.channel, 'Seb' + assert_equal seb_channel.class.config_namespace_name, 'seb' + + lhv_channel = PaymentOrder.create_with_type(type: 'lhv', invoice: @invoice) + assert_equal lhv_channel.channel, 'Lhv' + assert_equal lhv_channel.class.config_namespace_name, 'lhv' + + admin_channel = PaymentOrder.create_with_type(type: 'admin_payment', invoice: @invoice) + assert_equal admin_channel.channel, 'AdminPayment' + assert_equal admin_channel.class.config_namespace_name, 'admin_payment' + + system_channel = PaymentOrder.create_with_type(type: 'system_payment', invoice: @invoice) + assert_equal system_channel.channel, 'SystemPayment' + assert_equal system_channel.class.config_namespace_name, 'system_payment' + end + def test_can_not_create_order_for_paid_invoice invoice = invoices(:one) payment_order = PaymentOrder.create_with_type(type: 'every_pay', invoice: invoice) diff --git a/test/tasks/invoices/process_payments_test.rb b/test/tasks/invoices/process_payments_test.rb index 8c3b6ec73..02855e9fa 100644 --- a/test/tasks/invoices/process_payments_test.rb +++ b/test/tasks/invoices/process_payments_test.rb @@ -58,6 +58,30 @@ class ProcessPaymentsTaskTest < ActiveSupport::TestCase assert @invoice.paid? end + def test_attaches_paid_payment_order_to_invoice + assert @invoice.unpaid? + + capture_io { run_task } + @invoice.reload + + payment_order = @invoice.payment_orders.last + assert_equal 'PaymentOrders::SystemPayment', payment_order.type + assert payment_order.paid? + end + + def test_attaches_failed_payment_order_to_invoice + assert @invoice.unpaid? + account = accounts(:cash) + account.update!(registrar: registrars(:goodnames)) + + capture_io { run_task } + @invoice.reload + + payment_order = @invoice.payment_orders.last + assert_equal 'PaymentOrders::SystemPayment', payment_order.type + assert payment_order.failed? + end + def test_output assert_output "Transactions processed: 1\n" do run_task @@ -75,4 +99,4 @@ class ProcessPaymentsTaskTest < ActiveSupport::TestCase invoice.update!({ account_activity: nil, cancelled_at: nil }.merge(attributes)) invoice end -end \ No newline at end of file +end From 37e7def669a9334bfe6f9decbe9ae0619b20d308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 4 Feb 2020 21:11:30 +0200 Subject: [PATCH 12/17] Provide better context for EveryPay / Banklink payment state alerts --- app/controllers/registrar/payments_controller.rb | 7 +++---- config/locales/registrar/payments.en.yml | 7 +++++++ 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 config/locales/registrar/payments.en.yml diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index e356f7049..c1944767f 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -29,14 +29,13 @@ class Registrar @payment_order.complete_transaction if @payment_order.invoice.paid? - flash[:notice] = t(:pending_applied) + flash[:notice] = t('.payment_successful') else - # flash[:alert] = t(:something_wrong) - flash[:alert] = 'We fucked up' + flash[:alert] = t('.successful_payment_backend_error') end else @payment_order.create_failure_report - flash[:alert] = t(:something_wrong) + flash[:alert] = t('.payment_not_received') end redirect_to registrar_invoice_path(@payment_order.invoice) end diff --git a/config/locales/registrar/payments.en.yml b/config/locales/registrar/payments.en.yml new file mode 100644 index 000000000..9c817e0ea --- /dev/null +++ b/config/locales/registrar/payments.en.yml @@ -0,0 +1,7 @@ +en: + registrar: + payments: + back: + payment_successful: 'Thank you! Payment received successfully.' + successful_payment_backend_error: 'We received your payment, but something went wrong on our side. Please contact us via email or phone.' + payment_not_received: 'Payment was unsuccessful. Please make sure you have enough funds on your account and try again.' From 5393130e34bc869bd42fc4c461059041c88f161a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 5 Feb 2020 09:15:56 +0200 Subject: [PATCH 13/17] Rename create_payment_method to create_internal_payment_record --- app/models/bank_transaction.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index 25c6b60e9..105f7d14f 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -43,10 +43,11 @@ class BankTransaction < ApplicationRecord else 'system_payment' end - record_system_payment(channel: channel, invoice: invoice, registrar: registrar) + create_internal_payment_record(channel: channel, invoice: invoice, + registrar: registrar) end - def record_system_payment(channel: nil, invoice:, registrar:) + def create_internal_payment_record(channel: nil, invoice:, registrar:) if channel.nil? create_activity(invoice.buyer, invoice) return @@ -75,8 +76,8 @@ class BankTransaction < ApplicationRecord validate_invoice_data(invoice) return if errors.any? - record_system_payment(channel: (manual ? 'admin_payment' : nil), invoice: invoice, - registrar: invoice.buyer) + create_internal_payment_record(channel: (manual ? 'admin_payment' : nil), invoice: invoice, + registrar: invoice.buyer) end def validate_invoice_data(invoice) From fe8d1d1f0b0b7ffba5a779a6faaef115ced16cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 5 Feb 2020 09:16:24 +0200 Subject: [PATCH 14/17] Show user only allowed customer-scoped payment methods --- app/models/payment_order.rb | 1 + app/views/registrar/invoices/show.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index c2cc883a6..3d788913b 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -7,6 +7,7 @@ class PaymentOrder < ApplicationRecord INTERNAL_PAYMENT_METHODS = %w[admin_payment system_payment].freeze PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS, INTERNAL_PAYMENT_METHODS].flatten.freeze + CUSTOMER_PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze belongs_to :invoice, optional: false diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml index d987241b1..5e6104091 100644 --- a/app/views/registrar/invoices/show.haml +++ b/app/views/registrar/invoices/show.haml @@ -17,4 +17,4 @@ - if @invoice.payable? .row.semifooter - .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrder::PAYMENT_METHODS } + .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrder::CUSTOMER_PAYMENT_METHODS } From 5d8e78f3c657056b7c8c50855ce7b1cb3dc3229d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 5 Feb 2020 16:28:01 +0200 Subject: [PATCH 15/17] Rename #create_with_type to #new_with_type --- .../registrar/payments_controller.rb | 8 +++++--- app/models/bank_transaction.rb | 2 +- app/models/payment_order.rb | 2 +- test/models/payment_orders_test.rb | 18 +++++++++--------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index c1944767f..598d13446 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -12,13 +12,15 @@ class Registrar invoice = Invoice.find(params[:invoice_id]) channel = params[:bank] - @payment_order = PaymentOrder.create_with_type(type: channel, invoice: invoice) - @payment_order.save && @payment_order.reload + @payment_order = PaymentOrder.new_with_type(type: channel, invoice: invoice) + @payment_order.save + @payment_order.reload @payment_order.return_url = registrar_return_payment_with_url(@payment_order) @payment_order.response_url = registrar_response_payment_with_url(@payment_order) - @payment_order.save && @payment_order.reload + @payment_order.save + @payment_order.reload end def back diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index 105f7d14f..ca41e8840 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -53,7 +53,7 @@ class BankTransaction < ApplicationRecord return end - payment_order = PaymentOrder.create_with_type(type: channel, invoice: invoice) + payment_order = PaymentOrder.new_with_type(type: channel, invoice: invoice) payment_order.save! if create_activity(registrar, invoice) diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb index 3d788913b..4317abb38 100644 --- a/app/models/payment_order.rb +++ b/app/models/payment_order.rb @@ -32,7 +32,7 @@ class PaymentOrder < ApplicationRecord supported end - def self.create_with_type(type:, invoice:) + def self.new_with_type(type:, invoice:) channel = ('PaymentOrders::' + type.camelize).constantize PaymentOrder.new(type: channel, invoice: invoice) diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb index 67267fec0..43996c6bc 100644 --- a/test/models/payment_orders_test.rb +++ b/test/models/payment_orders_test.rb @@ -44,34 +44,34 @@ class PaymentOrdersTest < ActiveSupport::TestCase end def test_correct_channel_is_assigned - everypay_channel = PaymentOrder.create_with_type(type: 'every_pay', invoice: @invoice) + everypay_channel = PaymentOrder.new_with_type(type: 'every_pay', invoice: @invoice) assert_equal everypay_channel.channel, 'EveryPay' assert_equal everypay_channel.class.config_namespace_name, 'every_pay' - swed_channel = PaymentOrder.create_with_type(type: 'swed', invoice: @invoice) + swed_channel = PaymentOrder.new_with_type(type: 'swed', invoice: @invoice) assert_equal swed_channel.channel, 'Swed' assert_equal swed_channel.class.config_namespace_name, 'swed' - seb_channel = PaymentOrder.create_with_type(type: 'seb', invoice: @invoice) + seb_channel = PaymentOrder.new_with_type(type: 'seb', invoice: @invoice) assert_equal seb_channel.channel, 'Seb' assert_equal seb_channel.class.config_namespace_name, 'seb' - lhv_channel = PaymentOrder.create_with_type(type: 'lhv', invoice: @invoice) + lhv_channel = PaymentOrder.new_with_type(type: 'lhv', invoice: @invoice) assert_equal lhv_channel.channel, 'Lhv' assert_equal lhv_channel.class.config_namespace_name, 'lhv' - admin_channel = PaymentOrder.create_with_type(type: 'admin_payment', invoice: @invoice) + admin_channel = PaymentOrder.new_with_type(type: 'admin_payment', invoice: @invoice) assert_equal admin_channel.channel, 'AdminPayment' assert_equal admin_channel.class.config_namespace_name, 'admin_payment' - system_channel = PaymentOrder.create_with_type(type: 'system_payment', invoice: @invoice) + system_channel = PaymentOrder.new_with_type(type: 'system_payment', invoice: @invoice) assert_equal system_channel.channel, 'SystemPayment' assert_equal system_channel.class.config_namespace_name, 'system_payment' end def test_can_not_create_order_for_paid_invoice invoice = invoices(:one) - payment_order = PaymentOrder.create_with_type(type: 'every_pay', invoice: invoice) + payment_order = PaymentOrder.new_with_type(type: 'every_pay', invoice: invoice) assert payment_order.invalid? assert_includes payment_order.errors[:invoice], 'is already paid' end @@ -84,7 +84,7 @@ class PaymentOrdersTest < ActiveSupport::TestCase def test_can_not_create_order_with_invalid_type assert_raise NameError do - PaymentOrder.create_with_type(type: 'not_implemented', invoice: Invoice.new) + PaymentOrder.new_with_type(type: 'not_implemented', invoice: Invoice.new) end end @@ -97,7 +97,7 @@ class PaymentOrdersTest < ActiveSupport::TestCase end def test_can_create_with_correct_subclass - payment = PaymentOrder.create_with_type(type: 'seb', invoice: Invoice.new) + payment = PaymentOrder.new_with_type(type: 'seb', invoice: Invoice.new) assert_equal PaymentOrders::Seb, payment.class end end From 101187687279abbc5d03e09fd991f9268088f0ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 12 Feb 2020 17:49:41 +0200 Subject: [PATCH 16/17] Link bank transaction with AccountActivity --- app/models/bank_transaction.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index ca41e8840..f53a286ba 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -59,9 +59,7 @@ class BankTransaction < ApplicationRecord if create_activity(registrar, invoice) payment_order.paid! else - payment_order.failed! - payment_order.notes = 'Failed to create activity' - payment_order.save! + payment_order.update(notes: 'Failed to create activity', status: 'failed') end end @@ -95,10 +93,12 @@ class BankTransaction < ApplicationRecord end def create_activity(registrar, invoice) - activity = AccountActivity.new(account: registrar.cash_account, - invoice: invoice, sum: invoice.subtotal, - currency: currency, description: description, - activity_type: AccountActivity::ADD_CREDIT) + activity = AccountActivity.new( + account: registrar.cash_account, bank_transaction: self, + invoice: invoice, sum: invoice.subtotal, + currency: currency, description: description, + activity_type: AccountActivity::ADD_CREDIT + ) if activity.save reset_pending_registrar_balance_reload true From d30281c421796be63e791a3504a6428136afa1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 27 Feb 2020 11:59:46 +0200 Subject: [PATCH 17/17] Update structure.sql --- db/structure.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/structure.sql b/db/structure.sql index d694da536..9adad4a04 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -885,6 +885,7 @@ CREATE TABLE public.invoices ( in_directo boolean DEFAULT false, buyer_vat_no character varying, issue_date date NOT NULL, + e_invoice_sent_at timestamp without time zone, CONSTRAINT invoices_due_date_is_not_before_issue_date CHECK ((due_date >= issue_date)) ); @@ -4460,6 +4461,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200113091254'), ('20200115102202'), ('20200130092113'), -('20200203143458'); +('20200203143458'), +('20200204103125');