From da66e186d264d152d5347314b97284f5a1db8b1b Mon Sep 17 00:00:00 2001 From: Sergei Tsoganov Date: Tue, 26 Sep 2023 16:33:19 +0300 Subject: [PATCH 1/3] Added e-invoicing feature to invoices --- .../e_invoice_response_controller.rb | 17 ++ app/controllers/invoices_controller.rb | 11 ++ app/models/concerns/invoice/book_keeping.rb | 88 ++++++++- app/services/application_service.rb | 6 + app/services/eis_billing/send_e_invoice.rb | 53 ++++++ app/views/common/pdf.html.erb | 4 +- app/views/invoices/show.html.erb | 20 +- config/customization.yml.sample | 11 -- config/locales/invoices.en.yml | 2 + config/locales/invoices.et.yml | 2 + config/routes.rb | 3 +- ...230925104427_modify_invoice_issuer_data.rb | 78 ++++++++ db/data_schema.rb | 3 +- ...130405_add_e_invoice_sent_at_to_invoice.rb | 5 + db/structure.sql | 176 +++++++++--------- test/fixtures/settings.yml | 54 +++++- .../eis_billing/e_invoice_response_test.rb | 19 ++ test/integration/invoices_test.rb | 27 +++ 18 files changed, 465 insertions(+), 114 deletions(-) create mode 100644 app/controllers/eis_billing/e_invoice_response_controller.rb create mode 100644 app/services/application_service.rb create mode 100644 app/services/eis_billing/send_e_invoice.rb create mode 100644 db/data/20230925104427_modify_invoice_issuer_data.rb create mode 100644 db/migrate/20230925130405_add_e_invoice_sent_at_to_invoice.rb create mode 100644 test/integration/eis_billing/e_invoice_response_test.rb diff --git a/app/controllers/eis_billing/e_invoice_response_controller.rb b/app/controllers/eis_billing/e_invoice_response_controller.rb new file mode 100644 index 000000000..e02032184 --- /dev/null +++ b/app/controllers/eis_billing/e_invoice_response_controller.rb @@ -0,0 +1,17 @@ +module EisBilling + class EInvoiceResponseController < EisBilling::BaseController + def update + invoice_number = params[:invoice_number] + + mark_e_invoice_sent_at(invoice_number) + render status: :ok, json: { message: 'Response received' } + end + + private + + def mark_e_invoice_sent_at(invoice_number) + invoice = ::Invoice.find_by(number: invoice_number) + invoice.update(e_invoice_sent_at: Time.zone.now) + end + end +end diff --git a/app/controllers/invoices_controller.rb b/app/controllers/invoices_controller.rb index 93ace6674..bb2fe392d 100644 --- a/app/controllers/invoices_controller.rb +++ b/app/controllers/invoices_controller.rb @@ -91,6 +91,17 @@ def oneoff end end + def send_e_invoice + invoice = Invoice.accessible_by(current_ability).find_by!(uuid: params[:uuid]) + response = EisBilling::SendEInvoice.call(invoice: invoice, payable: false) + + if response.result? + redirect_to invoice_path(invoice.uuid), notice: t('.sent_to_omniva') + else + redirect_to invoice_path(invoice.uuid), alert: response.errors + end + end + def update_predicate @invoice.issued? && @invoice.update(update_params) end diff --git a/app/models/concerns/invoice/book_keeping.rb b/app/models/concerns/invoice/book_keeping.rb index 3cdb083d2..886d8f77c 100644 --- a/app/models/concerns/invoice/book_keeping.rb +++ b/app/models/concerns/invoice/book_keeping.rb @@ -12,6 +12,88 @@ def as_directo_json invoice end + def e_invoice_data + invoice = as_json(only: %i[id issue_date due_date number]) + invoice['seller_name'] = seller_contact_name + invoice['seller_reg_no'] = seller_reg_no + invoice['seller_vat_no'] = seller_vat_no + invoice['seller_street'] = seller_street + invoice['seller_state'] = seller_state + invoice['seller_zip'] = seller_zip + invoice['seller_city'] = seller_city + invoice['seller_country_code'] = seller_country_code + invoice['buyer_name'] = billing_name + invoice['buyer_vat_no'] = billing_vat_code + invoice['buyer_street'] = street + invoice['buyer_state'] = state + invoice['buyer_zip'] = postal_code + invoice['buyer_city'] = city + invoice['buyer_country_code'] = billing_alpha_two_country_code + invoice['total'] = total.to_f + (enable_deposit? ? deposit : 0.0) + invoice['vat_rate'] = vat_rate * 100 + invoice['currency'] = Setting.find_by(code: 'auction_currency').retrieve + + invoice + end + + def e_invoice_sent? + e_invoice_sent_at.present? + end + + def do_not_send_e_invoice? + e_invoice_sent? || cancelled? + end + + def seller_contact_name + Setting.find_by(code: 'invoice_issuer').retrieve + end + + def seller_address + country_name = Countries.name_from_alpha2_code(seller_country_code) + [ + seller_street, + seller_state, + seller_zip, + country_name, + seller_city + ].reject(&:blank?).compact.join(', ') + end + + def seller_reg_no + Setting.find_by(code: 'invoice_issuer_reg_no').retrieve + end + + def seller_vat_no + Setting.find_by(code: 'invoice_issuer_vat_no').retrieve + end + + def seller_street + Setting.find_by(code: 'invoice_issuer_street').retrieve + end + + def seller_city + Setting.find_by(code: 'invoice_issuer_city').retrieve + end + + def seller_zip + Setting.find_by(code: 'invoice_issuer_zip').retrieve + end + + def seller_country_code + Setting.find_by(code: 'invoice_issuer_country_code').retrieve + end + + def seller_state + Setting.find_by(code: 'invoice_issuer_state').retrieve + end + + def issuer + "#{seller_contact_name}, #{seller_address}, " \ + "Reg. no #{seller_reg_no}, VAT number #{seller_vat_no}" + end + + private + def compose_invoice_meta(invoice) invoice['issue_date'] = issue_date.strftime('%Y-%m-%d') invoice['transaction_date'] = paid_at.strftime('%Y-%m-%d') @@ -36,12 +118,14 @@ def compose_directo_customer end def compose_directo_product - [{ 'product_id': 'OKSJON', + [ + { 'product_id': 'OKSJON', 'description': result.auction.domain_name, 'quantity': 1, 'unit': 1, 'price': ActionController::Base.helpers.number_with_precision( price.amount, precision: 2, separator: '.' - ) }].as_json + ) } + ].as_json end end diff --git a/app/services/application_service.rb b/app/services/application_service.rb new file mode 100644 index 000000000..00e548486 --- /dev/null +++ b/app/services/application_service.rb @@ -0,0 +1,6 @@ +# app/services/application_service.rb +class ApplicationService + def self.call(*args, &block) + new(*args, &block).call + end +end diff --git a/app/services/eis_billing/send_e_invoice.rb b/app/services/eis_billing/send_e_invoice.rb new file mode 100644 index 000000000..d62e49471 --- /dev/null +++ b/app/services/eis_billing/send_e_invoice.rb @@ -0,0 +1,53 @@ +module EisBilling + class SendEInvoice < ApplicationService + include EisBilling::Request + include EisBilling::BaseService + + attr_reader :invoice, :payable + + def initialize(invoice:, payable:) + @invoice = invoice + @payable = payable + end + + def call + prepared_data = { + invoice: invoice.e_invoice_data, + vat_amount: invoice.vat.amount, + invoice_subtotal: invoice.price.amount, + buyer_billing_email: invoice.user&.email, + payable: payable, + initiator: INITIATOR, + items: prepare_items(invoice) + } + + struct_response(post(e_invoice_url, prepared_data)) + end + + private + + def prepare_items(invoice) + invoice.items.map do |invoice_item| + { + description: item_description(invoice.result), + price: invoice_item.price.amount, + quantity: 1, + unit: 'piece', + subtotal: invoice_item.price.amount, + vat_rate: invoice.vat_rate.to_f * 100, + vat_amount: invoice.vat.amount, + total: invoice.total.to_f, + } + end + end + + def e_invoice_url + '/api/v1/e_invoice/e_invoice' + end + + def item_description(result) + I18n.t('invoice_items.name', domain_name: result.auction.domain_name, + auction_end: result.auction.ends_at.to_date) + end + end +end diff --git a/app/views/common/pdf.html.erb b/app/views/common/pdf.html.erb index 3d8eb1489..5cd3152e4 100644 --- a/app/views/common/pdf.html.erb +++ b/app/views/common/pdf.html.erb @@ -192,7 +192,7 @@ <%= t('invoices.issuer') %>
- <%= Setting.find_by(code: 'invoice_issuer').retrieve %> + <%= @invoice.issuer %>
<%= t('invoices.number') %> @@ -301,7 +301,7 @@
- <%= Setting.find_by(code: 'invoice_issuer').retrieve %> + <%= @invoice.issuer %>
diff --git a/app/views/invoices/show.html.erb b/app/views/invoices/show.html.erb index e8e4cfd67..5a952a029 100644 --- a/app/views/invoices/show.html.erb +++ b/app/views/invoices/show.html.erb @@ -27,15 +27,15 @@
<%= t('invoices.issuer') %>
- <%= Setting.find_by(code: 'invoice_issuer').retrieve %> -
+ <%= @invoice.issuer %> +
<%= t('invoices.issue_date') %>
- <%= @invoice.issue_date %> + <%= @invoice.issue_date %>
<%= t('invoices.due_date') %>
- <%= @invoice.due_date %> + <%= @invoice.due_date %>
<% if @invoice.paid? %>
@@ -62,8 +62,8 @@ <%= index + 1 %> <%= I18n.t('invoice_items.name', - domain_name: item.invoice.result.auction.domain_name, - auction_end: item.invoice.result.auction.ends_at.to_date) %> + domain_name: @invoice.result.auction.domain_name, + auction_end: @invoice.result.auction.ends_at.to_date) %> <%= item.price %> @@ -104,10 +104,16 @@
<% if @invoice.payable? %> -
+
<%= button_to t('invoices.show.pay'), oneoff_invoice_path(uuid: @invoice.uuid), class: 'ui button primary' %>
<% end %> + <% unless @invoice.do_not_send_e_invoice? %> +
+ <%= button_to t('invoices.show.send_e_invoice'), send_e_invoice_path(uuid: @invoice.uuid), class: 'ui button default', data: { turbo: false } %> +
+ <% end %> +
diff --git a/config/customization.yml.sample b/config/customization.yml.sample index 184ad9e23..ec6071cb5 100644 --- a/config/customization.yml.sample +++ b/config/customization.yml.sample @@ -1,14 +1,4 @@ default: &default - billing_system_integration: - enabled: true - #eis_billing_system_base_url_dev: 'http://eis_billing_system:3000' - #eis_billing_system_base_url_staging: 'https://st-billing.infra.tld.ee' - eis_billing_system_base_url: 'http://eis_billing_system:3000' - secret_access_word: 'please-Give-Me-accesS' - secret_word: 'this-secret-should-be-change' - billing_system_integrated: 'true' - - billing_secret: '0fb3661d89134de0cbcdd6b29780e23f2ec05e744c4d15feb381b1e7d7549d5ec960989c6471c9a31835ee455865cf7b2641529ae7cf1e6b4c3675f6361e98d0' # This is your application name, as displayed in the UI application_name: "EIS Auction Center" @@ -124,7 +114,6 @@ default: &default secret_word: 'this-secret-should-be-change' billing_system_integrated: 'true' billing_secret: '' - test_env: false development: <<: *default diff --git a/config/locales/invoices.en.yml b/config/locales/invoices.en.yml index 80ac8986d..ea8c6821a 100644 --- a/config/locales/invoices.en.yml +++ b/config/locales/invoices.en.yml @@ -26,6 +26,7 @@ en: paid_through: "Paid through" deposit: "Deposit" amount_due: "Amount due" + sent_to_omniva: "E-Invoice was successfully sent" outstanding: "Outstanding invoices" paid: "Paid invoices" @@ -49,6 +50,7 @@ en: change_billing_profile: "Change billing profile" pay: "Pay" redeem: Paying for cancelled invoice will redeem the violation but will not grant priority right to register that domain + send_e_invoice: "Send E-Invoice" edit: title: "Edit your invoice" diff --git a/config/locales/invoices.et.yml b/config/locales/invoices.et.yml index cdcb043d7..fcb231143 100644 --- a/config/locales/invoices.et.yml +++ b/config/locales/invoices.et.yml @@ -26,6 +26,7 @@ et: paid_through: "Makseviis" deposit: "Ettemaks" amount_due: "Tasuda" + sent_to_omniva: "E-arve saadeti edukalt" outstanding: "Tasumata arved" paid: "Tasutud arved" @@ -49,6 +50,7 @@ et: change_billing_profile: "Muuda arve aadressi" pay: "Maksa" redeem: Tühistatud arve tasumine eemaldab vastava arvega seotud rikkumise, kuid ei anna vastava domeeni registreerimiseks eelisõigust. + send_e_invoice: "Saada E-Arve" edit: title: "Muuda arvet" diff --git a/config/routes.rb b/config/routes.rb index 4b75d3594..b185fabce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -38,6 +38,7 @@ namespace :eis_billing, defaults: { format: 'json' } do put '/payment_status', to: 'payment_status#update', as: 'payment_status' put '/directo_response', to: 'directo_response#update', as: 'directo_response' + put '/e_invoice_response', to: 'e_invoice_response#update', as: 'e_invoice_response' end namespace :admin, constraints: Constraints::Administrator.new do @@ -90,11 +91,11 @@ resources :billing_profiles, param: :uuid match '/status', via: :get, to: 'health_checks#index' - resources :invoices, only: %i[show edit update index], param: :uuid do member do get 'download' post 'oneoff' + post 'send_e_invoice', as: :send_e end collection do diff --git a/db/data/20230925104427_modify_invoice_issuer_data.rb b/db/data/20230925104427_modify_invoice_issuer_data.rb new file mode 100644 index 000000000..707eed5a5 --- /dev/null +++ b/db/data/20230925104427_modify_invoice_issuer_data.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +class ModifyInvoiceIssuerData < ActiveRecord::Migration[7.0] + def up + hash = { + invoice_issuer: { + description: <<~TEXT.squish, + Text that should appear in invoice as issuer. Usually contains a company name. + TEXT + value: 'Eesti Interneti SA', + value_format: 'string' + }, + invoice_issuer_reg_no: { + description: <<~TEXT.squish, + Invoice issuer registration number + TEXT + value: '90010019', + value_format: 'string' + }, + invoice_issuer_vat_no: { + description: <<~TEXT.squish, + Invoice issuer VAT number. + TEXT + value: 'EE101286464', + value_format: 'string' + }, + invoice_issuer_street: { + description: <<~TEXT.squish, + Invoice issuer street name. + TEXT + value: 'Paldiski mnt 80', + value_format: 'string' + }, + invoice_issuer_state: { + description: <<~TEXT.squish, + Invoice issuer state name. + TEXT + value: 'Harjumaa', + value_format: 'string' + }, + invoice_issuer_zip: { + description: <<~TEXT.squish, + Invoice issuer zip code. + TEXT + value: '10617', + value_format: 'string' + }, + invoice_issuer_city: { + description: <<~TEXT.squish, + Invoice issuer city name. + TEXT + value: 'Tallinn', + value_format: 'string' + }, + invoice_issuer_country_code: { + description: <<~TEXT.squish, + Invoice issuer country code. + TEXT + value: 'EE', + value_format: 'string' + } + } + + Setting.transaction do + hash.each do |key, value_hash| + setting = Setting.find_or_create_by(code: key) + setting.update!(value: value_hash[:value], + description: value_hash[:description], + value_format: value_hash[:value_format]) + end + puts 'Invoice issuer settings updated.' + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/data_schema.rb b/db/data_schema.rb index bcf096a15..f8654a3da 100644 --- a/db/data_schema.rb +++ b/db/data_schema.rb @@ -1,2 +1 @@ -# encoding: UTF-8 -DataMigrate::Data.define(version: 20200527081406) +DataMigrate::Data.define(version: 20230925104427) diff --git a/db/migrate/20230925130405_add_e_invoice_sent_at_to_invoice.rb b/db/migrate/20230925130405_add_e_invoice_sent_at_to_invoice.rb new file mode 100644 index 000000000..bd3db63f2 --- /dev/null +++ b/db/migrate/20230925130405_add_e_invoice_sent_at_to_invoice.rb @@ -0,0 +1,5 @@ +class AddEInvoiceSentAtToInvoice < ActiveRecord::Migration[7.0] + def change + add_column :invoices, :e_invoice_sent_at, :datetime + end +end diff --git a/db/structure.sql b/db/structure.sql index bbd6d4173..f4b568d16 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -912,6 +912,38 @@ CREATE SEQUENCE public.auctions_id_seq ALTER SEQUENCE public.auctions_id_seq OWNED BY public.auctions.id; +-- +-- Name: auto_bids; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.auto_bids ( + id bigint NOT NULL, + wishlist_item_id bigint NOT NULL, + cents integer NOT NULL, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: auto_bids_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.auto_bids_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: auto_bids_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.auto_bids_id_seq OWNED BY public.auto_bids.id; + + -- -- Name: autobiders; Type: TABLE; Schema: public; Owner: - -- @@ -921,7 +953,7 @@ CREATE TABLE public.autobiders ( user_id bigint, domain_name character varying, cents integer, - uuid uuid DEFAULT gen_random_uuid(), + uuid uuid DEFAULT public.gen_random_uuid(), created_at timestamp(6) without time zone NOT NULL, updated_at timestamp(6) without time zone NOT NULL ); @@ -1021,6 +1053,15 @@ CREATE SEQUENCE public.billing_profiles_id_seq ALTER SEQUENCE public.billing_profiles_id_seq OWNED BY public.billing_profiles.id; +-- +-- Name: data_migrations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.data_migrations ( + version character varying NOT NULL +); + + -- -- Name: delayed_jobs; Type: TABLE; Schema: public; Owner: - -- @@ -1229,6 +1270,7 @@ CREATE TABLE public.invoices ( billing_address character varying DEFAULT ''::character varying NOT NULL, billing_vat_code character varying, billing_alpha_two_country_code character varying DEFAULT ''::character varying NOT NULL, + e_invoice_sent_at timestamp(6) without time zone, CONSTRAINT invoices_cents_are_non_negative CHECK ((cents >= 0)), CONSTRAINT invoices_due_date_is_not_before_issue_date CHECK ((issue_date <= due_date)), CONSTRAINT paid_at_is_filled_when_status_is_paid CHECK ((NOT ((status = 'paid'::public.invoice_status) AND (paid_at IS NULL)))), @@ -1544,6 +1586,7 @@ CREATE TABLE public.users ( uid character varying, updated_by character varying, daily_summary boolean DEFAULT false NOT NULL, + discarded_at timestamp without time zone, CONSTRAINT users_roles_are_known CHECK ((roles <@ ARRAY['participant'::character varying, 'administrator'::character varying])) ); @@ -1726,6 +1769,13 @@ ALTER TABLE ONLY audit.wishlist_items ALTER COLUMN id SET DEFAULT nextval('audit ALTER TABLE ONLY public.auctions ALTER COLUMN id SET DEFAULT nextval('public.auctions_id_seq'::regclass); +-- +-- Name: auto_bids id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.auto_bids ALTER COLUMN id SET DEFAULT nextval('public.auto_bids_id_seq'::regclass); + + -- -- Name: autobiders id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2027,6 +2077,14 @@ ALTER TABLE ONLY public.ar_internal_metadata ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key); +-- +-- Name: auto_bids auto_bids_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.auto_bids + ADD CONSTRAINT auto_bids_pkey PRIMARY KEY (id); + + -- -- Name: autobiders autobiders_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -2051,6 +2109,14 @@ ALTER TABLE ONLY public.billing_profiles ADD CONSTRAINT billing_profiles_pkey PRIMARY KEY (id); +-- +-- Name: data_migrations data_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.data_migrations + ADD CONSTRAINT data_migrations_pkey PRIMARY KEY (version); + + -- -- Name: delayed_jobs delayed_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -2375,6 +2441,13 @@ CREATE UNIQUE INDEX index_auctions_on_remote_id ON public.auctions USING btree ( CREATE UNIQUE INDEX index_auctions_on_uuid ON public.auctions USING btree (uuid); +-- +-- Name: index_auto_bids_on_wishlist_item_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_auto_bids_on_wishlist_item_id ON public.auto_bids USING btree (wishlist_item_id); + + -- -- Name: index_autobiders_on_domain_name; Type: INDEX; Schema: public; Owner: - -- @@ -2697,90 +2770,6 @@ CREATE INDEX index_wishlist_items_on_domain_name ON public.wishlist_items USING CREATE UNIQUE INDEX users_by_identity_code_and_country ON public.users USING btree (alpha_two_country_code, identity_code) WHERE ((alpha_two_country_code)::text = 'EE'::text); --- --- Name: auctions process_auction_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_auction_audit AFTER INSERT OR DELETE OR UPDATE ON public.auctions FOR EACH ROW EXECUTE FUNCTION public.process_auction_audit(); - - --- --- Name: bans process_ban_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_ban_audit AFTER INSERT OR DELETE OR UPDATE ON public.bans FOR EACH ROW EXECUTE FUNCTION public.process_ban_audit(); - - --- --- Name: billing_profiles process_billing_profile_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_billing_profile_audit AFTER INSERT OR DELETE OR UPDATE ON public.billing_profiles FOR EACH ROW EXECUTE FUNCTION public.process_billing_profile_audit(); - - --- --- Name: invoices process_invoice_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_invoice_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoices FOR EACH ROW EXECUTE FUNCTION public.process_invoice_audit(); - - --- --- Name: invoice_items process_invoice_item_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_invoice_item_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoice_items FOR EACH ROW EXECUTE FUNCTION public.process_invoice_item_audit(); - - --- --- Name: invoice_payment_orders process_invoice_payment_order_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_invoice_payment_order_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoice_payment_orders FOR EACH ROW EXECUTE FUNCTION public.process_invoice_payment_order_audit(); - - --- --- Name: offers process_offer_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_offer_audit AFTER INSERT OR DELETE OR UPDATE ON public.offers FOR EACH ROW EXECUTE FUNCTION public.process_offer_audit(); - - --- --- Name: payment_orders process_payment_order_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_payment_order_audit AFTER INSERT OR DELETE OR UPDATE ON public.payment_orders FOR EACH ROW EXECUTE FUNCTION public.process_payment_order_audit(); - - --- --- Name: results process_result_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_result_audit AFTER INSERT OR DELETE OR UPDATE ON public.results FOR EACH ROW EXECUTE FUNCTION public.process_result_audit(); - - --- --- Name: settings process_setting_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_setting_audit AFTER INSERT OR DELETE OR UPDATE ON public.settings FOR EACH ROW EXECUTE FUNCTION public.process_setting_audit(); - - --- --- Name: users process_user_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_user_audit AFTER INSERT OR DELETE OR UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.process_user_audit(); - - --- --- Name: wishlist_items process_wishlist_item_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_wishlist_item_audit AFTER INSERT OR DELETE OR UPDATE ON public.wishlist_items FOR EACH ROW EXECUTE FUNCTION public.process_wishlist_item_audit(); - - -- -- Name: bans fk_rails_070022cd76; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -2813,6 +2802,14 @@ ALTER TABLE ONLY public.autobiders ADD CONSTRAINT fk_rails_3d4f798ed7 FOREIGN KEY (user_id) REFERENCES public.users(id); +-- +-- Name: auto_bids fk_rails_473d19add3; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.auto_bids + ADD CONSTRAINT fk_rails_473d19add3 FOREIGN KEY (wishlist_item_id) REFERENCES public.wishlist_items(id); + + -- -- Name: wishlist_items fk_rails_5c10acf6bc; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -3006,11 +3003,14 @@ INSERT INTO "schema_migrations" (version) VALUES ('20191025092912'), ('20191028092316'), ('20191121162323'), +('20191129102035'), +('20191206123023'), ('20191209073454'), ('20191209083000'), ('20191209085222'), ('20191213082941'), ('20191220131845'), +('20200109093043'), ('20200110135003'), ('20200115145246'), ('20200205092158'), @@ -3022,6 +3022,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20220422094307'), ('20220422094556'), ('20220422095751'), +('20220422121056'), ('20220425103701'), ('20220426082102'), ('20220527064738'), @@ -3038,5 +3039,8 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230227085236'), ('20230309094132'), ('20230419114412'), +('20230607092953'), ('20230705192353'), -('20230607092953'); +('20230925130405'); + + diff --git a/test/fixtures/settings.yml b/test/fixtures/settings.yml index e0e7d9914..7edc3ea4e 100644 --- a/test/fixtures/settings.yml +++ b/test/fixtures/settings.yml @@ -121,9 +121,57 @@ remind_on_domain_registration_everyday: invoice_issuer: code: 'invoice_issuer' description: | - Text that should appear in invoice as issuer. Usually contains company name, VAT number and - local court registration number.e which the registration reminder email is sent on. Default: 5 - value: 'Eesti Interneti SA, VAT number EE101286464' + Text that should appear in invoice as issuer. Usually contains a company name + value: 'Eesti Interneti SA' + value_format: string + +invoice_issuer_reg_no: + code: 'invoice_issuer_reg_no' + description: | + Invoice issuer registration number + value: '90010019' + value_format: string + +invoice_issuer_vat_no: + code: 'invoice_issuer_vat_no' + description: | + Invoice issuer VAT number + value: 'EE101286464' + value_format: string + +invoice_issuer_street: + code: 'invoice_issuer_street' + description: | + Invoice issuer street name + value: 'Paldiski mnt 80' + value_format: string + +invoice_issuer_state: + code: 'invoice_issuer_state' + description: | + Invoice issuer state name + value: 'Harjumaa' + value_format: string + +invoice_issuer_zip: + code: 'invoice_issuer_zip' + description: | + Invoice issuer zip code + value: '10617' + value_format: string + +invoice_issuer_city: + code: 'invoice_issuer_city' + description: | + Invoice issuer city name + value: 'Tallinn' + value_format: string + +invoice_issuer_country_code: + code: 'invoice_issuer_country_code' + description: | + Invoice issuer country code + value: 'EE' value_format: string invoice_reminder_in_days: diff --git a/test/integration/eis_billing/e_invoice_response_test.rb b/test/integration/eis_billing/e_invoice_response_test.rb new file mode 100644 index 000000000..ce93afe2c --- /dev/null +++ b/test/integration/eis_billing/e_invoice_response_test.rb @@ -0,0 +1,19 @@ +require 'test_helper' + +class EInvoiceResponseTest < ActionDispatch::IntegrationTest + include Devise::Test::IntegrationHelpers + + setup do + sign_in users(:participant) + @invoice = invoices(:payable) + Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true) + end + + def test_invoice_should_be_mark_as_sent + assert_nil @invoice.e_invoice_sent_at + put eis_billing_e_invoice_response_path, params: { invoice_number: @invoice.number } + + @invoice.reload + assert_not_nil @invoice.e_invoice_sent_at + end +end diff --git a/test/integration/invoices_test.rb b/test/integration/invoices_test.rb index 5a8178778..4d945d700 100644 --- a/test/integration/invoices_test.rb +++ b/test/integration/invoices_test.rb @@ -7,6 +7,7 @@ def setup @user = users(:participant) @user_two = users(:second_place_participant) @auction = auctions(:valid_without_offers) + @invoice = invoices(:payable) @user.reload sign_in @user @@ -56,4 +57,30 @@ def test_completely_banned_user_cannot_pay_any_deposit assert_redirected_to root_path assert_equal 'You are not authorized to access this page.', flash[:alert] end + + def test_should_send_e_invoice + body = { + message: 'Invoice data received', + } + stub_request(:post, 'http://eis_billing_system:3000/api/v1/e_invoice/e_invoice') + .to_return(status: :created, body: body.to_json, headers: {}) + + post send_e_invoice_path(uuid: @invoice.uuid), params: nil, headers: {} + + assert_redirected_to invoice_path(@invoice.uuid) + assert_equal 'E-Invoice was successfully sent', flash[:notice] + end + + def test_send_e_invoice_with_billing_system_error + body = { + error: 'Internal server error', + } + stub_request(:post, 'http://eis_billing_system:3000/api/v1/e_invoice/e_invoice') + .to_return(status: 500, body: body.to_json, headers: {}) + + post send_e_invoice_path(uuid: @invoice.uuid), params: nil, headers: {} + + assert_redirected_to invoice_path(@invoice.uuid) + assert_equal body[:error], flash[:alert] + end end From 549bea4e51ec7cd95332af354db9f4fd2acce432 Mon Sep 17 00:00:00 2001 From: Sergei Tsoganov Date: Wed, 27 Sep 2023 09:39:13 +0300 Subject: [PATCH 2/3] Added finbite logo and corrected structure.sql --- app/views/invoices/show.html.erb | 10 ++-- db/structure.sql | 82 +++++++++++++++++++++++++++++++ public/images/finbite.png | Bin 0 -> 10715 bytes 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 public/images/finbite.png diff --git a/app/views/invoices/show.html.erb b/app/views/invoices/show.html.erb index 5a952a029..2bf745660 100644 --- a/app/views/invoices/show.html.erb +++ b/app/views/invoices/show.html.erb @@ -108,11 +108,13 @@ <%= button_to t('invoices.show.pay'), oneoff_invoice_path(uuid: @invoice.uuid), class: 'ui button primary' %> <% end %> - <% unless @invoice.do_not_send_e_invoice? %> -
+
+ <% if @invoice.do_not_send_e_invoice? %> + EInvoice + <% else %> <%= button_to t('invoices.show.send_e_invoice'), send_e_invoice_path(uuid: @invoice.uuid), class: 'ui button default', data: { turbo: false } %> -
- <% end %> + <% end %> +
diff --git a/db/structure.sql b/db/structure.sql index f4b568d16..2e592e364 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -2769,6 +2769,88 @@ CREATE INDEX index_wishlist_items_on_domain_name ON public.wishlist_items USING CREATE UNIQUE INDEX users_by_identity_code_and_country ON public.users USING btree (alpha_two_country_code, identity_code) WHERE ((alpha_two_country_code)::text = 'EE'::text); +-- +-- Name: auctions process_auction_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_auction_audit AFTER INSERT OR DELETE OR UPDATE ON public.auctions FOR EACH ROW EXECUTE FUNCTION public.process_auction_audit(); + + +-- +-- Name: bans process_ban_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_ban_audit AFTER INSERT OR DELETE OR UPDATE ON public.bans FOR EACH ROW EXECUTE FUNCTION public.process_ban_audit(); + + +-- +-- Name: billing_profiles process_billing_profile_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_billing_profile_audit AFTER INSERT OR DELETE OR UPDATE ON public.billing_profiles FOR EACH ROW EXECUTE FUNCTION public.process_billing_profile_audit(); + + +-- +-- Name: invoices process_invoice_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_invoice_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoices FOR EACH ROW EXECUTE FUNCTION public.process_invoice_audit(); + + +-- +-- Name: invoice_items process_invoice_item_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_invoice_item_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoice_items FOR EACH ROW EXECUTE FUNCTION public.process_invoice_item_audit(); + + +-- +-- Name: invoice_payment_orders process_invoice_payment_order_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_invoice_payment_order_audit AFTER INSERT OR DELETE OR UPDATE ON public.invoice_payment_orders FOR EACH ROW EXECUTE FUNCTION public.process_invoice_payment_order_audit(); + + +-- +-- Name: offers process_offer_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_offer_audit AFTER INSERT OR DELETE OR UPDATE ON public.offers FOR EACH ROW EXECUTE FUNCTION public.process_offer_audit(); + + +-- +-- Name: payment_orders process_payment_order_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_payment_order_audit AFTER INSERT OR DELETE OR UPDATE ON public.payment_orders FOR EACH ROW EXECUTE FUNCTION public.process_payment_order_audit(); + + +-- +-- Name: results process_result_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_result_audit AFTER INSERT OR DELETE OR UPDATE ON public.results FOR EACH ROW EXECUTE FUNCTION public.process_result_audit(); + + +-- +-- Name: settings process_setting_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_setting_audit AFTER INSERT OR DELETE OR UPDATE ON public.settings FOR EACH ROW EXECUTE FUNCTION public.process_setting_audit(); + + +-- +-- Name: users process_user_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_user_audit AFTER INSERT OR DELETE OR UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.process_user_audit(); + + +-- +-- Name: wishlist_items process_wishlist_item_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_wishlist_item_audit AFTER INSERT OR DELETE OR UPDATE ON public.wishlist_items FOR EACH ROW EXECUTE FUNCTION public.process_wishlist_item_audit(); -- -- Name: bans fk_rails_070022cd76; Type: FK CONSTRAINT; Schema: public; Owner: - diff --git a/public/images/finbite.png b/public/images/finbite.png new file mode 100644 index 0000000000000000000000000000000000000000..9521fd2f8ed62452dc703fef52f84a63c64cb010 GIT binary patch literal 10715 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 Date: Wed, 27 Sep 2023 09:49:30 +0300 Subject: [PATCH 3/3] Updated system test --- test/system/invoices_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/system/invoices_test.rb b/test/system/invoices_test.rb index 52905cad1..259ed3ccf 100644 --- a/test/system/invoices_test.rb +++ b/test/system/invoices_test.rb @@ -47,7 +47,7 @@ def test_user_cannot_update_billing_profile_on_paid_invoice visit edit_invoice_path(@invoice.uuid) # select_from_dropdown('Joe John Participant', from: 'invoice[billing_profile_id]') select 'Joe John Participant', from: 'invoice[billing_profile_id]' - + click_link_or_button('Submit') assert_text('Something went wrong.') @@ -56,7 +56,7 @@ def test_user_cannot_update_billing_profile_on_paid_invoice def test_invoice_view_contains_issuer_info visit invoice_path(@invoice.uuid) - assert_text('Eesti Interneti SA, VAT number EE101286464') + assert_text('Eesti Interneti SA') setting = settings(:invoice_issuer) setting.update!(value: 'foo bar baz')