stay_commerce 0.1.14 → 0.1.16

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21d65148be51476482fe86e79472e2e0bf311f49f9def7ee1be0d94cc908484e
4
- data.tar.gz: d930047ffebe22e514475ee2a965c840ec7961265d2e3dd48126ac27551b01ef
3
+ metadata.gz: ea9bf5bd2ce5586107d49503bcbbab44973eb929e6cf58fbe762892444a437ec
4
+ data.tar.gz: f32e5da8fb4d2b3840efc4115ca06ebcde81cbf9bc95b8c8cb505a845a9a384a
5
5
  SHA512:
6
- metadata.gz: f4edf72e5d17bd18491b58f3b84b945ea297c01c7a0eb85e309a6899ed69a99cd92f96f81b121d387f22082fed143fe08ccc505fd9210849293f43fde2b5a405
7
- data.tar.gz: 5fa10e530142899cffc424179a44001aabd2eb4e6897c836a76537b1c3323540005ba646212c74f9867f6c10740329396eedfa389fa19da0689018f96599294f
6
+ metadata.gz: 7f48289085a2aa3f9156d871ae5d6e76631a2c1dd25f90ca735bf84f51fe9f21cdfdd4d71cc959b23a85f18de45bef2a27130db01268967cd4c826fec3bbd4dc
7
+ data.tar.gz: 9eee63d5b3ed3c65c4a672e3ad97c2c7a43828de56b4b6a855497f803ad4445768bdfd75a7521d9b7728b10374b3fa55f4b96b5edf1d31cefce5808ca0e38b5f
@@ -1,72 +1,107 @@
1
+ require "openssl"
2
+ require "base64"
3
+ require "dotenv/load"
1
4
  module Stay
2
5
  module StripeConcern
3
- extend ActiveSupport::Concern
4
- def user
5
- current_devise_api_user || current_user
6
- end
6
+ extend ActiveSupport::Concern
7
7
 
8
- def create_payment_method
9
- Stripe::PaymentMethod.create({
10
- type: params[:payment_method_type],
11
- card: {
12
- number: params[:number],
13
- exp_month: params[:exp_month],
14
- exp_year: params[:exp_year],
15
- cvc: params[:cvc],
16
- },
17
- })
18
- end
19
- def create_customer
20
- Stripe::Customer.create({
21
- email: user.email,
22
- name: "#{user.first_name} #{user.last_name}",
23
- address: {
24
- city: user.addresses.last&.city,
25
- state: user.addresses.last&.state.name,
26
- country: user.addresses.last&.country.name,
27
- line1: user.addresses.last&.address1,
28
- line2: user.addresses.last&.address2,
29
- postal_code: user.addresses.last&.zipcode
30
- },
31
- metadata: { order_id: user.id }
32
- })
33
- end
8
+ included do
9
+ Stripe.api_key = ENV["STRIPE_SECRECT_KEY"]
10
+ end
34
11
 
35
- def create_or_retrieve_customer
36
- customers = Stripe::Customer.list(email: user.email).data
37
- if customers.empty?
38
- create_customer
39
- else
40
- customers.first
41
- end
42
- end
12
+ def user
13
+ current_devise_api_user || current_user
14
+ end
15
+
16
+ def create_payment_method
17
+ Stripe::PaymentMethod.create({
18
+ type: params[:payment_method_type],
19
+ card: {
20
+ number: params[:number],
21
+ exp_month: params[:exp_month],
22
+ exp_year: params[:exp_year],
23
+ cvc: params[:cvc]
24
+ }
25
+ })
26
+ end
27
+
28
+ def create_customer
29
+ customer = Stripe::Customer.create({
30
+ email: user.email,
31
+ name: "#{user.first_name} #{user.last_name}",
32
+ address: {
33
+ city: user.addresses.last&.city,
34
+ state: user.addresses.last&.state&.name,
35
+ country: user.addresses.last&.country&.name,
36
+ line1: user.addresses.last&.address1,
37
+ line2: user.addresses.last&.address2,
38
+ postal_code: user.addresses.last&.zipcode
39
+ },
40
+ metadata: { order_id: user.id }
41
+ })
42
+ user.update(stripe_customer_id: customer.id)
43
+ end
43
44
 
44
- def create_payment_intent
45
- Stripe::PaymentIntent.create(
46
- amount: @booking.total.to_i* 100,
47
- description: @booking.user.email,
48
- currency: params[:currency] || 'INR',
49
- payment_method: params[:payment_method_id],
50
- automatic_payment_methods: { enabled: true },
51
- receipt_email: user.email,
52
- customer: @customer,
53
- confirm: params[:confirm],
54
- return_url: params[:redirect_url]
55
- )
45
+ def create_or_retrieve_customer
46
+ if user.stripe_customer_id.present?
47
+ @customer = Stripe::Customer.retrieve(user.stripe_customer_id)
48
+ else
49
+ @customer = create_customer
56
50
  end
51
+ end
52
+
53
+ def create_payment_intent
54
+ payment_method_id = params[:payment_method_id]
55
+ payment_intent = Stripe::PaymentIntent.create(
56
+ amount: (@booking.total_amount * 100).to_i,
57
+ description: @booking.user.email,
58
+ currency: params[:currency] || "usd",
59
+ payment_method: payment_method_id,
60
+ receipt_email: user.email,
61
+ customer: @customer,
62
+ confirm: false
63
+ )
64
+ if payment_intent.status == "requires_confirmation"
65
+ payment_intent = confirm_payment_intent(payment_intent.id, payment_method_id)
66
+ end
67
+ end
68
+
69
+ def get_payment_intent
70
+ Stripe::PaymentIntent.retrieve(@booking.payment_intent_id)
71
+ end
72
+
73
+ def attach_payment_method_to_customer(payment_method_token, customer_id)
74
+ Stripe::PaymentMethod.attach(
75
+ payment_method_token,{ customer: customer_id }
76
+ )
77
+ end
78
+
79
+ def create_payment_method_from_token(token)
80
+ payment_method = Stripe::PaymentMethod.create({
81
+ type: "card",
82
+ card: { token: token }
83
+ })
57
84
 
58
- def get_payment_intent
59
- Stripe::PaymentIntent.retrieve(@booking.payment_intent_id)
60
- end
85
+ attach_payment_method_to_customer( payment_method.id, current_devise_api_user.stripe_customer_id)
86
+ payment_method.id
87
+ end
61
88
 
62
- def confirm_payment_intent
63
- Stripe::PaymentIntent.confirm(
64
- params[:payment_intent_id],
65
- {
66
- payment_method: params[:payment_method_id],
67
- return_url: params[redirect_url],
68
- })
69
- end
70
-
71
- end
72
- end
89
+ def confirm_payment_intent(payment_intent_id, payment_method_id)
90
+ Stripe::PaymentIntent.confirm(
91
+ payment_intent_id,
92
+ {
93
+ payment_method: payment_method_id,
94
+ # return_url: params[redirect_url]
95
+ })
96
+ end
97
+
98
+ def destroy_payment_method(payment_method_token)
99
+ begin
100
+ Stripe::PaymentMethod.detach(payment_method_token)
101
+ rescue Stripe::InvalidRequestError => e
102
+ raise "Failed to detach payment method: #{e.message}"
103
+ end
104
+ end
105
+
106
+ end
107
+ end
@@ -43,40 +43,36 @@ class Stay::Api::V1::BookingsController < Stay::BaseApiController
43
43
  end
44
44
 
45
45
  def host_booking
46
- begin
47
- page = params[:page].to_i > 0 ? params[:page].to_i : 1
48
- per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 10
49
-
50
- cumulative_per_page = page * per_page
51
- @request = Stay::Booking.joins(:property).where(stay_properties: { user_id: current_devise_api_user&.id }).confirmed
52
- @bookings = @request.order(created_at: :desc).limit(cumulative_per_page)
53
-
54
- total_count = @request.count
55
- total_pages = (total_count.to_f / per_page).ceil
56
-
57
- if @bookings.empty?
58
- return render json: { error: "No bookings found", bookings: [], success: false }, status: :ok
59
- end
60
-
61
- render json: {
62
- data: "Bookings Found",
63
- bookings: ActiveModelSerializers::SerializableResource.new(@bookings, each_serializer: BookingSerializer),
64
- success: true,
65
- meta: {
66
- total_pages: total_pages,
67
- current_page: page,
68
- next_page: page < total_pages ? page + 1 : nil,
69
- prev_page: page > 1 ? page - 1 : nil,
70
- total_count: total_count
71
- }
72
- }, status: :ok
73
- rescue ActiveRecord::RecordNotFound => e
74
- render json: { success: false, error: "Bookings not found", message: e.message }, status: :not_found
75
- rescue ArgumentError => e
76
- render json: { success: false, error: "Invalid pagination parameters", message: e.message }, status: :bad_request
77
- rescue StandardError => e
78
- render json: { success: false, error: "Internal server error", message: e.message }, status: :internal_server_error
79
- end
46
+ begin
47
+ page = params[:page].to_i > 0 ? params[:page].to_i : 1
48
+
49
+ @bookings = Stay::Booking.current_host_booking(current_devise_api_user).confirmed
50
+ @bookings = @bookings.joins(:property).where("stay_properties.title ILIKE ?", "%#{params[:q]}%") if params[:q].present?
51
+ @bookings = @bookings.order(updated_at: :desc).page(page).per(10)
52
+
53
+ if @bookings.empty?
54
+ return render json: { error: "No bookings found", bookings: [], success: false }, status: :ok
55
+ end
56
+
57
+ render json: {
58
+ data: "Bookings Found",
59
+ bookings: ActiveModelSerializers::SerializableResource.new(@bookings, each_serializer: BookingListingSerializer),
60
+ success: true,
61
+ meta: {
62
+ total_pages: @bookings.total_pages,
63
+ current_page: @bookings.current_page,
64
+ next_page: @bookings.next_page,
65
+ prev_page: @bookings.prev_page,
66
+ total_count: @bookings.total_count
67
+ }
68
+ }, status: :ok
69
+ rescue ActiveRecord::RecordNotFound => e
70
+ render json: { success: false, error: "Bookings not found", message: e.message }, status: :not_found
71
+ rescue ArgumentError => e
72
+ render json: { success: false, error: "Invalid pagination parameters", message: e.message }, status: :bad_request
73
+ rescue StandardError => e
74
+ render json: { success: false, error: "Internal server error", message: e.message }, status: :internal_server_error
75
+ end
80
76
  end
81
77
 
82
78
  def host_request
@@ -97,7 +93,7 @@ class Stay::Api::V1::BookingsController < Stay::BaseApiController
97
93
 
98
94
  render json: {
99
95
  data: "Bookings Found",
100
- bookings: ActiveModelSerializers::SerializableResource.new(@bookings, each_serializer: BookingSerializer),
96
+ bookings: ActiveModelSerializers::SerializableResource.new(@bookings, each_serializer: BookingListingSerializer),
101
97
  success: true,
102
98
  meta: {
103
99
  total_pages: total_pages,
@@ -1,6 +1,7 @@
1
1
  class Stay::Api::V1::CreditCardsController < Stay::BaseApiController
2
2
  before_action :authenticate_devise_api_token!
3
- before_action :set_credit_card, only: %i[show edit update]
3
+ before_action :set_credit_card, only: %i[show edit update destroy]
4
+ include Stay::StripeConcern
4
5
 
5
6
  def index
6
7
  @credit_cards = current_devise_api_user.credit_cards
@@ -25,11 +26,17 @@ class Stay::Api::V1::CreditCardsController < Stay::BaseApiController
25
26
  end
26
27
 
27
28
  def create
28
- @credit_card = current_devise_api_user.credit_cards.build(credit_card_params)
29
- if @credit_card.save
30
- render json: { message: "Credit card saved successfully", data: CreditCardSerializer.new(@credit_card), success: true }, status: :ok
31
- else
32
- render json: { error: "Credit card not saved", success: false, errors: @credit_card.errors.full_messages }, status: :unprocessable_entity
29
+ begin
30
+ token = create_payment_method_from_token(credit_card_params[:card_token])
31
+ @credit_card = current_devise_api_user.credit_cards.build(credit_card_params.merge(payment_method_token: token))
32
+
33
+ if @credit_card.save
34
+ render json: { message: "Credit card saved successfully", data: CreditCardSerializer.new(@credit_card), success: true }, status: :ok
35
+ else
36
+ render json: { error: "Credit card not saved", success: false, errors: @credit_card.errors.full_messages }, status: :unprocessable_entity
37
+ end
38
+ rescue Stripe::InvalidRequestError => e
39
+ render json: { error: e.message, success: false }, status: :unprocessable_entity
33
40
  end
34
41
  end
35
42
 
@@ -38,17 +45,31 @@ class Stay::Api::V1::CreditCardsController < Stay::BaseApiController
38
45
  end
39
46
 
40
47
  def update
41
- if @credit_card.update(credit_card_params)
48
+ if @credit_card.update(credit_card_params.except(:card_token))
42
49
  render json: { message: "Credit card updated successfully", data: CreditCardSerializer.new(@credit_card), success: true }, status: :ok
43
50
  else
44
51
  render json: { error: "Credit card not updated", success: false, errors: @credit_card.errors.full_messages }, status: :unprocessable_entity
45
52
  end
46
53
  end
47
54
 
48
- # def destroy
49
- # @credit_card.destroy
50
- # render json: { message: "Credit card successfully deleted", success: true }, status: :ok
51
- # end
55
+ def destroy
56
+ begin
57
+ destroy_payment_method(@credit_card.payment_method_token)
58
+
59
+ if @credit_card.destroy
60
+ render json: { message: "Credit card successfully deleted", success: true }, status: :ok
61
+ else
62
+ render json: { error: "Failed to delete credit card", success: false, errors: @credit_card.errors.full_messages }, status: :unprocessable_entity
63
+ end
64
+ rescue Stripe::InvalidRequestError => e
65
+ render json: { error: "Stripe error: #{e.message}", success: false }, status: :unprocessable_entity
66
+ rescue ActiveRecord::RecordNotFound
67
+ render json: { error: "Credit card not found", success: false }, status: :not_found
68
+ rescue StandardError => e
69
+ render json: { error: "An unexpected error occurred: #{e.message}", success: false }, status: :internal_server_error
70
+ end
71
+ end
72
+
52
73
 
53
74
  private
54
75
 
@@ -57,6 +78,6 @@ class Stay::Api::V1::CreditCardsController < Stay::BaseApiController
57
78
  end
58
79
 
59
80
  def credit_card_params
60
- params.require(:credit_card).permit(:month, :year, :cc_number, :cc_type, :name)
81
+ params.require(:credit_card).permit(:month, :year, :cc_number, :cc_type, :name, :card_token, :payment_method_token)
61
82
  end
62
83
  end
@@ -19,22 +19,26 @@ class Stay::Api::V1::MessagesController < Stay::BaseApiController
19
19
  total_pages = (total_count.to_f / per_page).ceil
20
20
 
21
21
  messages = @chat.messages
22
- .order(created_at: :asc)
23
- .limit(cumulative_limit)
22
+ .order(created_at: :desc)
23
+ .limit(cumulative_limit)
24
24
 
25
- chat_json = ChatSerializer.new(
26
- @chat,
27
- scope: { current_user: current_devise_api_user }
28
- ).as_json
25
+ grouped_messages = messages
26
+ .select("DATE(created_at) as message_date, stay_messages.*")
27
+ .group_by { |message| message.created_at.to_date }
29
28
 
30
- messages_json = messages.map do |message|
31
- MessageSerializer.new(message, scope: current_devise_api_user).as_json
29
+ grouped_messages_json = grouped_messages.transform_keys(&:to_s).map do |date, msgs|
30
+ {
31
+ date: formatted_date(date.to_date),
32
+ messages: ActiveModelSerializers::SerializableResource.new(msgs, each_serializer: MessageSerializer)
33
+ }
32
34
  end
33
35
 
36
+ serialized_chat = ActiveModelSerializers::SerializableResource.new(@chat, serializer: ChatSerializer, scope: { current_user: current_devise_api_user })
37
+
34
38
  render json: {
35
39
  data: "Messages Found",
36
- chat: chat_json,
37
- message: messages_json,
40
+ chat: serialized_chat,
41
+ message: grouped_messages_json,
38
42
  success: true,
39
43
  meta: {
40
44
  total_pages: total_pages,
@@ -48,6 +52,7 @@ class Stay::Api::V1::MessagesController < Stay::BaseApiController
48
52
  render json: { error: e.message, success: false }, status: :internal_server_error
49
53
  end
50
54
  end
55
+
51
56
  def new
52
57
  @message = @chat.messages.new
53
58
  render json: { data: "Message form loaded", message: @message, success: true }, status: :ok
@@ -1,5 +1,5 @@
1
1
  class Stay::Api::V1::PaymentsController < Stay::BaseApiController
2
- include Stay::StripeConcern
2
+ include Stay::StripeConcern
3
3
 
4
4
  before_action :set_booking, except: :payment_method
5
5
  before_action :authenticate_devise_api_token!
@@ -13,33 +13,80 @@ class Stay::Api::V1::PaymentsController < Stay::BaseApiController
13
13
  render json: { error: "no method found", success: false }, status: :unprocessable_entity
14
14
  end
15
15
  end
16
-
16
+
17
+ def create_payment_method
18
+ payment_method = create_payment_method(payment_method_params)
19
+ attach_payment_method(payment_method.id)
20
+ render json: { message: "Payment method created and attached successfully.", payment_method: payment_method }
21
+ rescue Stripe::StripeError => e
22
+ render json: { error: e.message }, status: :unprocessable_entity
23
+ end
24
+
25
+ def list_payment_methods
26
+ payment_methods = list_payment_methods
27
+ render json: { payment_methods: payment_methods.data }
28
+ rescue Stripe::StripeError => e
29
+ render json: { error: e.message }, status: :unprocessable_entity
30
+ end
31
+
17
32
  def create
18
- begin
19
- customer = create_or_retrieve_customer
20
- payment_intent = @booking.payment_intent_id ? get_payment_intent : create_payment_intent.tap { |pi| @booking.update(payment_intent_id: pi.id) }
21
- if params[:confirm]
22
- if payment_intent.status == 'succeeded'
23
- render json: { message: "Payment successful", payment_intent: payment_intent }, status: :ok
24
- elsif payment_intent.status == 'requires_action'
25
- render json: { message: "Payment requires further action", client_secret: payment_intent.client_secret, payment_intent_id: payment_intent["id"] }, status: :ok
26
- else
27
- render json: { message: "Payment failed", error: payment_intent.last_payment_error }, status: :unprocessable_entity
28
- end
29
- else
30
- render json: {payment_intent: payment_intent, client_secret: payment_intent.client_secret}, status: :ok
31
- end
32
- rescue Stripe::CardError => e
33
- render json: { error: e.message }, status: :unprocessable_entity
34
- rescue => e
35
- render json: { error: "Something went wrong" }, status: :internal_server_error
33
+ begin
34
+ customer = create_or_retrieve_customer
35
+
36
+ payment_intent = if @booking.payment_intent_id && @booking.payment_state == "confirmed"
37
+ get_payment_intent
38
+ else
39
+ create_payment_intent
40
+ end
41
+
42
+ payment_status = case payment_intent.status
43
+ when "succeeded"
44
+ "confirmed"
45
+ when "requires_action"
46
+ "pending"
47
+ else
48
+ "failed"
49
+ end
50
+ create_payment(payment_intent, payment_status, @booking)
51
+ @booking.update(payment_intent_id: payment_intent.id, payment_state:payment_status)
52
+
53
+ if payment_intent.status == "requires_action"
54
+ render json: {
55
+ message: "Payment requires further action",
56
+ client_secret: payment_intent.client_secret,
57
+ payment_intent_id: payment_intent.id
58
+ }, status: :ok
59
+ elsif payment_intent.status == "succeeded"
60
+ render json: {
61
+ message: "Payment successful",
62
+ payment_intent: payment_intent
63
+ }, status: :ok
64
+ else
65
+ render json: {
66
+ message: "Payment failed",
67
+ error: payment_intent.last_payment_error
68
+ }, status: :unprocessable_entity
36
69
  end
70
+ rescue Stripe::CardError => e
71
+ render json: { error: e.message }, status: :unprocessable_entity
72
+ rescue => e
73
+ render json: { error: e.message }, status: :internal_server_error
74
+ end
75
+ end
76
+
77
+ def create_payment(payment_intent, status, booking)
78
+ Stay::Payment.create!(
79
+ booking: booking,
80
+ payment_method: Stay::PaymentMethod.last,
81
+ amount: booking.total_amount,
82
+ state: status,
83
+ )
37
84
  end
38
-
85
+
39
86
  def confirm
40
87
  payment_intent = get_payment_intent
41
- if payment_intent.status == 'succeeded'
42
- @booking.update(status: 'completed')
88
+ if payment_intent.status == "succeeded"
89
+ @booking.update(status: "completed")
43
90
  render json: { success: true, redirect_url: params[:redirect_url] }
44
91
  else
45
92
  render json: { error: payment_intent.last_payment_error.message }, status: 422
@@ -48,14 +95,12 @@ class Stay::Api::V1::PaymentsController < Stay::BaseApiController
48
95
 
49
96
  private
50
97
 
51
-
98
+
52
99
  def payment_params
53
100
  params.require(:payment).permit(:amount, :currency, :payment_method_id, :description, :customer_email)
54
101
  end
55
-
102
+
56
103
  def set_booking
57
104
  @booking = Stay::Booking.find(params[:booking_id])
58
105
  end
59
-
60
- end
61
-
106
+ end
@@ -21,7 +21,7 @@ class Stay::Api::V1::ProfilesController < Stay::BaseApiController
21
21
  end
22
22
 
23
23
  def profile_params
24
- params.require(:profile).permit(:first_name, :last_name, :phone, :date_of_birth, :gender, :profile_image )
24
+ params.require(:profile).permit(:first_name, :last_name, :phone, :date_of_birth, :gender, :profile_image, :about_me )
25
25
  end
26
26
 
27
27
  end
@@ -200,7 +200,7 @@ class Stay::Api::V1::PropertiesController < Stay::BaseApiController
200
200
  property_house_rules_attributes: [ :id, :house_rule_id, :value, :_destroy ],
201
201
  property_amenities_attributes: [ :id, :amenity_id, :_destroy ],
202
202
  property_features_attributes: [ :id, :name, :feature_id, :_destroy ],
203
- rooms_attributes: [ :id, :max_guests, :price_per_month, :status, :booking_start, :booking_end, :description, :size, :bed_type_id, :room_type_id, :_destroy, room_images: [],
203
+ rooms_attributes: [ :id, :name, :max_guests, :price_per_month, :status, :booking_start, :booking_end, :description, :size, :bed_type_id, :room_type_id, :_destroy, room_images: [],
204
204
  room_features_attributes: [ :id, :feature_id, :_destroy ],
205
205
  room_amenities_attributes: [ :id, :amenity_id, :_destroy ]
206
206
  ],
@@ -1,11 +1,11 @@
1
1
  class Stay::PaymentsController < ApplicationController
2
2
  include Stay::StripeConcern
3
-
4
- before_action :authenticate_user!
3
+ skip_before_action :verify_authenticity_token
4
+ before_action :authenticate_devise_api_token!
5
5
  before_action :set_property_and_booking
6
-
6
+
7
7
  def new
8
- render layout: 'stay/application'
8
+ render layout: "stay/application"
9
9
  end
10
10
 
11
11
  def create
@@ -13,28 +13,28 @@ class Stay::PaymentsController < ApplicationController
13
13
  @customer = create_or_retrieve_customer
14
14
  payment_intent = @booking.payment_intent_id ? get_payment_intent : create_payment_intent.tap { |pi| @booking.update(payment_intent_id: pi.id) }
15
15
  if params[:confirm]
16
- if payment_intent.status == 'succeeded'
16
+ if payment_intent.status == "succeeded"
17
17
  render json: { success: true, redirect_url: params[:redirect_url] }, status: :ok
18
- elsif payment_intent.status == 'requires_action'
18
+ elsif payment_intent.status == "requires_action"
19
19
  render json: { message: "Payment requires further action", client_secret: payment_intent.client_secret }, status: :ok
20
20
  else
21
21
  render json: { message: "Payment failed", error: payment_intent.last_payment_error }, status: :unprocessable_entity
22
22
  end
23
- else
24
- render json: {payment_intent: payment_intent, client_secret: payment_intent.client_secret}, status: :ok
23
+ else
24
+ render json: { payment_intent: payment_intent, client_secret: payment_intent.client_secret }, status: :ok
25
25
  end
26
26
  rescue Stripe::CardError => e
27
27
  render json: { error: e.message }, status: :unprocessable_entity
28
28
  rescue => e
29
- render json: { error: e.message}, status: :internal_server_error
29
+ render json: { error: e.message }, status: :internal_server_error
30
30
  end
31
31
  end
32
32
 
33
33
  def confirm
34
34
  payment_intent = get_payment_intent
35
- if payment_intent.status == 'succeeded'
36
- @booking.update(status: 'completed')
37
- flash[:notice] = 'Payment Completed Successfully'
35
+ if payment_intent.status == "succeeded"
36
+ @booking.update(status: "completed")
37
+ flash[:notice] = "Payment Completed Successfully"
38
38
  render json: { success: true, redirect_url: params[:redirect_url] }
39
39
  else
40
40
  flash[:alert] = payment_intent.last_payment_error.message
@@ -47,4 +47,4 @@ class Stay::PaymentsController < ApplicationController
47
47
  @property = Stay::Property.find(params[:property_id])
48
48
  @booking = Stay::Booking.find(params[:booking_id])
49
49
  end
50
- end
50
+ end
@@ -1,11 +1,11 @@
1
1
  module Stay
2
2
  class Amenity < ApplicationRecord
3
3
  belongs_to :amenity_category, class_name: "Stay::AmenityCategory", optional: true
4
- has_many :property_amenities, class_name: "Stay::PropertyAmenity"
4
+ has_many :property_amenities, class_name: "Stay::PropertyAmenity", dependent: :destroy
5
5
  has_many :properties, through: :property_amenities, class_name: "Stay::Property"
6
6
  enum :amenity_type, { property: 0, room: 1 }
7
7
 
8
- has_many :room_amenities, class_name: "Stay::RoomAmenity"
8
+ has_many :room_amenities, class_name: "Stay::RoomAmenity", dependent: :destroy
9
9
  has_many :rooms, through: :room_amenities, class_name: "Stay::Room"
10
10
  end
11
11
  end
@@ -19,6 +19,9 @@ module Stay
19
19
  scope :incomplete, -> { where(completed_at: nil).where(payment_state: [ "failed", nil ]).where.not(status: :canceled) }
20
20
  scope :not_canceled, -> { where.not(status: "canceled") }
21
21
  scope :confirmed, -> { where(status: "confirmed").where(payment_state: "paid") }
22
+ scope :current_host_booking, ->(host) {
23
+ joins(:property).where(stay_properties: { user: host })
24
+ }
22
25
 
23
26
  after_commit :booking_completed_at
24
27
  before_create :link_by_email, :generate_number
@@ -1,8 +1,8 @@
1
1
  module Stay
2
2
  class Feature < ApplicationRecord
3
- has_many :property_features, class_name: "Stay::PropertyFeature"
3
+ has_many :property_features, class_name: "Stay::PropertyFeature", dependent: :destroy
4
4
  has_many :properties, through: :property_features, class_name: "Stay::Property"
5
- has_many :room_features, class_name: "Stay::RoomFeature"
5
+ has_many :room_features, class_name: "Stay::RoomFeature", dependent: :destroy
6
6
  has_many :rooms, through: :room_features, class_name: "Stay::Room"
7
7
 
8
8
  enum :feature_type, { property: 0, room: 1 }
@@ -5,6 +5,9 @@ module Stay
5
5
  devise :database_authenticatable, :registerable,
6
6
  :recoverable, :rememberable, :validatable, :api
7
7
 
8
+
9
+ Stripe.api_key = ENV["STRIPES_SECRECT_KEY"]
10
+
8
11
  has_many :role_users, class_name: "Stay::RoleUser", dependent: :destroy
9
12
  has_many :stay_roles, through: :role_users, class_name: "Stay::Role", source: :role
10
13
  has_many :bookings
@@ -35,8 +38,7 @@ module Stay
35
38
 
36
39
  # callbacks
37
40
  after_create :welcome_email
38
- # after_create :assign_default_role
39
- # after_create :admin_host_email
41
+ after_create :create_stripe_account
40
42
 
41
43
  attr_accessor :updating_password
42
44
 
@@ -106,5 +108,23 @@ module Stay
106
108
  def assign_default_role
107
109
  Stay::RoleUser.create(user: self, role: Stay::Role.where(name: Stay::Role::USER).first_or_create) unless stay_roles.exists?
108
110
  end
111
+
112
+ def create_stripe_account
113
+ user = self
114
+ customer = Stripe::Customer.create({
115
+ email: user.email,
116
+ name: "#{user&.first_name} #{user&.last_name}",
117
+ address: {
118
+ city: user&.addresses&.last&.city,
119
+ state: user&.addresses&.last&.state&.name,
120
+ country: user&.addresses&.last&.country&.name,
121
+ line1: user&.addresses&.last&.address1,
122
+ line2: user&.addresses&.last&.address2,
123
+ postal_code: user&.addresses&.last&.zipcode
124
+ },
125
+ })
126
+ user.update(stripe_customer_id: customer.id)
127
+
128
+ end
109
129
  end
110
130
  end
@@ -0,0 +1,64 @@
1
+ class BookingListingSerializer < ActiveModel::Serializer
2
+ attributes :id, :number, :total, :total_amount, :check_in_date, :check_out_date, :item_total, :is_shared_property, :booked_room, :room_images,
3
+ :number_of_guests, :payment_state, :status, :request_by, :invoice_no, :calculate_cleaning_fee, :calculate_city_fee, :extra_guest_amount, :property
4
+
5
+
6
+ def total
7
+ object.total_amount
8
+ end
9
+
10
+ def property
11
+ property = object.property
12
+
13
+ {
14
+ id: property.id,
15
+ title: property.title,
16
+ price_per_month: property.price_per_month,
17
+ city: property.city,
18
+ state: property.state,
19
+ slug: property.slug,
20
+ rooms_count:property.rooms.count,
21
+ }
22
+ end
23
+
24
+ def room_images
25
+ object.rooms.last.room_images.map(&:url).compact
26
+ end
27
+
28
+ def is_shared_property
29
+ object.property&.shared_property
30
+ end
31
+
32
+ def booked_room
33
+ object.line_items.any? ? object.line_items.last.room&.name : nil
34
+ end
35
+
36
+ def calculate_cleaning_fee
37
+ nil # object.property.cleaning_fee
38
+ end
39
+
40
+ def calculate_city_fee
41
+ nil # object.property.city_fee
42
+ end
43
+
44
+ def extra_guest_amount
45
+ object.extra_guest_amount
46
+ end
47
+
48
+ def check_in_date
49
+ object.check_in_date.strftime("%B %d, %Y")
50
+ end
51
+
52
+ def check_out_date
53
+ object.check_out_date.strftime("%B %d, %Y")
54
+ end
55
+
56
+ def request_by
57
+ object.user&.full_name || nil
58
+ end
59
+
60
+ def invoice_no
61
+ object.invoice ? object.invoice.id : nil
62
+ end
63
+
64
+ end
@@ -1,6 +1,6 @@
1
1
  class BookingSerializer < ActiveModel::Serializer
2
2
  attributes :id, :number, :calculate_totals, :tax_total, :total, :total_amount, :item_total, :room_count, :check_in_date, :check_out_date,
3
- :number_of_guests, :completed_at, :payment_state, :calculate_city_fee, :calculate_cleaning_fee, :status, :invoice_total, :extra_guest_amount, :last_five_messages
3
+ :number_of_guests, :completed_at, :payment_state, :calculate_city_fee, :calculate_cleaning_fee, :status, :invoice_total, :extra_guest_amount, :last_five_messages , :property_user
4
4
  belongs_to :property, serializer: PropertyListingSerializer
5
5
  belongs_to :user, serializer: UserListingSerializer
6
6
  has_many :line_items, serializer: LineItemSerializer
@@ -40,6 +40,10 @@ class BookingSerializer < ActiveModel::Serializer
40
40
  object.extra_guest_amount
41
41
  end
42
42
 
43
+ def property_user
44
+ object.property.user.present? ? UserListingSerializer.new(object.property.user) : nil
45
+ end
46
+
43
47
  def invoice_total
44
48
  object.invoice&.total
45
49
  end
@@ -1,7 +1,3 @@
1
1
  class CreditCardSerializer < ActiveModel::Serializer
2
- attributes :id, :month, :year, :cc_number, :cc_type, :name, :user
3
- belongs_to :user
4
- # def user
5
- # UserSerializer.new(object.user)
6
- # end
2
+ attributes :id, :month, :year, :cc_number, :cc_type, :name, :payment_method_token, :card_token
7
3
  end
@@ -1,7 +1,7 @@
1
1
  class PropertyListingSerializer < ActiveModel::Serializer
2
2
  attributes :id, :title, :price_per_month, :place_images, :total_rooms,
3
3
  :availability_end, :availability_start, :extra_guest, :latitude,
4
- :longitude, :address, :city, :state, :country, :active, :property_state, :slug
4
+ :longitude, :address, :city, :state, :country, :active, :property_state, :slug ,:description
5
5
 
6
6
  belongs_to :property_category, Serializer: :PropertyCategorySerializer
7
7
  belongs_to :property_type, Serializer: :PropertyTypeSerializer
@@ -1,8 +1,8 @@
1
- # API_CONFIG = YAML.load_file(Rails.root.join('config', 'api_config.yml'))[Rails.env]
1
+ require "dotenv/load"
2
2
 
3
- # Rails.configuration.stripe = {
4
- # publishable_key: API_CONFIG['stripe_publishable_key'],
5
- # secret_key: API_CONFIG['stripe_secret_key']
6
- # }
3
+ Rails.configuration.stripe = {
4
+ publishable_key: ENV["PUBLISHABLE_KEY"],
5
+ secret_key: ENV["SECRET_KEY"]
6
+ }
7
7
 
8
- # Stripe.api_key = Rails.configuration.stripe[:secret_key]
8
+ Stripe.api_key = Rails.configuration.stripe[:secret_key]
data/config/routes.rb CHANGED
@@ -27,7 +27,11 @@ Stay::Engine.routes.draw do
27
27
  resources :rooms
28
28
  resources :bookings
29
29
  resources :payment_methods
30
- resources :payments
30
+ resources :payments do
31
+ collection do
32
+ post :create_payment_method
33
+ end
34
+ end
31
35
  resources :reviews
32
36
  resources :chats
33
37
  resources :messages
@@ -0,0 +1,5 @@
1
+ class AddStripeCustomerIdToStayUsers < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :stay_users, :stripe_customer_id, :string
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddPaymentMethodIdToCreditCards < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :stay_credit_cards, :payment_method_token, :string, null: true
4
+ add_column :stay_credit_cards, :card_token, :string, null: true
5
+ end
6
+ end
data/lib/stay/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Stay
2
- VERSION = "0.1.14"
2
+ VERSION = "0.1.16"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stay_commerce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.1.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - w3villa-vikaspal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-28 00:00:00.000000000 Z
11
+ date: 2025-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -422,20 +422,34 @@ dependencies:
422
422
  - - ">="
423
423
  - !ruby/object:Gem::Version
424
424
  version: '0'
425
+ - !ruby/object:Gem::Dependency
426
+ name: dotenv-rails
427
+ requirement: !ruby/object:Gem::Requirement
428
+ requirements:
429
+ - - ">="
430
+ - !ruby/object:Gem::Version
431
+ version: '0'
432
+ type: :runtime
433
+ prerelease: false
434
+ version_requirements: !ruby/object:Gem::Requirement
435
+ requirements:
436
+ - - ">="
437
+ - !ruby/object:Gem::Version
438
+ version: '0'
425
439
  - !ruby/object:Gem::Dependency
426
440
  name: letter_opener
427
441
  requirement: !ruby/object:Gem::Requirement
428
442
  requirements:
429
- - - "~>"
443
+ - - ">="
430
444
  - !ruby/object:Gem::Version
431
- version: '1.10'
445
+ version: '0'
432
446
  type: :development
433
447
  prerelease: false
434
448
  version_requirements: !ruby/object:Gem::Requirement
435
449
  requirements:
436
- - - "~>"
450
+ - - ">="
437
451
  - !ruby/object:Gem::Version
438
- version: '1.10'
452
+ version: '0'
439
453
  description: Description of Stay.
440
454
  email:
441
455
  - vikas.pal@w3villa.com
@@ -606,6 +620,7 @@ files:
606
620
  - app/serializers/amenity_category_serializer.rb
607
621
  - app/serializers/amenity_serializer.rb
608
622
  - app/serializers/bed_type_serializer.rb
623
+ - app/serializers/booking_listing_serializer.rb
609
624
  - app/serializers/booking_query_serializer.rb
610
625
  - app/serializers/booking_serializer.rb
611
626
  - app/serializers/cancellation_policy_serializer.rb
@@ -936,6 +951,8 @@ files:
936
951
  - db/migrate/20241205092943_create_friendly_id_slugs.rb
937
952
  - db/migrate/20241217044817_add_deleted_atto_stay_property.rb
938
953
  - db/migrate/20241230064432_modify_property_category_on_properties.rb
954
+ - db/migrate/20250123053039_add_stripe_customer_id_to_stay_users.rb
955
+ - db/migrate/20250123112636_add_payment_method_id_to_credit_cards.rb
939
956
  - db/migrate/20250407101335_add_field_to_stay_users.rb
940
957
  - db/seeds.rb
941
958
  - lib/stay.rb