Skip to content

Commit 73cbd3d

Browse files
committed
generate receipt after sale
1 parent 515c193 commit 73cbd3d

22 files changed

+699
-16
lines changed

Gemfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ gem "aws-sdk-s3", require: false
4848
gem "pdftoimage"
4949
gem "money-rails"
5050
gem "prawn"
51+
gem "prawn-table"
5152
gem "omise"
5253
gem "pagy"
5354
gem "openssl"
@@ -68,13 +69,16 @@ group :development, :test do
6869
gem "rspec-rails"
6970
gem "factory_bot_rails"
7071
gem "launchy"
71-
gem "rack-mini-profiler", require: false
72+
gem "rack-mini-profiler"
7273
gem "sinatra", require: false
7374
end
7475

7576
group :development do
7677
# Use console on exceptions pages [https://github.com/rails/web-console]
7778
gem "web-console"
79+
80+
# Preview emails in the browser instead of sending them
81+
gem "letter_opener"
7882
end
7983

8084
group :test do

Gemfile.lock

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ GEM
224224
addressable (~> 2.8)
225225
childprocess (~> 5.0)
226226
logger (~> 1.6)
227+
letter_opener (1.10.0)
228+
launchy (>= 2.2, < 4)
227229
lint_roller (1.1.0)
228230
logger (1.7.0)
229231
loofah (2.24.1)
@@ -314,6 +316,8 @@ GEM
314316
matrix (~> 0.4)
315317
pdf-core (~> 0.10.0)
316318
ttfunk (~> 1.8)
319+
prawn-table (0.2.2)
320+
prawn (>= 1.3.0, < 3.0.0)
317321
prettyprint (0.2.0)
318322
prism (1.6.0)
319323
propshaft (1.3.1)
@@ -397,7 +401,7 @@ GEM
397401
rspec-expectations (3.13.5)
398402
diff-lcs (>= 1.2.0, < 2.0)
399403
rspec-support (~> 3.13.0)
400-
rspec-mocks (3.13.6)
404+
rspec-mocks (3.13.7)
401405
diff-lcs (>= 1.2.0, < 2.0)
402406
rspec-support (~> 3.13.0)
403407
rspec-rails (8.0.2)
@@ -578,13 +582,15 @@ DEPENDENCIES
578582
jbuilder
579583
kamal
580584
launchy
585+
letter_opener
581586
money-rails
582587
omise
583588
openssl
584589
pagy
585590
pdftoimage
586591
pg (~> 1.1)
587592
prawn
593+
prawn-table
588594
propshaft
589595
puma (>= 5.0)
590596
pundit (~> 2.5)
34.2 KB
Binary file not shown.
36.4 KB
Binary file not shown.
34.5 KB
Binary file not shown.
36.8 KB
Binary file not shown.

app/controllers/orders_controller.rb

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class OrdersController < ApplicationController
2-
before_action :set_order, only: %i[ verify complete ]
2+
before_action :set_order, only: %i[ verify complete receipt ]
33

44
# POST /orders or /orders.json
55
def create
@@ -53,9 +53,18 @@ def verify
5353

5454
if charge.paid
5555
@order.paid!
56+
@order.update!(paid_at: Time.current)
5657

5758
# Create subscription for the user
5859
if CreateSubscriptionForOrder.new(@order).perform
60+
# Generate receipt number and send email
61+
@order.generate_receipt_number
62+
@order.save!
63+
64+
# Send receipt email with PDF attachment
65+
OrderMailer.receipt_email(@order).deliver_later
66+
@order.update!(receipt_sent_at: Time.current)
67+
5968
# Clear the user's cart after successful order
6069
ClearCurrentUserCart.new(@order.member).perform
6170
redirect_to complete_order_path(@order)
@@ -79,6 +88,27 @@ def verify
7988
def complete
8089
end
8190

91+
def receipt
92+
# Check if order belongs to current user
93+
unless @order.member == current_user
94+
redirect_to root_path, alert: "Unauthorized access" and return
95+
end
96+
97+
# Check if receipt number exists (order is paid)
98+
unless @order.receipt_number.present?
99+
redirect_to root_path, alert: "Receipt not available" and return
100+
end
101+
102+
# Generate PDF
103+
pdf = Receipts::SimplifiedReceiptPdf.new(@order)
104+
105+
# Send PDF as download
106+
send_data pdf.render,
107+
filename: "receipt-#{@order.receipt_number}.pdf",
108+
type: "application/pdf",
109+
disposition: "attachment"
110+
end
111+
82112
private
83113
def set_order
84114
@order = Order.find(params[:id])

app/mailers/application_mailer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
class ApplicationMailer < ActionMailer::Base
2-
default from: "from@example.com"
2+
default from: -> { Company.first&.email || "noreply@dailynews.com" }
33
layout "mailer"
44
end

app/mailers/order_mailer.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class OrderMailer < ApplicationMailer
2+
default from: Rails.application.credentials.dig(:smtp, :from)
3+
4+
def receipt_email(order)
5+
@order = order
6+
@subscription = order.subscription
7+
@product = order.product
8+
@user = order.member
9+
10+
# Generate PDF receipt
11+
pdf = Receipts::SimplifiedReceiptPdf.new(order)
12+
13+
# Attach PDF to email
14+
attachments["receipt-#{order.receipt_number}.pdf"] = pdf.render
15+
16+
mail(
17+
to: @user.email,
18+
subject: "ใบเสร็จรับเงิน - #{@product.title}"
19+
)
20+
end
21+
end

app/models/order.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,26 @@ def tax_amount
3333
def tax_rate_percentage
3434
(TAX_RATE * 100).to_i
3535
end
36+
37+
# Generate receipt number in format: DNT-YYYYMMDD-XXXXX
38+
def generate_receipt_number
39+
return if receipt_number.present?
40+
41+
date_prefix = Time.current.strftime("%Y%m%d")
42+
43+
# Get the last receipt number for today
44+
last_receipt = Order.where("receipt_number LIKE ?", "DNT-#{date_prefix}-%")
45+
.order(receipt_number: :desc)
46+
.first
47+
48+
if last_receipt && last_receipt.receipt_number.present?
49+
# Extract sequence number and increment
50+
sequence = last_receipt.receipt_number.split("-").last.to_i + 1
51+
else
52+
# Start with 1 for the first receipt of the day
53+
sequence = 1
54+
end
55+
56+
self.receipt_number = "DNT-#{date_prefix}-#{sequence.to_s.rjust(5, '0')}"
57+
end
3658
end

0 commit comments

Comments
 (0)