1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-19 13:54:25 +01:00

remove references to Invoice.invoiced

This commit is contained in:
Sylvain 2021-05-27 15:58:55 +02:00
parent 13f50c0e33
commit 5f5ec8dbb6
35 changed files with 192 additions and 199 deletions

View File

@ -14,6 +14,7 @@
- `SUPERADMIN_EMAIL` renamed to `ADMINSYS_EMAIL`
- `scripts/run-tests.sh` renamed to `scripts/tests.sh`
- [BREAKING CHANGE] GET `open_api/v1/invoices` won't return `stp_invoice_id` OR `stp_payment_intent_id` anymore. The new field `payment_gateway_object` will contain some similar data if the invoice was paid online by card.
- [BREAKING CHANGE] GET `open_api/v1/invoices` won't return `invoiced_id`, `invoiced_type` OR `invoiced.created_at` anymore. The new field `main_object` will contain the equivalent data.
- [TODO DEPLOY] `rails fablab:stripe:set_gateway`
- [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet`
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/rename-adminsys.sh | bash`

View File

@ -8,7 +8,7 @@ class API::InvoicesController < API::ApiController
def index
authorize Invoice
@invoices = Invoice.includes(
:avoir, :invoiced, :invoicing_profile, invoice_items: %i[subscription invoice_item]
:avoir, :invoicing_profile, invoice_items: %i[subscription invoice_item]
).all.order('reference DESC')
end

View File

@ -22,9 +22,7 @@ class OpenAPI::V1::InvoicesDoc < OpenAPI::V1::BaseDoc
"invoices": [
{
"id": 2809,
"invoiced_id": 3257,
"user_id": 211,
"invoiced_type": "Reservation",
"payment_gateway_object": {
id: "in_187DLE4zBvgjueAZ6L7SyQlU",
type: "Stripe::Invoice"
@ -34,15 +32,15 @@ class OpenAPI::V1::InvoicesDoc < OpenAPI::V1::BaseDoc
"type": null,
"description": null,
"invoice_url": "/open_api/v1/invoices/2809/download",
"invoiced": {
"main_object": {
"type": "Reservation",
"id": 3257,
"created_at": "2016-05-04T01:54:16.686+02:00"
}
},
{
"id": 2783,
"invoiced_id": 3229,
"user_id": 211,
"invoiced_type": "Reservation",
"payment_gateway_object": {
id: "pi_2Dat4P2eYbKYlo2C3MxszwQp",
type: "Stripe::PaymentIntent"
@ -52,15 +50,15 @@ class OpenAPI::V1::InvoicesDoc < OpenAPI::V1::BaseDoc
"type": null,
"description": null,
"invoice_url": "/open_api/v1/invoices/2783/download",
"invoiced": {
"main_object": {
"type": "Reservation",
"id": 3229,
"created_at": "2016-04-28T18:14:52.524+02:00"
}
},
{
"id": 2773,
"invoiced_id": 3218,
"user_id": 211,
"invoiced_type": "Reservation",
"payment_gateway_object": {
id: "ba15dc9d8f3e0fa17bf527466",
type: "PayZen::Order"
@ -70,7 +68,9 @@ class OpenAPI::V1::InvoicesDoc < OpenAPI::V1::BaseDoc
"type": null,
"description": null,
"invoice_url": "/open_api/v1/invoices/2773/download",
"invoiced": {
"main_object": {
"type": "Reservation",
"id": 3218,
"created_at": "2016-04-27T10:50:30.806+02:00"
}
}

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true
# Invoice correspond to a single purchase made by an user. This purchase may
# include reservation(s) and/or a subscription
# Invoice correspond to a single purchase made by an user. This purchase is linked to one or many invoice_items
class Invoice < PaymentDocument
include NotifyWith::NotificationAttachedObject
require 'fileutils'
@ -54,7 +53,7 @@ class Invoice < PaymentDocument
# for debug & used by rake task "fablab:maintenance:regenerate_invoices"
def regenerate_invoice_pdf
pdf = ::PDF::Invoice.new(self, subscription&.expiration_date).render
pdf = ::PDF::Invoice.new(self, invoice_items.find(&:subscription)&.expiration_date).render
File.binwrite(file, pdf)
end
@ -100,7 +99,7 @@ class Invoice < PaymentDocument
def subscription_invoice?
invoice_items.each do |ii|
return true if ii.subscription
return true if ii.object_type == 'Subscription'
end
false
end
@ -130,13 +129,17 @@ class Invoice < PaymentDocument
return true if user.nil?
# workaround for reservation saved after invoice
if invoiced_type == 'Reservation' && invoiced&.reservable_type == 'Training'
user.trainings.include?(invoiced.reservable_id)
if main_item.object_type == 'Reservation' && main_item.object&.reservable_type == 'Training'
user.trainings.include?(main_item.object.reservable_id)
else
false
end
end
def main_item
invoice_items.where(main: true).first
end
# get amount total paid
def amount_paid
total - (wallet_amount || 0)
@ -168,8 +171,8 @@ class Invoice < PaymentDocument
return unless Setting.get('invoicing_module')
unless Rails.env.test?
puts "Creating an InvoiceWorker job to generate the following invoice: id(#{id}), invoiced_id(#{invoiced_id}), " \
"invoiced_type(#{invoiced_type}), user_id(#{invoicing_profile.user_id})"
puts "Creating an InvoiceWorker job to generate the following invoice: id(#{id}), main_item.object_id(#{main_item.object_id}), " \
"main_item.object_type(#{main_item.object_type}), user_id(#{invoicing_profile.user_id})"
end
InvoiceWorker.perform_async(id, user&.subscription&.expired_at)
end

View File

@ -13,6 +13,7 @@ class PaymentSchedule < PaymentDocument
has_many :payment_schedule_items
has_many :payment_gateway_objects, as: :item
has_many :payment_schedule_objects
before_create :add_environment
after_create :update_reference, :chain_record
@ -52,6 +53,10 @@ class PaymentSchedule < PaymentDocument
payment_gateway_objects.map(&:gateway_object).find { |item| !item.payment_mean? }
end
def main_object
payment_schedule_objects.where(main: true).first
end
def user
invoicing_profile.user
end

View File

@ -53,14 +53,12 @@ class Subscription < ApplicationRecord
od = offer_days.create(start_at: expired_at, end_at: expiration)
invoice = Invoice.new(
invoiced_id: od.id,
invoiced_type: 'OfferDay',
invoicing_profile: user.invoicing_profile,
statistic_profile: user.statistic_profile,
operator_profile_id: operator_profile_id,
total: 0
)
invoice.invoice_items.push InvoiceItem.new(amount: 0, description: plan.name, subscription_id: id)
invoice.invoice_items.push InvoiceItem.new(amount: 0, description: plan.name, subscription_id: id, object: od)
invoice.save
if save

View File

@ -44,7 +44,7 @@ class PDF::Invoice < Prawn::Document
if Setting.get('invoice_code-active')
text I18n.t('invoices.code', CODE: Setting.get('invoice_code-value')), leading: 3
end
if invoice.invoiced_type != WalletTransaction.name
if invoice.main_item.object_type != WalletTransaction.name
if invoice.is_a?(Avoir)
text I18n.t('invoices.order_number', NUMBER: invoice.invoice.order_number), leading: 3
else
@ -84,18 +84,18 @@ class PDF::Invoice < Prawn::Document
# object
move_down 25
if invoice.is_a?(Avoir)
object = if invoice.invoiced_type == WalletTransaction.name
object = if invoice.main_item.object_type == WalletTransaction.name
I18n.t('invoices.wallet_credit')
else
I18n.t('invoices.cancellation_of_invoice_REF', REF: invoice.invoice.reference)
end
else
case invoice.invoiced_type
case invoice.main_item.object_type
when 'Reservation'
object = I18n.t('invoices.reservation_of_USER_on_DATE_at_TIME',
USER: name,
DATE: I18n.l(invoice.invoiced.slots[0].start_at.to_date),
TIME: I18n.l(invoice.invoiced.slots[0].start_at, format: :hour_minute))
DATE: I18n.l(invoice.main_item.object.slots[0].start_at.to_date),
TIME: I18n.l(invoice.main_item.object.slots[0].start_at, format: :hour_minute))
invoice.invoice_items.each do |item|
next unless item.subscription_id
@ -105,13 +105,13 @@ class PDF::Invoice < Prawn::Document
break
end
when 'Subscription'
object = subscription_verbose(invoice.invoiced, name)
object = subscription_verbose(invoice.main_item.object, name)
when 'OfferDay'
object = offer_day_verbose(invoice.invoiced, name)
object = offer_day_verbose(invoice.main_item.object, name)
when 'Error'
object = I18n.t('invoices.error_invoice')
else
puts "ERROR : specified invoiced type (#{invoice.invoiced_type}) is unknown"
puts "ERROR : specified main_item.object_type type (#{invoice.main_item.object_type}) is unknown"
end
end
text I18n.t('invoices.object') + ' ' + object
@ -134,10 +134,10 @@ class PDF::Invoice < Prawn::Document
if item.subscription_id ### Subscription
subscription = Subscription.find item.subscription_id
if invoice.invoiced_type == 'OfferDay'
if invoice.main_item.object_type == 'OfferDay'
details += I18n.t('invoices.subscription_extended_for_free_from_START_to_END',
START: I18n.l(invoice.invoiced.start_at.to_date),
END: I18n.l(invoice.invoiced.end_at.to_date))
START: I18n.l(invoice.main_item.object.start_at.to_date),
END: I18n.l(invoice.main_item.object.end_at.to_date))
else
subscription_end_at = if subscription_expiration_date.is_a?(Time)
subscription_expiration_date
@ -155,7 +155,7 @@ class PDF::Invoice < Prawn::Document
else ### Reservation
case invoice.invoiced.try(:reservable_type)
case invoice.main_item.object.try(:reservable_type)
### Machine reservation
when 'Machine'
details += I18n.t('invoices.machine_reservation_DESCRIPTION', DESCRIPTION: item.description)
@ -168,10 +168,10 @@ class PDF::Invoice < Prawn::Document
when 'Event'
details += I18n.t('invoices.event_reservation_DESCRIPTION', DESCRIPTION: item.description)
# details of the number of tickets
if invoice.invoiced.nb_reserve_places.positive?
details += "\n " + I18n.t('invoices.full_price_ticket', count: invoice.invoiced.nb_reserve_places)
if invoice.main_item.object.nb_reserve_places.positive?
details += "\n " + I18n.t('invoices.full_price_ticket', count: invoice.main_item.object.nb_reserve_places)
end
invoice.invoiced.tickets.each do |t|
invoice.main_item.object.tickets.each do |t|
details += "\n " + I18n.t('invoices.other_rate_ticket',
count: t.booked,
NAME: t.event_price_category.price_category.name)

View File

@ -63,15 +63,15 @@ class AccountingExportService
# Generate the "subscription" and "reservation" rows associated with the provided invoice
def items_rows(invoice)
rows = invoice.subscription_invoice? ? "#{subscription_row(invoice)}\n" : ''
if invoice.invoiced_type == 'Reservation'
items = invoice.invoice_items.select { |ii| ii.subscription.nil? }
if invoice.main_item.object_type == 'Reservation'
items = invoice.invoice_items.reject { |ii| ii.object_type == 'Subscription' }
items.each do |item|
rows << "#{reservation_row(invoice, item)}\n"
end
elsif invoice.invoiced_type == 'WalletTransaction'
elsif invoice.main_item.object_type == 'WalletTransaction'
rows << "#{wallet_row(invoice)}\n"
elsif invoice.invoiced_type == 'Error'
items = invoice.invoice_items.select { |ii| ii.subscription.nil? }
elsif invoice.main_item.object_type == 'Error'
items = invoice.invoice_items.reject { |ii| ii.object_type == 'Subscription' }
items.each do |item|
rows << "#{error_row(invoice, item)}\n"
end
@ -110,7 +110,7 @@ class AccountingExportService
# Generate the "subscription" row, which contains the credit to the subscription account, all taxes excluded
def subscription_row(invoice)
subscription_item = invoice.invoice_items.select(&:subscription).first
subscription_item = invoice.invoice_items.select { |ii| ii.object_type == 'Subscription' }.first
row(
invoice,
account(invoice, :subscription),
@ -206,13 +206,13 @@ class AccountingExportService
puts "WARN: Invoice #{invoice.id} has no subscription"
end
when :reservation
if invoice.invoiced_type == 'Reservation'
Setting.find_by(name: "accounting_#{invoice.invoiced.reservable_type}_#{type}")&.value
if invoice.main_item.object_type == 'Reservation'
Setting.find_by(name: "accounting_#{invoice.main_item.object.reservable_type}_#{type}")&.value
else
puts "WARN: Invoice #{invoice.id} has no reservation"
end
when :wallet
if invoice.invoiced_type == 'WalletTransaction'
if invoice.main_item.object_type == 'WalletTransaction'
Setting.find_by(name: "accounting_wallet_#{type}")&.value
else
puts "WARN: Invoice #{invoice.id} is not a wallet credit"
@ -257,8 +257,8 @@ class AccountingExportService
reference = invoice.reference
items = invoice.subscription_invoice? ? [I18n.t('accounting_export.subscription')] : []
items.push I18n.t("accounting_export.#{invoice.reservation.reservable_type}_reservation") if invoice.invoiced_type == 'Reservation'
items.push I18n.t('accounting_export.wallet') if invoice.invoiced_type == 'WalletTransaction'
items.push I18n.t("accounting_export.#{invoice.main_item.object.reservable_type}_reservation") if invoice.main_item.object_type == 'Reservation'
items.push I18n.t('accounting_export.wallet') if invoice.main_item.object_type == 'WalletTransaction'
summary = items.join(' + ')
res = "#{reference}, #{summary}"

View File

@ -79,7 +79,6 @@ class InvoicesService
end
invoice = Invoice.new(
invoiced: reservation || subscription,
invoicing_profile: user.invoicing_profile,
statistic_profile: user.statistic_profile,
operator_profile_id: operator_profile_id,
@ -114,7 +113,7 @@ class InvoicesService
return unless subscription || reservation&.plan_id
subscription = reservation.generate_subscription if !subscription && reservation.plan_id
InvoicesService.generate_subscription_item(invoice, subscription, payment_details)
InvoicesService.generate_subscription_item(invoice, subscription, payment_details, reservation.nil?)
end
##
@ -141,7 +140,9 @@ class InvoicesService
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
invoice.invoice_items.push InvoiceItem.new(
amount: price_slot[:price],
description: description
description: description,
object: reservation,
main: true
)
end
end
@ -160,7 +161,9 @@ class InvoicesService
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
invoice.invoice_items.push InvoiceItem.new(
amount: price_slot[:price],
description: description
description: description,
object: reservation,
main: true
)
end
end
@ -169,13 +172,15 @@ class InvoicesService
# Generate an InvoiceItem for the given subscription and save it in invoice.invoice_items.
# This method must be called only with a valid subscription
##
def self.generate_subscription_item(invoice, subscription, payment_details)
def self.generate_subscription_item(invoice, subscription, payment_details, main = true)
raise TypeError unless subscription
invoice.invoice_items.push InvoiceItem.new(
amount: payment_details[:elements][:plan],
description: subscription.plan.name,
subscription_id: subscription.id
subscription_id: subscription.id,
object: subscription,
main: main
)
end

View File

@ -87,7 +87,6 @@ class PaymentScheduleService
def generate_invoice(payment_schedule_item, payment_method: nil, payment_id: nil, payment_type: nil)
# build the base invoice
invoice = Invoice.new(
invoiced: payment_schedule_item.payment_schedule.scheduled,
invoicing_profile: payment_schedule_item.payment_schedule.invoicing_profile,
statistic_profile: payment_schedule_item.payment_schedule.statistic_profile,
operator_profile_id: payment_schedule_item.payment_schedule.operator_profile_id,
@ -120,7 +119,7 @@ class PaymentScheduleService
# @param filters {Hash} allowed filters: reference, customer, date.
##
def self.list(page, size, filters = {})
ps = PaymentSchedule.includes(:invoicing_profile, :payment_schedule_items, :subscription)
ps = PaymentSchedule.includes(:invoicing_profile, :payment_schedule_items)
.joins(:invoicing_profile)
.order('payment_schedules.created_at DESC')
.page(page)
@ -167,7 +166,7 @@ class PaymentScheduleService
private
##
# The first PaymentScheduleItem contains references to the reservation price (if any) and to the adjustement price
# The first PaymentScheduleItem contains references to the reservation price (if any) and to the adjustment price
# for the subscription (if any) and the wallet transaction (if any)
##
def complete_first_invoice(payment_schedule_item, invoice)
@ -178,9 +177,9 @@ class PaymentScheduleService
# the subscription and reservation items
subscription = Subscription.find(payment_schedule_item.details['subscription_id'])
if payment_schedule_item.payment_schedule.scheduled_type == Reservation.name
if payment_schedule_item.payment_schedule.main_object.object_type == Reservation.name
details[:reservation] = payment_schedule_item.details['other_items']
reservation = payment_schedule_item.payment_schedule.scheduled
reservation = payment_schedule_item.payment_schedule.main_object
end
# the wallet transaction
@ -213,7 +212,7 @@ class PaymentScheduleService
return unless subscription
generate_subscription_item(invoice, subscription, payment_details)
generate_subscription_item(invoice, subscription, payment_details, reservation.nil?)
end
##
@ -230,7 +229,9 @@ class PaymentScheduleService
invoice.invoice_items.push InvoiceItem.new(
amount: payment_details[:reservation],
description: description
description: description,
object: reservation,
main: true
)
end
@ -238,13 +239,14 @@ class PaymentScheduleService
# Generate an InvoiceItem for the given subscription and save it in invoice.invoice_items.
# This method must be called only with a valid subscription
##
def generate_subscription_item(invoice, subscription, payment_details)
def generate_subscription_item(invoice, subscription, payment_details, main = true)
raise TypeError unless subscription
invoice.invoice_items.push InvoiceItem.new(
amount: payment_details[:subscription],
description: subscription.plan.name,
subscription_id: subscription.id
object: subscription,
main: main
)
end

View File

@ -130,7 +130,7 @@ class StatisticService
.eager_load(invoice: [:coupon], subscription: [:plan, statistic_profile: [:group]]).each do |i|
next if i.invoice.is_a?(Avoir)
sub = i.subscription
sub = i.invoice_items.find(&:subscription)
next unless sub
@ -275,7 +275,7 @@ class StatisticService
.eager_load(:invoice_items, statistic_profile: [:group])
.each do |i|
# the following line is a workaround for issue #196
profile = i.statistic_profile || i.invoiced&.wallet&.user&.statistic_profile
profile = i.statistic_profile || i.main_item.object&.wallet&.user&.statistic_profile
avoirs_ca_list.push OpenStruct.new({
date: options[:start_date].to_date,
ca: calcul_avoir_ca(i)
@ -394,7 +394,7 @@ class StatisticService
ca = 0
# sum each items in the invoice (+ for invoices/- for refunds)
invoice.invoice_items.each do |ii|
next if ii.subscription_id
next if ii.object_type == 'Subscription'
ca = if invoice.is_a?(Avoir)
ca - ii.amount.to_i

View File

@ -54,7 +54,6 @@ class WalletService
def create_avoir(wallet_transaction, avoir_date, description)
avoir = Avoir.new
avoir.type = 'Avoir'
avoir.invoiced = wallet_transaction
avoir.avoir_date = avoir_date
avoir.created_at = avoir_date
avoir.description = description
@ -68,6 +67,7 @@ class WalletService
ii = InvoiceItem.new
ii.amount = wallet_transaction.amount * 100.0
ii.description = I18n.t('invoices.wallet_credit')
ii.object = wallet_transaction
ii.invoice = avoir
ii.save!
end

View File

@ -1,4 +1,6 @@
json.extract! @avoir, :id, :created_at, :reference, :invoiced_type, :avoir_date, :payment_method, :invoice_id
# frozen_string_literal: true
json.extract! @avoir, :id, :created_at, :reference, :avoir_date, :payment_method, :invoice_id
json.user_id @avoir.invoicing_profile.user_id
json.total @avoir.total / 100.00
json.name @avoir.user.profile.full_name

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
json.array!(@invoices) do |invoice|
json.extract! invoice, :id, :created_at, :reference, :invoiced_type, :user_id, :avoir_date
json.total (invoice.total / 100.00)
json.extract! invoice, :id, :created_at, :reference, :user_id, :avoir_date
json.total invoice.total / 100.00
json.name invoice.user.profile.full_name
json.has_avoir invoice.refunded?

View File

@ -4,7 +4,7 @@ max_invoices = @invoices.except(:offset, :limit, :order).count
json.array!(@invoices) do |invoice|
json.maxInvoices max_invoices
json.extract! invoice, :id, :created_at, :reference, :invoiced_type, :avoir_date
json.extract! invoice, :id, :created_at, :reference, :avoir_date
json.user_id invoice.invoicing_profile.user_id
json.total invoice.total / 100.00

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
json.extract! @invoice, :id, :created_at, :reference, :invoiced_type, :avoir_date, :description
json.extract! @invoice, :id, :created_at, :reference, :avoir_date, :description
json.user_id @invoice.invoicing_profile&.user_id
json.total @invoice.total / 100.00
json.name @invoice.user.profile.full_name
@ -10,6 +10,9 @@ json.is_subscription_invoice @invoice.subscription_invoice?
json.stripe @invoice.paid_by_card?
json.date @invoice.is_a?(Avoir) ? @invoice.avoir_date : @invoice.created_at
json.chained_footprint @invoice.check_footprint
json.main_object do
json.type @invoice.main_item.object_type
end
json.items @invoice.invoice_items do |item|
json.id item.id
json.amount item.amount / 100.0

View File

@ -87,8 +87,6 @@ end
json.invoices @member.invoices.order('reference DESC') do |i|
json.id i.id
json.reference i.reference
json.type i.invoiced_type
json.invoiced_id i.invoiced_id
json.total i.total / 100.00
json.is_avoir i.is_a?(Avoir)
json.date i.is_a?(Avoir) ? i.avoir_date : i.created_at

View File

@ -10,15 +10,6 @@ json.invoices do
end
end
json.total number_to_currency(invoice[:invoice].total / 100.0)
json.invoiced do
json.type invoice[:invoice].invoiced_type
json.id invoice[:invoice].invoiced_id
if invoice[:invoice].invoiced_type == Subscription.name
json.partial! 'archive/subscription', invoiced: invoice[:invoice].invoiced
elsif invoice[:invoice].invoiced_type == Reservation.name
json.partial! 'archive/reservation', invoiced: invoice[:invoice].invoiced, vat_rate: invoice[:vat_rate]
end
end
json.user do
json.extract! invoice[:invoice].invoicing_profile, :user_id, :email, :first_name, :last_name
json.address invoice[:invoice].invoicing_profile&.address&.address
@ -31,13 +22,17 @@ json.invoices do
end
end
json.invoice_items invoice[:invoice].invoice_items do |item|
json.extract! item, :id, :created_at, :description, :footprint
json.extract! item, :id, :main, :created_at, :description, :footprint
if item.payment_gateway_object
json.payment_gateway_object do
json.id item.payment_gateway_object.gateway_object_id
json.type item.payment_gateway_object.gateway_object_type
end
end
json.object do
json.type item.object_type
json.id item.object_id
end
json.partial! 'archive/vat', price: item.amount, vat_rate: invoice[:vat_rate]
end
end

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
json.extract! invoiced, :created_at
json.reservable do
json.type invoiced.reservable_type
json.id invoiced.reservable_id
if [Training.name, Machine.name, Space.name].include?(invoiced.reservable_type) && !invoiced.reservable.nil?
json.extract! invoiced.reservable, :name, :created_at
elsif invoiced.reservable_type == Event.name && !invoiced.reservable.nil?
json.extract! invoiced.reservable, :title, :created_at
json.prices do
json.standard_price do
json.partial! 'archive/vat', price: invoiced.reservable.amount, vat_rate: vat_rate
end
json.other_prices invoiced.reservable.event_price_categories do |price|
json.partial! 'archive/vat', price: price.amount, vat_rate: vat_rate
json.price_category do
json.extract! price.price_category, :id, :name, :created_at
end
end
end
end
end

View File

@ -1,15 +0,0 @@
# frozen_string_literal: true
json.extract! invoiced, :created_at, :expiration_date, :canceled_at
if invoiced.payment_gateway_object
json.payment_gateway_object do
json.id invoiced.payment_gateway_object.gateway_object_id
json.type invoiced.payment_gateway_object.gateway_object_type
end
end
json.plan do
json.extract! invoiced.plan, :id, :base_name, :interval, :interval_count, :stp_plan_id, :is_rolling
json.group do
json.extract! invoiced.plan.group, :id, :name
end
end

View File

@ -6,6 +6,6 @@
USER: @attached_object.invoicing_profile&.full_name) if @attached_object.invoice %>
<%= t('.body.wallet_refund_created',
AMOUNT: number_to_currency(@attached_object.total / 100.00),
USER: @attached_object.invoicing_profile&.full_name) if @attached_object.invoiced_type === WalletTransaction.name %>
USER: @attached_object.invoicing_profile&.full_name) if @attached_object.main_item.object_type === WalletTransaction.name %>
</p>
<p><a href="<%= "#{root_url}api/invoices/#{@attached_object.id}/download" %>" target="_blank"><%= t('.body.download') %></a></p>

View File

@ -5,7 +5,7 @@
{
DATE: I18n.l(@attached_object.avoir_date.to_date),
AMOUNT: number_to_currency(@attached_object.total / 100.0),
TYPE: @attached_object.invoiced_type
TYPE: @attached_object.main_item.object_type
})
# messageFormat
%>

View File

@ -5,7 +5,7 @@
{
DATE: I18n.l(@attached_object.created_at.to_date),
AMOUNT: number_to_currency(@attached_object.total / 100.0),
TYPE: @attached_object.invoiced_type
TYPE: @attached_object.main_item.object_type
})
# messageFormat
%>

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
json.invoices @invoices do |invoice|
json.extract! invoice, :id, :invoiced_id, :user_id, :invoiced_type, :reference, :total, :type, :description
json.extract! invoice, :id, :user_id, :reference, :total, :type, :description
if invoice.payment_gateway_object
json.payment_gateway_object do
json.id invoice.payment_gateway_object.gateway_object_id
@ -10,7 +10,9 @@ json.invoices @invoices do |invoice|
end
json.invoice_url download_open_api_v1_invoice_path(invoice)
json.invoiced do
json.created_at invoice.invoiced.created_at
json.main_object do
json.type invoice.main_item.object_type
json.id invoice.main_item.object_id
json.created_at invoice.main_item.object.created_at
end
end

View File

@ -26,7 +26,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
Invoice.where.not(invoiced_type: 'Reservation').each do |invoice|
execute %(
UPDATE invoice_items
SET object_id = #{invoice.invoiced_id},
SET object_id = #{invoice.invoiced_id || 'NULL'},
object_type = '#{invoice.invoiced_type}',
main = true
WHERE id = #{invoice.invoice_items.first.id}
@ -35,7 +35,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
Invoice.where(invoiced_type: 'Reservation').each do |invoice|
execute %(
UPDATE invoice_items
SET object_id = #{invoice.invoiced_id},
SET object_id = #{invoice.invoiced_id || 'NULL'},
object_type = '#{invoice.invoiced_type}',
main = true
WHERE id = #{invoice.invoice_items.where(subscription_id: nil).first.id}
@ -43,7 +43,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
invoice.invoice_items.where(subscription_id: nil)[1..-1].each do |ii|
execute %(
UPDATE invoice_items
SET object_id = #{invoice.invoiced_id},
SET object_id = #{invoice.invoiced_id || 'NULL'},
object_type = '#{invoice.invoiced_type}'
WHERE id = #{ii.id}
)
@ -53,7 +53,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
execute %(
UPDATE invoice_items
SET object_id = #{subscription_item.subscription_id},
SET object_id = #{subscription_item.subscription_id || 'NULL'},
object_type = 'Subscription'
WHERE id = #{subscription_item.id}
)
@ -83,7 +83,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
InvoiceItem.where(main: true).each do |ii|
execute %(
UPDATE invoices
SET invoiced_id = #{ii.object_id},
SET invoiced_id = #{ii.object_id || 'NULL'},
invoiced_type = '#{ii.object_type}'
WHERE id = #{ii.invoice.id}
)
@ -91,7 +91,7 @@ class AddObjectToInvoiceItem < ActiveRecord::Migration[5.2]
InvoiceItem.where(object_type: 'Subscription').each do |ii|
execute %(
UPDATE invoice_items
SET subscription_id = #{ii.object_id}
SET subscription_id = #{ii.object_id || 'NULL'}
WHERE id = #{ii.id}
)
end

View File

@ -5213,6 +5213,22 @@ CREATE INDEX profiles_lower_unaccent_last_name_trgm_idx ON public.profiles USING
CREATE INDEX projects_search_vector_idx ON public.projects USING gin (search_vector);
--
-- Name: accounting_periods accounting_periods_del_protect; Type: RULE; Schema: public; Owner: -
--
CREATE RULE accounting_periods_del_protect AS
ON DELETE TO public.accounting_periods DO INSTEAD NOTHING;
--
-- Name: accounting_periods accounting_periods_upd_protect; Type: RULE; Schema: public; Owner: -
--
CREATE RULE accounting_periods_upd_protect AS
ON UPDATE TO public.accounting_periods DO INSTEAD NOTHING;
--
-- Name: projects projects_search_content_trigger; Type: TRIGGER; Schema: public; Owner: -
--

View File

@ -97,7 +97,8 @@ class Events::AsUserTest < ActionDispatch::IntegrationTest
assert_equal 51_000, reservation_item.amount # full total
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
VCR.use_cassette('reserve_event_with_many_prices_and_payment_means_retrieve_invoice_from_stripe') do

View File

@ -118,7 +118,7 @@ class Exports::AccountingExportTest < ActionDispatch::IntegrationTest
client_row = data[data.length - 4]
item_row = data[data.length - 3]
if machine_invoice.invoiced_type == 'Reservation' && machine_invoice.invoiced.reservable_type == 'Machine'
if machine_invoice.main_item.object_type == 'Reservation' && machine_invoice.main_item.object.reservable_type == 'Machine'
assert_match I18n.t('accounting_export.Machine_reservation'),
client_row[I18n.t('accounting_export.line_label')],
'Line label does not contains the reference to the invoiced item'

View File

@ -69,7 +69,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal machine.prices.find_by(group_id: @user_without_subscription.group_id, plan_id: nil).amount, invoice_item.amount
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification
@ -128,7 +129,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal invoice_item.amount, training.amount_by_group(@user_without_subscription.group_id).amount
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification
@ -207,7 +209,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal [reservation.slots.count, plan.machine_credits.find_by(creditable_id: machine.id).hours].min, users_credit.hours_used
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification
@ -272,7 +275,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal machine.prices.find_by(group_id: @vlonchamp.group_id, plan_id: nil).amount, invoice_item.amount
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification
@ -351,7 +355,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal invoice.total, 2000
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification
@ -492,7 +497,8 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert(invoice_items.any? { |ii| ii.amount.zero? })
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
# notification

View File

@ -64,13 +64,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert reservation.invoice
assert_equal 1, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# invoice_items assertions
invoice_item = InvoiceItem.last
@ -78,9 +71,14 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert invoice_item.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# notification
assert_not_empty Notification.where(attached_object: reservation)
end
@ -188,13 +186,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert reservation.invoice
assert_equal 1, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# invoice_items
invoice_item = InvoiceItem.last
@ -202,9 +193,14 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert invoice_item.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# notification
assert_not_empty Notification.where(attached_object: reservation)
end
@ -268,13 +264,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert reservation.invoice
assert_equal 2, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# invoice_items assertions
invoice_items = InvoiceItem.last(2)
machine_price = machine.prices.find_by(group_id: @user_with_subscription.group_id, plan_id: plan.id).amount
@ -290,9 +279,14 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert_equal [reservation.slots.count, plan.machine_credits.find_by(creditable_id: machine.id).hours].min, users_credit.hours_used
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# notification
assert_not_empty Notification.where(attached_object: reservation)
end
@ -347,13 +341,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert reservation.invoice
assert_equal 1, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
assert invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# invoice_items
invoice_item = InvoiceItem.last
@ -361,9 +348,14 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert invoice_item.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
assert invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# notification
assert_not_empty Notification.where(attached_object: reservation)
@ -429,13 +421,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert reservation.invoice
assert_equal 1, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# invoice_items assertions
invoice_item = InvoiceItem.last
@ -443,9 +428,14 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert invoice_item.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert invoice.check_footprint
# notification
assert_not_empty Notification.where(attached_object: reservation)
@ -521,17 +511,15 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert_equal 2, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
assert_equal invoice.total, 2000
assert invoice.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
assert_invoice_pdf invoice
# notification
assert_not_empty Notification.where(attached_object: reservation)
@ -603,11 +591,13 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
# reservation assertions
reservation = Reservation.last
assert reservation.invoice
assert reservation.invoice_items.count == 1
assert_equal 2, reservation.invoice.invoice_items.count
# invoice assertions
invoice = reservation.invoice
item = InvoiceItem.find_by(object: reservation)
invoice = item.invoice
assert_invoice_pdf invoice
refute invoice.payment_gateway_object.blank?
refute invoice.total.blank?
@ -631,10 +621,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
assert_equal subscription.plan_id, plan.id
assert subscription_item.check_footprint
# invoice assertions
invoice = Invoice.find_by(invoiced: reservation)
assert_invoice_pdf invoice
VCR.use_cassette('reservations_machine_and_plan_using_coupon_retrieve_invoice_from_stripe') do
stp_intent = invoice.payment_gateway_object.gateway_object.retrieve
assert_equal stp_intent.amount, invoice.total

View File

@ -56,7 +56,8 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
assert_equal user.id, notification.receiver_id, 'wrong user notified'
# Check generated invoice
invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id])
item = InvoiceItem.find_by(object_type: 'Subscription', object_id: subscription[:id])
invoice = item.invoice
assert_invoice_pdf invoice
assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription'
end

View File

@ -66,7 +66,8 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
end
# Check generated invoice
invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id])
item = InvoiceItem.find_by(object_type: 'Subscription', object_id: subscription[:id])
invoice = item.invoice
assert_invoice_pdf invoice
assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription'
end
@ -167,7 +168,8 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
end
# Check generated invoice
invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id])
item = InvoiceItem.find_by(object_type: 'Subscription', object_id: subscription[:id])
invoice = item.invoice
assert_invoice_pdf invoice
assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription'

View File

@ -68,7 +68,8 @@ class Subscriptions::RenewAsAdminTest < ActionDispatch::IntegrationTest
assert_equal user.id, notification.receiver_id, 'wrong user notified'
# Check generated invoice
invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id])
item = InvoiceItem.find_by(object_type: 'Subscription', object_id: subscription[:id])
invoice = item.invoice
assert_invoice_pdf invoice
assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription'
end

View File

@ -69,7 +69,8 @@ class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest
end
# Check generated invoice
invoice = Invoice.find_by(invoiced_type: 'Subscription', invoiced_id: subscription[:id])
item = InvoiceItem.find_by(object_type: 'Subscription', object_id: subscription[:id])
invoice = item.invoice
assert_invoice_pdf invoice
assert_equal plan.amount, invoice.total, 'Invoice total price does not match the bought subscription'
end

View File

@ -77,7 +77,7 @@ class WalletsTest < ActionDispatch::IntegrationTest
assert_equal w.amount, wallet[:amount]
# no refund invoices should have been generated
assert_empty Invoice.where(invoiced: w.wallet_transactions.last)
assert_empty InvoiceItem.where(object: w.wallet_transactions.last)
end
test 'admin credit wallet with refund invoice generation' do
@ -103,7 +103,8 @@ class WalletsTest < ActionDispatch::IntegrationTest
assert_equal w.amount, wallet[:amount]
# refund invoice must be generated
invoice = Invoice.where(invoiced: w.wallet_transactions.last).first
item = InvoiceItem.find_by(object: w.wallet_transactions.last)
invoice = item.invoice
assert_equal amount, (invoice.total / 100.0), 'Avoir total does not match the amount credited to the wallet'
assert_equal amount, (invoice.invoice_items.first.amount / 100.0), 'Invoice item amount does not match'
assert_invoice_pdf invoice