diff --git a/Gemfile b/Gemfile
index b6586e5f..792f8db3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -83,6 +83,9 @@ group :development do
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-rbenv'
gem 'capistrano-passenger'
+
+ # Solves readline lib errors on OSX
+ gem 'rb-readline'
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index 5e888ef3..e9a89083 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -238,6 +238,7 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
+ rb-readline (0.5.5)
rbtree3 (0.5.0)
rdoc (4.3.0)
react-rails (1.10.0)
@@ -374,6 +375,7 @@ DEPENDENCIES
purecss-rails
rails (= 5.2.3)
rails-controller-testing
+ rb-readline
react-rails (~> 1.10.0)
rolify
rpush (~> 4.1)
diff --git a/app/assets/images/zeuswpi.svg b/app/assets/images/zeuswpi.svg
new file mode 100644
index 00000000..bf5a07db
--- /dev/null
+++ b/app/assets/images/zeuswpi.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 3e791941..0813471f 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -35,3 +35,7 @@ $(document).on('turbolinks:load', function() {
});
})
});
+
+$(function () {
+ $('[data-toggle="tooltip"]').tooltip()
+})
diff --git a/app/controllers/admin/bank_transfer_requests_controller.rb b/app/controllers/admin/bank_transfer_requests_controller.rb
new file mode 100644
index 00000000..40dc4816
--- /dev/null
+++ b/app/controllers/admin/bank_transfer_requests_controller.rb
@@ -0,0 +1,33 @@
+class Admin::BankTransferRequestsController < AdminController
+ before_action :load_bank_transfer_request, only: [:approve, :decline]
+ authorize_resource :bank_transfer_request, id_param: :bank_transfer_request_id, only: [:approve, :decline]
+
+ def index
+ @bank_transfer_requests = BankTransferRequest.all
+ end
+
+ def approve
+ if @bank_transfer_request.approvable?
+ @bank_transfer_request.approve!
+ else
+ flash[:warning] = "This bank transfer request is not approvable."
+ end
+
+ redirect_to action: :index
+ end
+
+ def decline
+ if @bank_transfer_request.declinable?
+ @bank_transfer_request.decline!(params[:reason])
+ else
+ flash[:warning] = "This bank transfer request is not declinable."
+ end
+ redirect_to action: :index
+ end
+
+ private
+
+ def load_bank_transfer_request
+ @bank_transfer_request = BankTransferRequest.find params[:bank_transfer_request_id]
+ end
+end
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
new file mode 100644
index 00000000..e7d10aa0
--- /dev/null
+++ b/app/controllers/admin_controller.rb
@@ -0,0 +1,9 @@
+class AdminController < ApplicationController
+ before_action :require_admin
+
+ def require_admin
+ unless current_user.penning?
+ redirect_to root_path
+ end
+ end
+end
diff --git a/app/controllers/bank_transfer_requests_controller.rb b/app/controllers/bank_transfer_requests_controller.rb
new file mode 100644
index 00000000..533f2147
--- /dev/null
+++ b/app/controllers/bank_transfer_requests_controller.rb
@@ -0,0 +1,48 @@
+class BankTransferRequestsController < ApplicationController
+ load_and_authorize_resource :user, find_by: :name
+
+ before_action :load_bank_transfer_request, only: [:cancel]
+ authorize_resource :bank_transfer_request, id_param: :bank_transfer_request_id, only: [:cancel]
+
+ def index
+ @bank_transfer_requests = @user.bank_transfer_requests
+ @bank_transfer_request = BankTransferRequest.new
+ end
+
+ def create
+ @bank_transfer_request = BankTransferRequest.new(
+ create_params.merge(user: @user)
+ )
+ @bank_transfer_request.set_payment_code
+
+ if @bank_transfer_request.save
+ flash[:success] = "Bank transfer request ##{@bank_transfer_request.id} with payment code #{@bank_transfer_request.payment_code} created. Use this payment code in the description field of your bank transaction.".html_safe
+ Notification.create user: User.zeus, message: "#{@bank_transfer_request.user.name} just created a bank transfer request ##{@bank_transfer_request.id} for €#{@bank_transfer_request.amount} with payment code #{@bank_transfer_request.payment_code}."
+
+ @bank_transfer_request = BankTransferRequest.new
+ end
+
+ @bank_transfer_requests = @user.bank_transfer_requests
+ render :index
+ end
+
+ def cancel
+ if @bank_transfer_request.cancellable?
+ @bank_transfer_request.cancel!
+ else
+ flash[:warning] = "This bank transfer request is not cancellable."
+ end
+
+ redirect_to action: :index
+ end
+
+ private
+
+ def load_bank_transfer_request
+ @bank_transfer_request = BankTransferRequest.find params[:bank_transfer_request_id]
+ end
+
+ def create_params
+ params.require(:bank_transfer_request).permit(:amount)
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index c9cdb016..dc1f724b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -10,4 +10,8 @@ def euro_from_cents(f)
nil
end
end
+
+ def form_errors(object)
+ render partial: 'form_errors', locals: { object: object }
+ end
end
diff --git a/app/models/android_device_registration_token.rb b/app/models/android_device_registration_token.rb
index 13d34eaf..3d466f9c 100644
--- a/app/models/android_device_registration_token.rb
+++ b/app/models/android_device_registration_token.rb
@@ -1,3 +1,14 @@
-class AndroidDeviceRegistrationToken < ActiveRecord::Base
+# == Schema Information
+#
+# Table name: android_device_registration_tokens
+#
+# id :integer not null, primary key
+# token :string
+# user_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class AndroidDeviceRegistrationToken < ApplicationRecord
belongs_to :user
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 00000000..10a4cba8
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
diff --git a/app/models/bank_transfer_request.rb b/app/models/bank_transfer_request.rb
new file mode 100644
index 00000000..6036a34d
--- /dev/null
+++ b/app/models/bank_transfer_request.rb
@@ -0,0 +1,124 @@
+# == Schema Information
+#
+# Table name: bank_transfer_requests
+#
+# id :integer not null, primary key
+# user_id :integer
+# amount_in_cents :integer not null
+# status :string default("pending"), not null
+# decline_reason :string
+# payment_code :string not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class BankTransferRequest < ApplicationRecord
+ belongs_to :user, required: true
+
+ enum status: {
+ pending: "pending",
+ approved: "approved",
+ declined: "declined",
+ cancelled: "cancelled"
+ }
+
+ validates :amount_in_cents, presence: true, numericality: { only_integer: true, greater_than: 0 }
+ validates :payment_code, presence: true, uniqueness: true
+
+ PAYMENT_CODE_PREFIX = "TAB"
+
+ def set_payment_code
+ self.payment_code = self.class.generate_payment_code
+ end
+
+ def amount
+ from_cents read_attribute(:amount_in_cents)
+ end
+
+ def amount=(value)
+ write_attribute(:amount_in_cents, to_cents(value))
+ end
+
+ def approve!
+ if self.declined?
+ message = "Declined bank transfer request ##{self.id} with code #{self.payment_code} has been reversed and is now accepted."
+ else
+ message = "Bank transfer request ##{self.id} with code #{self.payment_code} has been approved."
+ end
+ Transaction.create!(
+ debtor: User.zeus,
+ creditor: self.user,
+ issuer: User.zeus,
+ amount: self.amount_in_cents,
+ message: message
+ )
+ Notification.create user: self.user, message: message
+
+ self.approved!
+ end
+
+ def decline!(reason=nil)
+ self.decline_reason = reason
+ if self.approved?
+ # Transaction needs to be reversed
+ message = "Approved bank transfer request ##{self.id} with code #{self.payment_code} has been reversed and is now declined."
+
+ Transaction.create!(
+ debtor: self.user,
+ creditor: User.zeus,
+ issuer: User.zeus,
+ amount: self.amount_in_cents,
+ message: message
+ )
+ else
+ message = "Bank transfer request ##{self.id} with code #{self.payment_code} has been declined."
+ end
+
+ Notification.create user: self.user, message: message
+
+ self.declined!
+ end
+
+ def cancel!
+ self.cancelled!
+ end
+
+ def approvable?
+ self.pending? || self.declined?
+ end
+
+ def declinable?
+ self.pending? || self.approved?
+ end
+
+ def cancellable?
+ self.pending?
+ end
+
+
+ def self.generate_payment_code
+ random = rand(10**15)
+ return sprintf("#{PAYMENT_CODE_PREFIX}%02d%015d", random % 97, random)
+ end
+
+ def self.find_payment_code_from_csv(csvline)
+ match = /#{PAYMENT_CODE_PREFIX}\d+/.match(csvline)
+ if match
+ return self.find_by_payment_code(match[0])
+ else
+ return false
+ end
+ end
+
+ private
+
+ def from_cents(value)
+ (value || 0) / 100.0
+ end
+
+ def to_cents(value)
+ if value.is_a? String then value.sub!(',', '.') end
+ (value.to_f * 100).to_int
+ end
+
+end
diff --git a/app/models/client.rb b/app/models/client.rb
index c3f47629..0cc84e06 100644
--- a/app/models/client.rb
+++ b/app/models/client.rb
@@ -9,7 +9,7 @@
# updated_at :datetime not null
#
-class Client < ActiveRecord::Base
+class Client < ApplicationRecord
rolify
has_many :issued_transactions, as: :issuer, class_name: 'Transaction'
before_create :generate_key
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 3ceeab25..43cf77c2 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -10,7 +10,7 @@
# updated_at :datetime not null
#
-class Notification < ActiveRecord::Base
+class Notification < ApplicationRecord
belongs_to :user
after_save :send_gcm_notification
diff --git a/app/models/request.rb b/app/models/request.rb
index 1988cb7b..72593a87 100644
--- a/app/models/request.rb
+++ b/app/models/request.rb
@@ -5,16 +5,16 @@
# id :integer not null, primary key
# debtor_id :integer not null
# creditor_id :integer not null
-# issuer_id :integer not null
# issuer_type :string not null
+# issuer_id :integer not null
# amount :integer default(0), not null
# message :string
-# status :integer default(0)
+# status :integer default("open")
# created_at :datetime not null
# updated_at :datetime not null
#
-class Request < ActiveRecord::Base
+class Request < ApplicationRecord
include BaseTransaction
enum status: [:open, :confirmed, :declined, :cancelled]
diff --git a/app/models/role.rb b/app/models/role.rb
index 7440b967..50e5323d 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -1,4 +1,16 @@
-class Role < ActiveRecord::Base
+# == Schema Information
+#
+# Table name: roles
+#
+# id :integer not null, primary key
+# name :string
+# resource_type :string
+# resource_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class Role < ApplicationRecord
has_and_belongs_to_many :clients, join_table: :clients_roles
belongs_to :resource,
diff --git a/app/models/transaction.rb b/app/models/transaction.rb
index 42c2037f..d4fc3dca 100644
--- a/app/models/transaction.rb
+++ b/app/models/transaction.rb
@@ -14,7 +14,7 @@
# id_at_client :integer
#
-class Transaction < ActiveRecord::Base
+class Transaction < ApplicationRecord
include BaseTransaction
include TransactionHelpers
diff --git a/app/models/user.rb b/app/models/user.rb
index fe991077..d4af5e7a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -8,9 +8,10 @@
# penning :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
+# key :string
#
-class User < ActiveRecord::Base
+class User < ApplicationRecord
include FriendlyId
friendly_id :name, use: :finders
devise :timeoutable, :omniauthable, :omniauth_providers => [:zeuswpi]
@@ -27,6 +28,8 @@ class User < ActiveRecord::Base
has_many :issued_transactions, as: :issuer, class_name: 'Transaction'
+ has_many :bank_transfer_requests
+
validates :name, presence: true, uniqueness: true
scope :humans, -> { where.not(id: self.zeus) }
diff --git a/app/models/user_ability.rb b/app/models/user_ability.rb
index ee830d72..77ccd19e 100644
--- a/app/models/user_ability.rb
+++ b/app/models/user_ability.rb
@@ -13,5 +13,7 @@ def initialize(user)
can :create, Transaction do |t|
t.debtor == user && t.amount <= Rails.application.config.maximum_amount
end
+ can :create, BankTransferRequest, user_id: user.id
+ can :cancel, BankTransferRequest, user_id: user.id
end
end
diff --git a/app/views/admin/bank_transfer_requests/index.html.haml b/app/views/admin/bank_transfer_requests/index.html.haml
new file mode 100644
index 00000000..ef38e140
--- /dev/null
+++ b/app/views/admin/bank_transfer_requests/index.html.haml
@@ -0,0 +1,36 @@
+%h4 Bank transfer requests
+%table.pure-table.pure-table-striped
+ %thead
+ %tr
+ %th ID
+ %th User
+ %th Amount
+ %th Payment code
+ %th Status
+ %th Actions
+ %tbody
+ - (@bank_transfer_requests || []).each do |r|
+ %tr
+ %td= r.id
+ %td= r.user.name
+ %td= euro r.amount
+ %td= r.payment_code
+ %td
+ = r.status.capitalize
+ - if r.declined?
+ %span.glyphicon.glyphicon-question-sign{"data-toggle" => "tooltip", "data-placement": 'top', title: r.decline_reason }
+ %td
+ - if r.approvable?
+ = link_to admin_bank_transfer_request_approve_path(r), method: :post, class: "btn btn-success btn-sm" do
+ %i.glyphicon.glyphicon-ok
+ Accept
+ - if r.pending?
+
+ - if r.declinable?
+ = form_with url: admin_bank_transfer_request_decline_path(r), html: { style: "display: inline; float: right" } do |f|
+ %span.input-group.input-group-sm
+ = f.text_field :reason, class: "form-control", placeholder: "Reason"
+ %span.input-group-btn
+ = f.button class: "btn btn-danger" do
+ %i.glyphicon.glyphicon-remove
+ Decline
diff --git a/app/views/application/_form_errors.html.haml b/app/views/application/_form_errors.html.haml
new file mode 100644
index 00000000..75415611
--- /dev/null
+++ b/app/views/application/_form_errors.html.haml
@@ -0,0 +1,14 @@
+- if object.errors.any?
+ - errors = object.errors.empty? ? flash_alerts : object.errors.full_messages
+ - messages = errors.map { |msg| content_tag(:li, msg) }.join
+ - sentence = I18n.t('errors.messages.not_saved',
+ count: object.errors.count,
+ resource: object.class.model_name.human.downcase)
+ .alert.alert-danger.alert-dismissable
+ %button.close{type: 'button', "data-dismiss" => "alert"}
+ ×
+ %strong
+ Error!
+ = sentence.html_safe
+ = messages.html_safe
+
diff --git a/app/views/application/_menu.html.haml b/app/views/application/_menu.html.haml
index e558cc13..40467e9b 100644
--- a/app/views/application/_menu.html.haml
+++ b/app/views/application/_menu.html.haml
@@ -6,16 +6,26 @@
= link_to user_requests_path(current_user), class: 'menu-item' do
Requests
%span.badge= current_user.incoming_requests.open.size
+ = link_to user_bank_transfer_requests_path(current_user), class: 'menu-item' do
+ Bank requests
+ %span.badge= current_user.bank_transfer_requests.pending.size
= link_to user_notifications_path(current_user), class: 'menu-item' do
Notifications
%span.badge= current_user.notifications.unread.size
- if current_user.penning
- = link_to 'Zeus', User.zeus, class: 'menu-item'
+ = link_to User.zeus, class: 'menu-item' do
+ = image_tag "zeuswpi.svg", height: 35
= link_to user_requests_path(User.zeus), class: 'menu-item' do
- Zeus Requests
+ = image_tag "zeuswpi.svg", height: 15
+ Requests
%span.badge= User.zeus.incoming_requests.size
+ = link_to admin_bank_transfer_requests_path, class: 'menu-item' do
+ = image_tag "zeuswpi.svg", height: 15
+ Bank Requests
+ %span.badge= BankTransferRequest.pending.size
= link_to user_notifications_path(User.zeus), class: 'menu-item' do
- Zeus Notifications
+ = image_tag "zeuswpi.svg", height: 15
+ Notifications
%span.badge= User.zeus.notifications.size
.menu-list.menu-right
%span.menu-item= euro_from_cents current_user.balance
diff --git a/app/views/bank_transfer_requests/index.html.haml b/app/views/bank_transfer_requests/index.html.haml
new file mode 100644
index 00000000..d43cac21
--- /dev/null
+++ b/app/views/bank_transfer_requests/index.html.haml
@@ -0,0 +1,37 @@
+%h3 Bank transfer requests
+
+%h4 Request a transfer code
+= form_with model: @bank_transfer_request, url: user_bank_transfer_requests_path(@user), html: { class: "pure-form form-inline" } do |f|
+ = form_errors(@bank_transfer_request)
+ .input-group
+ %span.input-group-addon
+ %span.glyphicon.glyphicon-euro
+ = f.number_field :amount, value: @bank_transfer_request.amount,
+ placeholder: "Amount", step: 0.01,
+ class: "form-control", size: 20, required: true
+ = f.submit "Request it!", class: "pure-button pure-button-primary btn"
+
+%h4 Overview
+%table.pure-table
+ %thead
+ %tr
+ %th ID
+ %th Amount
+ %th Payment code
+ %th Status
+ %th Actions
+ %tbody
+ - (@bank_transfer_requests || []).each do |r|
+ %tr
+ %td= r.id
+ %td= euro(r.amount)
+ %td= r.payment_code
+ %td
+ = r.status.capitalize
+ - if r.declined?
+ %span.glyphicon.glyphicon-question-sign{"data-toggle" => "tooltip", "data-placement": 'top', title: r.decline_reason }
+ %td
+ - if r.cancellable?
+ = link_to user_bank_transfer_request_cancel_path(@user, r), method: :post, class: "btn btn-warning btn-sm" do
+ %i.glyphicon.glyphicon-trash
+ Cancel
diff --git a/config/application.rb b/config/application.rb
index 29802563..69d8cc7a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -2,6 +2,7 @@
require 'rails/all'
+
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
@@ -9,13 +10,13 @@
module Tab
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
- # config.load_defaults 5.0
+ # config.load_defaults 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
-
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'Brussels'
diff --git a/config/routes.rb b/config/routes.rb
index 348cf957..6de8563d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -26,6 +26,16 @@
resources :transactions, only: [:index], shallow: true
post :reset_key, on: :member
post :add_registration_token, on: :member
+ resources :bank_transfer_requests, only: [:index, :create] do
+ post :cancel
+ end
+ end
+
+ namespace :admin do
+ resources :bank_transfer_requests, only: [:index] do
+ post :approve
+ post :decline
+ end
end
get 'datatables/:id' => 'datatables#transactions_for_user', as: "user_transactions_datatable"
diff --git a/db/migrate/20191007235439_create_bank_transfer_requests.rb b/db/migrate/20191007235439_create_bank_transfer_requests.rb
new file mode 100644
index 00000000..2f0b33d9
--- /dev/null
+++ b/db/migrate/20191007235439_create_bank_transfer_requests.rb
@@ -0,0 +1,13 @@
+class CreateBankTransferRequests < ActiveRecord::Migration[5.2]
+ def change
+ create_table :bank_transfer_requests do |t|
+ t.references :user, foreign_key: true
+ t.integer :amount_in_cents, null: false
+ t.string :status, null: false, default: "pending"
+ t.string :decline_reason
+ t.string :payment_code, null: false, unique: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 6d25c8a9..95c52e9a 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.define(version: 2019_05_08_204816) do
+ActiveRecord::Schema.define(version: 2019_10_07_235439) do
create_table "android_device_registration_tokens", force: :cascade do |t|
t.string "token"
@@ -20,6 +20,17 @@
t.index ["user_id"], name: "index_android_device_registration_tokens_on_user_id"
end
+ create_table "bank_transfer_requests", force: :cascade do |t|
+ t.integer "user_id"
+ t.integer "amount_in_cents", null: false
+ t.string "status", default: "pending", null: false
+ t.string "decline_reason"
+ t.string "payment_code", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["user_id"], name: "index_bank_transfer_requests_on_user_id"
+ end
+
create_table "clients", force: :cascade do |t|
t.string "name", null: false
t.string "key", null: false
diff --git a/spec/factories/android_device_registration_tokens.rb b/spec/factories/android_device_registration_tokens.rb
index ae468c81..7d167bb7 100644
--- a/spec/factories/android_device_registration_tokens.rb
+++ b/spec/factories/android_device_registration_tokens.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: android_device_registration_tokens
+#
+# id :integer not null, primary key
+# token :string
+# user_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
FactoryBot.define do
factory :android_device_registration_token do
token { Faker::Lorem.word }
diff --git a/spec/factories/bank_transfer_requests.rb b/spec/factories/bank_transfer_requests.rb
new file mode 100644
index 00000000..7dd6eaac
--- /dev/null
+++ b/spec/factories/bank_transfer_requests.rb
@@ -0,0 +1,22 @@
+# == Schema Information
+#
+# Table name: bank_transfer_requests
+#
+# id :integer not null, primary key
+# user_id :integer
+# amount_in_cents :integer not null
+# status :string default("pending"), not null
+# decline_reason :string
+# payment_code :string not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+FactoryBot.define do
+ factory :bank_transfer_request do
+ user { nil }
+ amount { 1 }
+ status { "" }
+ decline_reason { "MyString" }
+ end
+end
diff --git a/spec/factories/requests.rb b/spec/factories/requests.rb
index 4048d9df..e8321400 100644
--- a/spec/factories/requests.rb
+++ b/spec/factories/requests.rb
@@ -5,11 +5,11 @@
# id :integer not null, primary key
# debtor_id :integer not null
# creditor_id :integer not null
-# issuer_id :integer not null
# issuer_type :string not null
+# issuer_id :integer not null
# amount :integer default(0), not null
# message :string
-# status :integer default(0)
+# status :integer default("open")
# created_at :datetime not null
# updated_at :datetime not null
#
diff --git a/spec/factories/roles.rb b/spec/factories/roles.rb
index b2069181..9092aaaf 100644
--- a/spec/factories/roles.rb
+++ b/spec/factories/roles.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: roles
+#
+# id :integer not null, primary key
+# name :string
+# resource_type :string
+# resource_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
FactoryBot.define do
factory :role do
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index d18342e2..ad85c620 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -8,6 +8,7 @@
# penning :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
+# key :string
#
FactoryBot.define do
diff --git a/spec/models/android_device_registration_token_spec.rb b/spec/models/android_device_registration_token_spec.rb
index 770cacfa..19a44317 100644
--- a/spec/models/android_device_registration_token_spec.rb
+++ b/spec/models/android_device_registration_token_spec.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: android_device_registration_tokens
+#
+# id :integer not null, primary key
+# token :string
+# user_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
require 'rails_helper'
RSpec.describe AndroidDeviceRegistrationToken, type: :model do
diff --git a/spec/models/bank_transfer_request_spec.rb b/spec/models/bank_transfer_request_spec.rb
new file mode 100644
index 00000000..b03385d9
--- /dev/null
+++ b/spec/models/bank_transfer_request_spec.rb
@@ -0,0 +1,19 @@
+# == Schema Information
+#
+# Table name: bank_transfer_requests
+#
+# id :integer not null, primary key
+# user_id :integer
+# amount_in_cents :integer not null
+# status :string default("pending"), not null
+# decline_reason :string
+# payment_code :string not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+require 'rails_helper'
+
+RSpec.describe BankTransferRequest, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/request_spec.rb b/spec/models/request_spec.rb
index 1aab9ee1..f7be087c 100644
--- a/spec/models/request_spec.rb
+++ b/spec/models/request_spec.rb
@@ -5,11 +5,11 @@
# id :integer not null, primary key
# debtor_id :integer not null
# creditor_id :integer not null
-# issuer_id :integer not null
# issuer_type :string not null
+# issuer_id :integer not null
# amount :integer default(0), not null
# message :string
-# status :integer default(0)
+# status :integer default("open")
# created_at :datetime not null
# updated_at :datetime not null
#
diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb
index 41d40605..8879ccf6 100644
--- a/spec/models/role_spec.rb
+++ b/spec/models/role_spec.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: roles
+#
+# id :integer not null, primary key
+# name :string
+# resource_type :string
+# resource_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
require 'rails_helper'
RSpec.describe Role, type: :model do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index e188fc15..c778c41e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -8,6 +8,7 @@
# penning :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
+# key :string
#
describe User, type: :model do