From 6542ff55506bba75b5b3c150654fb2e9d6535d05 Mon Sep 17 00:00:00 2001 From: Danilo Date: Thu, 18 Jul 2024 19:49:44 -0300 Subject: [PATCH 1/7] =?UTF-8?q?Adicionado=20Tela=20de=20lan=C3=A7amento=20?= =?UTF-8?q?de=20multa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lucas Lima --- app/controllers/application_controller.rb | 21 +++++++--- app/controllers/fines_controller.rb | 41 +++++++++++++++++++ app/controllers/residents_controller.rb | 13 +++++- .../controllers/fines_controller.js | 40 ++++++++++++++++++ app/javascript/controllers/index.js | 3 ++ app/models/single_charge.rb | 7 ++++ app/views/condos/show.html.erb | 11 +++++ app/views/fines/new.html.erb | 36 ++++++++++++++++ config/locales/models/single_charge.pt-BR.yml | 27 ++++++++++++ config/routes.rb | 1 + .../20240718203804_create_single_charges.rb | 14 +++++++ db/schema.rb | 21 +++++++++- spec/factories/single_charges.rb | 10 +++++ spec/models/single_charge_spec.rb | 5 +++ spec/requests/form_request_towers_spec.rb | 2 +- .../superintendent_register_fine_spec.rb | 35 ++++++++++++++++ 16 files changed, 279 insertions(+), 8 deletions(-) create mode 100644 app/controllers/fines_controller.rb create mode 100644 app/javascript/controllers/fines_controller.js create mode 100644 app/models/single_charge.rb create mode 100644 app/views/fines/new.html.erb create mode 100644 config/locales/models/single_charge.pt-BR.yml create mode 100644 db/migrate/20240718203804_create_single_charges.rb create mode 100644 spec/factories/single_charges.rb create mode 100644 spec/models/single_charge_spec.rb create mode 100644 spec/system/superintendent/superintendent_register_fine_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 085171c3..c85b3790 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,11 +24,22 @@ def authorize_super_manager! end def authorize_condo_manager!(condo) - unless (manager_signed_in? && current_manager.is_super) || - (manager_signed_in? && current_manager.condos.include?(condo)) || - (resident_signed_in? && condo.residents.include?(current_resident)) - redirect_to root_path, alert: I18n.t('alerts.manager.not_authorized') - end + return if super? || condo_manager?(condo) || condo_resident?(condo) + + redirect_to root_path, alert: I18n.t('alerts.manager.not_authorized') + true + end + + def super? + manager_signed_in? && current_manager.is_super + end + + def condo_manager?(condo) + manager_signed_in? && current_manager.condos.include?(condo) + end + + def condo_resident?(condo) + resident_signed_in? && condo && condo.residents.include?(current_resident) end def block_manager_from_resident_sign_in diff --git a/app/controllers/fines_controller.rb b/app/controllers/fines_controller.rb new file mode 100644 index 00000000..12354dfe --- /dev/null +++ b/app/controllers/fines_controller.rb @@ -0,0 +1,41 @@ +class FinesController < ApplicationController + def new + @condo = Condo.find params[:condo_id] + @fine = SingleCharge.new(condo: @condo) + end + + def create + @condo = Condo.find params[:condo_id] + @fine = SingleCharge.new(fine_params) + + return unless @fine.save + + redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + end + + private + + def find_tower_and_floor + return unless params['single_charge'] + + tower = Tower.find_by(id: params['single_charge']['tower_id']) + return tower.floors[params['single_charge']['floor'].to_i - 1] if tower + + nil + end + + def find_unit_id + floor = find_tower_and_floor + + return floor.units[params['single_charge']['unit'].to_i - 1].id if floor + + nil + end + + def fine_params + @condo = Condo.find params[:condo_id] + params.require(:single_charge).permit(:value_cents, + :description).merge({ charge_type: :fine, condo: @condo, + unit_id: find_unit_id }) + end +end diff --git a/app/controllers/residents_controller.rb b/app/controllers/residents_controller.rb index 089013ff..7b23410b 100644 --- a/app/controllers/residents_controller.rb +++ b/app/controllers/residents_controller.rb @@ -1,5 +1,5 @@ class ResidentsController < ApplicationController - before_action :authenticate_manager!, only: %i[new create find_towers show] + before_action :authenticate_manager!, only: %i[new create show] before_action :set_resident, only: %i[update edit_photo update_photo show] before_action :authenticate_resident!, only: %i[update edit_photo update_photo] @@ -47,6 +47,9 @@ def update def find_towers condo = Condo.find_by(id: params[:id]) + + return if authorize_condo_manager!(condo) + return render status: :not_found, json: [] unless condo towers = condo.towers @@ -74,6 +77,14 @@ def update_photo protected + def authorize_condo_manager!(condo) + return true if super + return unless current_resident && !current_resident.superintendent + + redirect_to root_path + true + end + def find_tower_and_floor return unless params['resident'] diff --git a/app/javascript/controllers/fines_controller.js b/app/javascript/controllers/fines_controller.js new file mode 100644 index 00000000..7f83d6a8 --- /dev/null +++ b/app/javascript/controllers/fines_controller.js @@ -0,0 +1,40 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = [ 'condo', 'tower', 'floor', 'unit' ] + + searchTowers(condoId){ + fetch(`${window.origin}/residents/find_towers?id=${condoId}`) + .then((response)=>{ + return response.json() + }) + .then((towers)=>{ + this.towerTarget.innerHTML = "" + towers.forEach(tower => { + this.towerTarget.options.add(new Option(tower.name, tower.id)) + }); + this.towers = towers + this.changeTower() + }) + .catch(()=>{console.log('Towers not found')}) + } + + connect(){ + this.searchTowers(this.element.getAttribute('condo-id')) + } + + changeTower(){ + let tower = this.towers[this.towerTarget.selectedIndex] + console.log(tower) + this.unitTarget.innerHTML = "" + this.floorTarget.innerHTML = "" + + for (let floor = 1; floor <= tower.floor_quantity; floor++) { + this.floorTarget.options.add(new Option(`${floor}`, `${floor}`)) + } + + for (let unit = 1; unit <= tower.units_per_floor; unit++) { + this.unitTarget.options.add(new Option(`${unit}`, `${unit}`)) + } + } +} \ No newline at end of file diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 486e14af..8c6c7bb1 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -20,3 +20,6 @@ application.register("resident", ResidentController) import UnitsController from "./units_controller" application.register("units", UnitsController) + +import FinesController from "./fines_controller" +application.register("fines", FinesController) diff --git a/app/models/single_charge.rb b/app/models/single_charge.rb new file mode 100644 index 00000000..7739603d --- /dev/null +++ b/app/models/single_charge.rb @@ -0,0 +1,7 @@ +class SingleCharge < ApplicationRecord + belongs_to :condo + belongs_to :unit + belongs_to :common_area, optional: true + + enum charge_type: { fine: 0, common_area_fee: 1 } +end diff --git a/app/views/condos/show.html.erb b/app/views/condos/show.html.erb index 44aba0ce..3e61994f 100644 --- a/app/views/condos/show.html.erb +++ b/app/views/condos/show.html.erb @@ -78,6 +78,17 @@ <% end %> <%= render 'condos/dashboard/common_area_list' %> + + <%= link_to new_condo_fine_path(@condo), class:"btn py-2 rounded-pill d-flex justify-content-center align-items-center mb-2 shadow-sm mt-2", style: "width: 100%; background-color: #FDE879;" do %> + Lançar Multa + + + + + + + <% end %> + diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb new file mode 100644 index 00000000..5f0c042d --- /dev/null +++ b/app/views/fines/new.html.erb @@ -0,0 +1,36 @@ +
+

Lançar Multa

+ <%= form_with model: [@condo, @fine], url:condo_fines_path(@condo, @fine) do |f| %> +
+
+
+ <%= f.label :tower_id%> + <%= f.collection_select :tower_id, {}, {}, {}, {}, :'data-fines-target' => "tower", :'data-action' => "change->fines#changeTower", class: 'form-control form-select' %> +
+ +
+ <%= f.label :floor %> + <%= f.collection_select :floor, {}, {}, {}, {}, :'data-fines-target' => "floor", class: 'form-control form-select' %> +
+ +
+ <%= f.label :unit %> + <%= f.collection_select :unit, {}, {}, {}, {}, :'data-fines-target' => "unit", class: 'form-control form-select' %> +
+
+ +
+ <%= f.label :description %> + <%= f.text_field :description %> +
+ +
+ <%= f.label :value_cents %> + <%= f.number_field :value_cents %> +
+ +
+ <%= f.submit 'Lançar Multa', class:"btn btn-dark rounded-pill px-4 mt-3" %> +
+ <% end %> +
\ No newline at end of file diff --git a/config/locales/models/single_charge.pt-BR.yml b/config/locales/models/single_charge.pt-BR.yml new file mode 100644 index 00000000..27ad3485 --- /dev/null +++ b/config/locales/models/single_charge.pt-BR.yml @@ -0,0 +1,27 @@ +pt-BR: + notices: + single_charge: + updated: 'Pavimento Tipo atualizado com sucesso!' + alerts: + single_charge: + not_created: 'Não foi possível cadastrar o andar.' + not_ready: 'Você deve atualizar o pavimento tipo antes de acessar essa página' + activerecord: + models: + single_charge: + one: 'Cobrança Avulsa' + other: 'Cobranças Avulsa' + attributes: + single_charge: + tower: 'Torre' + tower_id: 'Torre' + floor: 'Andar' + floor_id: 'Andar' + unit: 'Unidade' + unit_id: 'Unidade' + condo: 'Condomínio' + condo_id: 'Condomínio' + description: 'Descrição' + value_cents: 'Valor' + common_area: 'Área Comum' + charge_type: 'Tipo' \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cbb540db..ed107083 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,6 +40,7 @@ resources :unit_types, only: [:new, :create] resources :visitor_entries, only: [:index, :new, :create] resources :superintendents, only: [:show, :new, :create, :edit, :update] + resources :fines, only: [:new, :create] resources :towers, only: [:new, :create] do member do diff --git a/db/migrate/20240718203804_create_single_charges.rb b/db/migrate/20240718203804_create_single_charges.rb new file mode 100644 index 00000000..06a2dfc2 --- /dev/null +++ b/db/migrate/20240718203804_create_single_charges.rb @@ -0,0 +1,14 @@ +class CreateSingleCharges < ActiveRecord::Migration[7.1] + def change + create_table :single_charges do |t| + t.text :description + t.integer :value_cents, null: false + t.integer :charge_type, null: false + t.references :condo, null: false, foreign_key: true + t.references :unit, null: false, foreign_key: true + t.references :common_area, null: true, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 3cfb3976..bdb7a5b5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_17_033755) do +ActiveRecord::Schema[7.1].define(version: 2024_07_18_203804) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -131,6 +131,20 @@ t.index ["reset_password_token"], name: "index_residents_on_reset_password_token", unique: true end + create_table "single_charges", force: :cascade do |t| + t.text "description" + t.integer "value_cents", null: false + t.integer "charge_type", null: false + t.integer "condo_id", null: false + t.integer "unit_id", null: false + t.integer "common_area_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["common_area_id"], name: "index_single_charges_on_common_area_id" + t.index ["condo_id"], name: "index_single_charges_on_condo_id" + t.index ["unit_id"], name: "index_single_charges_on_unit_id" + end + create_table "superintendents", force: :cascade do |t| t.date "start_date", null: false t.date "end_date", null: false @@ -208,6 +222,11 @@ add_foreign_key "floors", "towers" add_foreign_key "reservations", "common_areas" add_foreign_key "reservations", "residents" + add_foreign_key "single_charges", "common_areas" + add_foreign_key "single_charges", "condos" + add_foreign_key "single_charges", "units" + add_foreign_key "superintendents", "condos" + add_foreign_key "superintendents", "residents", column: "tenant_id" add_foreign_key "towers", "condos" add_foreign_key "unit_types", "condos" add_foreign_key "units", "floors" diff --git a/spec/factories/single_charges.rb b/spec/factories/single_charges.rb new file mode 100644 index 00000000..e6ee5bf7 --- /dev/null +++ b/spec/factories/single_charges.rb @@ -0,0 +1,10 @@ +FactoryBot.define do + factory :single_charge do + description { 'MyText' } + value_cents { 1 } + charge_type { 1 } + condo { nil } + unit { nil } + common_area { nil } + end +end diff --git a/spec/models/single_charge_spec.rb b/spec/models/single_charge_spec.rb new file mode 100644 index 00000000..f476a3ee --- /dev/null +++ b/spec/models/single_charge_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SingleCharge, type: :model do + "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/form_request_towers_spec.rb b/spec/requests/form_request_towers_spec.rb index cc7e5819..98bcb0a1 100644 --- a/spec/requests/form_request_towers_spec.rb +++ b/spec/requests/form_request_towers_spec.rb @@ -26,7 +26,7 @@ get find_towers_residents_path 'condo' => condo - expect(response).to redirect_to new_manager_session_path + expect(response).to redirect_to root_path end it 'must be authenticated as manager' do diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb new file mode 100644 index 00000000..a95b68d3 --- /dev/null +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -0,0 +1,35 @@ +require 'rails_helper' + +describe 'Superintendent register fine' do + it 'successful' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, name: 'Torre X', floor_quantity: 3, units_per_floor: 2, condo:) + unit11 = tower.floors[0].units[0] + unit22 = tower.floors[1].units[1] + create :resident, full_name: 'Fernando Almeida', properties: [unit22], residence: unit22, + email: 'fernando@email.com' + resident_super = create :resident, full_name: 'Dona Alvara', residence: unit11, email: 'alvara@email.com' + create(:superintendent, condo:, tenant: resident_super, start_date: Time.zone.today, + end_date: Time.zone.today >> 2) + + login_as resident_super, scope: :resident + + visit root_path + click_on 'Condomínio X' + click_on 'Lançar Multa' + + within '#form_data' do + select 'Torre X', from: 'Torre' + select '2', from: 'Andar' + select '2', from: 'Unidade' + fill_in 'Valor', with: 50_000 + fill_in 'Descrição', with: 'Som alto' + click_on 'Lançar Multa' + end + + expect(current_path).to eq condo_path condo + expect(page).to have_content 'Multa lançada com sucesso para a Unidade 22' + expect(SingleCharge.last.unit).to eq unit22 + expect(SingleCharge.last.value_cents).to eq 50_000 + end +end From 44720337f559ddce8131b279559ebf7063264ebe Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Fri, 19 Jul 2024 00:30:35 -0300 Subject: [PATCH 2/7] Implementa lancamento de multas. Co-authored-by: Danilo Ribeiro --- app/controllers/fines_controller.rb | 24 +++-- .../controllers/fines_controller.js | 32 +++---- app/models/single_charge.rb | 11 +++ app/views/condos/show.html.erb | 18 ++-- app/views/fines/new.html.erb | 1 + config/locales/models/single_charge.pt-BR.yml | 6 +- .../superintendent_register_fine_spec.rb | 89 +++++++++++++++++++ .../superintendent_register_fine_spec.rb | 87 +++++++++++++++++- 8 files changed, 231 insertions(+), 37 deletions(-) create mode 100644 spec/requests/superintendent_register_fine_spec.rb diff --git a/app/controllers/fines_controller.rb b/app/controllers/fines_controller.rb index 12354dfe..863c21ce 100644 --- a/app/controllers/fines_controller.rb +++ b/app/controllers/fines_controller.rb @@ -1,20 +1,35 @@ class FinesController < ApplicationController + before_action :set_condo, only: %i[new create] + before_action :authorize_superintendent, only: %i[new create] + def new - @condo = Condo.find params[:condo_id] @fine = SingleCharge.new(condo: @condo) end def create - @condo = Condo.find params[:condo_id] @fine = SingleCharge.new(fine_params) - return unless @fine.save + if @fine.save + return redirect_to @condo, + notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + end - redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + flash.now.alert = t('alerts.single_charge.fine_not_created') + render 'new', status: :unprocessable_entity end private + def authorize_superintendent + return if resident_signed_in? && @condo.superintendent && @condo.superintendent.tenant == current_resident + + redirect_to root_path + end + + def set_condo + @condo = Condo.find params[:condo_id] + end + def find_tower_and_floor return unless params['single_charge'] @@ -33,7 +48,6 @@ def find_unit_id end def fine_params - @condo = Condo.find params[:condo_id] params.require(:single_charge).permit(:value_cents, :description).merge({ charge_type: :fine, condo: @condo, unit_id: find_unit_id }) diff --git a/app/javascript/controllers/fines_controller.js b/app/javascript/controllers/fines_controller.js index 7f83d6a8..d07c9f34 100644 --- a/app/javascript/controllers/fines_controller.js +++ b/app/javascript/controllers/fines_controller.js @@ -1,29 +1,29 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { - static targets = [ 'condo', 'tower', 'floor', 'unit' ] + static targets = ['condo', 'tower', 'floor', 'unit'] - searchTowers(condoId){ + searchTowers(condoId) { fetch(`${window.origin}/residents/find_towers?id=${condoId}`) - .then((response)=>{ - return response.json() - }) - .then((towers)=>{ - this.towerTarget.innerHTML = "" - towers.forEach(tower => { - this.towerTarget.options.add(new Option(tower.name, tower.id)) - }); - this.towers = towers - this.changeTower() - }) - .catch(()=>{console.log('Towers not found')}) + .then((response) => { + return response.json() + }) + .then((towers) => { + this.towerTarget.innerHTML = "" + towers.forEach(tower => { + this.towerTarget.options.add(new Option(tower.name, tower.id)) + }); + this.towers = towers + this.changeTower() + }) + .catch(() => { console.log('Towers not found') }) } - connect(){ + connect() { this.searchTowers(this.element.getAttribute('condo-id')) } - changeTower(){ + changeTower() { let tower = this.towers[this.towerTarget.selectedIndex] console.log(tower) this.unitTarget.innerHTML = "" diff --git a/app/models/single_charge.rb b/app/models/single_charge.rb index 7739603d..96f1f388 100644 --- a/app/models/single_charge.rb +++ b/app/models/single_charge.rb @@ -3,5 +3,16 @@ class SingleCharge < ApplicationRecord belongs_to :unit belongs_to :common_area, optional: true + validates :value_cents, :charge_type, presence: true + validates :description, presence: true, if: -> { charge_type == 'fine' } + + validate :unit_valid? + enum charge_type: { fine: 0, common_area_fee: 1 } + + def unit_valid? + return false if unit.owner + + errors.add(:unit, 'Não há proprietário para a unidade selecionada') + end end diff --git a/app/views/condos/show.html.erb b/app/views/condos/show.html.erb index 3e61994f..86491243 100644 --- a/app/views/condos/show.html.erb +++ b/app/views/condos/show.html.erb @@ -79,14 +79,16 @@ <%= render 'condos/dashboard/common_area_list' %> - <%= link_to new_condo_fine_path(@condo), class:"btn py-2 rounded-pill d-flex justify-content-center align-items-center mb-2 shadow-sm mt-2", style: "width: 100%; background-color: #FDE879;" do %> - Lançar Multa - - - - - - + <% if resident_signed_in? && current_resident&.superintendent %> + <%= link_to new_condo_fine_path(@condo), class:"btn py-2 rounded-pill d-flex justify-content-center align-items-center mb-2 shadow-sm mt-2", style: "width: 100%; background-color: #FDE879;" do %> + Lançar Multa + + + + + + + <% end %> <% end %>
diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb index 5f0c042d..aa8a4797 100644 --- a/app/views/fines/new.html.erb +++ b/app/views/fines/new.html.erb @@ -1,3 +1,4 @@ +<%= render 'shared/errors', model: @fine %>

Lançar Multa

<%= form_with model: [@condo, @fine], url:condo_fines_path(@condo, @fine) do |f| %> diff --git a/config/locales/models/single_charge.pt-BR.yml b/config/locales/models/single_charge.pt-BR.yml index 27ad3485..2417196f 100644 --- a/config/locales/models/single_charge.pt-BR.yml +++ b/config/locales/models/single_charge.pt-BR.yml @@ -1,11 +1,7 @@ pt-BR: - notices: - single_charge: - updated: 'Pavimento Tipo atualizado com sucesso!' alerts: single_charge: - not_created: 'Não foi possível cadastrar o andar.' - not_ready: 'Você deve atualizar o pavimento tipo antes de acessar essa página' + fine_not_created: 'Não foi possível lançar a multa.' activerecord: models: single_charge: diff --git a/spec/requests/superintendent_register_fine_spec.rb b/spec/requests/superintendent_register_fine_spec.rb new file mode 100644 index 00000000..24500bf9 --- /dev/null +++ b/spec/requests/superintendent_register_fine_spec.rb @@ -0,0 +1,89 @@ +require 'rails_helper' + +describe 'Superintendent register fine' do + context 'GET /condos/:condo_id/fines/new' do + it 'and must be authenticated' do + condo = create :condo, name: 'Condomínio X' + + get new_condo_fine_path(condo) + + expect(response).to redirect_to root_path + end + + it 'and must be authenticated as a superintendent to access' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + resident = create :resident, full_name: 'Dona Alvara', residence: unit11, email: 'alvara@email.com' + + login_as resident, scope: :resident + + get new_condo_fine_path(condo) + + expect(response).to redirect_to root_path + end + + it 'and is authenticated as a manager' do + condo = create :condo, name: 'Condomínio X' + manager = create :manager + + login_as manager, scope: :manager + + get new_condo_fine_path(condo) + + expect(response).to redirect_to root_path + end + end + + context 'POST /condos/:condo_id/fines' do + it 'and must be authenticated' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + create :resident, properties: [unit11] + + params = { single_charge: { tower_id: '1', floor: '1', unit: '1', + description: 'Barulho dms', value_cents: '5000' }, condo_id: '1' } + + post(condo_fines_path(condo), params:) + + expect(response).to redirect_to root_path + expect(SingleCharge.last).to eq nil + end + + it 'and must be authenticated as a superintendent to access' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + resident = create :resident, properties: [unit11] + + login_as resident, scope: :resident + + params = { single_charge: { tower_id: '1', floor: '1', unit: '1', + description: 'Barulho dms', value_cents: '5000' }, condo_id: '1' } + + post(condo_fines_path(condo), params:) + + expect(response).to redirect_to root_path + expect(SingleCharge.last).to eq nil + end + + it 'and is authenticated as a manager' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + create :resident, properties: [unit11] + manager = create :manager + + login_as manager, scope: :manager + + params = { single_charge: { tower_id: '1', floor: '1', unit: '1', + description: 'Barulho dms', value_cents: '5000' }, condo_id: '1' } + + post(condo_fines_path(condo), params:) + + expect(response).to redirect_to root_path + expect(SingleCharge.last).to eq nil + end + end +end diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb index a95b68d3..89e6334c 100644 --- a/spec/system/superintendent/superintendent_register_fine_spec.rb +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -6,9 +6,8 @@ tower = create(:tower, name: 'Torre X', floor_quantity: 3, units_per_floor: 2, condo:) unit11 = tower.floors[0].units[0] unit22 = tower.floors[1].units[1] - create :resident, full_name: 'Fernando Almeida', properties: [unit22], residence: unit22, - email: 'fernando@email.com' - resident_super = create :resident, full_name: 'Dona Alvara', residence: unit11, email: 'alvara@email.com' + create :resident, properties: [unit22], residence: unit22, email: 'fernando@email.com' + resident_super = create :resident, residence: unit11, email: 'alvara@email.com' create(:superintendent, condo:, tenant: resident_super, start_date: Time.zone.today, end_date: Time.zone.today >> 2) @@ -32,4 +31,86 @@ expect(SingleCharge.last.unit).to eq unit22 expect(SingleCharge.last.value_cents).to eq 50_000 end + + it 'with missing params' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, name: 'Torre X', floor_quantity: 3, units_per_floor: 2, condo:) + unit11 = tower.floors[0].units[0] + unit22 = tower.floors[1].units[1] + create :resident, properties: [unit22], residence: unit22, email: 'fernando@email.com' + resident_super = create :resident, residence: unit11, email: 'alvara@email.com' + create(:superintendent, condo:, tenant: resident_super, start_date: Time.zone.today, + end_date: Time.zone.today >> 2) + + login_as resident_super, scope: :resident + + visit root_path + click_on 'Condomínio X' + click_on 'Lançar Multa' + + within '#form_data' do + fill_in 'Valor', with: '' + fill_in 'Descrição', with: '' + click_on 'Lançar Multa' + end + + expect(page).to have_content 'Não foi possível lançar a multa' + expect(page).to have_content 'Valor não pode ficar em branco' + expect(page).to have_content 'Descrição não pode ficar em branco' + expect(SingleCharge.last).to eq nil + end + + it 'to a unit that has no owner' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, name: 'Torre X', floor_quantity: 3, units_per_floor: 2, condo:) + unit11 = tower.floors[0].units[0] + resident_super = create :resident, residence: unit11 + create(:superintendent, condo:, tenant: resident_super, start_date: Time.zone.today, + end_date: Time.zone.today >> 2) + + login_as resident_super, scope: :resident + + visit root_path + click_on 'Condomínio X' + click_on 'Lançar Multa' + + within '#form_data' do + select 'Torre X', from: 'Torre' + select '2', from: 'Andar' + select '2', from: 'Unidade' + fill_in 'Valor', with: 50_000 + fill_in 'Descrição', with: 'Som alto' + click_on 'Lançar Multa' + end + + expect(page).to have_content 'Não foi possível lançar a multa' + expect(page).to have_content 'Não há proprietário para a unidade selecionada' + expect(SingleCharge.last).to eq nil + end + + it 'is not authenticated as a superintendent' do + condo = create :condo, name: 'Condomínio X' + tower = create(:tower, name: 'Torre X', floor_quantity: 3, units_per_floor: 2, condo:) + unit11 = tower.floors[0].units[0] + resident = create :resident, residence: unit11 + + login_as resident, scope: :resident + + visit root_path + click_on 'Condomínio X' + + expect(page).not_to have_link 'Lançar Multa' + end + + it 'is authenticated as a manager' do + create :condo, name: 'Condomínio X' + manager = create :manager + + login_as manager, scope: :manager + + visit root_path + click_on 'Condomínio X' + + expect(page).not_to have_link 'Lançar Multa' + end end From 22c736563ca99ecb02a1c0bf681cdbb4c2f7a4f3 Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Fri, 19 Jul 2024 19:20:02 -0300 Subject: [PATCH 3/7] Implementa consumo de API externa para o lancamento de multas. Co-authored-by: Danilo Ribeiro --- Gemfile | 1 + Gemfile.lock | 10 +++++ app/controllers/fines_controller.rb | 28 ++++++++++-- app/models/single_charge.rb | 2 +- spec/requests/pague_aluguel/fine_spec.rb | 45 +++++++++++++++++++ .../superintendent_register_fine_spec.rb | 4 +- 6 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 spec/requests/pague_aluguel/fine_spec.rb diff --git a/Gemfile b/Gemfile index 138bcd22..b6a5c6d8 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'breadcrumbs_on_rails' gem 'cpf_cnpj' gem 'cssbundling-rails' gem 'devise' +gem 'faraday' gem 'image_processing', '>= 1.2' gem 'jbuilder' gem 'jsbundling-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 299f4645..25e3e9ee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -123,6 +123,11 @@ GEM factory_bot_rails (6.4.3) factory_bot (~> 6.4) railties (>= 5.0.0) + faraday (2.10.0) + faraday-net_http (>= 2.0, < 3.2) + logger + faraday-net_http (3.1.0) + net-http ferrum (0.15) addressable (~> 2.5) concurrent-ruby (~> 1.1) @@ -148,6 +153,7 @@ GEM railties (>= 6.0.0) json (2.7.2) language_server-protocol (3.17.0.3) + logger (1.6.0) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -163,6 +169,8 @@ GEM minitest (5.24.1) msgpack (1.7.2) mutex_m (0.2.0) + net-http (0.4.1) + uri net-imap (0.4.14) date net-protocol @@ -305,6 +313,7 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) + uri (0.13.0) warden (1.2.9) rack (>= 2.0.9) webrick (1.8.1) @@ -329,6 +338,7 @@ DEPENDENCIES debug devise factory_bot_rails + faraday image_processing (>= 1.2) jbuilder jsbundling-rails diff --git a/app/controllers/fines_controller.rb b/app/controllers/fines_controller.rb index 863c21ce..e2160426 100644 --- a/app/controllers/fines_controller.rb +++ b/app/controllers/fines_controller.rb @@ -9,11 +9,13 @@ def new def create @fine = SingleCharge.new(fine_params) - if @fine.save - return redirect_to @condo, - notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" - end + response = post_response + if @fine.valid? && response.success? + @fine.save + return redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + end + @fine.valid? flash.now.alert = t('alerts.single_charge.fine_not_created') render 'new', status: :unprocessable_entity end @@ -52,4 +54,22 @@ def fine_params :description).merge({ charge_type: :fine, condo: @condo, unit_id: find_unit_id }) end + + def single_charge_params + { single_charge: { + description: @fine.description, + value_cents: @fine.value_cents, + charge_type: @fine.charge_type, + issue_date: 5.days.from_now.to_date, + condo_id: @fine.condo.id, + common_area_id: nil, + unit_id: @fine.unit.id + } } + end + + def post_response + Faraday.new(url: 'http://localhost:4000') + .post('/api/v1/single_charges/', single_charge_params.to_json, + 'Content-Type' => 'application/json') + end end diff --git a/app/models/single_charge.rb b/app/models/single_charge.rb index 96f1f388..3cc12ece 100644 --- a/app/models/single_charge.rb +++ b/app/models/single_charge.rb @@ -11,7 +11,7 @@ class SingleCharge < ApplicationRecord enum charge_type: { fine: 0, common_area_fee: 1 } def unit_valid? - return false if unit.owner + return true if unit.owner errors.add(:unit, 'Não há proprietário para a unidade selecionada') end diff --git a/spec/requests/pague_aluguel/fine_spec.rb b/spec/requests/pague_aluguel/fine_spec.rb new file mode 100644 index 00000000..9d965f44 --- /dev/null +++ b/spec/requests/pague_aluguel/fine_spec.rb @@ -0,0 +1,45 @@ +require 'rails_helper' + +RSpec.describe FinesController, type: :controller do + describe 'POST #create' do + include Devise::Test::ControllerHelpers + include Warden::Test::Helpers + + before do + Warden.test_mode! + end + + after do + Warden.test_reset! + end + + it 'successfully' do + condo = create(:condo, name: 'Condomínio X') + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + resident = create(:resident, full_name: 'Dona Alvara', properties: [unit11], email: 'alvara@email.com') + create(:superintendent, condo:, tenant: resident, start_date: Time.zone.today, + end_date: Time.zone.today >> 2) + + login_as resident, scope: :resident + + single_charge = { + description: 'Multa por barulho durante a madrugada', + value_cents: 10_000, + charge_type: 'fine', + unit_id: unit11.id + } + + fake_response = instance_double(Faraday::Response, success?: true, body: { message: 'Success' }.to_json) + fake_connection = instance_double(Faraday::Connection) + + allow(Faraday).to receive(:new).and_return(fake_connection) + allow(fake_connection).to receive(:post).with('/api/v1/single_charges/', single_charge.to_json, + 'Content-Type' => 'application/json').and_return(fake_response) + + post :create, params: { condo_id: condo.id, single_charge: } + + expect(response).to have_http_status(:found) + end + end +end diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb index 89e6334c..6ff63e42 100644 --- a/spec/system/superintendent/superintendent_register_fine_spec.rb +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -26,7 +26,7 @@ click_on 'Lançar Multa' end - expect(current_path).to eq condo_path condo + expect(page).to have_current_path condo_path(condo), wait: 2 expect(page).to have_content 'Multa lançada com sucesso para a Unidade 22' expect(SingleCharge.last.unit).to eq unit22 expect(SingleCharge.last.value_cents).to eq 50_000 @@ -54,6 +54,7 @@ click_on 'Lançar Multa' end + sleep 5 expect(page).to have_content 'Não foi possível lançar a multa' expect(page).to have_content 'Valor não pode ficar em branco' expect(page).to have_content 'Descrição não pode ficar em branco' @@ -83,6 +84,7 @@ click_on 'Lançar Multa' end + sleep 2 expect(page).to have_content 'Não foi possível lançar a multa' expect(page).to have_content 'Não há proprietário para a unidade selecionada' expect(SingleCharge.last).to eq nil From bd2de78704816e0a7168bf78a2c30dbecee8602c Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Sun, 21 Jul 2024 13:47:27 -0300 Subject: [PATCH 4/7] Implementa uso da API na aplicacao. Co-authored-by: Danilo Ribeiro --- app/controllers/fines_controller.rb | 14 +++--- app/models/unit.rb | 4 ++ app/views/fines/new.html.erb | 2 +- spec/requests/pague_aluguel/fine_spec.rb | 45 ------------------ .../superintendent_register_fine_spec.rb | 46 +++++++++++++++++++ .../superintendent_register_fine_spec.rb | 20 +++++++- 6 files changed, 76 insertions(+), 55 deletions(-) delete mode 100644 spec/requests/pague_aluguel/fine_spec.rb diff --git a/app/controllers/fines_controller.rb b/app/controllers/fines_controller.rb index e2160426..e0e0c3aa 100644 --- a/app/controllers/fines_controller.rb +++ b/app/controllers/fines_controller.rb @@ -9,13 +9,13 @@ def new def create @fine = SingleCharge.new(fine_params) - response = post_response - - if @fine.valid? && response.success? - @fine.save - return redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + if @fine.valid? + response = post_response + if response.success? + @fine.save + return redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" + end end - @fine.valid? flash.now.alert = t('alerts.single_charge.fine_not_created') render 'new', status: :unprocessable_entity end @@ -60,7 +60,7 @@ def single_charge_params description: @fine.description, value_cents: @fine.value_cents, charge_type: @fine.charge_type, - issue_date: 5.days.from_now.to_date, + issue_date: Time.zone.today, condo_id: @fine.condo.id, common_area_id: nil, unit_id: @fine.unit.id diff --git a/app/models/unit.rb b/app/models/unit.rb index de0d7731..499b3cac 100644 --- a/app/models/unit.rb +++ b/app/models/unit.rb @@ -15,6 +15,10 @@ def short_identifier "#{floor.identifier}#{floor.units.index(self) + 1}" end + def identifier + floor.units.index(self) + 1 + end + def tower_identifier "#{floor.tower.name} - #{short_identifier}" end diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb index aa8a4797..a6fceee5 100644 --- a/app/views/fines/new.html.erb +++ b/app/views/fines/new.html.erb @@ -27,7 +27,7 @@
<%= f.label :value_cents %> - <%= f.number_field :value_cents %> + <%= f.text_field :value_cents %>
diff --git a/spec/requests/pague_aluguel/fine_spec.rb b/spec/requests/pague_aluguel/fine_spec.rb deleted file mode 100644 index 9d965f44..00000000 --- a/spec/requests/pague_aluguel/fine_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'rails_helper' - -RSpec.describe FinesController, type: :controller do - describe 'POST #create' do - include Devise::Test::ControllerHelpers - include Warden::Test::Helpers - - before do - Warden.test_mode! - end - - after do - Warden.test_reset! - end - - it 'successfully' do - condo = create(:condo, name: 'Condomínio X') - tower = create(:tower, condo:) - unit11 = tower.floors.first.units.first - resident = create(:resident, full_name: 'Dona Alvara', properties: [unit11], email: 'alvara@email.com') - create(:superintendent, condo:, tenant: resident, start_date: Time.zone.today, - end_date: Time.zone.today >> 2) - - login_as resident, scope: :resident - - single_charge = { - description: 'Multa por barulho durante a madrugada', - value_cents: 10_000, - charge_type: 'fine', - unit_id: unit11.id - } - - fake_response = instance_double(Faraday::Response, success?: true, body: { message: 'Success' }.to_json) - fake_connection = instance_double(Faraday::Connection) - - allow(Faraday).to receive(:new).and_return(fake_connection) - allow(fake_connection).to receive(:post).with('/api/v1/single_charges/', single_charge.to_json, - 'Content-Type' => 'application/json').and_return(fake_response) - - post :create, params: { condo_id: condo.id, single_charge: } - - expect(response).to have_http_status(:found) - end - end -end diff --git a/spec/requests/superintendent_register_fine_spec.rb b/spec/requests/superintendent_register_fine_spec.rb index 24500bf9..c45fb0d1 100644 --- a/spec/requests/superintendent_register_fine_spec.rb +++ b/spec/requests/superintendent_register_fine_spec.rb @@ -85,5 +85,51 @@ expect(response).to redirect_to root_path expect(SingleCharge.last).to eq nil end + + it 'returns failure message if theres an external server error' do + condo = create(:condo, name: 'Condomínio X') + tower = create(:tower, condo:) + unit11 = tower.floors.first.units.first + resident = create(:resident, full_name: 'Dona Alvara', properties: [unit11], email: 'alvara@email.com') + create(:superintendent, condo:, tenant: resident, start_date: Time.zone.today, + end_date: Time.zone.today >> 2) + + login_as resident, scope: :resident + + create_params = { + description: 'Multa por barulho durante a madrugada', + value_cents: 10_000, + charge_type: :fine, + issue_date: Time.zone.today, + tower_id: tower.id, + floor: unit11.floor.identifier, + unit: unit11.identifier + } + + single_charge = + { single_charge: { + description: 'Multa por barulho durante a madrugada', + value_cents: 10_000, + charge_type: :fine, + issue_date: Time.zone.today, + condo_id: condo.id, + common_area_id: nil, + unit_id: unit11.id + } } + + fake_response = instance_double(Faraday::Response, status: 422, success?: false, body: {}) + fake_connection = instance_double(Faraday::Connection) + + allow(Faraday).to receive(:new).and_return(fake_connection) + allow(fake_connection).to receive(:post) + .with('/api/v1/single_charges/', single_charge.to_json, 'Content-Type' => 'application/json') + .and_return(fake_response) + + post condo_fines_path(condo), params: { condo_id: condo.id, single_charge: create_params } + + expect(response).to have_http_status(:unprocessable_entity) + expect(flash.now[:alert]).to eq(I18n.t('alerts.single_charge.fine_not_created')) + expect(SingleCharge.last).to eq nil + end end end diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb index 6ff63e42..136a45f9 100644 --- a/spec/system/superintendent/superintendent_register_fine_spec.rb +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -10,6 +10,24 @@ resident_super = create :resident, residence: unit11, email: 'alvara@email.com' create(:superintendent, condo:, tenant: resident_super, start_date: Time.zone.today, end_date: Time.zone.today >> 2) + single_charge = + { single_charge: { + description: 'Som alto', + value_cents: 50_000, + charge_type: :fine, + issue_date: Time.zone.today, + condo_id: condo.id, + common_area_id: nil, + unit_id: unit22.id + } } + + fake_response = instance_double(Faraday::Response, status: 201, success?: true, body: { message: :created }.to_json) + fake_connection = instance_double(Faraday::Connection) + + allow(Faraday).to receive(:new).and_return(fake_connection) + allow(fake_connection).to receive(:post) + .with('/api/v1/single_charges/', single_charge.to_json, 'Content-Type' => 'application/json') + .and_return(fake_response) login_as resident_super, scope: :resident @@ -54,7 +72,6 @@ click_on 'Lançar Multa' end - sleep 5 expect(page).to have_content 'Não foi possível lançar a multa' expect(page).to have_content 'Valor não pode ficar em branco' expect(page).to have_content 'Descrição não pode ficar em branco' @@ -84,7 +101,6 @@ click_on 'Lançar Multa' end - sleep 2 expect(page).to have_content 'Não foi possível lançar a multa' expect(page).to have_content 'Não há proprietário para a unidade selecionada' expect(SingleCharge.last).to eq nil From 9228fe1870955b1af8433f47e1bb0467b83d79ff Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Sun, 21 Jul 2024 14:43:04 -0300 Subject: [PATCH 5/7] =?UTF-8?q?Adiciona=20money=20rails=20e=20atualiza=20e?= =?UTF-8?q?stiliza=C3=A7=C3=A3o=20da=20pagina=20de=20lancar=20multas.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danilo Ribeiro --- Gemfile | 1 + Gemfile.lock | 10 ++ app/controllers/fines_controller.rb | 11 +- app/models/single_charge.rb | 2 + app/views/fines/new.html.erb | 23 ++-- config/initializers/money.rb | 116 ++++++++++++++++++ config/locales/models/single_charge.pt-BR.yml | 1 + .../superintendent_register_fine_spec.rb | 8 +- 8 files changed, 150 insertions(+), 22 deletions(-) create mode 100644 config/initializers/money.rb diff --git a/Gemfile b/Gemfile index b6a5c6d8..5b7828e0 100644 --- a/Gemfile +++ b/Gemfile @@ -13,6 +13,7 @@ gem 'faraday' gem 'image_processing', '>= 1.2' gem 'jbuilder' gem 'jsbundling-rails' +gem 'money-rails', '~> 1.12' gem 'puma', '~> 6.0' gem 'simple_calendar' gem 'sprockets-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 25e3e9ee..83cf7978 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -167,6 +167,15 @@ GEM mini_magick (4.13.2) mini_mime (1.1.5) minitest (5.24.1) + monetize (1.13.0) + money (~> 6.12) + money (6.19.0) + i18n (>= 0.6.4, <= 2) + money-rails (1.15.0) + activesupport (>= 3.0) + monetize (~> 1.9) + money (~> 6.13) + railties (>= 3.0) msgpack (1.7.2) mutex_m (0.2.0) net-http (0.4.1) @@ -342,6 +351,7 @@ DEPENDENCIES image_processing (>= 1.2) jbuilder jsbundling-rails + money-rails (~> 1.12) puma (~> 6.0) rails (~> 7.1.3.1) rspec-rails diff --git a/app/controllers/fines_controller.rb b/app/controllers/fines_controller.rb index e0e0c3aa..b2bf82dc 100644 --- a/app/controllers/fines_controller.rb +++ b/app/controllers/fines_controller.rb @@ -9,13 +9,10 @@ def new def create @fine = SingleCharge.new(fine_params) - if @fine.valid? - response = post_response - if response.success? - @fine.save - return redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" - end + if @fine.valid? && post_response.success? && @fine.save + return redirect_to @condo, notice: "Multa lançada com sucesso para a #{@fine.unit.print_identifier}" end + flash.now.alert = t('alerts.single_charge.fine_not_created') render 'new', status: :unprocessable_entity end @@ -50,7 +47,7 @@ def find_unit_id end def fine_params - params.require(:single_charge).permit(:value_cents, + params.require(:single_charge).permit(:value, :description).merge({ charge_type: :fine, condo: @condo, unit_id: find_unit_id }) end diff --git a/app/models/single_charge.rb b/app/models/single_charge.rb index 3cc12ece..a374e7f4 100644 --- a/app/models/single_charge.rb +++ b/app/models/single_charge.rb @@ -10,6 +10,8 @@ class SingleCharge < ApplicationRecord enum charge_type: { fine: 0, common_area_fee: 1 } + monetize :value_cents, as: :value, with_model_currency: :currency + def unit_valid? return true if unit.owner diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb index a6fceee5..b5a57c8a 100644 --- a/app/views/fines/new.html.erb +++ b/app/views/fines/new.html.erb @@ -19,19 +19,20 @@ <%= f.collection_select :unit, {}, {}, {}, {}, :'data-fines-target' => "unit", class: 'form-control form-select' %>
+
+
+ <%= f.label :description , class: "form-label"%> + <%= f.text_field :description, class: "form-control" %> +
-
- <%= f.label :description %> - <%= f.text_field :description %> -
- -
- <%= f.label :value_cents %> - <%= f.text_field :value_cents %> -
+
+ <%= f.label :value, class: "form-label" %> + <%= f.text_field :value, value: @fine.value_cents, placeholder: '0,00', step: '0.01', pattern: '\d+(\,\d{2})?', class: "form-control" %> +
-
- <%= f.submit 'Lançar Multa', class:"btn btn-dark rounded-pill px-4 mt-3" %>
+
+ <%= f.submit 'Lançar Multa', class:"btn btn-dark rounded-pill px-4 mt-3" %> +
<% end %>
\ No newline at end of file diff --git a/config/initializers/money.rb b/config/initializers/money.rb new file mode 100644 index 00000000..e088f7d5 --- /dev/null +++ b/config/initializers/money.rb @@ -0,0 +1,116 @@ +# encoding : utf-8 + +MoneyRails.configure do |config| + + # To set the default currency + # + config.default_currency = :brl + Money.locale_backend = :i18n + Money.rounding_mode = BigDecimal::ROUND_HALF_UP + # Set default bank object + # + # Example: + # config.default_bank = EuCentralBank.new + + # Add exchange rates to current money bank object. + # (The conversion rate refers to one direction only) + # + # Example: + # config.add_rate "USD", "CAD", 1.24515 + # config.add_rate "CAD", "USD", 0.803115 + + # To handle the inclusion of validations for monetized fields + # The default value is true + # + # config.include_validations = true + + # Default ActiveRecord migration configuration values for columns: + # + # config.amount_column = { prefix: '', # column name prefix + # postfix: '_cents', # column name postfix + # column_name: nil, # full column name (overrides prefix, postfix and accessor name) + # type: :integer, # column type + # present: true, # column will be created + # null: false, # other options will be treated as column options + # default: 0 + # } + # + # config.currency_column = { prefix: '', + # postfix: '_currency', + # column_name: nil, + # type: :string, + # present: true, + # null: false, + # default: 'USD' + # } + + # Register a custom currency + # + # Example: + # config.register_currency = { + # priority: 1, + # iso_code: "EU4", + # name: "Euro with subunit of 4 digits", + # symbol: "€", + # symbol_first: true, + # subunit: "Subcent", + # subunit_to_unit: 10000, + # thousands_separator: ".", + # decimal_mark: "," + # } + + # Specify a rounding mode + # Any one of: + # + # BigDecimal::ROUND_UP, + # BigDecimal::ROUND_DOWN, + # BigDecimal::ROUND_HALF_UP, + # BigDecimal::ROUND_HALF_DOWN, + # BigDecimal::ROUND_HALF_EVEN, + # BigDecimal::ROUND_CEILING, + # BigDecimal::ROUND_FLOOR + # + # set to BigDecimal::ROUND_HALF_EVEN by default + # + # config.rounding_mode = BigDecimal::ROUND_HALF_UP + + # Set default money format globally. + # Default value is nil meaning "ignore this option". + # Example: + # + # config.default_format = { + # no_cents_if_whole: nil, + # symbol: nil, + # sign_before_symbol: nil + # } + + # If you would like to use I18n localization (formatting depends on the + # locale): + # config.locale_backend = :i18n + # + # Example (using default localization from rails-i18n): + # + # I18n.locale = :en + # Money.new(10_000_00, 'USD').format # => $10,000.00 + # I18n.locale = :es + # Money.new(10_000_00, 'USD').format # => $10.000,00 + # + # For the legacy behaviour of "per currency" localization (formatting depends + # only on currency): + # config.locale_backend = :currency + # + # Example: + # Money.new(10_000_00, 'USD').format # => $10,000.00 + # Money.new(10_000_00, 'EUR').format # => €10.000,00 + # + # In case you don't need localization and would like to use default values + # (can be redefined using config.default_format): + # config.locale_backend = nil + + # Set default raise_error_on_money_parsing option + # It will be raise error if assigned different currency + # The default value is false + # + # Example: + # config.raise_error_on_money_parsing = false +end diff --git a/config/locales/models/single_charge.pt-BR.yml b/config/locales/models/single_charge.pt-BR.yml index 2417196f..6380a429 100644 --- a/config/locales/models/single_charge.pt-BR.yml +++ b/config/locales/models/single_charge.pt-BR.yml @@ -19,5 +19,6 @@ pt-BR: condo_id: 'Condomínio' description: 'Descrição' value_cents: 'Valor' + value: 'Valor' common_area: 'Área Comum' charge_type: 'Tipo' \ No newline at end of file diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb index 136a45f9..f834b8d9 100644 --- a/spec/system/superintendent/superintendent_register_fine_spec.rb +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -13,7 +13,7 @@ single_charge = { single_charge: { description: 'Som alto', - value_cents: 50_000, + value_cents: 50_059, charge_type: :fine, issue_date: Time.zone.today, condo_id: condo.id, @@ -39,7 +39,7 @@ select 'Torre X', from: 'Torre' select '2', from: 'Andar' select '2', from: 'Unidade' - fill_in 'Valor', with: 50_000 + fill_in 'Valor', with: '500,59' fill_in 'Descrição', with: 'Som alto' click_on 'Lançar Multa' end @@ -47,7 +47,7 @@ expect(page).to have_current_path condo_path(condo), wait: 2 expect(page).to have_content 'Multa lançada com sucesso para a Unidade 22' expect(SingleCharge.last.unit).to eq unit22 - expect(SingleCharge.last.value_cents).to eq 50_000 + expect(SingleCharge.last.value_cents).to eq 50_059 end it 'with missing params' do @@ -73,7 +73,7 @@ end expect(page).to have_content 'Não foi possível lançar a multa' - expect(page).to have_content 'Valor não pode ficar em branco' + expect(page).to have_content 'Valor não é um número' expect(page).to have_content 'Descrição não pode ficar em branco' expect(SingleCharge.last).to eq nil end From 89b0dcae1078d1232a3e7ebb93c3af86be3ce397 Mon Sep 17 00:00:00 2001 From: Danilo Date: Sun, 21 Jul 2024 20:45:04 -0300 Subject: [PATCH 6/7] Hot fix corrige mensagem de erro ao lancar multa. Co-authored-by: Lucas Lima --- app/models/single_charge.rb | 2 +- app/views/fines/new.html.erb | 2 +- db/seeds.rb | 4 ++++ .../superintendent/superintendent_register_fine_spec.rb | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/models/single_charge.rb b/app/models/single_charge.rb index a374e7f4..c9d4cee4 100644 --- a/app/models/single_charge.rb +++ b/app/models/single_charge.rb @@ -15,6 +15,6 @@ class SingleCharge < ApplicationRecord def unit_valid? return true if unit.owner - errors.add(:unit, 'Não há proprietário para a unidade selecionada') + errors.add(:unit, 'não possui um proprietário.') end end diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb index 3a5b8c34..a1de24d1 100644 --- a/app/views/fines/new.html.erb +++ b/app/views/fines/new.html.erb @@ -30,7 +30,7 @@
<%= f.label :value, class: "form-label" %> - <%= f.text_field :value, value: @fine.value_cents, placeholder: '0,00', step: '0.01', pattern: '\d+(\,\d{2})?', class: "form-control #{'is-invalid'if @fine.errors[:value].any?}" %> + <%= f.text_field :value, placeholder: '0,00', step: '0.01', pattern: '\d+(\,\d{2})?', class: "form-control #{'is-invalid'if @fine.errors[:value].any?}" %> <%= render("shared/errors", model: @fine, attribute: :value) if @fine.errors[:value].any? %>
diff --git a/db/seeds.rb b/db/seeds.rb index e1aee2d4..295be91e 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -365,6 +365,7 @@ status: :property_registration_pending, full_name: 'Cláudia Rodrigues Gomes', registration_number: '458.456.480-92', + properties: [tower1.floors[0].units[0]], residence: tower1.floors[0].units[0] ) @@ -374,6 +375,7 @@ status: :property_registration_pending, full_name: 'João da Silva', registration_number: '478.040.830-09', + properties: [tower1.floors[1].units[0]], residence: tower1.floors[1].units[0] ) @@ -383,6 +385,7 @@ status: :property_registration_pending, full_name: 'Maria Oliveira', registration_number: '231.887.610-07', + properties: [tower1.floors[2].units[0]], residence: tower1.floors[2].units[0] ) @@ -392,6 +395,7 @@ status: :residence_registration_pending, full_name: 'Pedro Alves', registration_number: '185.894.110-52', + properties: [tower1.floors[3].units[0]], residence: tower1.floors[3].units[0] ) diff --git a/spec/system/superintendent/superintendent_register_fine_spec.rb b/spec/system/superintendent/superintendent_register_fine_spec.rb index f834b8d9..404f324d 100644 --- a/spec/system/superintendent/superintendent_register_fine_spec.rb +++ b/spec/system/superintendent/superintendent_register_fine_spec.rb @@ -102,7 +102,7 @@ end expect(page).to have_content 'Não foi possível lançar a multa' - expect(page).to have_content 'Não há proprietário para a unidade selecionada' + expect(page).to have_content 'Unidade não possui um proprietário.' expect(SingleCharge.last).to eq nil end From 7e17c07376746d2179fde4ea3afca28e6342274e Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Mon, 22 Jul 2024 09:07:25 -0300 Subject: [PATCH 7/7] =?UTF-8?q?Corrige=20estiliza=C3=A7=C3=A3o=20do=20form?= =?UTF-8?q?ul=C3=A1rio=20de=20lan=C3=A7amento=20de=20multas.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danilo Ribeiro --- app/views/fines/new.html.erb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/views/fines/new.html.erb b/app/views/fines/new.html.erb index 4e484c40..8817785d 100644 --- a/app/views/fines/new.html.erb +++ b/app/views/fines/new.html.erb @@ -1,8 +1,8 @@ -
+

Lançar Multa

- <%= form_with model: [@condo, @fine], url:condo_fines_path(@condo, @fine) do |f| %> + <%= form_with model: [@condo, @fine], url: condo_fines_path(@condo, @fine) do |f| %>
-
+
<%= f.label :tower_id %> <%= f.collection_select :tower_id, {}, {}, {}, {}, :'data-fines-target' => "tower", :'data-action' => "change->fines#changeTower", class: "form-control form-select #{'is-invalid' if @fine.errors[:tower_id].any?}" %> @@ -23,8 +23,8 @@
- <%= f.label :description , class: "form-label" %> - <%= f.text_field :description, placeholder: 'Descreva o motivo da multa...', class: "form-control #{'is-invalid' if @fine.errors[:description].any?}" %> + <%= f.label :description, class: "form-label" %> + <%= f.text_field :description, placeholder: 'Descreva o motivo da multa...', class: "form-control #{'is-invalid' if @fine.errors[:description].any?}" %> <%= render("shared/errors", model: @fine, attribute: :description) if @fine.errors[:description].any? %>
@@ -33,10 +33,10 @@ <%= f.text_field :value, placeholder: '0,00', step: '0.01', pattern: '\d+(\,\d{2})?', class: "form-control #{'is-invalid' if @fine.errors[:value].any?}" %> <%= render("shared/errors", model: @fine, attribute: :value) if @fine.errors[:value].any? %>
-
-
- <%= f.submit 'Lançar Multa', class:"btn btn-dark rounded-pill px-4 mt-3" %> -
+
+ <%= f.submit 'Lançar Multa', class: "btn btn-dark rounded-pill px-4 mt-3" %> +
+
<% end %>
\ No newline at end of file