auctify 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +229 -0
- data/Rakefile +34 -0
- data/app/assets/config/auctify_manifest.js +1 -0
- data/app/assets/javascripts/folio/console/main_app.coffee +1 -0
- data/app/assets/stylesheets/auctify/application.css +15 -0
- data/app/assets/stylesheets/auctify/bidder_registrations.css +4 -0
- data/app/assets/stylesheets/auctify/bids.css +4 -0
- data/app/assets/stylesheets/auctify/sales.css +4 -0
- data/app/assets/stylesheets/auctify/sales_packs.css +4 -0
- data/app/assets/stylesheets/folio/console/_main_app.sass +1 -0
- data/app/assets/stylesheets/scaffold.css +80 -0
- data/app/cells/folio/console/atoms/previews/main_app.coffee +1 -0
- data/app/concerns/auctify/behavior/base.rb +20 -0
- data/app/concerns/auctify/behavior/buyer.rb +16 -0
- data/app/concerns/auctify/behavior/item.rb +27 -0
- data/app/concerns/auctify/behavior/seller.rb +36 -0
- data/app/concerns/auctify/sale/auction_callbacks.rb +44 -0
- data/app/controllers/auctify/api/v1/auctions_controller.rb +61 -0
- data/app/controllers/auctify/api/v1/base_controller.rb +22 -0
- data/app/controllers/auctify/api/v1/console/bids_controller.rb +37 -0
- data/app/controllers/auctify/application_controller.rb +8 -0
- data/app/controllers/auctify/bidder_registrations_controller.rb +65 -0
- data/app/controllers/auctify/bids_controller.rb +64 -0
- data/app/controllers/auctify/sales_controller.rb +75 -0
- data/app/controllers/auctify/sales_packs_controller.rb +75 -0
- data/app/helpers/auctify/application_helper.rb +10 -0
- data/app/helpers/auctify/bidder_registrations_helper.rb +6 -0
- data/app/helpers/auctify/bids_helper.rb +6 -0
- data/app/helpers/auctify/sales_helper.rb +15 -0
- data/app/helpers/auctify/sales_packs_helper.rb +6 -0
- data/app/jobs/auctify/application_job.rb +6 -0
- data/app/jobs/auctify/bidding_closer_job.rb +23 -0
- data/app/jobs/auctify/bidding_is_close_to_end_notifier_job.rb +29 -0
- data/app/mailers/auctify/application_mailer.rb +8 -0
- data/app/models/auctify/application_record.rb +14 -0
- data/app/models/auctify/behaviors.rb +27 -0
- data/app/models/auctify/bid.rb +72 -0
- data/app/models/auctify/bidder_registration.rb +84 -0
- data/app/models/auctify/sale/auction.rb +404 -0
- data/app/models/auctify/sale/base.rb +210 -0
- data/app/models/auctify/sale/retail.rb +97 -0
- data/app/models/auctify/sales_pack.rb +101 -0
- data/app/serializers/auctify/sale/auction_serializer.rb +46 -0
- data/app/services/auctify/bids_appender.rb +241 -0
- data/app/services/auctify/service_base.rb +78 -0
- data/app/types/auctify/minimal_bids_ladder_type.rb +77 -0
- data/app/views/auctify/api/v1/console/bids/index.html.erb +1 -0
- data/app/views/auctify/api/v1/console/bids/show.html.erb +1 -0
- data/app/views/auctify/bidder_registrations/_form.html.erb +27 -0
- data/app/views/auctify/bidder_registrations/edit.html.erb +6 -0
- data/app/views/auctify/bidder_registrations/index.html.erb +33 -0
- data/app/views/auctify/bidder_registrations/new.html.erb +5 -0
- data/app/views/auctify/bidder_registrations/show.html.erb +24 -0
- data/app/views/auctify/bids/_form.html.erb +32 -0
- data/app/views/auctify/bids/edit.html.erb +6 -0
- data/app/views/auctify/bids/index.html.erb +31 -0
- data/app/views/auctify/bids/new.html.erb +5 -0
- data/app/views/auctify/bids/show.html.erb +19 -0
- data/app/views/auctify/sales/_form.html.erb +32 -0
- data/app/views/auctify/sales/edit.html.erb +6 -0
- data/app/views/auctify/sales/index.html.erb +36 -0
- data/app/views/auctify/sales/new.html.erb +5 -0
- data/app/views/auctify/sales/show.html.erb +19 -0
- data/app/views/auctify/sales_packs/_form.html.erb +57 -0
- data/app/views/auctify/sales_packs/edit.html.erb +6 -0
- data/app/views/auctify/sales_packs/index.html.erb +40 -0
- data/app/views/auctify/sales_packs/new.html.erb +5 -0
- data/app/views/auctify/sales_packs/show.html.erb +44 -0
- data/app/views/layouts/auctify/application.html.erb +15 -0
- data/config/locales/auctify.cs.yml +121 -0
- data/config/locales/default.cs.yml +220 -0
- data/config/locales/default.en.yml +215 -0
- data/config/routes.rb +23 -0
- data/db/migrate/20210212163000_create_auctify_sales.rb +16 -0
- data/db/migrate/20210216151350_add_type_to_auctify_sales.rb +7 -0
- data/db/migrate/20210217101246_add_state_to_auctify_sales.rb +7 -0
- data/db/migrate/20210217110819_add_prices_to_auctify_sales.rb +9 -0
- data/db/migrate/20210222103031_add_published_at_to_auctify_sale.rb +7 -0
- data/db/migrate/20210223090240_create_auctify_bidder_registrations.rb +15 -0
- data/db/migrate/20210223152139_create_auctify_bids.rb +13 -0
- data/db/migrate/20210225103227_add_bid_steps_ladder_to_auctify_sales.rb +7 -0
- data/db/migrate/20210412114319_add_reserve_price_to_auctify_sales.rb +7 -0
- data/db/migrate/20210416140603_create_auctify_sales_packs.rb +17 -0
- data/db/migrate/20210416141111_add_pack_reference_to_auctify_sales.rb +7 -0
- data/db/migrate/20210419075003_add_ends_at_to_auctify_sales.rb +7 -0
- data/db/migrate/20210419082800_add_position_to_auctify_sales.rb +8 -0
- data/db/migrate/20210419083321_add_indexes.rb +12 -0
- data/db/migrate/20210421093652_add_number_to_auctify_sales.rb +7 -0
- data/db/migrate/20210423071326_removing_polymorphic_assoc_sale_to_item.rb +7 -0
- data/db/migrate/20210423071534_add_currently_ends_at_to_auctify_sales.rb +7 -0
- data/db/migrate/20210427121353_change_column_published_on_auctify_sale.rb +15 -0
- data/db/migrate/20210427122315_add_featured_to_auctify_sales.rb +7 -0
- data/db/migrate/20210428045651_add_sales_bool_indices.rb +9 -0
- data/db/migrate/20210428064615_allow_seller_to_be_nil.rb +13 -0
- data/db/migrate/20210429051508_add_sales_pack_start_and_end.rb +15 -0
- data/db/migrate/20210430080419_add_sales_slug.rb +11 -0
- data/db/migrate/20210503095704_add_cancelled_to_auctify_bids.rb +7 -0
- data/db/migrate/20210504072041_add_commission_and_contract_to_auctify_sales.rb +8 -0
- data/db/migrate/20210506064100_add_winner_to_auctify_sales.rb +7 -0
- data/db/migrate/20210506072438_add_bids_count_to_auctify_sales.rb +7 -0
- data/db/migrate/20210507085845_rename_bids_count_to_applied_bids_count.rb +7 -0
- data/db/migrate/20210510063146_add_dont_confirm_bids_to_registrations.rb +7 -0
- data/db/migrate/20210511081556_add_index_on_cancelled_on.rb +7 -0
- data/db/migrate/20210512162942_add_sold_at_to_auctify_sales.rb +7 -0
- data/db/migrate/20210607113440_add_commission_in_percent_to_sales_packs.rb +7 -0
- data/db/migrate/20210617062509_add_index_to_auctify_sales_currently_ends_at.rb +7 -0
- data/db/migrate/20210625125732_add_current_winner_to_auctify_sales.rb +7 -0
- data/lib/auctify.rb +7 -0
- data/lib/auctify/configuration.rb +43 -0
- data/lib/auctify/engine.rb +25 -0
- data/lib/auctify/version.rb +5 -0
- data/lib/tasks/auctify_tasks.rake +23 -0
- metadata +442 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Auctify
|
4
|
+
module Sale
|
5
|
+
class Base < ApplicationRecord
|
6
|
+
include Folio::FriendlyId
|
7
|
+
include Folio::Positionable
|
8
|
+
include Folio::Featurable::Basic
|
9
|
+
include Folio::Publishable::Basic
|
10
|
+
|
11
|
+
self.table_name = "auctify_sales"
|
12
|
+
|
13
|
+
attribute :bid_steps_ladder, MinimalBidsLadderType.new
|
14
|
+
|
15
|
+
include Auctify::Behavior::Base
|
16
|
+
|
17
|
+
belongs_to :seller, polymorphic: true, optional: true
|
18
|
+
belongs_to :buyer, polymorphic: true, optional: true
|
19
|
+
# added on usage of `auctify_as :item` => belongs_to :item, class_name: ???
|
20
|
+
belongs_to :pack, class_name: "Auctify::SalesPack", inverse_of: :sales, optional: true, counter_cache: :sales_count
|
21
|
+
|
22
|
+
validate :valid_seller
|
23
|
+
validate :valid_item
|
24
|
+
validate :valid_buyer
|
25
|
+
|
26
|
+
validates :offered_price,
|
27
|
+
:current_price,
|
28
|
+
:sold_price,
|
29
|
+
:reserve_price,
|
30
|
+
numericality: { greater_than_or_equal_to: 0 },
|
31
|
+
allow_nil: true
|
32
|
+
|
33
|
+
validate :validate_offered_price_when_published
|
34
|
+
|
35
|
+
scope :not_sold, -> { where(sold_price: nil) }
|
36
|
+
|
37
|
+
# need auction scopes here because of has_many :sales, class_name: "Auctify::Sale::Base"
|
38
|
+
scope :auctions_open_for_bids, -> do
|
39
|
+
where(aasm_state: "in_sale").where("currently_ends_at > ?", Time.current)
|
40
|
+
end
|
41
|
+
|
42
|
+
scope :auctions_finished, -> do
|
43
|
+
where.not(aasm_state: %w[offered accepted refused]).where("currently_ends_at < ?", Time.current)
|
44
|
+
end
|
45
|
+
|
46
|
+
scope :latest_published_by_item, -> { joins(latest_published_sales_by_item_subtable.join_sources) }
|
47
|
+
|
48
|
+
delegate :to_label,
|
49
|
+
to: :item
|
50
|
+
|
51
|
+
def self.latest_published_sales_by_item_subtable
|
52
|
+
# see https://www.salsify.com/blog/engineering/most-recent-by-group-in-rails
|
53
|
+
sales_table = self.arel_table
|
54
|
+
|
55
|
+
latest_sales_query = sales_table.project(sales_table[:item_id],
|
56
|
+
sales_table[:id].maximum.as("latest_sale_id"))
|
57
|
+
.where(sales_table[:published].eq(true))
|
58
|
+
.group(sales_table[:item_id])
|
59
|
+
|
60
|
+
latest_sales_table = Arel::Table.new(latest_sales_query).alias(:latest_sales) # need to perform join
|
61
|
+
|
62
|
+
sales_table.join(latest_sales_query.as(latest_sales_table.name.to_s), Arel::Nodes::InnerJoin)
|
63
|
+
.on(sales_table[:id].eq(latest_sales_table[:latest_sale_id]))
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(*args)
|
67
|
+
super
|
68
|
+
|
69
|
+
self.bid_steps_ladder = configuration.default_bid_steps_ladder if bid_steps_ladder.blank?
|
70
|
+
end
|
71
|
+
|
72
|
+
# need to cover wrong class of item before assigning
|
73
|
+
def item=(item)
|
74
|
+
@item = item
|
75
|
+
valid_item
|
76
|
+
|
77
|
+
super if errors.blank?
|
78
|
+
end
|
79
|
+
|
80
|
+
[:seller, :buyer, :item].each do |behavior|
|
81
|
+
define_method("#{behavior}_auctify_id=") do |auctify_id|
|
82
|
+
self.send("#{behavior}=", object_from_auctify_id(auctify_id))
|
83
|
+
end
|
84
|
+
|
85
|
+
define_method("#{behavior}_auctify_id") do
|
86
|
+
self.send("#{behavior}")&.auctify_id
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def publish!
|
91
|
+
self.published = true
|
92
|
+
save
|
93
|
+
end
|
94
|
+
|
95
|
+
def auctioneer_commission
|
96
|
+
return nil if sold_price.nil?
|
97
|
+
|
98
|
+
percent = commission_in_percent \
|
99
|
+
|| (pack&.commission_in_percent) \
|
100
|
+
|| Auctify.configuration.auctioneer_commission_in_percent
|
101
|
+
|
102
|
+
sold_price * percent * 0.01
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
def valid_seller
|
107
|
+
return true if seller_id.blank?
|
108
|
+
|
109
|
+
db_seller = db_presence_of(seller)
|
110
|
+
|
111
|
+
errors.add(:seller, :required) unless db_seller.present?
|
112
|
+
end
|
113
|
+
|
114
|
+
def valid_item
|
115
|
+
item = @item || self.item
|
116
|
+
errors.delete(:item)
|
117
|
+
|
118
|
+
db_item = db_presence_of(item)
|
119
|
+
if db_item.present?
|
120
|
+
errors.add(:item, :already_on_sale_in_sales_pack, sale_pack_title: pack.title) if pack && pack.sales
|
121
|
+
.where(item: db_item)
|
122
|
+
.where.not(id: self.id)
|
123
|
+
.exists?
|
124
|
+
else
|
125
|
+
# Rails will add "required" on item.nil? automagically (and after this validation) but not for non-persisted item
|
126
|
+
# we do not allow creating sale along with item, so this trying to cover that
|
127
|
+
errors.add(:item, :required) unless item.blank? || errors.details[:item].include?({ error: :blank })
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def valid_buyer
|
132
|
+
db_buyer = db_presence_of(buyer)
|
133
|
+
errors.add(:buyer, :required) if buyer.present? && db_buyer.blank?
|
134
|
+
end
|
135
|
+
|
136
|
+
def db_presence_of(record)
|
137
|
+
return nil if record.blank?
|
138
|
+
|
139
|
+
record.reload
|
140
|
+
rescue ActiveRecord::RecordNotFound
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def configuration
|
145
|
+
Auctify.configuration
|
146
|
+
end
|
147
|
+
|
148
|
+
def validate_offered_price_when_published
|
149
|
+
if published? && offered_price.blank?
|
150
|
+
errors.add(:offered_price, :required_for_published)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def slug_candidates
|
155
|
+
base = try(:item).try(:title).presence || self.class.model_name.human
|
156
|
+
year = Time.zone.now.year
|
157
|
+
[base, "#{base}-#{year}"] + 9.times.map { |i| "#{base}-#{year}-#{i + 2}" }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# == Schema Information
|
164
|
+
#
|
165
|
+
# Table name: auctify_sales
|
166
|
+
#
|
167
|
+
# id :bigint(8) not null, primary key
|
168
|
+
# seller_type :string
|
169
|
+
# seller_id :integer
|
170
|
+
# buyer_type :string
|
171
|
+
# buyer_id :integer
|
172
|
+
# item_id :integer not null
|
173
|
+
# created_at :datetime not null
|
174
|
+
# updated_at :datetime not null
|
175
|
+
# type :string default("Auctify::Sale::Base")
|
176
|
+
# aasm_state :string default("offered"), not null
|
177
|
+
# offered_price :decimal(, )
|
178
|
+
# current_price :decimal(, )
|
179
|
+
# sold_price :decimal(, )
|
180
|
+
# bid_steps_ladder :json
|
181
|
+
# reserve_price :decimal(, )
|
182
|
+
# pack_id :bigint(8)
|
183
|
+
# ends_at :datetime
|
184
|
+
# position :integer
|
185
|
+
# number :string
|
186
|
+
# currently_ends_at :datetime
|
187
|
+
# published :boolean default(FALSE)
|
188
|
+
# featured :boolean default(FALSE)
|
189
|
+
# slug :string
|
190
|
+
# contract_number :string
|
191
|
+
# commission_in_percent :integer
|
192
|
+
# winner_type :string
|
193
|
+
# winner_id :bigint(8)
|
194
|
+
# applied_bids_count :integer default(0)
|
195
|
+
# sold_at :datetime
|
196
|
+
# current_winner_type :string
|
197
|
+
# current_winner_id :bigint(8)
|
198
|
+
#
|
199
|
+
# Indexes
|
200
|
+
#
|
201
|
+
# index_auctify_sales_on_buyer_type_and_buyer_id (buyer_type,buyer_id)
|
202
|
+
# index_auctify_sales_on_currently_ends_at (currently_ends_at)
|
203
|
+
# index_auctify_sales_on_featured (featured)
|
204
|
+
# index_auctify_sales_on_pack_id (pack_id)
|
205
|
+
# index_auctify_sales_on_position (position)
|
206
|
+
# index_auctify_sales_on_published (published)
|
207
|
+
# index_auctify_sales_on_seller_type_and_seller_id (seller_type,seller_id)
|
208
|
+
# index_auctify_sales_on_slug (slug) UNIQUE
|
209
|
+
# index_auctify_sales_on_winner_type_and_winner_id (winner_type,winner_id)
|
210
|
+
#
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Auctify
|
4
|
+
module Sale
|
5
|
+
class Retail < Auctify::Sale::Base
|
6
|
+
include AASM
|
7
|
+
|
8
|
+
aasm do
|
9
|
+
state :offered, initial: true, color: "red"
|
10
|
+
state :accepted, color: "red"
|
11
|
+
state :refused, color: "dark"
|
12
|
+
state :in_sale, color: "yellow"
|
13
|
+
state :sold, color: "green"
|
14
|
+
state :not_sold, color: "dark"
|
15
|
+
state :cancelled, color: "red"
|
16
|
+
|
17
|
+
event :accept_offer do
|
18
|
+
transitions from: :offered, to: :accepted
|
19
|
+
end
|
20
|
+
|
21
|
+
event :refuse_offer do
|
22
|
+
transitions from: :offered, to: :refused
|
23
|
+
end
|
24
|
+
|
25
|
+
event :start_sale do
|
26
|
+
transitions from: :accepted, to: :in_sale
|
27
|
+
end
|
28
|
+
|
29
|
+
event :sell do
|
30
|
+
transitions from: :in_sale, to: :sold
|
31
|
+
after do |*args| # TODO: sold_at
|
32
|
+
params = args.first # expecting keys :buyer, :price
|
33
|
+
self.buyer = params[:buyer]
|
34
|
+
self.sold_price = params[:price]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
event :end_sale do
|
39
|
+
transitions from: :in_sale, to: :not_sold
|
40
|
+
end
|
41
|
+
|
42
|
+
event :cancel do
|
43
|
+
transitions from: [:offered, :accepted], to: :cancelled
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# == Schema Information
|
51
|
+
#
|
52
|
+
# Table name: auctify_sales
|
53
|
+
#
|
54
|
+
# id :bigint(8) not null, primary key
|
55
|
+
# seller_type :string
|
56
|
+
# seller_id :integer
|
57
|
+
# buyer_type :string
|
58
|
+
# buyer_id :integer
|
59
|
+
# item_id :integer not null
|
60
|
+
# created_at :datetime not null
|
61
|
+
# updated_at :datetime not null
|
62
|
+
# type :string default("Auctify::Sale::Base")
|
63
|
+
# aasm_state :string default("offered"), not null
|
64
|
+
# offered_price :decimal(, )
|
65
|
+
# current_price :decimal(, )
|
66
|
+
# sold_price :decimal(, )
|
67
|
+
# bid_steps_ladder :json
|
68
|
+
# reserve_price :decimal(, )
|
69
|
+
# pack_id :bigint(8)
|
70
|
+
# ends_at :datetime
|
71
|
+
# position :integer
|
72
|
+
# number :string
|
73
|
+
# currently_ends_at :datetime
|
74
|
+
# published :boolean default(FALSE)
|
75
|
+
# featured :boolean default(FALSE)
|
76
|
+
# slug :string
|
77
|
+
# contract_number :string
|
78
|
+
# commission_in_percent :integer
|
79
|
+
# winner_type :string
|
80
|
+
# winner_id :bigint(8)
|
81
|
+
# applied_bids_count :integer default(0)
|
82
|
+
# sold_at :datetime
|
83
|
+
# current_winner_type :string
|
84
|
+
# current_winner_id :bigint(8)
|
85
|
+
#
|
86
|
+
# Indexes
|
87
|
+
#
|
88
|
+
# index_auctify_sales_on_buyer_type_and_buyer_id (buyer_type,buyer_id)
|
89
|
+
# index_auctify_sales_on_currently_ends_at (currently_ends_at)
|
90
|
+
# index_auctify_sales_on_featured (featured)
|
91
|
+
# index_auctify_sales_on_pack_id (pack_id)
|
92
|
+
# index_auctify_sales_on_position (position)
|
93
|
+
# index_auctify_sales_on_published (published)
|
94
|
+
# index_auctify_sales_on_seller_type_and_seller_id (seller_type,seller_id)
|
95
|
+
# index_auctify_sales_on_slug (slug) UNIQUE
|
96
|
+
# index_auctify_sales_on_winner_type_and_winner_id (winner_type,winner_id)
|
97
|
+
#
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Auctify
|
4
|
+
class SalesPack < ApplicationRecord
|
5
|
+
include Folio::FriendlyId
|
6
|
+
include Folio::HasAttachments
|
7
|
+
include Folio::Positionable
|
8
|
+
include Folio::Publishable::Basic
|
9
|
+
include Folio::Sitemap::Base
|
10
|
+
|
11
|
+
has_many :sales, class_name: "Auctify::Sale::Base", foreign_key: :pack_id, inverse_of: :pack, dependent: :restrict_with_error
|
12
|
+
has_many :items, through: :sales
|
13
|
+
|
14
|
+
validates :title,
|
15
|
+
presence: true,
|
16
|
+
uniqueness: true
|
17
|
+
|
18
|
+
validates :start_date,
|
19
|
+
:end_date,
|
20
|
+
presence: true
|
21
|
+
|
22
|
+
validates :sales_interval,
|
23
|
+
numericality: { greater_than: 0, less_than: 240 }
|
24
|
+
|
25
|
+
validates :sales_beginning_hour,
|
26
|
+
numericality: { greater_than_or_equal: 0, less_than: 24 }
|
27
|
+
|
28
|
+
validates :sales_beginning_minutes,
|
29
|
+
numericality: { greater_than_or_equal: 0, less_than: 60 }
|
30
|
+
|
31
|
+
validate :validate_start_and_end_dates
|
32
|
+
|
33
|
+
scope :ordered, -> { order(start_date: :desc, id: :desc) }
|
34
|
+
|
35
|
+
pg_search_scope :by_query,
|
36
|
+
against: %i[title],
|
37
|
+
ignoring: :accents,
|
38
|
+
using: { tsearch: { prefix: true } }
|
39
|
+
|
40
|
+
after_initialize :set_commission
|
41
|
+
|
42
|
+
def to_label
|
43
|
+
title
|
44
|
+
end
|
45
|
+
|
46
|
+
def dates_to_label
|
47
|
+
if start_date && end_date
|
48
|
+
if start_date.year == end_date.year
|
49
|
+
if start_date.month == end_date.month
|
50
|
+
"#{start_date.strftime('%-d.')}–#{end_date.strftime('%-d. %-m. %y')}"
|
51
|
+
else
|
52
|
+
"#{start_date.strftime('%-d. %-m.')} – #{end_date.strftime('%-d. %-m. %y')}"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
"#{start_date.strftime('%-d. %-m. %y')} – #{end_date.strftime('%-d. %-m. %y')}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def validate_start_and_end_dates
|
62
|
+
if start_date.present? && end_date.present? && start_date > end_date
|
63
|
+
errors.add(:end_date, :smaller_than_start_date)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_commission
|
68
|
+
return if self.commission_in_percent.present?
|
69
|
+
|
70
|
+
self.commission_in_percent = Auctify.configuration.auctioneer_commission_in_percent
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# == Schema Information
|
76
|
+
#
|
77
|
+
# Table name: auctify_sales_packs
|
78
|
+
#
|
79
|
+
# id :bigint(8) not null, primary key
|
80
|
+
# title :string
|
81
|
+
# description :text
|
82
|
+
# position :integer default(0)
|
83
|
+
# slug :string
|
84
|
+
# place :string
|
85
|
+
# published :boolean default(FALSE)
|
86
|
+
# created_at :datetime not null
|
87
|
+
# updated_at :datetime not null
|
88
|
+
# sales_count :integer default(0)
|
89
|
+
# start_date :date
|
90
|
+
# end_date :date
|
91
|
+
# sales_interval :integer default(3)
|
92
|
+
# sales_beginning_hour :integer default(20)
|
93
|
+
# sales_beginning_minutes :integer default(0)
|
94
|
+
# commission_in_percent :integer
|
95
|
+
#
|
96
|
+
# Indexes
|
97
|
+
#
|
98
|
+
# index_auctify_sales_packs_on_position (position)
|
99
|
+
# index_auctify_sales_packs_on_published (published)
|
100
|
+
# index_auctify_sales_packs_on_slug (slug) UNIQUE
|
101
|
+
#
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Auctify::Sale::AuctionSerializer
|
4
|
+
include FastJsonapi::ObjectSerializer
|
5
|
+
|
6
|
+
attributes :id,
|
7
|
+
:current_price,
|
8
|
+
:current_minimal_bid,
|
9
|
+
:currently_ends_at,
|
10
|
+
:ends_at,
|
11
|
+
:open_for_bids?
|
12
|
+
|
13
|
+
attribute :current_winner do |auction|
|
14
|
+
winner = auction.current_winner
|
15
|
+
{
|
16
|
+
id: winner.id,
|
17
|
+
auctify_id: winner.auctify_id,
|
18
|
+
to_label: winner.to_label
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
# assert_equal auction.current_winner.id, json_attributes["current_winner"]["id"]
|
27
|
+
# assert_equal auction.current_winner.auctify_id, json_attributes["current_winner"]["auctify_id"]
|
28
|
+
# assert_equal auction.current_winner.to_label, json_attributes["current_winner"]["to_label"]
|
29
|
+
# assert_equal auction.current_price, json_attributes["current_price"]
|
30
|
+
# assert_equal auction.current_minimal_bid, json_attributes["current_minimal_bid"]
|
31
|
+
# assert_equal auction.ends_at, json_attributes["ends_at"]
|
32
|
+
# assert_equal auction.currently_ends_at, json_attributes["currently_ends_at"]
|
33
|
+
# assert_equal auction.open_for_bids?, json_attributes["open_for_bids?"]
|
34
|
+
|
35
|
+
|
36
|
+
# attributes :name, :year
|
37
|
+
# has_many :actors
|
38
|
+
# belongs_to :owner, record_type: :user
|
39
|
+
# belongs_to :movie_ty
|
40
|
+
# # link :url do |object|
|
41
|
+
# # Rails.application
|
42
|
+
# # .routes
|
43
|
+
# # .url_helpers
|
44
|
+
# # .url_for([object, only_path: true])
|
45
|
+
# # end
|
46
|
+
end
|