snf_core 0.3.5 → 0.3.7

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/snf_core/auth_controller.rb +18 -4
  3. data/app/models/snf_core/user.rb +2 -2
  4. data/app/models/snf_core/virtual_account.rb +0 -1
  5. data/config/routes.rb +1 -1
  6. data/db/migrate/20250313103149_update_password_changed_default_to_true.rb +6 -0
  7. data/lib/snf_core/version.rb +1 -1
  8. data/spec/dummy/db/schema.rb +3 -2
  9. data/spec/dummy/log/development.log +272 -0
  10. data/spec/dummy/log/test.log +22146 -0
  11. data/spec/dummy/tmp/storage/1x/b3/1xb3eynux1c60fek1qhc2nvp1pqp +0 -0
  12. data/spec/dummy/tmp/storage/3e/c1/3ec10l44sr1t2nptye9ayc3ghqct +0 -0
  13. data/spec/dummy/tmp/storage/45/yw/45ywj4zlnzf7xbzqqgetpqgfvelo +0 -0
  14. data/spec/dummy/tmp/storage/51/7m/517mx6cnxxarv8xn2e01m1jify0e +0 -0
  15. data/spec/dummy/tmp/storage/7t/23/7t23ey0ydqoi3vvknk65qar4vx3g +0 -0
  16. data/spec/dummy/tmp/storage/ap/xq/apxqtkgu8fer3br2c18jxt7vutnh +0 -0
  17. data/spec/dummy/tmp/storage/b9/k7/b9k78cse446bw87afsu7le780d5a +0 -0
  18. data/spec/dummy/tmp/storage/cy/k0/cyk0yrltd4ks0dc8hrszbewlq4c7 +0 -0
  19. data/spec/dummy/tmp/storage/e9/gz/e9gzn6o116l2c1f9hdouj5v0vlya +0 -0
  20. data/spec/dummy/tmp/storage/ev/rr/evrrtvk7ccv3ilfm4ucup7l4m72p +0 -0
  21. data/spec/dummy/tmp/storage/if/vw/ifvwj0dh8zlakag28t1y17fa88yd +0 -0
  22. data/spec/dummy/tmp/storage/jj/04/jj04m0xpisku4b7q7js1uyve7xdw +0 -0
  23. data/spec/dummy/tmp/storage/jv/ei/jveir920ptm7hq7zysbwk36wfq0x +0 -0
  24. data/spec/dummy/tmp/storage/kv/ic/kviccu3f65r4e4hpm4gx7negl8qn +0 -0
  25. data/spec/dummy/tmp/storage/l3/c1/l3c1ez2fev3a3xkrk7wbp2xdwviv +0 -0
  26. data/spec/dummy/tmp/storage/on/yx/onyxcojw95x7e5klv51dlcfkag23 +0 -0
  27. data/spec/dummy/tmp/storage/pi/6w/pi6wgg4yvzioszy2learhkxyfnyz +0 -0
  28. data/spec/dummy/tmp/storage/sf/i9/sfi9c5zedobbdh9jqt4vzhd9je6b +0 -0
  29. data/spec/dummy/tmp/storage/uo/n6/uon6sfic7g8p3ghvde3zt00r2mid +0 -0
  30. data/spec/dummy/tmp/storage/xw/pd/xwpdbtvmuy3gdokrgrpu3gxv28yp +0 -0
  31. data/spec/examples.txt +204 -199
  32. data/spec/factories/snf_core/users.rb +1 -0
  33. data/spec/models/snf_core/user_spec.rb +1 -0
  34. data/spec/requests/snf_core/auth_spec.rb +48 -1
  35. metadata +23 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5c3846a61247a975565c121fb8a4f40fc5df57bd7c194aa6cc057fc065147c2
4
- data.tar.gz: 62b4e90257c49fe1b9bfdc8483cbe8222745b81d2da6fb9e25df3e0859db782b
3
+ metadata.gz: a35328a0021c1e91dd51f13689b198090fa04a2118d333f42bc4e856652bce46
4
+ data.tar.gz: 7df51380a96c5f9ad7abc4778438756b9b0af94cfc2c17ee6aa2b2ad07e7344e
5
5
  SHA512:
6
- metadata.gz: 4d10278f0afecf87dc071c2398d1233823882a4d3d1352751367b851ae2bcd3b505227c97779b58aafb856eb7a4ac17918f6e292e3223276751289c1dac949c9
7
- data.tar.gz: 0fec193cecf15421b0731383602c24b550839dd20ca2a94d5b15b2d44641dba4d7118f588ec24be00c64d8540b5bece0aaba921b17885d74be0b4c3434e29472
6
+ metadata.gz: bb3c7dc5d5cf944cb52bdecb170fe9aa3f40e3e037ea8d7c4be6e316279d2191e464c74bcdd701973c5cd6359befaaa9aef070d5f1adc15a8b2e2dbfafadb7f0
7
+ data.tar.gz: 5803f1fa54fe16ed11370fb0494490cc1ee820b8a27b430b9ad05ae408b24c70778163e61d75b3a4a10b91ef124b1fc8515b7326dbf68cea0516486bb30e387e
@@ -37,7 +37,7 @@ module SnfCore
37
37
  if @user.save
38
38
  # Assign default user role
39
39
  user_role = Role.find_by(name: "User")
40
- UserRole.create!(user: @user, role: user_role)
40
+ UserRole.find_or_create_by!(user: @user, role: user_role)
41
41
 
42
42
  @business = Business.new(
43
43
  user: @user,
@@ -45,7 +45,6 @@ module SnfCore
45
45
  tin_number: signup_params[:tin_number],
46
46
  business_type: signup_params[:business_type]
47
47
  )
48
-
49
48
  if @business.save
50
49
  render json: {
51
50
  success: true,
@@ -82,6 +81,21 @@ module SnfCore
82
81
  render json: { success: true, token: token, user: user.as_json(except: [ :password_digest ]), role: role.name }
83
82
  end
84
83
 
84
+ def admin_login
85
+ user = User.find_by(phone_number: auth_params[:phone_number])
86
+ return render json: { success: false, error: "User doesn't exist" }, status: :unauthorized unless user
87
+ return render json: { success: false, error: "Invalid email or password" }, status: :unauthorized unless user.authenticate(auth_params[:password])
88
+
89
+ user_role = UserRole.find_by(user: user)
90
+ return render json: { success: false, error: "No role was assigned to your user" }, status: :unauthorized unless user_role
91
+
92
+ role = Role.find(user_role.role_id)
93
+ return render json: { success: false, error: "Unauthorized access" }, status: :unauthorized unless role.name == "Admin"
94
+
95
+ token = @token_service.encode({ user: user.as_json.except("password_digest", "created_at", "updated_at"), role: role.name })
96
+ render json: { success: true, token: token, user: user.as_json(except: [ :password_digest ]), role: role.name }
97
+ end
98
+
85
99
  private
86
100
 
87
101
  def token_service
@@ -97,7 +111,7 @@ module SnfCore
97
111
  :first_name, :middle_name, :last_name, :password,
98
112
  :phone_number, :business_name, :tin_number, :business_type,
99
113
  :date_of_birth, :nationality, :occupation, :source_of_funds, :kyc_status,
100
- :gender, :verified_at, :verified_by_id, :email
114
+ :gender, :verified_at, :verified_by_id, :email, :fayda_id
101
115
  )
102
116
  end
103
117
 
@@ -106,7 +120,7 @@ module SnfCore
106
120
  :first_name, :middle_name, :last_name, :password,
107
121
  :phone_number, :date_of_birth, :nationality,
108
122
  :occupation, :source_of_funds, :kyc_status,
109
- :gender, :verified_at, :verified_by_id, :email
123
+ :gender, :verified_at, :verified_by_id, :email, :fayda_id
110
124
  )
111
125
  end
112
126
 
@@ -7,8 +7,8 @@ module SnfCore
7
7
 
8
8
  has_one :wallet, dependent: :destroy
9
9
 
10
- validates :first_name, :middle_name, :last_name, :phone_number, :date_of_birth, :nationality, presence: true
11
- validates :phone_number, :email, uniqueness: true
10
+ validates :first_name, :middle_name, :last_name, :phone_number, :date_of_birth, :nationality, :fayda_id, presence: true
11
+ validates :phone_number, uniqueness: true
12
12
 
13
13
  enum :kyc_status, { pending: 0, approved: 1, rejected: 2 }
14
14
  enum :gender, { male: 0, female: 1 }
@@ -11,7 +11,6 @@ module SnfCore
11
11
 
12
12
  enum :status, {
13
13
  pending: 0,
14
- applied: 1,
15
14
  approved: 2,
16
15
  declined: 3
17
16
  }
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  SnfCore::Engine.routes.draw do
2
- mount SnfCore::Engine => "/snf_core"
3
2
  post "auth/login"
3
+ post "auth/admin/login", to: "auth#admin_login"
4
4
  post "auth/signup"
5
5
  post "auth/validate_token"
6
6
  end
@@ -0,0 +1,6 @@
1
+ class UpdatePasswordChangedDefaultToTrue < ActiveRecord::Migration[8.0]
2
+ def change
3
+ change_column_default :snf_core_users, :password_changed, from: false, to: true
4
+ add_column :snf_core_users, :fayda_id, :string
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module SnfCore
2
- VERSION = "0.3.5"
2
+ VERSION = "0.3.7"
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_12_141147) do
13
+ ActiveRecord::Schema[8.0].define(version: 2025_03_13_103149) 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
 
@@ -253,7 +253,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_12_141147) do
253
253
  t.datetime "created_at", null: false
254
254
  t.datetime "updated_at", null: false
255
255
  t.string "password_digest", null: false
256
- t.boolean "password_changed", default: false
256
+ t.boolean "password_changed", default: true
257
257
  t.string "reset_password_token"
258
258
  t.date "date_of_birth", null: false
259
259
  t.string "nationality", null: false
@@ -264,6 +264,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_12_141147) do
264
264
  t.datetime "verified_at"
265
265
  t.bigint "verified_by_id"
266
266
  t.bigint "address_id"
267
+ t.string "fayda_id"
267
268
  end
268
269
 
269
270
  create_table "snf_core_virtual_account_transactions", force: :cascade do |t|
@@ -8920,3 +8920,275 @@ FOREIGN KEY ("user_id")
8920
8920
  ActiveRecord::InternalMetadata Load (0.4ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'schema_sha1' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
8921
8921
  ActiveRecord::InternalMetadata Create (0.5ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ('schema_sha1', 'e5ce873c596e29727a72a2140a63fcb330b84481', '2025-03-12 19:56:14.870566', '2025-03-12 19:56:14.870570') RETURNING "key" /*application='Dummy'*/
8922
8922
  ActiveRecord::SchemaMigration Load (4.5ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8923
+  (0.8ms) SELECT pg_try_advisory_lock(869468062957908540) /*application='Dummy'*/
8924
+ ActiveRecord::SchemaMigration Load (1.9ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8925
+ ActiveRecord::InternalMetadata Load (4.0ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
8926
+ Migrating to UpdatePasswordChangedDefaultToTrue (20250313103149)
8927
+ TRANSACTION (0.1ms) BEGIN /*application='Dummy'*/
8928
+  (8.5ms) ALTER TABLE "snf_core_users" ALTER COLUMN "password_changed" SET DEFAULT TRUE /*application='Dummy'*/
8929
+  (0.4ms) ALTER TABLE "snf_core_users" ADD "fayda_id" character varying /*application='Dummy'*/
8930
+ ActiveRecord::SchemaMigration Create (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ('20250313103149') RETURNING "version" /*application='Dummy'*/
8931
+ TRANSACTION (0.4ms) COMMIT /*application='Dummy'*/
8932
+  (0.3ms) SELECT pg_advisory_unlock(869468062957908540) /*application='Dummy'*/
8933
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8934
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8935
+ ActiveRecord::InternalMetadata Load (0.3ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
8936
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8937
+ ActiveRecord::InternalMetadata Load (0.6ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
8938
+ ActiveRecord::SchemaMigration Load (4.3ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
8939
+ ActiveRecord::InternalMetadata Load (0.5ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
8940
+ SQL (0.1ms) SET search_path TO public /*application='Dummy'*/
8941
+  (78.7ms) DROP DATABASE IF EXISTS "snf_test" /*application='Dummy'*/
8942
+  (117.3ms) CREATE DATABASE "snf_test" ENCODING = 'unicode' /*application='Dummy'*/
8943
+ SQL (20.3ms) CREATE EXTENSION IF NOT EXISTS "plpgsql" SCHEMA pg_catalog /*application='Dummy'*/
8944
+  (0.2ms) DROP TABLE IF EXISTS "active_storage_attachments" CASCADE /*application='Dummy'*/
8945
+  (4.2ms) CREATE TABLE "active_storage_attachments" ("id" bigserial primary key, "name" character varying NOT NULL, "record_type" character varying NOT NULL, "record_id" bigint NOT NULL, "blob_id" bigint NOT NULL, "created_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8946
+  (1.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") /*application='Dummy'*/
8947
+  (0.8ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") /*application='Dummy'*/
8948
+  (0.2ms) DROP TABLE IF EXISTS "active_storage_blobs" CASCADE /*application='Dummy'*/
8949
+  (2.2ms) CREATE TABLE "active_storage_blobs" ("id" bigserial primary key, "key" character varying NOT NULL, "filename" character varying NOT NULL, "content_type" character varying, "metadata" text, "service_name" character varying NOT NULL, "byte_size" bigint NOT NULL, "checksum" character varying, "created_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8950
+  (0.7ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") /*application='Dummy'*/
8951
+  (0.2ms) DROP TABLE IF EXISTS "active_storage_variant_records" CASCADE /*application='Dummy'*/
8952
+  (1.6ms) CREATE TABLE "active_storage_variant_records" ("id" bigserial primary key, "blob_id" bigint NOT NULL, "variation_digest" character varying NOT NULL) /*application='Dummy'*/
8953
+  (1.1ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") /*application='Dummy'*/
8954
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_account_transfers" CASCADE /*application='Dummy'*/
8955
+  (2.3ms) CREATE TABLE "snf_core_account_transfers" ("id" bigserial primary key, "source_account_type" character varying NOT NULL, "source_account_id" bigint NOT NULL, "destination_account_type" character varying NOT NULL, "destination_account_id" bigint NOT NULL, "user_id" bigint NOT NULL, "amount" decimal(15,2) NOT NULL, "reference_number" character varying NOT NULL, "status" integer DEFAULT 0 NOT NULL, "transfer_type" integer NOT NULL, "description" text, "failure_reason" text, "completed_at" timestamp(6), "reversal_transfer_id" bigint, "cbs_response_data" jsonb, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8956
+  (0.7ms) CREATE INDEX "index_snf_core_account_transfers_on_destination_account" ON "snf_core_account_transfers" ("destination_account_type", "destination_account_id") /*application='Dummy'*/
8957
+  (0.6ms) CREATE UNIQUE INDEX "index_snf_core_account_transfers_on_reference_number" ON "snf_core_account_transfers" ("reference_number") /*application='Dummy'*/
8958
+  (0.8ms) CREATE INDEX "index_snf_core_account_transfers_on_reversal_transfer_id" ON "snf_core_account_transfers" ("reversal_transfer_id") /*application='Dummy'*/
8959
+  (0.7ms) CREATE INDEX "index_snf_core_account_transfers_on_source_account" ON "snf_core_account_transfers" ("source_account_type", "source_account_id") /*application='Dummy'*/
8960
+  (0.6ms) CREATE INDEX "index_snf_core_account_transfers_on_user_id" ON "snf_core_account_transfers" ("user_id") /*application='Dummy'*/
8961
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_addresses" CASCADE /*application='Dummy'*/
8962
+  (2.1ms) CREATE TABLE "snf_core_addresses" ("id" bigserial primary key, "address_type" character varying NOT NULL, "city" character varying NOT NULL, "sub_city" character varying NOT NULL, "woreda" character varying, "latitude" decimal, "longitude" decimal, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL, "house_number" character varying) /*application='Dummy'*/
8963
+  (0.4ms) DROP TABLE IF EXISTS "snf_core_business_documents" CASCADE /*application='Dummy'*/
8964
+  (1.4ms) CREATE TABLE "snf_core_business_documents" ("id" bigserial primary key, "business_id" bigint NOT NULL, "document_type" integer NOT NULL, "verified_at" timestamp(6), "verified_by_id" bigint, "uploaded_at" timestamp(6), "is_verified" boolean DEFAULT FALSE NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8965
+  (0.7ms) CREATE INDEX "index_snf_core_business_documents_on_business_id" ON "snf_core_business_documents" ("business_id") /*application='Dummy'*/
8966
+  (0.6ms) CREATE INDEX "index_snf_core_business_documents_on_verified_by_id" ON "snf_core_business_documents" ("verified_by_id") /*application='Dummy'*/
8967
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_businesses" CASCADE /*application='Dummy'*/
8968
+  (1.9ms) CREATE TABLE "snf_core_businesses" ("id" bigserial primary key, "user_id" bigint NOT NULL, "business_name" character varying NOT NULL, "tin_number" character varying NOT NULL, "business_type" integer NOT NULL, "verified_at" timestamp(6), "verification_status" integer DEFAULT 0 NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8969
+  (0.7ms) CREATE INDEX "index_snf_core_businesses_on_user_id" ON "snf_core_businesses" ("user_id") /*application='Dummy'*/
8970
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_categories" CASCADE /*application='Dummy'*/
8971
+  (2.0ms) CREATE TABLE "snf_core_categories" ("id" bigserial primary key, "name" character varying NOT NULL, "description" character varying, "parent_id" bigint, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8972
+  (0.7ms) CREATE INDEX "index_snf_core_categories_on_parent_id" ON "snf_core_categories" ("parent_id") /*application='Dummy'*/
8973
+  (0.3ms) DROP TABLE IF EXISTS "snf_core_customer_groups" CASCADE /*application='Dummy'*/
8974
+  (2.3ms) CREATE TABLE "snf_core_customer_groups" ("id" bigserial primary key, "discount_code" character varying, "expire_date" timestamp(6), "is_used" boolean, "group_id" bigint NOT NULL, "customer_id" bigint NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8975
+  (0.8ms) CREATE INDEX "index_snf_core_customer_groups_on_customer_id" ON "snf_core_customer_groups" ("customer_id") /*application='Dummy'*/
8976
+  (0.6ms) CREATE INDEX "index_snf_core_customer_groups_on_group_id" ON "snf_core_customer_groups" ("group_id") /*application='Dummy'*/
8977
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_delivery_orders" CASCADE /*application='Dummy'*/
8978
+  (1.9ms) CREATE TABLE "snf_core_delivery_orders" ("id" bigserial primary key, "order_id" bigint NOT NULL, "delivery_address" character varying NOT NULL, "contact_phone" character varying NOT NULL, "delivery_notes" text NOT NULL, "estimated_delivery_time" timestamp(6) NOT NULL, "actual_delivery_time" timestamp(6), "status" integer NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8979
+  (1.0ms) CREATE INDEX "index_snf_core_delivery_orders_on_order_id" ON "snf_core_delivery_orders" ("order_id") /*application='Dummy'*/
8980
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_groups" CASCADE /*application='Dummy'*/
8981
+  (2.4ms) CREATE TABLE "snf_core_groups" ("id" bigserial primary key, "name" character varying NOT NULL, "business_id" bigint NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8982
+  (0.8ms) CREATE INDEX "index_snf_core_groups_on_business_id" ON "snf_core_groups" ("business_id") /*application='Dummy'*/
8983
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_item_requests" CASCADE /*application='Dummy'*/
8984
+  (1.9ms) CREATE TABLE "snf_core_item_requests" ("id" bigserial primary key, "user_id" bigint NOT NULL, "product_id" bigint NOT NULL, "quantity" integer NOT NULL, "requested_delivery_date" date NOT NULL, "notes" text, "status" integer DEFAULT 0 NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL, "unit" character varying) /*application='Dummy'*/
8985
+  (0.8ms) CREATE INDEX "index_snf_core_item_requests_on_product_id" ON "snf_core_item_requests" ("product_id") /*application='Dummy'*/
8986
+  (0.7ms) CREATE INDEX "index_snf_core_item_requests_on_user_id" ON "snf_core_item_requests" ("user_id") /*application='Dummy'*/
8987
+  (0.1ms) DROP TABLE IF EXISTS "snf_core_order_items" CASCADE /*application='Dummy'*/
8988
+  (2.2ms) CREATE TABLE "snf_core_order_items" ("id" bigserial primary key, "order_id" bigint NOT NULL, "store_inventory_id" bigint NOT NULL, "quantity" integer NOT NULL, "unit_price" decimal NOT NULL, "subtotal" decimal NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8989
+  (0.8ms) CREATE INDEX "index_snf_core_order_items_on_order_id" ON "snf_core_order_items" ("order_id") /*application='Dummy'*/
8990
+  (0.9ms) CREATE INDEX "index_snf_core_order_items_on_store_inventory_id" ON "snf_core_order_items" ("store_inventory_id") /*application='Dummy'*/
8991
+  (0.3ms) DROP TABLE IF EXISTS "snf_core_orders" CASCADE /*application='Dummy'*/
8992
+  (2.1ms) CREATE TABLE "snf_core_orders" ("id" bigserial primary key, "user_id" bigint NOT NULL, "store_id" bigint NOT NULL, "status" integer DEFAULT 1 NOT NULL, "total_amount" decimal DEFAULT 0.0 NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8993
+  (1.2ms) CREATE INDEX "index_snf_core_orders_on_store_id" ON "snf_core_orders" ("store_id") /*application='Dummy'*/
8994
+  (0.8ms) CREATE INDEX "index_snf_core_orders_on_user_id" ON "snf_core_orders" ("user_id") /*application='Dummy'*/
8995
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_products" CASCADE /*application='Dummy'*/
8996
+  (2.4ms) CREATE TABLE "snf_core_products" ("id" bigserial primary key, "sku" character varying NOT NULL, "name" character varying NOT NULL, "description" character varying, "category_id" bigint NOT NULL, "base_price" float, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
8997
+  (0.8ms) CREATE INDEX "index_snf_core_products_on_category_id" ON "snf_core_products" ("category_id") /*application='Dummy'*/
8998
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_quotations" CASCADE /*application='Dummy'*/
8999
+  (2.1ms) CREATE TABLE "snf_core_quotations" ("id" bigserial primary key, "item_request_id" bigint NOT NULL, "price" decimal NOT NULL, "delivery_date" date NOT NULL, "valid_until" timestamp(6) NOT NULL, "status" integer DEFAULT 0 NOT NULL, "notes" text, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9000
+  (1.2ms) CREATE INDEX "index_snf_core_quotations_on_item_request_id" ON "snf_core_quotations" ("item_request_id") /*application='Dummy'*/
9001
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_roles" CASCADE /*application='Dummy'*/
9002
+  (2.4ms) CREATE TABLE "snf_core_roles" ("id" bigserial primary key, "name" character varying NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9003
+  (0.3ms) DROP TABLE IF EXISTS "snf_core_store_inventories" CASCADE /*application='Dummy'*/
9004
+  (1.5ms) CREATE TABLE "snf_core_store_inventories" ("id" bigserial primary key, "store_id" bigint NOT NULL, "product_id" bigint NOT NULL, "base_price" decimal(10,2) NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL, "status" integer DEFAULT 0 NOT NULL) /*application='Dummy'*/
9005
+  (0.9ms) CREATE INDEX "index_snf_core_store_inventories_on_product_id" ON "snf_core_store_inventories" ("product_id") /*application='Dummy'*/
9006
+  (0.8ms) CREATE UNIQUE INDEX "index_snf_core_store_inventories_on_store_id_and_product_id" ON "snf_core_store_inventories" ("store_id", "product_id") /*application='Dummy'*/
9007
+  (0.8ms) CREATE INDEX "index_snf_core_store_inventories_on_store_id" ON "snf_core_store_inventories" ("store_id") /*application='Dummy'*/
9008
+  (0.4ms) DROP TABLE IF EXISTS "snf_core_stores" CASCADE /*application='Dummy'*/
9009
+  (6.0ms) CREATE TABLE "snf_core_stores" ("id" bigserial primary key, "name" character varying NOT NULL, "email" character varying, "operational_status" integer DEFAULT 1 NOT NULL, "business_id" bigint NOT NULL, "address_id" bigint NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9010
+  (1.2ms) CREATE INDEX "index_snf_core_stores_on_address_id" ON "snf_core_stores" ("address_id") /*application='Dummy'*/
9011
+  (1.1ms) CREATE INDEX "index_snf_core_stores_on_business_id" ON "snf_core_stores" ("business_id") /*application='Dummy'*/
9012
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_user_roles" CASCADE /*application='Dummy'*/
9013
+  (2.4ms) CREATE TABLE "snf_core_user_roles" ("id" bigserial primary key, "user_id" bigint NOT NULL, "role_id" bigint NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9014
+  (1.2ms) CREATE INDEX "index_snf_core_user_roles_on_role_id" ON "snf_core_user_roles" ("role_id") /*application='Dummy'*/
9015
+  (1.2ms) CREATE INDEX "index_snf_core_user_roles_on_user_id" ON "snf_core_user_roles" ("user_id") /*application='Dummy'*/
9016
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_users" CASCADE /*application='Dummy'*/
9017
+  (6.2ms) CREATE TABLE "snf_core_users" ("id" bigserial primary key, "first_name" character varying NOT NULL, "middle_name" character varying NOT NULL, "last_name" character varying NOT NULL, "email" character varying, "phone_number" character varying NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL, "password_digest" character varying NOT NULL, "password_changed" boolean DEFAULT TRUE, "reset_password_token" character varying, "date_of_birth" date NOT NULL, "nationality" character varying NOT NULL, "occupation" character varying, "source_of_funds" character varying, "kyc_status" integer, "gender" integer, "verified_at" timestamp(6), "verified_by_id" bigint, "address_id" bigint, "fayda_id" character varying) /*application='Dummy'*/
9018
+  (0.5ms) DROP TABLE IF EXISTS "snf_core_virtual_account_transactions" CASCADE /*application='Dummy'*/
9019
+  (3.9ms) CREATE TABLE "snf_core_virtual_account_transactions" ("id" bigserial primary key, "from_account_id" bigint, "to_account_id" bigint, "amount" decimal NOT NULL, "transaction_type" integer NOT NULL, "status" integer DEFAULT 0 NOT NULL, "reference_number" character varying NOT NULL, "description" text, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9020
+  (1.8ms) CREATE INDEX "index_snf_core_virtual_account_transactions_on_created_at" ON "snf_core_virtual_account_transactions" ("created_at") /*application='Dummy'*/
9021
+  (2.2ms) CREATE INDEX "index_snf_core_virtual_account_transactions_on_from_account_id" ON "snf_core_virtual_account_transactions" ("from_account_id") /*application='Dummy'*/
9022
+  (1.5ms) CREATE UNIQUE INDEX "idx_on_reference_number_bd9be00f20" ON "snf_core_virtual_account_transactions" ("reference_number") /*application='Dummy'*/
9023
+  (1.3ms) CREATE INDEX "index_snf_core_virtual_account_transactions_on_to_account_id" ON "snf_core_virtual_account_transactions" ("to_account_id") /*application='Dummy'*/
9024
+  (0.3ms) DROP TABLE IF EXISTS "snf_core_virtual_accounts" CASCADE /*application='Dummy'*/
9025
+  (4.8ms) CREATE TABLE "snf_core_virtual_accounts" ("id" bigserial primary key, "user_id" bigint NOT NULL, "account_number" character varying(11) NOT NULL, "cbs_account_number" character varying NOT NULL, "balance" decimal DEFAULT 0.0 NOT NULL, "interest_rate" decimal DEFAULT 0.0 NOT NULL, "interest_type" integer DEFAULT 0 NOT NULL, "active" boolean DEFAULT TRUE NOT NULL, "branch_code" character varying(3) NOT NULL, "product_scheme" character varying(1) NOT NULL, "voucher_type" character varying(1) NOT NULL, "status" integer DEFAULT 0 NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9026
+  (1.6ms) CREATE UNIQUE INDEX "index_snf_core_virtual_accounts_on_account_number" ON "snf_core_virtual_accounts" ("account_number") /*application='Dummy'*/
9027
+  (1.4ms) CREATE INDEX "idx_on_branch_code_product_scheme_voucher_type_b7038b3d5f" ON "snf_core_virtual_accounts" ("branch_code", "product_scheme", "voucher_type") /*application='Dummy'*/
9028
+  (1.2ms) CREATE UNIQUE INDEX "index_snf_core_virtual_accounts_on_cbs_account_number" ON "snf_core_virtual_accounts" ("cbs_account_number") /*application='Dummy'*/
9029
+  (1.3ms) CREATE INDEX "index_snf_core_virtual_accounts_on_user_id" ON "snf_core_virtual_accounts" ("user_id") /*application='Dummy'*/
9030
+  (0.2ms) DROP TABLE IF EXISTS "snf_core_wallets" CASCADE /*application='Dummy'*/
9031
+  (5.8ms) CREATE TABLE "snf_core_wallets" ("id" bigserial primary key, "user_id" bigint NOT NULL, "wallet_number" character varying NOT NULL, "balance" decimal NOT NULL, "is_active" boolean DEFAULT TRUE NOT NULL, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9032
+  (1.9ms) CREATE INDEX "index_snf_core_wallets_on_user_id" ON "snf_core_wallets" ("user_id") /*application='Dummy'*/
9033
+  (1.5ms) CREATE UNIQUE INDEX "index_snf_core_wallets_on_wallet_number" ON "snf_core_wallets" ("wallet_number") /*application='Dummy'*/
9034
+  (4.3ms) ALTER TABLE "active_storage_attachments" ADD CONSTRAINT "fk_rails_c3b3935057"
9035
+ FOREIGN KEY ("blob_id")
9036
+ REFERENCES "active_storage_blobs" ("id")
9037
+ /*application='Dummy'*/
9038
+  (2.1ms) ALTER TABLE "active_storage_variant_records" ADD CONSTRAINT "fk_rails_993965df05"
9039
+ FOREIGN KEY ("blob_id")
9040
+ REFERENCES "active_storage_blobs" ("id")
9041
+ /*application='Dummy'*/
9042
+  (2.5ms) ALTER TABLE "snf_core_account_transfers" ADD CONSTRAINT "fk_rails_0d109a55ef"
9043
+ FOREIGN KEY ("user_id")
9044
+ REFERENCES "snf_core_users" ("id")
9045
+ /*application='Dummy'*/
9046
+  (2.5ms) ALTER TABLE "snf_core_business_documents" ADD CONSTRAINT "fk_rails_1efd7338ed"
9047
+ FOREIGN KEY ("business_id")
9048
+ REFERENCES "snf_core_businesses" ("id")
9049
+ /*application='Dummy'*/
9050
+  (2.1ms) ALTER TABLE "snf_core_business_documents" ADD CONSTRAINT "fk_rails_a6157021cc"
9051
+ FOREIGN KEY ("verified_by_id")
9052
+ REFERENCES "snf_core_users" ("id")
9053
+ /*application='Dummy'*/
9054
+  (1.5ms) ALTER TABLE "snf_core_businesses" ADD CONSTRAINT "fk_rails_a61edcbd4b"
9055
+ FOREIGN KEY ("user_id")
9056
+ REFERENCES "snf_core_users" ("id")
9057
+ /*application='Dummy'*/
9058
+  (1.8ms) ALTER TABLE "snf_core_categories" ADD CONSTRAINT "fk_rails_26a925b05d"
9059
+ FOREIGN KEY ("parent_id")
9060
+ REFERENCES "snf_core_categories" ("id")
9061
+ /*application='Dummy'*/
9062
+  (2.1ms) ALTER TABLE "snf_core_customer_groups" ADD CONSTRAINT "fk_rails_9c45f4015a"
9063
+ FOREIGN KEY ("group_id")
9064
+ REFERENCES "snf_core_groups" ("id")
9065
+ /*application='Dummy'*/
9066
+  (2.2ms) ALTER TABLE "snf_core_customer_groups" ADD CONSTRAINT "fk_rails_792eb3404d"
9067
+ FOREIGN KEY ("customer_id")
9068
+ REFERENCES "snf_core_users" ("id")
9069
+ /*application='Dummy'*/
9070
+  (2.8ms) ALTER TABLE "snf_core_delivery_orders" ADD CONSTRAINT "fk_rails_450d17b1b2"
9071
+ FOREIGN KEY ("order_id")
9072
+ REFERENCES "snf_core_orders" ("id")
9073
+ /*application='Dummy'*/
9074
+  (1.4ms) ALTER TABLE "snf_core_groups" ADD CONSTRAINT "fk_rails_c52b27ad67"
9075
+ FOREIGN KEY ("business_id")
9076
+ REFERENCES "snf_core_businesses" ("id")
9077
+ /*application='Dummy'*/
9078
+  (2.2ms) ALTER TABLE "snf_core_item_requests" ADD CONSTRAINT "fk_rails_a718316b94"
9079
+ FOREIGN KEY ("product_id")
9080
+ REFERENCES "snf_core_products" ("id")
9081
+ /*application='Dummy'*/
9082
+  (3.2ms) ALTER TABLE "snf_core_item_requests" ADD CONSTRAINT "fk_rails_0aa2ea2057"
9083
+ FOREIGN KEY ("user_id")
9084
+ REFERENCES "snf_core_users" ("id")
9085
+ /*application='Dummy'*/
9086
+  (2.5ms) ALTER TABLE "snf_core_order_items" ADD CONSTRAINT "fk_rails_1f4046ba92"
9087
+ FOREIGN KEY ("order_id")
9088
+ REFERENCES "snf_core_orders" ("id")
9089
+ /*application='Dummy'*/
9090
+  (1.9ms) ALTER TABLE "snf_core_order_items" ADD CONSTRAINT "fk_rails_50419437e9"
9091
+ FOREIGN KEY ("store_inventory_id")
9092
+ REFERENCES "snf_core_store_inventories" ("id")
9093
+ /*application='Dummy'*/
9094
+  (1.8ms) ALTER TABLE "snf_core_orders" ADD CONSTRAINT "fk_rails_400cf2029c"
9095
+ FOREIGN KEY ("store_id")
9096
+ REFERENCES "snf_core_stores" ("id")
9097
+ /*application='Dummy'*/
9098
+  (1.9ms) ALTER TABLE "snf_core_orders" ADD CONSTRAINT "fk_rails_45b78fb6f9"
9099
+ FOREIGN KEY ("user_id")
9100
+ REFERENCES "snf_core_users" ("id")
9101
+ /*application='Dummy'*/
9102
+  (1.6ms) ALTER TABLE "snf_core_products" ADD CONSTRAINT "fk_rails_a0ba3fa883"
9103
+ FOREIGN KEY ("category_id")
9104
+ REFERENCES "snf_core_categories" ("id")
9105
+ /*application='Dummy'*/
9106
+  (1.9ms) ALTER TABLE "snf_core_quotations" ADD CONSTRAINT "fk_rails_3ec8abd328"
9107
+ FOREIGN KEY ("item_request_id")
9108
+ REFERENCES "snf_core_item_requests" ("id")
9109
+ /*application='Dummy'*/
9110
+  (1.3ms) ALTER TABLE "snf_core_store_inventories" ADD CONSTRAINT "fk_rails_15fb263e75"
9111
+ FOREIGN KEY ("product_id")
9112
+ REFERENCES "snf_core_products" ("id")
9113
+ /*application='Dummy'*/
9114
+  (1.5ms) ALTER TABLE "snf_core_store_inventories" ADD CONSTRAINT "fk_rails_2ca88d30e2"
9115
+ FOREIGN KEY ("store_id")
9116
+ REFERENCES "snf_core_stores" ("id")
9117
+ /*application='Dummy'*/
9118
+  (1.6ms) ALTER TABLE "snf_core_stores" ADD CONSTRAINT "fk_rails_421441da8e"
9119
+ FOREIGN KEY ("address_id")
9120
+ REFERENCES "snf_core_addresses" ("id")
9121
+ /*application='Dummy'*/
9122
+  (1.7ms) ALTER TABLE "snf_core_stores" ADD CONSTRAINT "fk_rails_e100fc7454"
9123
+ FOREIGN KEY ("business_id")
9124
+ REFERENCES "snf_core_businesses" ("id")
9125
+ /*application='Dummy'*/
9126
+  (2.3ms) ALTER TABLE "snf_core_user_roles" ADD CONSTRAINT "fk_rails_0e70d7ce00"
9127
+ FOREIGN KEY ("role_id")
9128
+ REFERENCES "snf_core_roles" ("id")
9129
+ /*application='Dummy'*/
9130
+  (1.5ms) ALTER TABLE "snf_core_user_roles" ADD CONSTRAINT "fk_rails_9ad2e78133"
9131
+ FOREIGN KEY ("user_id")
9132
+ REFERENCES "snf_core_users" ("id")
9133
+ /*application='Dummy'*/
9134
+  (1.7ms) ALTER TABLE "snf_core_users" ADD CONSTRAINT "fk_rails_aaf9dcb5a5"
9135
+ FOREIGN KEY ("address_id")
9136
+ REFERENCES "snf_core_addresses" ("id")
9137
+ /*application='Dummy'*/
9138
+  (2.0ms) ALTER TABLE "snf_core_users" ADD CONSTRAINT "fk_rails_e672dea3f8"
9139
+ FOREIGN KEY ("verified_by_id")
9140
+ REFERENCES "snf_core_users" ("id")
9141
+ ON DELETE SET NULL /*application='Dummy'*/
9142
+  (3.0ms) ALTER TABLE "snf_core_virtual_account_transactions" ADD CONSTRAINT "fk_rails_746fa19f46"
9143
+ FOREIGN KEY ("from_account_id")
9144
+ REFERENCES "snf_core_virtual_accounts" ("id")
9145
+ /*application='Dummy'*/
9146
+  (1.3ms) ALTER TABLE "snf_core_virtual_account_transactions" ADD CONSTRAINT "fk_rails_87430c1b60"
9147
+ FOREIGN KEY ("to_account_id")
9148
+ REFERENCES "snf_core_virtual_accounts" ("id")
9149
+ /*application='Dummy'*/
9150
+  (1.4ms) ALTER TABLE "snf_core_virtual_accounts" ADD CONSTRAINT "fk_rails_5b22a265fb"
9151
+ FOREIGN KEY ("user_id")
9152
+ REFERENCES "snf_core_users" ("id")
9153
+ /*application='Dummy'*/
9154
+  (12.2ms) ALTER TABLE "snf_core_wallets" ADD CONSTRAINT "fk_rails_77c94979ce"
9155
+ FOREIGN KEY ("user_id")
9156
+ REFERENCES "snf_core_users" ("id")
9157
+ /*application='Dummy'*/
9158
+  (3.2ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY) /*application='Dummy'*/
9159
+ ActiveRecord::SchemaMigration Load (0.8ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='Dummy'*/
9160
+  (0.6ms) INSERT INTO "schema_migrations" (version) VALUES (20250313103149) /*application='Dummy'*/
9161
+  (0.7ms) INSERT INTO "schema_migrations" (version) VALUES
9162
+ (20250312141147),
9163
+ (20250312043359),
9164
+ (20250311000000),
9165
+ (20250310143604),
9166
+ (20250310133249),
9167
+ (20250310123127),
9168
+ (20250310122954),
9169
+ (20250306074713),
9170
+ (20250305232530),
9171
+ (20250305232529),
9172
+ (20250305201008),
9173
+ (20250305170248),
9174
+ (20250305165926),
9175
+ (20250227102833),
9176
+ (20250227075048),
9177
+ (20250226193938),
9178
+ (20250226192104),
9179
+ (20250226190000),
9180
+ (20250226181007),
9181
+ (20250226123213),
9182
+ (20250226115215),
9183
+ (20250226110217),
9184
+ (20250226102931),
9185
+ (20250226080323),
9186
+ (20250226064444),
9187
+ (20250226042622); /*application='Dummy'*/
9188
+  (4.3ms) CREATE TABLE "ar_internal_metadata" ("key" character varying NOT NULL PRIMARY KEY, "value" character varying, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL) /*application='Dummy'*/
9189
+ ActiveRecord::InternalMetadata Load (1.2ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
9190
+ ActiveRecord::InternalMetadata Create (0.8ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ('environment', 'development', '2025-03-13 11:44:38.624113', '2025-03-13 11:44:38.624119') RETURNING "key" /*application='Dummy'*/
9191
+ ActiveRecord::InternalMetadata Load (0.3ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
9192
+ ActiveRecord::InternalMetadata Update (1.5ms) UPDATE "ar_internal_metadata" SET "value" = 'test', "updated_at" = '2025-03-13 11:44:38.654064' WHERE "ar_internal_metadata"."key" = 'environment' /*application='Dummy'*/
9193
+ ActiveRecord::InternalMetadata Load (0.4ms) SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'schema_sha1' ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1 /*application='Dummy'*/
9194
+ ActiveRecord::InternalMetadata Create (0.6ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ('schema_sha1', '218184097ba896dfad8023903cb8f560edf494c0', '2025-03-13 11:44:38.657479', '2025-03-13 11:44:38.657481') RETURNING "key" /*application='Dummy'*/