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 +4 -4
- data/app/controllers/concerns/stay/stripe_concern.rb +99 -64
- data/app/controllers/stay/api/v1/bookings_controller.rb +31 -35
- data/app/controllers/stay/api/v1/credit_cards_controller.rb +33 -12
- data/app/controllers/stay/api/v1/messages_controller.rb +15 -10
- data/app/controllers/stay/api/v1/payments_controller.rb +73 -28
- data/app/controllers/stay/api/v1/profiles_controller.rb +1 -1
- data/app/controllers/stay/api/v1/properties_controller.rb +1 -1
- data/app/controllers/stay/payments_controller.rb +13 -13
- data/app/models/stay/amenity.rb +2 -2
- data/app/models/stay/booking.rb +3 -0
- data/app/models/stay/feature.rb +2 -2
- data/app/models/stay/user.rb +22 -2
- data/app/serializers/booking_listing_serializer.rb +64 -0
- data/app/serializers/booking_serializer.rb +5 -1
- data/app/serializers/credit_card_serializer.rb +1 -5
- data/app/serializers/property_listing_serializer.rb +1 -1
- data/config/initializers/stripe.rb +6 -6
- data/config/routes.rb +5 -1
- data/db/migrate/20250123053039_add_stripe_customer_id_to_stay_users.rb +5 -0
- data/db/migrate/20250123112636_add_payment_method_id_to_credit_cards.rb +6 -0
- data/lib/stay/version.rb +1 -1
- metadata +23 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea9bf5bd2ce5586107d49503bcbbab44973eb929e6cf58fbe762892444a437ec
|
4
|
+
data.tar.gz: f32e5da8fb4d2b3840efc4115ca06ebcde81cbf9bc95b8c8cb505a845a9a384a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
4
|
-
def user
|
5
|
-
current_devise_api_user || current_user
|
6
|
-
end
|
6
|
+
extend ActiveSupport::Concern
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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:
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
23
|
-
|
22
|
+
.order(created_at: :desc)
|
23
|
+
.limit(cumulative_limit)
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
31
|
-
|
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:
|
37
|
-
message:
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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 ==
|
42
|
-
@booking.update(status:
|
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 :
|
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:
|
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 ==
|
16
|
+
if payment_intent.status == "succeeded"
|
17
17
|
render json: { success: true, redirect_url: params[:redirect_url] }, status: :ok
|
18
|
-
elsif payment_intent.status ==
|
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 ==
|
36
|
-
@booking.update(status:
|
37
|
-
flash[:notice] =
|
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
|
data/app/models/stay/amenity.rb
CHANGED
@@ -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
|
data/app/models/stay/booking.rb
CHANGED
@@ -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
|
data/app/models/stay/feature.rb
CHANGED
@@ -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 }
|
data/app/models/stay/user.rb
CHANGED
@@ -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
|
-
|
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, :
|
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
|
-
|
1
|
+
require "dotenv/load"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Rails.configuration.stripe = {
|
4
|
+
publishable_key: ENV["PUBLISHABLE_KEY"],
|
5
|
+
secret_key: ENV["SECRET_KEY"]
|
6
|
+
}
|
7
7
|
|
8
|
-
|
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
|
data/lib/stay/version.rb
CHANGED
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.
|
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-
|
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: '
|
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: '
|
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
|