Skip to content

Example DDD application service

Adam Mikulasev edited this page Jun 21, 2025 · 1 revision
# app/services/accountify/invoice_service.rb

module Accountify
  class InvoiceService
    # Issues an invoice.
    #
    # @param total_amount [Money] The full amount of the invoice
    # @param time [Time] The Time dependency
    #
    # @return [Hash{Symbol => Integer}]
    #   A hash containing:
    #     - :id       => ID of the created invoice
    #     - :event_id => ID of the emitted event
    #
    # @example
    #   Accountify::InvoiceService.issue(
    #     total_amount: Money.new(25000, "AUD"),
    #     time: Time.current
    #   )
    #   # => { id: 1, event_id: 42 }
    def self.issue(total_amount:, time:)
      ActiveRecord::Base.connection_pool.with_connection do
        ActiveRecord::Base.transaction do
          current_time = time

          invoice = Invoice.create!(
            status: Invoice::Statuses::ISSUED,
            total_amount_fractional: total_amount.fractional,
            total_amount_currency_iso_code: total_amount.currency.iso_code,
            issued_at: current_time,
            created_at: current_time,
            updated_at: current_time
          )

          event = InvoiceIssuedEvent.create!(
            body: {
              invoice_id: invoice.id,
              issued_at: invoice.issued_at.iso8601,
              status: Invoice::Statuses::ISSUED,
              total_amount_cents: invoice.total_amount_fractional,
              currency: invoice.total_amount_currency_iso_code,
              created_at: current_time
            },
            created_at: current_time
          )

          Outboxer::Message.queue(messageable: event, queued_at: current_time)

          { id: invoice.id, event_id: event.id }
        end
      end
    end
  end
end
Clone this wiki locally