Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/4/create tradings #12

Merged
merged 9 commits into from
Jan 25, 2023
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
5 changes: 5 additions & 0 deletions app/controllers/tradings_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class TradingsController < ApplicationController
def index
@tradings = current_user.tradings
end
end
5 changes: 5 additions & 0 deletions app/helpers/tradings_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module TradingsHelper
def trading_locale_kind(kind)
I18n.t(kind, scope: 'activerecord.attributes.trading.kind_enum')
end
end
2 changes: 2 additions & 0 deletions app/models/asset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ class Asset < ApplicationRecord
belongs_to :user
belongs_to :stock

has_many :tradings, dependent: :restrict_with_error

validates :stock, :user, :amount, :average_price, :total_invested, presence: true
validates :stock_id, uniqueness: { scope: [:user_id] }

Expand Down
1 change: 1 addition & 0 deletions app/models/stock.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Stock < ApplicationRecord
has_many :assets, dependent: :restrict_with_error
has_many :tradings, dependent: :restrict_with_error

validates :code, presence: true
validates :code, length: { in: 5..6 }
Expand Down
15 changes: 15 additions & 0 deletions app/models/trading.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Trading < ApplicationRecord
belongs_to :user
belongs_to :stock
belongs_to :asset

enum kind: { buy: 0, sale: 1 }

validates :amount, :value_unit, :total_value, :date, :kind, :asset, :stock, :user, presence: true

validates :amount, :value_unit, :total_value, numericality: { greater_than_or_equal_to: 0 }

validate do
errors.add(:date, I18n.t(:after_today, scope: 'errors.messages')) if date && date > Time.zone.today
end
end
1 change: 1 addition & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable

has_many :tradings, dependent: :delete_all
has_many :assets, dependent: :delete_all
has_many :stocks, through: :assets

Expand Down
7 changes: 7 additions & 0 deletions app/views/tradings/_trading.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="card">
<p><strong><%= Trading.human_attribute_name('stock_code') %></strong>: <%= trading.stock.code %></p>
<p><strong><%= Trading.human_attribute_name('amount') %></strong>: <%= trading.amount %></p>
<p><strong><%= Trading.human_attribute_name('value_unit') %></strong>: <%= number_to_currency trading.value_unit %></p>
<p><strong><%= Trading.human_attribute_name('total_value') %></strong>: <%= number_to_currency trading.total_value %></p>
<p><strong><%= Trading.human_attribute_name('kind') %></strong>: <%= trading_locale_kind trading.kind %></p>
</div>
9 changes: 9 additions & 0 deletions app/views/tradings/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<main class="container">
<div class="header">
<h1><%= t(:trading, scope: 'activerecord.models').pluralize %></h1>
</div>

<div class="tradings cards">
<%= render @tradings %>
</div>
</main>
15 changes: 15 additions & 0 deletions config/locales/activerecord/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pt-BR:
models:
asset: 'Ativo'
stock: 'Ação'
trading: 'Movimentações'
user: 'Usuário'
attributes:
stock:
Expand All @@ -15,6 +16,20 @@ pt-BR:
user: 'Usuário'
stock: 'Ação'
stock_code: 'Código'
trading:
amount: 'Quant.'
date: 'Data'
kind: 'C / V'
total_value: 'Valor total'
value_unit: 'Valor unit.'
asset: 'Ativo'
stock: 'Ação'
stock_code: 'Código'
user: 'Usuário'
kind_enum:
buy: 'Compra'
sale: 'Venda'

errors:
messages:
record_invalid: 'A validação falhou: %{errors}'
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ en:

routes:
assets: 'my-assets'
tradings: 'tradings'
88 changes: 50 additions & 38 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pt-BR:

routes:
assets: 'ativos'
tradings: 'movimentacoes'
users: 'users'

helpers:
Expand Down Expand Up @@ -73,42 +74,53 @@ pt-BR:
format:
delimiter:

date:
formats:
default: "%d/%m/%Y"
long: "%d de %B de %Y"
short: "%d de %B"
order:
- :day
- :month
- :year

errors:
format: '%{attribute} %{message}'
messages:
accepted: 'deve ser aceito'
access_denied: 'Acesso Negado'
blank: 'não pode ficar em branco'
confirmation: 'não é igual a %{attribute}'
empty: 'não pode ficar vazio'
equal_to: 'deve ser igual a %{count}'
even: 'deve ser par'
exclusion: 'não está disponível'
greater_than: 'deve ser maior que %{count}'
greater_than_or_equal_to: 'deve ser maior ou igual a %{count}'
inclusion: 'não está incluído na lista'
invalid: 'não é válido'
less_than: 'deve ser menor que %{count}'
less_than_or_equal_to: 'deve ser menor ou igual a %{count}'
model_invalid: 'A validação falhou: %{errors}'
not_a_number: 'não é um número'
not_an_integer: 'não é um número inteiro'
odd: 'deve ser ímpar'
other_than: 'deve ser diferente de %{count}'
present: 'deve ficar em branco'
required: 'é obrigatório(a)'
taken: 'já está em uso'
too_long:
one: 'é muito longo (máximo: 1 caracter)'
other: 'é muito longo (máximo: %{count} caracteres)'
too_short:
one: 'é muito curto (mínimo: 1 caracter)'
other: 'é muito curto (mínimo: %{count} caracteres)'
wrong_length:
one: 'não possui o tamanho esperado (1 caracter)'
other: 'não possui o tamanho esperado (%{count} caracteres)'
template:
body: 'Por favor, verifique o(s) seguinte(s) campo(s):'
header:
one: 'Não foi possível gravar %{model}: 1 erro'
other: 'Não foi possível gravar %{model}: %{count} erros'
format: '%{attribute} %{message}'
messages:
accepted: 'deve ser aceito'
access_denied: 'Acesso Negado'
after_today: 'não pode ser do futuro'
blank: 'não pode ficar em branco'
confirmation: 'não é igual a %{attribute}'
empty: 'não pode ficar vazio'
equal_to: 'deve ser igual a %{count}'
even: 'deve ser par'
exclusion: 'não está disponível'
greater_than: 'deve ser maior que %{count}'
greater_than_or_equal_to: 'deve ser maior ou igual a %{count}'
inclusion: 'não está incluído na lista'
invalid: 'não é válido'
less_than: 'deve ser menor que %{count}'
less_than_or_equal_to: 'deve ser menor ou igual a %{count}'
model_invalid: 'A validação falhou: %{errors}'
not_a_number: 'não é um número'
not_an_integer: 'não é um número inteiro'
odd: 'deve ser ímpar'
other_than: 'deve ser diferente de %{count}'
present: 'deve ficar em branco'
required: 'é obrigatório(a)'
taken: 'já está em uso'
too_long:
one: 'é muito longo (máximo: 1 caracter)'
other: 'é muito longo (máximo: %{count} caracteres)'
too_short:
one: 'é muito curto (mínimo: 1 caracter)'
other: 'é muito curto (mínimo: %{count} caracteres)'
wrong_length:
one: 'não possui o tamanho esperado (1 caracter)'
other: 'não possui o tamanho esperado (%{count} caracteres)'
template:
body: 'Por favor, verifique o(s) seguinte(s) campo(s):'
header:
one: 'Não foi possível gravar %{model}: 1 erro'
other: 'Não foi possível gravar %{model}: %{count} erros'
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
devise_for :users

resources :assets, only: :index, path: I18n.t('routes.assets')
resources :tradings, only: :index, path: I18n.t('routes.tradings')
end
16 changes: 16 additions & 0 deletions db/migrate/20230125120827_create_tradings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class CreateTradings < ActiveRecord::Migration[7.0]
def change
create_table :tradings, id: :uuid do |t|
t.integer :amount, default: 0
t.float :value_unit, default: 0
t.float :total_value, default: 0
t.integer :kind, default: 0
t.date :date
t.references :user, null: false, foreign_key: true, type: :uuid
t.references :stock, null: false, foreign_key: true, type: :uuid
t.references :asset, null: false, foreign_key: true, type: :uuid

t.timestamps
end
end
end
21 changes: 20 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions db/seeds.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }])
# Character.create(name: "Luke", movie: movies.first)
user = User.create(email: '[email protected]', password: '123456', password_confirmation: '123456')

stock = Stock.create(code: 'PETR4')

asset = Asset.create(amount: 10, total_invested: 20, average_price: 2, user:, stock:)

Trading.create(amount: 10, total_value: 20, value_unit: 2, date: Date.yesterday, user:, stock:, asset:)
12 changes: 12 additions & 0 deletions spec/factories/tradings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FactoryBot.define do
factory :trading do
amount { 2 }
value_unit { 2.5 }
total_value { 2.5 }
kind { :buy }
date { Date.yesterday }
asset { create(:asset) }
stock { create(:stock) }
user { create(:user) }
end
end
8 changes: 8 additions & 0 deletions spec/helpers/tradings_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'rails_helper'

RSpec.describe TradingsHelper, type: :helper do
context '.trading_locale_kind' do
it { expect(helper.trading_locale_kind('buy')).to eq('Compra') }
it { expect(helper.trading_locale_kind('sale')).to eq('Venda') }
end
end
29 changes: 29 additions & 0 deletions spec/models/trading_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'rails_helper'

RSpec.describe Trading, type: :model do
describe 'validates' do
context 'presence' do
it { should validate_presence_of(:value_unit) }
it { should validate_presence_of(:total_value) }
it { should validate_presence_of(:amount) }
it { should validate_presence_of(:user) }
it { should validate_presence_of(:asset) }
it { should validate_presence_of(:stock) }
end

context 'validate numericality' do
it { should validate_numericality_of(:value_unit).is_greater_than_or_equal_to(0) }
it { should validate_numericality_of(:amount).is_greater_than_or_equal_to(0) }
it { should validate_numericality_of(:total_value).is_greater_than_or_equal_to(0) }
end

context 'date after today' do
it 'should return error date after today' do
trading = build(:trading, date: Date.tomorrow)

expect(trading.valid?).to be_falsey
expect(trading.errors.full_messages).to eq(['Data não pode ser do futuro'])
end
end
end
end
26 changes: 26 additions & 0 deletions spec/requests/tradings_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'rails_helper'

RSpec.describe 'Tradings', type: :request do
describe 'GET /index' do
context 'when user is logged' do
before :each do
user = create(:user)
create_list(:trading, 3, user:)

sign_in(user)
end

it 'returns http success' do
get tradings_path
expect(response).to have_http_status(:success)
end
end

context 'when not logged' do
it 'returns http success' do
get tradings_path
expect(response).to have_http_status(:redirect)
end
end
end
end