Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/dashboards_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class DashboardsController < ApplicationController
def index
@properties = authenticated_user.properties
.includes(:expenses, :tenant_payments, tenancies: [ :parties, :tenant_payments, :charges ])
.includes(:expenses, :receipts, tenancies: [ :parties, :receipts, :charges ])
@property_summaries = Dashboards::PropertySummariesQuery.new(properties: @properties).call
end
end
8 changes: 6 additions & 2 deletions app/controllers/payment_documents_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
class PaymentDocumentsController < ApplicationController
def destroy
document = authenticated_user.payment_documents.find(params[:id])
document.destroy!
redirect_to payment_ingestions_path, notice: "Upload record was removed.", status: :see_other
result = PaymentDocuments::DestroyService.call(user: authenticated_user, document: document)
if result.success?
redirect_to payment_ingestions_path, notice: "Upload record was removed.", status: :see_other
else
redirect_to payment_ingestions_path, alert: result.failure.error, status: :see_other
end
end
end
10 changes: 7 additions & 3 deletions app/controllers/payment_ingestions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def confirm
begin
result = PaymentIngestions::ConfirmService.call(user: authenticated_user, ingestion: @ingestion, create_alias: create_alias)
if result.success?
redirect_to payment_ingestions_path, notice: "Payment confirmed and tenant payment created successfully."
redirect_to payment_ingestions_path, notice: "Payment confirmed and payment receipt created successfully."
else
redirect_to payment_ingestion_path(@ingestion), alert: result.failure.error
end
Expand All @@ -70,8 +70,12 @@ def download
end

def destroy
@ingestion.destroy!
redirect_to payment_ingestions_path, notice: "Ingestion record was deleted.", status: :see_other
result = PaymentIngestions::DestroyService.call(user: authenticated_user, ingestion: @ingestion)
if result.success?
redirect_to payment_ingestions_path, notice: "Ingestion record was deleted.", status: :see_other
else
redirect_to payment_ingestion_path(@ingestion), alert: result.failure.error
end
end

private
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/properties_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ def show
:rentable_units,
:expenses,
:charges,
:tenant_payments,
tenancies: %i[parties tenant_payments charges]
:receipts,
tenancies: %i[parties receipts charges]
).find(params.expect(:id))
@financial_items = @property.financial_items(@year)
end
Expand Down
278 changes: 278 additions & 0 deletions app/controllers/receipts_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
class ReceiptsController < ApplicationController
before_action :set_tenancy, only: %i[new create]
before_action :set_receipt, only: %i[show correction correct void]

def index
@receipts = authenticated_user.receipts
.includes(:payer_party, tenancy: { rentable_unit: :property })
.order(received_on: :desc, created_at: :desc)
end

def show
respond_to do |format|
format.html
format.pdf do
pdf_data = Receipts::ReceiptPdfService.call(receipt: @receipt, view_context: view_context)
send_data pdf_data,
filename: "receipt-#{@receipt.id}.pdf",
type: "application/pdf",
disposition: "inline"
end
end
end

def new
@receipt = Receipt.new(
tenancy: @tenancy,
received_on: Date.current
)

if (t = @tenancy)
balance = t.current_balance
@receipt.amount = balance > 0 ? balance : nil
active_tenants = t.tenancy_parties.active.where(role: :tenant).map(&:party).compact
@receipt.payer_party = active_tenants.first if active_tenants.size == 1
end

load_form_collections
end

def create
if (t = @tenancy)
if receipt_params[:tenancy_id].present? && receipt_params[:tenancy_id].to_s != t.id.to_s
@receipt = Receipt.new(receipt_params)
@receipt.tenancy = t
flash.now[:alert] = "Submitted tenancy does not match route tenancy"
load_form_collections
return respond_to do |format|
format.html { render :new, status: :unprocessable_content }
format.turbo_stream do
render turbo_stream: turbo_stream.replace("new_receipt_form",
partial: "receipts/modal_form",
locals: { receipt: @receipt, tenancy: @tenancy }),
status: :unprocessable_content
end
end
end
target_tenancy = t
else
if receipt_params[:tenancy_id].blank?
@receipt = Receipt.new(receipt_params)
flash.now[:alert] = "Tenancy is required"
load_form_collections
return respond_to do |format|
format.html { render :new, status: :unprocessable_content }
format.turbo_stream do
render turbo_stream: turbo_stream.replace("new_receipt_form",
partial: "receipts/modal_form",
locals: { receipt: @receipt, tenancy: @tenancy }),
status: :unprocessable_content
end
end
end

target_tenancy = authenticated_user.tenancies.find_by(id: receipt_params[:tenancy_id])
unless target_tenancy
@receipt = Receipt.new(receipt_params)
flash.now[:alert] = "Tenancy was not found"
load_form_collections
return respond_to do |format|
format.html { render :new, status: :unprocessable_content }
format.turbo_stream do
render turbo_stream: turbo_stream.replace("new_receipt_form",
partial: "receipts/modal_form",
locals: { receipt: @receipt, tenancy: @tenancy }),
status: :unprocessable_content
end
end
end
end

target_payer = if receipt_params[:payer_party_id].present?
authenticated_user.parties.find_by(id: receipt_params[:payer_party_id])
end

if receipt_params[:payer_party_id].present? && target_payer.nil?
@receipt = Receipt.new(receipt_params)
@receipt.tenancy = target_tenancy
flash.now[:alert] = "Payer party was not found"
load_form_collections
return respond_to do |format|
format.html { render :new, status: :unprocessable_content }
format.turbo_stream do
render turbo_stream: turbo_stream.replace("new_receipt_form",
partial: "receipts/modal_form",
locals: { receipt: @receipt, tenancy: @tenancy }),
status: :unprocessable_content
end
end
end

result = Receipts::CreateService.call(
tenancy: target_tenancy,
payer_party: target_payer,
amount: receipt_params[:amount],
received_on: receipt_params[:received_on],
payment_method: receipt_params[:payment_method],
external_reference: receipt_params[:external_reference],
memo: receipt_params[:memo]
)

if result.success?
created_receipt = result.value!.data[:receipt]
respond_to do |format|
format.html { redirect_to receipt_path(created_receipt), notice: "Payment recorded successfully." }
format.turbo_stream do
if (property = target_tenancy.property)
render turbo_stream: [
turbo_stream.replace("property_financials",
partial: "properties/financials",
locals: {
property: property,
year: created_receipt.received_on.year,
financial_items: property.financial_items(year: created_receipt.received_on.year),
active_years: property.active_years
}),
turbo_stream.update("flash",
partial: "shared/flash",
locals: { notice: "Payment recorded successfully." })
]
else
redirect_to receipt_path(created_receipt), notice: "Payment recorded successfully."
end
end
end
else
@receipt = Receipt.new(receipt_params)
@receipt.tenancy = target_tenancy
@receipt.payer_party = target_payer
flash.now[:alert] = result.failure.error
load_form_collections
respond_to do |format|
format.html { render :new, status: :unprocessable_content }
format.turbo_stream do
render turbo_stream: turbo_stream.replace("new_receipt_form",
partial: "receipts/modal_form",
locals: { receipt: @receipt, tenancy: @tenancy }),
status: :unprocessable_content
end
end
end
end

def correction
@replacement_receipt = Receipt.new(
tenancy: @receipt.tenancy,
payer_party: @receipt.payer_party,
amount_cents: @receipt.amount_cents,
received_on: @receipt.received_on,
payment_method: @receipt.payment_method,
external_reference: @receipt.external_reference,
memo: @receipt.memo
)
load_form_collections
end

def correct
if receipt_params[:tenancy_id].present?
target_tenancy = authenticated_user.tenancies.find_by(id: receipt_params[:tenancy_id])
unless target_tenancy
@replacement_receipt = Receipt.new(receipt_params)
flash.now[:alert] = "Tenancy was not found"
load_form_collections
return render :correction, status: :unprocessable_content
end
else
target_tenancy = @receipt.tenancy
end

if receipt_params[:payer_party_id].present?
target_payer = authenticated_user.parties.find_by(id: receipt_params[:payer_party_id])
unless target_payer
@replacement_receipt = Receipt.new(receipt_params)
@replacement_receipt.tenancy = target_tenancy
flash.now[:alert] = "Payer party was not found"
load_form_collections
return render :correction, status: :unprocessable_content
end
else
target_payer = @receipt.payer_party
end

result = Receipts::CorrectService.call(
receipt: @receipt,
tenancy: target_tenancy,
payer_party: target_payer,
amount: receipt_params[:amount],
received_on: receipt_params[:received_on],
payment_method: receipt_params[:payment_method],
external_reference: receipt_params[:external_reference],
memo: receipt_params[:memo]
)

if result.success?
replacement = result.value!.data[:receipt]
redirect_to receipt_path(replacement), notice: "Payment corrected successfully. Original payment ##{@receipt.id} has been reversed."
else
@replacement_receipt = Receipt.new(receipt_params)
@replacement_receipt.tenancy = target_tenancy
@replacement_receipt.payer_party = target_payer
flash.now[:alert] = result.failure.error
load_form_collections
render :correction, status: :unprocessable_content
end
end

def void
result = Receipts::VoidService.call(
receipt: @receipt,
reason: params[:reason]
)

if result.success?
redirect_to receipt_path(@receipt), notice: "Payment has been voided and accounting entries reversed."
else
redirect_to receipt_path(@receipt), alert: result.failure.error
end
end

private

def set_tenancy
@tenancy = authenticated_user.tenancies.find(params[:tenancy_id]) if params[:tenancy_id]
end

def set_receipt
@receipt = authenticated_user.receipts.find(params.expect(:id))
end

def receipt_params
receipt_p = params[:receipt]
if receipt_p.is_a?(ActionController::Parameters)
receipt_p.permit(
:tenancy_id,
:payer_party_id,
:amount,
:received_on,
:payment_method,
:external_reference,
:memo
)
else
ActionController::Parameters.new.permit(
:tenancy_id,
:payer_party_id,
:amount,
:received_on,
:payment_method,
:external_reference,
:memo
)
end
end

def load_form_collections
@tenancies = authenticated_user.tenancies.includes(:parties, rentable_unit: :property)
@parties = authenticated_user.parties.order(:display_name)
end
end
Loading