snf_core 0.2.95 → 0.2.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/snf_core/auth_controller.rb +0 -42
  3. data/app/models/snf_core/quotation.rb +41 -0
  4. data/app/models/snf_core/user.rb +18 -19
  5. data/app/models/snf_core/virtual_account.rb +4 -4
  6. data/app/models/snf_core/virtual_account_transaction.rb +10 -10
  7. data/config/routes.rb +0 -3
  8. data/db/migrate/20250310122954_create_snf_core_virtual_accounts.rb +1 -1
  9. data/db/migrate/20250310143604_create_snf_core_item_requests.rb +5 -5
  10. data/db/migrate/20250312043359_create_snf_core_quotations.rb +14 -0
  11. data/lib/snf_core/version.rb +1 -1
  12. data/spec/dummy/db/schema.rb +14 -1
  13. data/spec/dummy/log/development.log +798 -0
  14. data/spec/dummy/log/test.log +16434 -0
  15. data/spec/dummy/tmp/storage/39/fi/39fibqwgi0xq9xbood6b68hlp4af +0 -0
  16. data/spec/dummy/tmp/storage/5m/j8/5mj8ypl6zxx8g3h7vqmu4p2la4pk +0 -0
  17. data/spec/dummy/tmp/storage/7u/5y/7u5ymxnw5e2jbr7037m2eth7qdkl +0 -0
  18. data/spec/dummy/tmp/storage/dw/75/dw75t7gej4irzb3hcqssl8w5vhde +0 -0
  19. data/spec/dummy/tmp/storage/dz/dq/dzdq3gkuy7tdiue1yqmciu86nzfg +0 -0
  20. data/spec/dummy/tmp/storage/iz/eu/izeu0nc2gf1beo8nvl7iblxc46oj +0 -0
  21. data/spec/dummy/tmp/storage/j4/ln/j4lnbjjufbp59yxsdetbqs0cyjia +0 -0
  22. data/spec/dummy/tmp/storage/l8/1u/l81unawd0p9c61x8k6ofq0y227yt +0 -0
  23. data/spec/dummy/tmp/storage/oh/ls/ohlsxs36tio52r2ydrbzez1u0w26 +0 -0
  24. data/spec/dummy/tmp/storage/qq/vt/qqvtf3h8ge74ce67gghth8ivch0g +0 -0
  25. data/spec/dummy/tmp/storage/uy/sl/uyslcroe2rycfyrrb5bhsfodzg5y +0 -0
  26. data/spec/dummy/tmp/storage/v5/c9/v5c9opt3yikmy2gwg4ftmde0vyt5 +0 -0
  27. data/spec/dummy/tmp/storage/za/ov/zaov1yasuhakxa5olzoed94khnf8 +0 -0
  28. data/spec/dummy/tmp/storage/zc/d6/zcd6d4lsb12obz7m7r6240qka8xw +0 -0
  29. data/spec/dummy/tmp/storage/zq/ts/zqtsmjmvozdu6y5i5d1n3kb9q0vw +0 -0
  30. data/spec/examples.txt +196 -189
  31. data/spec/factories/snf_core/quotations.rb +10 -0
  32. data/spec/models/snf_core/item_request_spec.rb +2 -2
  33. data/spec/models/snf_core/quotation_spec.rb +54 -0
  34. data/spec/models/snf_core/user_spec.rb +18 -19
  35. data/spec/models/snf_core/virtual_account_spec.rb +0 -1
  36. data/spec/models/snf_core/virtual_account_transaction_spec.rb +1 -1
  37. data/spec/requests/snf_core/auth_spec.rb +0 -84
  38. metadata +21 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ca8bd2392a69ff49850fa101f216f512c1b9f02ebca883ed26ca979ee4b1849
4
- data.tar.gz: 18480de028a99981ee91e8888d28323ce631abdf25ec99bf1d97d3fffc226790
3
+ metadata.gz: fd314fc21e427da9d504f8db415fff1d4d66e3b3ad00e675778180b596ca9b1d
4
+ data.tar.gz: 8f6c6e6c7d54ca74bb588461dda607b973a6ac07c6b3b609918681d6af753ea6
5
5
  SHA512:
6
- metadata.gz: b1de2c64f43d2fe35478de2f507b9b6ea887c980fb41f72dbddded1db7e7c2e5a4d252a848625dc9a450b826183c372ac8913357f71459407ed999cf5662c71d
7
- data.tar.gz: a1952a64ba5b261f4e97629e4028c6417f2983a84cf8e7de5e60809d8eaa0d794302489bbb63187e8336939fc7f5a4813d8c80e88c0bf20657f801314e96f17a
6
+ metadata.gz: 4397affa157cbadfccad676c739dca187953acb090b1e3d77c93dfe3c729cdf2631c700565b4f6bd38691c1e36a4387261a1dace0786245d6250a8bb6ce36789
7
+ data.tar.gz: 470a2d192ebabec579dd38bbe92daf77935b4761d7968a6247339b24c18cf8c4f96511fbc12910e86d930eec256c1c2402f48f5a18fb01740aa5b47c0216686a
@@ -40,48 +40,6 @@ module SnfCore
40
40
  render json: { success: true, token: token }
41
41
  end
42
42
 
43
- def reset_password_request
44
- user = User.find_by(phone_number: auth_params[:phone_number])
45
- return render json: { success: false, error: "User doesn't exist" }, status: :unauthorized unless user
46
- user.reset_password_token = SecureRandom.hex
47
- user.save!
48
- AuthMailer.with(
49
- user: user,
50
- reset_url: params[:reset_url] || "http://localhost:3000/reset-password"
51
- ).reset_password.deliver_now
52
- render json: { success: true, message: "Reset password token sent to your email" }
53
- end
54
-
55
- def reset_password
56
- user = User.find_by(reset_password_token: auth_params[:reset_password_token])
57
- return render json: { success: false, error: "Token has expired please try again!" }, status: :unauthorized unless user
58
- if user.reset_password_token == auth_params[:reset_password_token]
59
- return render json: { success: false, error: "You can't use the same password as your current password" }, status: :unprocessable_entity if BCrypt::Password.new(user.password_digest) == auth_params[:password]
60
- user.password = auth_params[:password]
61
- user.reset_password_token = nil
62
- user.password_changed = true
63
- user.save!
64
- render json: { success: true, message: "Password reset successfully" }
65
- else
66
- user.reset_password_token = nil
67
- user.save!
68
- render json: { success: false, error: "Reset password token doesn't match try again" }, status: :unprocessable_entity
69
- end
70
- end
71
-
72
- def change_password
73
- user = current_user
74
- if user && user.authenticate(auth_params[:password])
75
- return render json: { success: false, error: "Can't use the same password as your current password" }, status: :unprocessable_entity if BCrypt::Password.new(user.password_digest) == auth_params[:new_password]
76
- user.password = auth_params[:new_password]
77
- user.password_changed = true
78
- user.save!
79
- render json: { success: true, message: "Password changed successfully" }
80
- else
81
- render json: { success: false, error: "Invalid password" }
82
- end
83
- end
84
-
85
43
  private
86
44
 
87
45
  def token_service
@@ -0,0 +1,41 @@
1
+ module SnfCore
2
+ class Quotation < ApplicationRecord
3
+ belongs_to :item_request
4
+
5
+ validates :price, presence: true, numericality: { greater_than: 0 }
6
+ validates :valid_until, presence: true
7
+ validates :delivery_date, presence: true
8
+ validates :status, presence: true
9
+ validate :valid_until_cannot_be_in_past
10
+ validate :delivery_date_cannot_be_in_past
11
+
12
+ before_validation :check_expiration
13
+
14
+ enum :status, {
15
+ pending: 0,
16
+ accepted: 1,
17
+ rejected: 2,
18
+ expired: 3
19
+ }
20
+
21
+ private
22
+
23
+ def check_expiration
24
+ if valid_until.present? && valid_until < DateTime.current && !expired?
25
+ self.status = :expired
26
+ end
27
+ end
28
+
29
+ def valid_until_cannot_be_in_past
30
+ if valid_until.present? && valid_until < DateTime.current && new_record?
31
+ errors.add(:valid_until, "can't be in the past")
32
+ end
33
+ end
34
+
35
+ def delivery_date_cannot_be_in_past
36
+ if delivery_date.present? && delivery_date < Date.current
37
+ errors.add(:delivery_date, "can't be in the past")
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,19 +1,18 @@
1
- module SnfCore
2
- class User < ApplicationRecord
3
- has_secure_password
4
-
5
- belongs_to :verified_by, class_name: 'SnfCore::User', optional: true
6
- belongs_to :address
7
-
8
- has_one :wallet, dependent: :destroy
9
-
10
- validates :first_name, :middle_name, :last_name, :phone_number, :date_of_birth, :nationality, presence: true
11
- validates :phone_number, :email, uniqueness: true
12
-
13
- enum :kyc_status, { pending: 0, approved: 1, rejected: 2 }
14
- enum :gender, { male: 0, female: 1}
15
-
16
- has_one :virtual_account, dependent: :destroy
17
-
18
- end
19
- end
1
+ module SnfCore
2
+ class User < ApplicationRecord
3
+ has_secure_password
4
+
5
+ belongs_to :verified_by, class_name: "SnfCore::User", optional: true
6
+ belongs_to :address
7
+
8
+ has_one :wallet, dependent: :destroy
9
+
10
+ validates :first_name, :middle_name, :last_name, :phone_number, :date_of_birth, :nationality, presence: true
11
+ validates :phone_number, :email, uniqueness: true
12
+
13
+ enum :kyc_status, { pending: 0, approved: 1, rejected: 2 }
14
+ enum :gender, { male: 0, female: 1 }
15
+
16
+ has_one :virtual_account, dependent: :destroy
17
+ end
18
+ end
@@ -9,7 +9,7 @@ module SnfCore
9
9
  custom: 3 # Negotiated rates for specific cases
10
10
  }
11
11
 
12
- validates :account_number, presence: true, uniqueness: {case_sensitive: true}
12
+ validates :account_number, presence: true, uniqueness: { case_sensitive: true }
13
13
  validates :cbs_account_number, presence: true, uniqueness: true
14
14
  validates :balance, presence: true, numericality: { greater_than_or_equal_to: 0 }
15
15
  validates :interest_rate, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1 }
@@ -17,7 +17,7 @@ module SnfCore
17
17
  validates :branch_code, presence: true, length: { is: 3 }
18
18
  validates :product_scheme, presence: true, length: { is: 1 }
19
19
  validates :voucher_type, presence: true, length: { is: 1 }
20
- validates :active, presence:true, inclusion: { in: [true, false] }
20
+ validates :active, presence: true, inclusion: { in: [ true, false ] }
21
21
 
22
22
  before_validation :generate_account_number, on: :create
23
23
  validate :validate_interest_free_rate
@@ -26,7 +26,7 @@ module SnfCore
26
26
 
27
27
  def validate_interest_free_rate
28
28
  if interest_free? && !interest_rate.zero?
29
- errors.add(:interest_rate, 'must be 0 for interest-free accounts')
29
+ errors.add(:interest_rate, "must be 0 for interest-free accounts")
30
30
  end
31
31
  end
32
32
 
@@ -34,7 +34,7 @@ module SnfCore
34
34
  return if account_number.present?
35
35
 
36
36
  last_seq = self.class.maximum(:account_number).to_s[-6..-1].to_i
37
- seq = (last_seq + 1).to_s.rjust(6, '0')
37
+ seq = (last_seq + 1).to_s.rjust(6, "0")
38
38
  self.account_number = "#{branch_code}#{product_scheme}#{voucher_type}#{seq}"
39
39
  end
40
40
  end
@@ -1,7 +1,7 @@
1
1
  module SnfCore
2
2
  class VirtualAccountTransaction < ApplicationRecord
3
- belongs_to :from_account, class_name: 'SnfCore::VirtualAccount', optional: true
4
- belongs_to :to_account, class_name: 'SnfCore::VirtualAccount', optional: true
3
+ belongs_to :from_account, class_name: "SnfCore::VirtualAccount", optional: true
4
+ belongs_to :to_account, class_name: "SnfCore::VirtualAccount", optional: true
5
5
 
6
6
  enum :transaction_type, {
7
7
  transfer: 0,
@@ -30,18 +30,18 @@ module SnfCore
30
30
  return unless from_account
31
31
  return if from_account.balance >= amount
32
32
 
33
- errors.add(:amount, 'Insufficient balance')
33
+ errors.add(:amount, "Insufficient balance")
34
34
  end
35
35
 
36
36
  def validate_accounts
37
37
  case transaction_type.to_s
38
- when 'transfer'
39
- errors.add(:base, 'Transfer requires both from and to accounts') unless from_account && to_account
40
- errors.add(:base, 'Cannot transfer to same account') if from_account == to_account
41
- when 'deposit'
42
- errors.add(:base, 'Deposit requires to_account') unless to_account
43
- when 'withdrawal'
44
- errors.add(:base, 'Withdrawal requires from_account') unless from_account
38
+ when "transfer"
39
+ errors.add(:base, "Transfer requires both from and to accounts") unless from_account && to_account
40
+ errors.add(:base, "Cannot transfer to same account") if from_account == to_account
41
+ when "deposit"
42
+ errors.add(:base, "Deposit requires to_account") unless to_account
43
+ when "withdrawal"
44
+ errors.add(:base, "Withdrawal requires from_account") unless from_account
45
45
  end
46
46
  end
47
47
 
data/config/routes.rb CHANGED
@@ -1,7 +1,4 @@
1
1
  SnfCore::Engine.routes.draw do
2
2
  post "auth/login"
3
- post "auth/reset_password_request"
4
- post "auth/reset_password"
5
- post "auth/change_password"
6
3
  post "auth/signup"
7
4
  end
@@ -16,7 +16,7 @@ class CreateSnfCoreVirtualAccounts < ActiveRecord::Migration[8.0]
16
16
 
17
17
  t.index :account_number, unique: true
18
18
  t.index :cbs_account_number, unique: true
19
- t.index [:branch_code, :product_scheme, :voucher_type]
19
+ t.index [ :branch_code, :product_scheme, :voucher_type ]
20
20
  end
21
21
  end
22
22
  end
@@ -1,12 +1,12 @@
1
1
  class CreateSnfCoreItemRequests < ActiveRecord::Migration[8.0]
2
2
  def change
3
3
  create_table :snf_core_item_requests do |t|
4
- t.references :user, null: false, foreign_key: { to_table: :snf_core_users}
5
- t.references :product, null: false, foreign_key: {to_table: :snf_core_products}
6
- t.integer :quantity, null:false
7
- t.date :requested_delivery_date, null:false
4
+ t.references :user, null: false, foreign_key: { to_table: :snf_core_users }
5
+ t.references :product, null: false, foreign_key: { to_table: :snf_core_products }
6
+ t.integer :quantity, null: false
7
+ t.date :requested_delivery_date, null: false
8
8
  t.text :notes
9
- t.integer :status, null:false, default: 0
9
+ t.integer :status, null: false, default: 0
10
10
 
11
11
  t.timestamps
12
12
  end
@@ -0,0 +1,14 @@
1
+ class CreateSnfCoreQuotations < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :snf_core_quotations do |t|
4
+ t.references :item_request, null: false, foreign_key: {to_table: :snf_core_item_requests}
5
+ t.decimal :price , null: false
6
+ t.date :delivery_date, null: false
7
+ t.datetime :valid_until, null: false
8
+ t.integer :status, null: false, default: 0
9
+ t.text :notes
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module SnfCore
2
- VERSION = "0.2.95"
2
+ VERSION = "0.2.98"
3
3
  end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema[8.0].define(version: 2025_03_11_000000) do
13
+ ActiveRecord::Schema[8.0].define(version: 2025_03_12_043359) do
14
14
  # These are extensions that must be enabled in order to support this database
15
15
  enable_extension "pg_catalog.plpgsql"
16
16
 
@@ -192,6 +192,18 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_11_000000) do
192
192
  t.index ["category_id"], name: "index_snf_core_products_on_category_id"
193
193
  end
194
194
 
195
+ create_table "snf_core_quotations", force: :cascade do |t|
196
+ t.bigint "item_request_id", null: false
197
+ t.decimal "price", null: false
198
+ t.date "delivery_date", null: false
199
+ t.datetime "valid_until", null: false
200
+ t.integer "status", default: 0, null: false
201
+ t.text "notes"
202
+ t.datetime "created_at", null: false
203
+ t.datetime "updated_at", null: false
204
+ t.index ["item_request_id"], name: "index_snf_core_quotations_on_item_request_id"
205
+ end
206
+
195
207
  create_table "snf_core_roles", force: :cascade do |t|
196
208
  t.string "name", null: false
197
209
  t.datetime "created_at", null: false
@@ -317,6 +329,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_11_000000) do
317
329
  add_foreign_key "snf_core_orders", "snf_core_stores", column: "store_id"
318
330
  add_foreign_key "snf_core_orders", "snf_core_users", column: "user_id"
319
331
  add_foreign_key "snf_core_products", "snf_core_categories", column: "category_id"
332
+ add_foreign_key "snf_core_quotations", "snf_core_item_requests", column: "item_request_id"
320
333
  add_foreign_key "snf_core_store_inventories", "snf_core_products", column: "product_id"
321
334
  add_foreign_key "snf_core_store_inventories", "snf_core_stores", column: "store_id"
322
335
  add_foreign_key "snf_core_stores", "snf_core_addresses", column: "address_id"