rooftop-spektrix_sync 0.0.2.15
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 +7 -0
- data/.gitignore +23 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/rooftop/spektrix_sync/lib/event_sync.rb +92 -0
- data/lib/rooftop/spektrix_sync/lib/instance_sync.rb +76 -0
- data/lib/rooftop/spektrix_sync/lib/price_list_sync.rb +110 -0
- data/lib/rooftop/spektrix_sync/lib/sync_task.rb +227 -0
- data/lib/rooftop/spektrix_sync/process.rb +26 -0
- data/lib/rooftop/spektrix_sync/railtie.rb +10 -0
- data/lib/rooftop/spektrix_sync/tasks/import.rake +33 -0
- data/lib/rooftop/spektrix_sync/version.rb +5 -0
- data/lib/rooftop/spektrix_sync.rb +22 -0
- data/rooftop-spektrix_sync.gemspec +30 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb6fd037cce26a2e0f142bf431ef45fc4c1989a9
|
4
|
+
data.tar.gz: a7a3bb0ae24fe58aa5c0d8af3b3f51e8d8a2091e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b4d00862c48da22fc7cb8dface4fba4b0a9546d2ce964427d9dc59a83a715cf9073f3f21e25f05b23cd89151cf454b20d401a8c97db3d38232d5a36c9ec98ec4
|
7
|
+
data.tar.gz: 129902d9ea10654f3d6737bc759154306256286a408810a15c12dd8bbc8c9c044f7031b0a3ed4e1ea34891e366ee5b9d07d960815a7e089db29fa17331d2951c
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
.idea
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rooftop-spektrix_sync
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.3
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Ed Jones
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rooftop::SpektrixSync
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rooftop-spektrix_sync'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rooftop-spektrix_sync
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/[my-github-username]/rooftop-spektrix_sync/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module SpektrixSync
|
3
|
+
class EventSync
|
4
|
+
attr_reader :spektrix_event,
|
5
|
+
:rooftop_event,
|
6
|
+
:rooftop_price_lists,
|
7
|
+
:logger
|
8
|
+
|
9
|
+
def initialize(spektrix_event, sync_task)
|
10
|
+
@rooftop_events = sync_task.rooftop_events
|
11
|
+
@spektrix_events = sync_task.spektrix_events
|
12
|
+
@logger = sync_task.logger
|
13
|
+
@spektrix_event = spektrix_event
|
14
|
+
@rooftop_event = @rooftop_events.find {|e| e.meta_attributes[:spektrix_id].try(:to_i) == @spektrix_event.id.to_i}
|
15
|
+
@rooftop_price_lists = sync_task.rooftop_price_lists
|
16
|
+
end
|
17
|
+
|
18
|
+
def sync_to_rooftop
|
19
|
+
begin
|
20
|
+
# find the event
|
21
|
+
@rooftop_event ||= Rooftop::Events::Event.new({
|
22
|
+
title: @spektrix_event.title,
|
23
|
+
content: {basic: {content: @spektrix_event.description}},
|
24
|
+
meta_attributes: {},
|
25
|
+
status: nil
|
26
|
+
})
|
27
|
+
sync()
|
28
|
+
rescue => e
|
29
|
+
@logger.error(e.to_s)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def sync
|
34
|
+
update_meta_attributes
|
35
|
+
update_on_sale
|
36
|
+
if @rooftop_event.persisted?
|
37
|
+
# Ensure we're not overwriting newer stuff in RT with older stuff from this sync by
|
38
|
+
# removing the title and content if this is a PUT request (i.e. it already exists in RT)
|
39
|
+
@rooftop_event.restore_title!
|
40
|
+
@rooftop_event.restore_content!
|
41
|
+
@rooftop_event.restore_slug!
|
42
|
+
@rooftop_event.restore_link!
|
43
|
+
@rooftop_event.restore_event_instance_availabilities!
|
44
|
+
end
|
45
|
+
|
46
|
+
if @rooftop_event.save!
|
47
|
+
@logger.debug("Saved event: #{@rooftop_event.title} #{@rooftop_event.id}")
|
48
|
+
sync_instances
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def update_meta_attributes
|
54
|
+
@rooftop_event.meta_attributes ||= {}
|
55
|
+
@rooftop_event.meta_attributes[:spektrix_id] = @spektrix_event.id
|
56
|
+
@spektrix_event.custom_attributes.each do |key, value|
|
57
|
+
@rooftop_event.meta_attributes[key] = value
|
58
|
+
end
|
59
|
+
@rooftop_event.meta_attributes[:duration] = @spektrix_event.duration.to_i
|
60
|
+
end
|
61
|
+
|
62
|
+
def update_on_sale
|
63
|
+
if SpektrixSync.configuration.present? && SpektrixSync.configuration[:on_sale_if_new_event]
|
64
|
+
@rooftop_event.status = @spektrix_event.is_on_sale ? 'publish' : 'draft'
|
65
|
+
else
|
66
|
+
@rooftop_event.restore_status! #don't send status with the request
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def sync_instances
|
71
|
+
@rooftop_instances = @rooftop_event.instances.to_a
|
72
|
+
@spektrix_instances = @spektrix_event.instances.to_a
|
73
|
+
@spektrix_instances.each_with_index do |instance, i|
|
74
|
+
begin
|
75
|
+
tries ||= 2
|
76
|
+
instance_sync = Rooftop::SpektrixSync::InstanceSync.new(instance, self)
|
77
|
+
instance_sync.sync
|
78
|
+
rescue
|
79
|
+
retry unless (tries -= 1 ).zero?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
update_event_metadata unless @rooftop_instances.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
def update_event_metadata
|
87
|
+
@logger.debug("Saved event instances. Updating event metadata")
|
88
|
+
Rooftop::Events::Event.post("#{@rooftop_event.class.collection_path}/#{@rooftop_event.id}/update_metadata")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module SpektrixSync
|
3
|
+
class InstanceSync
|
4
|
+
|
5
|
+
def initialize(spektrix_instance, event_sync)
|
6
|
+
@spektrix_event = event_sync.spektrix_event
|
7
|
+
@rooftop_event = event_sync.rooftop_event
|
8
|
+
@logger = event_sync.logger
|
9
|
+
@spektrix_instance = spektrix_instance
|
10
|
+
@rooftop_instance = find_rooftop_instance_by_spektrix_id(@spektrix_instance.id) || @rooftop_event.instances.build(status: nil, meta_attributes: {})
|
11
|
+
@rooftop_price_lists = event_sync.rooftop_price_lists
|
12
|
+
end
|
13
|
+
|
14
|
+
def sync
|
15
|
+
# This is a bit of a hack: we have to create a new instance and assign all the attributes from the old one, so it has an _event_id param.
|
16
|
+
if @rooftop_instance.persisted?
|
17
|
+
@rooftop_instance = @rooftop_event.instances.build(@rooftop_instance.attributes)
|
18
|
+
instance_updated = true
|
19
|
+
end
|
20
|
+
update_price
|
21
|
+
if @rooftop_instance.price_list_id.nil?
|
22
|
+
@logger.warn("No price list for Spektrix instance id #{@spektrix_instance.id}")
|
23
|
+
return
|
24
|
+
end
|
25
|
+
update_meta_attributes
|
26
|
+
update_availability
|
27
|
+
update_on_sale
|
28
|
+
if @rooftop_instance.save!
|
29
|
+
@logger.debug("#{instance_updated ? "Updated" : "Created"} Rooftop instance #{@rooftop_instance.id}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def find_rooftop_instance_by_spektrix_id(spektrix_id)
|
35
|
+
@rooftop_event.instances.to_a.find {|i| i.meta_attributes[:spektrix_id] == spektrix_id }
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_price
|
39
|
+
@rooftop_instance.price_list_id = @rooftop_price_lists.find {|l| l.meta_attributes[:spektrix_id].to_i == @spektrix_instance.price_list_id}.try(:id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_meta_attributes
|
43
|
+
@rooftop_instance.meta_attributes = @spektrix_instance.custom_attributes.merge(spektrix_id: @spektrix_instance.id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_on_sale
|
47
|
+
# TODO: there is a bug in the Rooftop events plugin which means that instances which are draft won't be shown
|
48
|
+
# as assigned to the event. Because it's a nested resource, there's no real risk to publishing
|
49
|
+
# the instance immediately.
|
50
|
+
# if SpektrixSync.configuration.present? && SpektrixSync.configuration[:on_sale_if_new_event]
|
51
|
+
# @rooftop_instance.status = @spektrix_instance.is_on_sale ? 'publish' : 'draft'
|
52
|
+
# else
|
53
|
+
# @rooftop_instance.status ||= "draft"
|
54
|
+
# end
|
55
|
+
# @rooftop_instance.status = "publish"
|
56
|
+
|
57
|
+
@rooftop_instance.status = @spektrix_instance.is_on_sale=="true" ? 'publish' : 'draft'
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_availability
|
61
|
+
availability = {
|
62
|
+
availability: {
|
63
|
+
starts_at: @spektrix_instance.start.iso8601,
|
64
|
+
stops_at: @spektrix_instance.start.advance(seconds: @rooftop_event.meta_attributes[:duration]),
|
65
|
+
seats_capacity: @spektrix_instance.status.capacity,
|
66
|
+
seats_available: @spektrix_instance.status.available
|
67
|
+
}
|
68
|
+
}
|
69
|
+
@rooftop_instance.title = @rooftop_event.title + ": " + @spektrix_instance.start.strftime("%d %b %Y %H:%M")
|
70
|
+
@rooftop_instance.meta_attributes.merge!(availability)
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module SpektrixSync
|
3
|
+
class PriceListSync
|
4
|
+
|
5
|
+
def initialize(sync_task)
|
6
|
+
@spektrix_price_lists = sync_task.spektrix_price_lists
|
7
|
+
@rooftop_price_lists = sync_task.rooftop_price_lists
|
8
|
+
@rooftop_ticket_types = sync_task.rooftop_ticket_types
|
9
|
+
@rooftop_price_bands = sync_task.rooftop_price_bands
|
10
|
+
@logger = sync_task.logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
sync_price_lists
|
15
|
+
# Todo we need to put this in a rake task instead of running every time.
|
16
|
+
# remove_orphan_price_lists
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def sync_price_lists
|
22
|
+
# begin
|
23
|
+
@spektrix_price_lists.each do |spektrix_price_list|
|
24
|
+
# Don't bother syncing a price list where none of the prices have bands.
|
25
|
+
if spektrix_price_list.prices.select {|p| !p.band.nil?}.empty?
|
26
|
+
@logger.warn("Spektrix price list ID #{spektrix_price_list.id} has prices with missing bands.")
|
27
|
+
end
|
28
|
+
|
29
|
+
# find or create a price list
|
30
|
+
@rooftop_price_list = @rooftop_price_lists.find {|l| l.meta_attributes[:spektrix_id] == spektrix_price_list.id.to_s} || Rooftop::Events::PriceList.new(title: spektrix_price_list.id, meta_attributes: {})
|
31
|
+
@rooftop_price_list.meta_attributes[:spektrix_id] = spektrix_price_list.id
|
32
|
+
|
33
|
+
new_price_list = @rooftop_price_list.new?
|
34
|
+
# save the price list to rooftop
|
35
|
+
if @rooftop_price_list.save!
|
36
|
+
@logger.debug("#{new_price_list ? "Created" : "Updated"} price list #{spektrix_price_list.id}")
|
37
|
+
sync_prices(spektrix_price_list, @rooftop_price_list)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# rescue => e
|
41
|
+
# @logger.warn(e.to_s)
|
42
|
+
# end
|
43
|
+
end
|
44
|
+
|
45
|
+
def sync_prices(spektrix_price_list, rooftop_price_list)
|
46
|
+
# begin
|
47
|
+
spektrix_price_list.prices.each_with_index do |spektrix_price, i |
|
48
|
+
@logger.debug("syncing price #{i+1} / #{spektrix_price_list.prices.count}")
|
49
|
+
# skip ones without a band
|
50
|
+
if spektrix_price.band.nil?
|
51
|
+
@logger.warn("Spektrix price list ID: #{spektrix_price_list.id}: Price #{spektrix_price.price} with ticket type #{spektrix_price.ticket_type.name} does not have a band")
|
52
|
+
next
|
53
|
+
end
|
54
|
+
current_rooftop_price = find_rooftop_price(rooftop_price_list, spektrix_price)
|
55
|
+
# because updating a price is hard with a nested resource, we'll destroy and recreate with the same settings
|
56
|
+
new_price = rooftop_price_list.prices.build
|
57
|
+
if current_rooftop_price
|
58
|
+
new_price.assign_attributes(current_rooftop_price.attributes)
|
59
|
+
end
|
60
|
+
|
61
|
+
new_price.meta_attributes = {
|
62
|
+
is_band_default: (spektrix_price.is_band_default == "true"),
|
63
|
+
ticket_type_id: find_rooftop_ticket_type(spektrix_price).id,
|
64
|
+
price_band_id: find_rooftop_price_band(spektrix_price).id,
|
65
|
+
ticket_price: spektrix_price.price.to_f
|
66
|
+
}
|
67
|
+
|
68
|
+
new_price.title = "#{spektrix_price.band.name} (£#{new_price.meta_attributes[:ticket_price]})"
|
69
|
+
if new_price.save!
|
70
|
+
@logger.debug("Spektrix price list ID: #{spektrix_price_list.id}: Saved price £#{new_price.meta_attributes[:ticket_price]} with ticket type #{spektrix_price.ticket_type.name} for price band #{spektrix_price.band.name}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
# rescue => e
|
74
|
+
# @logger.error(e.to_s)
|
75
|
+
# end
|
76
|
+
end
|
77
|
+
|
78
|
+
def remove_orphan_price_lists
|
79
|
+
begin
|
80
|
+
rooftop_spektrix_ids = @rooftop_price_lists.collect {|l| l.meta_attributes[:spektrix_id].to_i}
|
81
|
+
spektrix_ids = @spektrix_price_lists.collect {|l| l.id.to_i}
|
82
|
+
spektrix_ids_to_remove = (rooftop_spektrix_ids - (rooftop_spektrix_ids & spektrix_ids))
|
83
|
+
rooftop_ids_to_remove = spektrix_ids_to_remove.collect do |spektrix_id|
|
84
|
+
@rooftop_price_lists.find {|l| l.meta_attributes[:spektrix_id].to_i == spektrix_id}.id
|
85
|
+
end
|
86
|
+
Rooftop::Events::PriceList.where(post__in: rooftop_ids_to_remove).each do |pricelist|
|
87
|
+
if pricelist.destroy
|
88
|
+
@logger.debug("Removed rooftop price list #{id} which didn't exist in spektrix")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
rescue => e
|
92
|
+
@logger.error(e.to_s)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_rooftop_price(rooftop_price_list,spektrix_price)
|
97
|
+
rooftop_price_list.prices.to_a.find {|p| p.meta_attributes[:spektrix_id] == spektrix_price.id}
|
98
|
+
end
|
99
|
+
|
100
|
+
def find_rooftop_ticket_type(spektrix_price)
|
101
|
+
@rooftop_ticket_types.find {|t| CGI::unescapeHTML(t.title.gsub(/–\;/, '-')) == CGI::unescapeHTML(spektrix_price.ticket_type.name)}
|
102
|
+
end
|
103
|
+
|
104
|
+
def find_rooftop_price_band(spektrix_price)
|
105
|
+
@rooftop_price_bands.find {|b| CGI::unescapeHTML(b.title.gsub(/–\;/, '-')) == CGI::unescapeHTML(spektrix_price.band.name)}
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module SpektrixSync
|
3
|
+
class SyncTask
|
4
|
+
attr_accessor :starting_at, :logger, :error_file
|
5
|
+
attr_reader :spektrix_events,
|
6
|
+
:rooftop_events,
|
7
|
+
:spektrix_price_lists,
|
8
|
+
:rooftop_price_lists,
|
9
|
+
:rooftop_ticket_types,
|
10
|
+
:rooftop_price_bands,
|
11
|
+
:options
|
12
|
+
|
13
|
+
PIDPATH = "/tmp/rooftop-spektrix-sync.pid"
|
14
|
+
|
15
|
+
def initialize(starting_at, opts={})
|
16
|
+
begin
|
17
|
+
Rooftop.preview = true
|
18
|
+
if defined?(Rooftop::Rails)
|
19
|
+
Rooftop::Rails.configuration.perform_object_caching = false
|
20
|
+
end
|
21
|
+
@starting_at = starting_at || DateTime.now
|
22
|
+
@logger = SpektrixSync.logger || Logger.new(STDOUT)
|
23
|
+
default_opts = {
|
24
|
+
import_price_bands: false,
|
25
|
+
import_ticket_types: false,
|
26
|
+
import_prices: false,
|
27
|
+
import_events: true,
|
28
|
+
delete_orphan_events: false,
|
29
|
+
accept_empty_rooftop_events: false
|
30
|
+
}
|
31
|
+
@options = default_opts.merge!(opts)
|
32
|
+
@logger.debug("*************************************************************************")
|
33
|
+
@logger.debug("Running with options: #{@options.select {|k,v| k if v}.keys.join(", ")}")
|
34
|
+
@logger.debug("*************************************************************************")
|
35
|
+
rescue => e
|
36
|
+
@logger.error("Couldn't start sync: #{e}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch_rooftop_and_spektrix_data
|
41
|
+
@logger.debug("Fetching all Spektrix events")
|
42
|
+
@spektrix_events = @spektrix_events.present? ? @spektrix_events : Spektrix::Events::Event.all(instance_start_from: @starting_at.iso8601).to_a
|
43
|
+
if @options[:spektrix_event_id]
|
44
|
+
@spektrix_events = @spektrix_events.select {|e| e.id == @options[:spektrix_event_id].to_s}
|
45
|
+
end
|
46
|
+
@logger.debug("Fetching all Rooftop events")
|
47
|
+
@rooftop_events = Rooftop::Events::Event.all.to_a
|
48
|
+
unless @options[:accept_empty_rooftop_events]
|
49
|
+
raise StandardError, "Rooftop returned an empty set of events which is probably wrong" if @rooftop_events.empty?
|
50
|
+
end
|
51
|
+
@logger.debug("Fetching all Spektrix price lists")
|
52
|
+
@spektrix_price_lists = @spektrix_price_lists.present? ? @spektrix_price_lists : Spektrix::Tickets::PriceList.all.to_a
|
53
|
+
@logger.debug("Fetching all Rooftop Price lists")
|
54
|
+
@rooftop_price_lists = Rooftop::Events::PriceList.all.to_a
|
55
|
+
@logger.debug("Fetching all Rooftop ticket types")
|
56
|
+
@rooftop_ticket_types = Rooftop::Events::TicketType.all.to_a
|
57
|
+
@logger.debug("Fetching all Rooftop price bands")
|
58
|
+
@rooftop_price_bands = Rooftop::Events::PriceBand.all.to_a
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
def self.run(starting_at=nil, opts={})
|
64
|
+
sync_pid = Process.get_pid(Rooftop::SpektrixSync::SyncTask::PIDPATH)
|
65
|
+
|
66
|
+
if sync_pid && Process.exists?(sync_pid.to_i)
|
67
|
+
raise 'Rooftop::SpektrixSync::SyncRunning'
|
68
|
+
end
|
69
|
+
|
70
|
+
# if we're here, we can create a new pidfile and start the sync
|
71
|
+
Process.create_pid(Rooftop::SpektrixSync::SyncTask::PIDPATH)
|
72
|
+
self.new(starting_at,opts).run
|
73
|
+
|
74
|
+
# remove the pid
|
75
|
+
Process.remove_pidfile(Rooftop::SpektrixSync::SyncTask::PIDPATH)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.run_events_import(starting_at=nil, event_id=nil)
|
79
|
+
opts = event_id.present? ? {spektrix_event_id: event_id} : {}
|
80
|
+
self.run(starting_at, opts)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.run_full_import(starting_at=nil)
|
84
|
+
self.run(starting_at, {
|
85
|
+
import_price_bands: true,
|
86
|
+
import_ticket_types: true,
|
87
|
+
import_prices: true,
|
88
|
+
import_events: true,
|
89
|
+
delete_orphan_events: false
|
90
|
+
})
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.run_prices_import(starting_at=nil)
|
94
|
+
self.run(starting_at, {
|
95
|
+
import_price_bands: true,
|
96
|
+
import_ticket_types: true,
|
97
|
+
import_prices: true,
|
98
|
+
import_events: false,
|
99
|
+
delete_orphan_events: false
|
100
|
+
})
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def run
|
105
|
+
begin
|
106
|
+
if @options[:import_price_bands]
|
107
|
+
fetch_rooftop_and_spektrix_data
|
108
|
+
create_or_update_price_bands
|
109
|
+
end
|
110
|
+
if @options[:import_ticket_types]
|
111
|
+
fetch_rooftop_and_spektrix_data
|
112
|
+
create_or_update_ticket_types
|
113
|
+
end
|
114
|
+
if @options[:import_prices]
|
115
|
+
fetch_rooftop_and_spektrix_data
|
116
|
+
create_or_update_prices
|
117
|
+
end
|
118
|
+
if @options[:import_events]
|
119
|
+
fetch_rooftop_and_spektrix_data
|
120
|
+
create_or_update_events
|
121
|
+
end
|
122
|
+
# TODO: the delete method is over-eager. Resolve the issue.
|
123
|
+
# if @options[:delete_orphan_events]
|
124
|
+
# fetch_event_data
|
125
|
+
# delete_orphan_spektrix_events
|
126
|
+
# end
|
127
|
+
rescue => e
|
128
|
+
@logger.error(e)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def create_or_update_events
|
136
|
+
begin
|
137
|
+
tries ||= 2
|
138
|
+
@spektrix_events.each_with_index do |event, i|
|
139
|
+
@logger.debug("Sync #{i+1} / #{@spektrix_events.length}: #{event.title}")
|
140
|
+
item = EventSync.new(event, self)
|
141
|
+
item.sync_to_rooftop
|
142
|
+
end
|
143
|
+
rescue => e
|
144
|
+
@logger.error(e.to_s)
|
145
|
+
retry unless (tries -= 1).zero?
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Mop up any Rooftop events which don't exist in spektrix, if they have spektrix ID
|
150
|
+
def delete_orphan_spektrix_events
|
151
|
+
@spektrix_event_ids = @spektrix_events.collect {|e| e.id.to_i}
|
152
|
+
@rooftop_event_ids = @rooftop_events.inject({}) do |hash, e|
|
153
|
+
hash[e.id] = e.meta_attributes[:spektrix_id].to_i
|
154
|
+
hash
|
155
|
+
end
|
156
|
+
@rooftop_event_ids.reject! {|k,v| v == 0} #remove events with no spektrix ID; we don't want to remove them.
|
157
|
+
spektrix_ids_to_delete = (@rooftop_event_ids.values - (@rooftop_event_ids.values & @spektrix_event_ids))
|
158
|
+
rooftop_ids_to_delete = @rooftop_event_ids.select {|k,v| spektrix_ids_to_delete.include?(v)}.keys
|
159
|
+
Rooftop::Events::Event.where(post__in: rooftop_ids_to_delete).each do |rooftop_event|
|
160
|
+
title = rooftop_event.title
|
161
|
+
if rooftop_event.destroy
|
162
|
+
@logger.debug("Removed Rooftop event #{title} which doesn't exist in Spektrix")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def create_or_update_price_bands
|
168
|
+
begin
|
169
|
+
rooftop_bands = Rooftop::Events::PriceBand.all.to_a
|
170
|
+
spektrix_bands = Spektrix::Tickets::Band.all.to_a
|
171
|
+
# create or update existing
|
172
|
+
spektrix_bands.each do |band|
|
173
|
+
@logger.debug("Updating band #{band.name}")
|
174
|
+
rooftop_band = rooftop_bands.find {|b| b.title == band.name} || Rooftop::Events::PriceBand.new
|
175
|
+
rooftop_band.title = band.name
|
176
|
+
rooftop_band.save!
|
177
|
+
end
|
178
|
+
|
179
|
+
#delete ones on rooftop which aren't in spektrix
|
180
|
+
rooftop_titles = rooftop_bands.collect(&:title)
|
181
|
+
spektrix_titles = spektrix_bands.collect(&:name)
|
182
|
+
(rooftop_titles - (rooftop_titles & spektrix_titles)).each do |title|
|
183
|
+
rooftop_bands.find {|b| b.title == title}.destroy
|
184
|
+
end
|
185
|
+
rescue => e
|
186
|
+
@logger.error(e.to_s)
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
def create_or_update_ticket_types
|
193
|
+
begin
|
194
|
+
rooftop_ticket_types = Rooftop::Events::TicketType.all.to_a
|
195
|
+
spektrix_ticket_types = Spektrix::Tickets::Type.all.to_a
|
196
|
+
# create or update exiting
|
197
|
+
spektrix_ticket_types.each do |type|
|
198
|
+
@logger.debug("Updating ticket type #{type.name}")
|
199
|
+
rooftop_ticket_type = rooftop_ticket_types.find {|t| t.title == type.name} || Rooftop::Events::TicketType.new
|
200
|
+
rooftop_ticket_type.title = type.name
|
201
|
+
rooftop_ticket_type.save!
|
202
|
+
end
|
203
|
+
|
204
|
+
#delete ones on rooftop which aren't in spektrix
|
205
|
+
rooftop_titles = rooftop_ticket_types.collect(&:title)
|
206
|
+
spektrix_titles = spektrix_ticket_types.collect(&:name)
|
207
|
+
(rooftop_titles - (rooftop_titles & spektrix_titles)).each do |title|
|
208
|
+
rooftop_ticket_types.find {|b| b.title == title}.destroy
|
209
|
+
end
|
210
|
+
rescue => e
|
211
|
+
@logger.error(e.to_s)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# This is where we generate a price list sync instance
|
216
|
+
def create_or_update_prices
|
217
|
+
PriceListSync.new(self).run
|
218
|
+
#In this circumstance, we need to assume some prices have changed, so we'll invalidate the
|
219
|
+
# instance variable which contains the collection of prices on both sides. This means that
|
220
|
+
# next time fetch_rooftop_and_spektrix_data is called, the latest will be pulled from the APIs.
|
221
|
+
@spektrix_price_lists = nil
|
222
|
+
@rooftop_price_lists = nil
|
223
|
+
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Process
|
2
|
+
def exists?(pid)
|
3
|
+
Process.kill(0, pid)
|
4
|
+
true
|
5
|
+
rescue => e
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_pid(path)
|
10
|
+
Pathname(path).write(Process.pid)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_pid(path)
|
14
|
+
File.read(path).to_i
|
15
|
+
rescue Errno::ENOENT
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_pidfile(path)
|
20
|
+
File.delete(path)
|
21
|
+
rescue Errno::ENOENT
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
module_function :exists?, :create_pid, :get_pid, :remove_pidfile
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
namespace :rooftop do
|
2
|
+
namespace :spektrix do
|
3
|
+
|
4
|
+
task :prepare, [:since, :logger_path] do |task, args|
|
5
|
+
logger_path = args[:logger_path] || STDOUT
|
6
|
+
Rooftop::SpektrixSync.logger = Logger.new(logger_path, 'daily')
|
7
|
+
@since = eval(args[:since]) rescue DateTime.now
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
desc "Synchronise events from Spektrix to Rooftop"
|
12
|
+
task :sync_events, [:since, :logger_path] => [:environment, :prepare] do |task, args|
|
13
|
+
Rooftop::SpektrixSync::SyncTask.run_events_import(@since)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Synchronise events and prices from Spektrix to Rooftop"
|
17
|
+
task :sync_all, [:since, :logger_path] => [:environment, :prepare] do |task, args|
|
18
|
+
Rooftop::SpektrixSync::SyncTask.run_full_import(@since)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Synchronise events and prices from Spektrix to Rooftop"
|
22
|
+
task :sync_prices, [:since, :logger_path] => [:environment, :prepare] do |task, args|
|
23
|
+
Rooftop::SpektrixSync::SyncTask.run_prices_import(@since)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Sync specific event"
|
27
|
+
task :sync_event, [:spektrix_event_id, :since, :logger_path] => [:environment, :prepare] do |task, args|
|
28
|
+
Rooftop::SpektrixSync::SyncTask.run_events_import(@since, args[:spektrix_event_id])
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
require "rooftop/spektrix_sync/version"
|
5
|
+
require 'require_all'
|
6
|
+
require_rel 'spektrix_sync/lib'
|
7
|
+
|
8
|
+
module Rooftop
|
9
|
+
module SpektrixSync
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :logger, :configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
if defined?(::Rails)
|
16
|
+
require 'rooftop/spektrix_sync/railtie'
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rooftop/spektrix_sync/process'
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rooftop/spektrix_sync/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rooftop-spektrix_sync"
|
8
|
+
spec.version = Rooftop::SpektrixSync::VERSION
|
9
|
+
spec.authors = ["Ed Jones"]
|
10
|
+
spec.email = ["ed@errorstudio.co.uk"]
|
11
|
+
spec.summary = %q{A set of tasks to sync events between Spektrix and Rooftop CMS}
|
12
|
+
spec.description = %q{A set of tasks to sync events between Spektrix and Rooftop CMS}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_dependency 'colorize'
|
25
|
+
spec.add_dependency 'activesupport'
|
26
|
+
spec.add_dependency 'require_all'
|
27
|
+
spec.add_dependency "rooftop-events"
|
28
|
+
spec.add_dependency 'rooftop', '~> 0.1.0'
|
29
|
+
spec.add_dependency "spektrix"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rooftop-spektrix_sync
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2.15
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ed Jones
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: require_all
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rooftop-events
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rooftop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.1.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.1.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: spektrix
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: A set of tasks to sync events between Spektrix and Rooftop CMS
|
126
|
+
email:
|
127
|
+
- ed@errorstudio.co.uk
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".ruby-gemset"
|
134
|
+
- ".ruby-version"
|
135
|
+
- Gemfile
|
136
|
+
- LICENSE.txt
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- lib/rooftop/spektrix_sync.rb
|
140
|
+
- lib/rooftop/spektrix_sync/lib/event_sync.rb
|
141
|
+
- lib/rooftop/spektrix_sync/lib/instance_sync.rb
|
142
|
+
- lib/rooftop/spektrix_sync/lib/price_list_sync.rb
|
143
|
+
- lib/rooftop/spektrix_sync/lib/sync_task.rb
|
144
|
+
- lib/rooftop/spektrix_sync/process.rb
|
145
|
+
- lib/rooftop/spektrix_sync/railtie.rb
|
146
|
+
- lib/rooftop/spektrix_sync/tasks/import.rake
|
147
|
+
- lib/rooftop/spektrix_sync/version.rb
|
148
|
+
- rooftop-spektrix_sync.gemspec
|
149
|
+
homepage: ''
|
150
|
+
licenses:
|
151
|
+
- MIT
|
152
|
+
metadata: {}
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project:
|
169
|
+
rubygems_version: 2.4.5.1
|
170
|
+
signing_key:
|
171
|
+
specification_version: 4
|
172
|
+
summary: A set of tasks to sync events between Spektrix and Rooftop CMS
|
173
|
+
test_files: []
|