wco_models 3.4.0.3 → 3.4.0.4
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/assets/stylesheets/wco/main.scss +3 -2
- data/app/controllers/wco/office_action_templates_controller.rb +3 -0
- data/app/controllers/wco/publishers_controller.rb +1 -15
- data/app/controllers/wco/sites_controller.rb +1 -1
- data/app/controllers/wco/tags_controller.rb +1 -1
- data/app/models/iro/option.rb +36 -3
- data/app/models/iro/priceitem.rb +62 -4
- data/app/models/tda/option.rb +39 -41
- data/app/models/wco/publisher.rb +14 -6
- data/app/models/wco/report.rb +1 -1
- data/app/models/wco/site.rb +1 -67
- data/app/models/wco/site.rb-trash +65 -0
- data/app/models/wco/tag.rb +7 -5
- data/app/views/wco/office_action_templates/index.haml +1 -1
- data/app/views/wco/office_actions/_actions.haml +1 -1
- data/app/views/wco/publishers/_form.haml +6 -2
- data/app/views/wco/publishers/_post_with.haml +1 -1
- data/app/views/wco/sites/index.haml +6 -0
- data/app/views/wco/tags/_form.haml +3 -0
- data/config/routes.rb +2 -2
- data/lib/wco_models.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b67195527c6adb04bc55d19eb97695989275618888d1f64857aa6876009d1119
|
|
4
|
+
data.tar.gz: e6534767809ec2d2d81f776df6005dc523dc8e8500ab42eb22f882c9cd16110a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 100de488e7b2a4d5a54f9eaecc1049c38f848264550546b9f8ff7c57bf297418894218dbebde164334f8d5460fe547a94bb794be4ed7c821745401369de3db01
|
|
7
|
+
data.tar.gz: ff5d054c4befbf19f7b3f2ae948c83aebf1c9b6b87575cd25a9ca1b175f85053c05e55dcda01f2230a1a9ad4b1f9b81489a9cefe296c96263767986cbbe39711
|
|
@@ -25,12 +25,15 @@ class Wco::OfficeActionTemplatesController < Wco::ApplicationController
|
|
|
25
25
|
def perform
|
|
26
26
|
@oat = OAT.find params[:id]
|
|
27
27
|
authorize! :run, @oat
|
|
28
|
+
|
|
28
29
|
@conversations = WcoEmail::Conversation.find( params[:conversation_ids] ) if params[:conversation_ids].present?
|
|
30
|
+
|
|
29
31
|
if 'rb' == @oat.action_type
|
|
30
32
|
out = eval( @oat.action_exe )
|
|
31
33
|
elsif 'sh' == @oat.action_type
|
|
32
34
|
out = `#{@oat.action_exe}`
|
|
33
35
|
end
|
|
36
|
+
|
|
34
37
|
flash_notice out
|
|
35
38
|
redirect_to action: :index
|
|
36
39
|
end
|
|
@@ -12,20 +12,6 @@ class Wco::PublishersController < Wco::ApplicationController
|
|
|
12
12
|
redirect_to action: 'index'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
## this is becoming obsolete - try using do_run_any
|
|
16
|
-
def do_run
|
|
17
|
-
@publisher = Wco::Publisher.find params[:id]
|
|
18
|
-
authorize! :do_run, @publisher
|
|
19
|
-
|
|
20
|
-
@publisher.props = OpenStruct.new( JSON.parse params[:publisher][:props] )
|
|
21
|
-
# @publisher.do_run binding
|
|
22
|
-
@publisher.do_run
|
|
23
|
-
|
|
24
|
-
flash_notice "Probably ok"
|
|
25
|
-
|
|
26
|
-
redirect_to action: 'index'
|
|
27
|
-
end
|
|
28
|
-
|
|
29
15
|
def do_run_any
|
|
30
16
|
@publisher = Wco::Publisher.find params[:id]
|
|
31
17
|
authorize! :do_run, @publisher
|
|
@@ -33,7 +19,7 @@ class Wco::PublishersController < Wco::ApplicationController
|
|
|
33
19
|
@publisher.props = OpenStruct.new( JSON.parse params[:props] )
|
|
34
20
|
@publisher.do_run
|
|
35
21
|
|
|
36
|
-
flash_notice "Probably ok"
|
|
22
|
+
flash_notice "#do_run_any Probably ok"
|
|
37
23
|
redirect_to request.referrer || { action: 'index' }
|
|
38
24
|
end
|
|
39
25
|
|
|
@@ -32,7 +32,7 @@ class Wco::TagsController < Wco::ApplicationController
|
|
|
32
32
|
|
|
33
33
|
def index
|
|
34
34
|
authorize! :index, Wco::Tag
|
|
35
|
-
@tags = Wco::Tag.
|
|
35
|
+
@tags = Wco::Tag.where( site: nil ).order_by( slug: :asc )
|
|
36
36
|
|
|
37
37
|
tags = Wco::Tag.all.to_a.group_by(&:parent_id)
|
|
38
38
|
build_tree = lambda do |parent_id|
|
data/app/models/iro/option.rb
CHANGED
|
@@ -8,7 +8,7 @@ class Iro::Option
|
|
|
8
8
|
attr_accessor :recompute
|
|
9
9
|
|
|
10
10
|
belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
|
|
11
|
-
|
|
11
|
+
field :ticker, type: :string
|
|
12
12
|
|
|
13
13
|
CALL = 'CALL'
|
|
14
14
|
PUT = 'PUT'
|
|
@@ -67,14 +67,47 @@ class Iro::Option
|
|
|
67
67
|
return options
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
field :symbol, type: :string
|
|
71
|
+
validates :symbol, uniqueness: true
|
|
72
|
+
index({ symbol: -1 }, { unique: true, name: 'symbol' })
|
|
73
|
+
# def symbol
|
|
74
|
+
# return self[:symbol] if self[:symbol]
|
|
75
|
+
# self[:symbol] = generate_symbol
|
|
76
|
+
# end
|
|
77
|
+
|
|
70
78
|
## for schwab, eg:
|
|
71
79
|
## "COST 260306C01030000"
|
|
72
|
-
def
|
|
80
|
+
def generate_symbol
|
|
73
81
|
p_c_ = put_call == 'PUT' ? 'P' : 'C'
|
|
74
82
|
strike_ = format("%08d", (strike.to_f * 1000).round)
|
|
75
83
|
sym = "#{stock.ticker.ljust(6)}#{expires_on.strftime("%y%m%d")}#{p_c_}#{strike_}"
|
|
76
84
|
end
|
|
77
85
|
|
|
86
|
+
def self.find_or_create_by_symbol symbol
|
|
87
|
+
option = Iro::Option.where( symbol: symbol ).first
|
|
88
|
+
return option if option
|
|
89
|
+
h = Iro::Option.symbol_to_h symbol
|
|
90
|
+
item = Iro::Option.new({
|
|
91
|
+
stock: Iro::Stock.find_by( ticker: h[:ticker] ),
|
|
92
|
+
ticker: h[:ticker],
|
|
93
|
+
put_call: h[:put_call],
|
|
94
|
+
strike: h[:strike],
|
|
95
|
+
expires_on: h[:expires_on],
|
|
96
|
+
symbol: symbol,
|
|
97
|
+
})
|
|
98
|
+
item.save
|
|
99
|
+
return item
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
## trash, I can save the symbol every time. 2026-10-04
|
|
103
|
+
# def self.find_by_symbol symbol
|
|
104
|
+
# option = self.where( symbol: symbol ).first
|
|
105
|
+
# return option if option
|
|
106
|
+
# h = Iro::Option.symbol_to_h symbol
|
|
107
|
+
# Iro::Option.where( h ).first
|
|
108
|
+
# end
|
|
109
|
+
|
|
110
|
+
|
|
78
111
|
=begin
|
|
79
112
|
symbol = "META 260424P00500000"
|
|
80
113
|
=end
|
|
@@ -83,7 +116,7 @@ class Iro::Option
|
|
|
83
116
|
date_str = symbol[6,6]
|
|
84
117
|
type = symbol[12] == 'P' ? 'PUT' : 'CALL'
|
|
85
118
|
strike_str = symbol[13,8]
|
|
86
|
-
expires_on = Date.strptime(date_str, "%y%m%d")
|
|
119
|
+
expires_on = Date.strptime(date_str, "%y%m%d").to_s
|
|
87
120
|
strike = strike_str.to_i / 1000.0
|
|
88
121
|
return {
|
|
89
122
|
ticker: ticker,
|
data/app/models/iro/priceitem.rb
CHANGED
|
@@ -21,18 +21,19 @@ class Iro::Priceitem
|
|
|
21
21
|
field :bidSize, type: Integer
|
|
22
22
|
field :ask, type: Float
|
|
23
23
|
field :askSize, type: Integer
|
|
24
|
-
field :last, type: Float ## this is important
|
|
24
|
+
field :last, type: Float ## this is important?
|
|
25
|
+
field :mark, type: Float ## no, this is important. (bid+ask)/2
|
|
25
26
|
|
|
26
27
|
field :openPrice, type: Float
|
|
27
28
|
field :lowPrice, type: Float
|
|
28
29
|
field :highPrice, type: Float
|
|
29
30
|
field :closePrice, type: Float
|
|
30
31
|
|
|
31
|
-
field :quote_at, type: DateTime ## this is important
|
|
32
|
+
field :quote_at, type: DateTime ## this is important?
|
|
32
33
|
field :quoteTimeInLong, type: Integer
|
|
33
|
-
field :timestamp, type: Integer ## do not use
|
|
34
|
+
field :timestamp, type: Integer ## do not use?
|
|
34
35
|
field :totalVolume, type: Integer
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
field :exchangeName, type: String
|
|
37
38
|
field :volatility, type: Float
|
|
38
39
|
|
|
@@ -43,6 +44,63 @@ class Iro::Priceitem
|
|
|
43
44
|
field :openInterest, type: Integer
|
|
44
45
|
field :strikePrice, type: Float
|
|
45
46
|
|
|
47
|
+
def self.create_from_chains!
|
|
48
|
+
Iro::Iro.schwab_exec_sync ## should be schwab_data_sync()
|
|
49
|
+
|
|
50
|
+
stocks = Iro::Stock.active
|
|
51
|
+
fridays = 3.times.map { |i| ( Date.current.next_occurring(:friday) + i.weeks ).to_s }
|
|
52
|
+
|
|
53
|
+
stocks.each do |stock|
|
|
54
|
+
puts "+++ Getting #{stock.ticker}..."
|
|
55
|
+
response = Tda::Option.get_chains({
|
|
56
|
+
ticker: stock.ticker,
|
|
57
|
+
fromDate: fridays[0],
|
|
58
|
+
toDate: fridays.last,
|
|
59
|
+
strikeCount: 10,
|
|
60
|
+
})
|
|
61
|
+
# puts! response.keys, 'response.keys'
|
|
62
|
+
# puts! response['symbol'], 'response symbol'
|
|
63
|
+
# sleep 10
|
|
64
|
+
|
|
65
|
+
first_val = nil
|
|
66
|
+
['callExpDateMap', 'putExpDateMap'].each do |which_map|
|
|
67
|
+
|
|
68
|
+
response[which_map].each do |_date, strikes|
|
|
69
|
+
if fridays.include?( _date.split(':')[0] )
|
|
70
|
+
strikes.each do |_strike, vals|
|
|
71
|
+
vals.each do |val|
|
|
72
|
+
if !first_val
|
|
73
|
+
first_val = val
|
|
74
|
+
puts! val.keys, 'val keys'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
option = Iro::Option.find_or_create_by_symbol( val['symbol'] )
|
|
78
|
+
|
|
79
|
+
# opt = OpenStruct.new val
|
|
80
|
+
pi = Iro::Priceitem.new( val.slice( 'expirationDate',
|
|
81
|
+
'putCall', 'symbol', 'exchangeName', 'bid', 'ask',
|
|
82
|
+
'last', 'mark', 'bidSize', 'askSize', 'totalVolume', 'quoteTimeInLong', 'volatility',
|
|
83
|
+
'delta', 'gamma', 'theta', 'openInterest', 'strikePrice' ) )
|
|
84
|
+
pi.stock = stock
|
|
85
|
+
pi.option = option
|
|
86
|
+
pi.quote_at = Time.at( val['quoteTimeInLong'] / 1000 )
|
|
87
|
+
pi.ticker = stock.ticker
|
|
88
|
+
pi.save!
|
|
89
|
+
|
|
90
|
+
# puts! pi
|
|
91
|
+
print '.'
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end ## end fridays.include?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end ## which_map
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
46
104
|
def self.my_find props={}
|
|
47
105
|
lookup = { '$lookup': {
|
|
48
106
|
'from': 'iro_price_items',
|
data/app/models/tda/option.rb
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
require 'httparty'
|
|
3
3
|
|
|
4
|
-
=begin
|
|
5
|
-
class Schwab
|
|
6
|
-
include HTTParty
|
|
7
|
-
debug_output $stdout
|
|
8
|
-
base_uri 'https://api.schwabapi.com/marketdata/v1'
|
|
9
|
-
end
|
|
10
|
-
=end
|
|
11
|
-
|
|
12
4
|
class Tda::Option
|
|
13
|
-
|
|
14
5
|
include ::HTTParty
|
|
15
6
|
# debug_output $stdout
|
|
16
7
|
base_uri 'https://api.schwabapi.com/marketdata/v1'
|
|
@@ -18,7 +9,7 @@ class Tda::Option
|
|
|
18
9
|
|
|
19
10
|
##
|
|
20
11
|
## Get entire chains for a ticker
|
|
21
|
-
## params: { ticker, force }
|
|
12
|
+
## params: { ticker, force, strikeCount, fromDate (yyyy-mm-dd), toDate }
|
|
22
13
|
##
|
|
23
14
|
## 2024-08-09 :: Continue
|
|
24
15
|
## 2024-08-21 :: Continue : )
|
|
@@ -29,7 +20,10 @@ class Tda::Option
|
|
|
29
20
|
return JSON.parse File.read filename
|
|
30
21
|
|
|
31
22
|
else
|
|
32
|
-
query = { symbol: params[:ticker] } ##
|
|
23
|
+
query = { symbol: params[:ticker] } ## says query[:symbol], not ticker.
|
|
24
|
+
query[:strikeCount] = params[:strikeCount] if params[:strikeCount]
|
|
25
|
+
query[:fromDate] = params[:fromDate] if params[:fromDate]
|
|
26
|
+
query[:toDate] = params[:toDate] if params[:toDate]
|
|
33
27
|
# puts! query, 'query'
|
|
34
28
|
|
|
35
29
|
headers = {
|
|
@@ -37,40 +31,30 @@ class Tda::Option
|
|
|
37
31
|
Authorization: "Bearer #{Iro::Iro.schwab_data_token}",
|
|
38
32
|
}
|
|
39
33
|
path = "/chains"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
out = out.parsed_response
|
|
45
|
-
# puts! out, 'outs'
|
|
34
|
+
response = self.get path, { headers: headers, query: query }
|
|
35
|
+
timestamp = DateTime.parse response.headers['date']
|
|
36
|
+
response = response.parsed_response
|
|
37
|
+
puts! response, '/chains got this response'
|
|
46
38
|
|
|
47
39
|
outs = []
|
|
48
40
|
%w| put call |.each do |contractType|
|
|
49
|
-
_out =
|
|
50
|
-
_out.each do |
|
|
41
|
+
_out = response["#{contractType}ExpDateMap"]
|
|
42
|
+
_out.each do |_date, vs| ## date="2023-02-10:5"
|
|
51
43
|
vs.each do |strike, _v| ## strike="18.5"
|
|
52
44
|
_v = _v[0] ## weird, keep
|
|
53
45
|
# puts! _v, '_v'
|
|
54
46
|
|
|
55
|
-
v =
|
|
56
|
-
|
|
57
|
-
symbol: _v['symbol'],
|
|
58
|
-
bid: _v['bid'],
|
|
59
|
-
ask: _v['ask'],
|
|
60
|
-
last: _v['last'],
|
|
61
|
-
totalVolume: _v['totalVolume'],
|
|
62
|
-
openInterest: _v['openInterest'],
|
|
63
|
-
strikePrice: _v['strikePrice'],
|
|
64
|
-
expirationDate: _v['expirationDate'],
|
|
65
|
-
}
|
|
47
|
+
v = _v.slice( 'putCall', 'symbol', 'bid', 'ask', 'last', 'mark', 'totalVolume', 'openInterest',
|
|
48
|
+
'strikePrice', 'expirationDate' )
|
|
66
49
|
v.each do |k, i|
|
|
67
50
|
if i == 'NaN'
|
|
68
51
|
v[k] = nil
|
|
69
52
|
end
|
|
70
53
|
end
|
|
71
54
|
|
|
72
|
-
v[:timestamp] = timestamp
|
|
73
|
-
v[:
|
|
55
|
+
v[:timestamp] = timestamp # _v['quoteTimeInLong']/1000.0
|
|
56
|
+
v[:quote_at] = Time.at(_v['quoteTimeInLong'] / 1000.0)
|
|
57
|
+
v[:ticker] = params[:ticker]
|
|
74
58
|
outs.push( v )
|
|
75
59
|
end
|
|
76
60
|
end
|
|
@@ -83,8 +67,8 @@ class Tda::Option
|
|
|
83
67
|
end
|
|
84
68
|
end
|
|
85
69
|
|
|
86
|
-
File.write filename,
|
|
87
|
-
return
|
|
70
|
+
File.write filename, JSON.pretty_generate(response)
|
|
71
|
+
return response
|
|
88
72
|
end
|
|
89
73
|
end
|
|
90
74
|
|
|
@@ -96,6 +80,8 @@ class Tda::Option
|
|
|
96
80
|
OpenStruct.new ::Tda::Option.get_quotes(params)[0]
|
|
97
81
|
end
|
|
98
82
|
|
|
83
|
+
## ...for a single symbol.
|
|
84
|
+
## but use get_quotes_h instead?!
|
|
99
85
|
##
|
|
100
86
|
## params: contractType, strike, expirationDate, ticker
|
|
101
87
|
##
|
|
@@ -250,19 +236,23 @@ class Tda::Option
|
|
|
250
236
|
end
|
|
251
237
|
|
|
252
238
|
def self.close_credit_call
|
|
239
|
+
throw 'r40 - not implemented'
|
|
253
240
|
end
|
|
254
241
|
def self.close_long_debit_call_spread
|
|
242
|
+
throw 'r41 - not implemented'
|
|
255
243
|
end
|
|
256
244
|
def self.close_short_debit_put_spread
|
|
245
|
+
throw 'r42 - not implemented'
|
|
257
246
|
end
|
|
258
247
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
248
|
+
## trash? remove.
|
|
249
|
+
# def self.get_token
|
|
250
|
+
# opts = {
|
|
251
|
+
# grant_type: 'authorization_code',
|
|
252
|
+
# access_type: 'offline',
|
|
253
|
+
# code: ::TD_AMERITRADE[:code],
|
|
254
|
+
# }
|
|
255
|
+
# end
|
|
266
256
|
|
|
267
257
|
def self.create_credit_call outer:, inner:, q:, price:
|
|
268
258
|
query = {
|
|
@@ -307,13 +297,21 @@ class Tda::Option
|
|
|
307
297
|
# puts! out, 'created credit call?'
|
|
308
298
|
end
|
|
309
299
|
def self.create_long_debit_call_spread
|
|
300
|
+
throw 'r43 - not implemented'
|
|
310
301
|
end
|
|
311
302
|
def self.create_short_debit_put_spread
|
|
303
|
+
throw 'r44 - not implemented'
|
|
312
304
|
end
|
|
313
305
|
|
|
314
306
|
|
|
315
307
|
end
|
|
316
308
|
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
317
315
|
##
|
|
318
316
|
## From: https://developer.tdameritrade.com/content/place-order-samples
|
|
319
317
|
## Buy Limit: Vertical Call Spread
|
data/app/models/wco/publisher.rb
CHANGED
|
@@ -23,22 +23,25 @@ class Wco::Publisher
|
|
|
23
23
|
attr_accessor :props
|
|
24
24
|
|
|
25
25
|
def do_run
|
|
26
|
+
publisher = self
|
|
27
|
+
|
|
26
28
|
@site = site
|
|
27
29
|
@headers = {}
|
|
28
30
|
@ctx = OpenStruct.new
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
puts! context_eval, 'context_eval'
|
|
31
33
|
eval( context_eval )
|
|
32
|
-
|
|
34
|
+
puts! @ctx, '@ctx'
|
|
33
35
|
|
|
34
|
-
tmpl = ERB.new post_body_tmpl
|
|
36
|
+
tmpl = ERB.new publisher.post_body_tmpl
|
|
35
37
|
body = JSON.parse tmpl.result(binding)
|
|
36
|
-
|
|
38
|
+
puts! body, 'body'
|
|
37
39
|
|
|
38
40
|
out = Wco::HTTParty.post( "#{@site.origin}#{post_path}", {
|
|
39
41
|
body: body.to_json,
|
|
40
42
|
headers: @headers,
|
|
41
43
|
basic_auth: { username: @site.username, password: @site.password },
|
|
44
|
+
debug_output: $stdout,
|
|
42
45
|
})
|
|
43
46
|
puts! out.response, 'publisher httparty response'
|
|
44
47
|
puts! out.body, 'publisher httparty body'
|
|
@@ -54,12 +57,17 @@ class Wco::Publisher
|
|
|
54
57
|
raise out.body
|
|
55
58
|
end
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
if after_eval.present?
|
|
61
|
+
puts! after_eval, 'after_eval'
|
|
62
|
+
eval( after_eval )
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
return true
|
|
58
66
|
end
|
|
59
67
|
|
|
60
68
|
|
|
61
69
|
def to_s
|
|
62
|
-
"#{
|
|
70
|
+
"#{site} :: #{slug}"
|
|
63
71
|
end
|
|
64
72
|
|
|
65
73
|
def self.list
|
data/app/models/wco/report.rb
CHANGED
|
@@ -32,7 +32,7 @@ class Wco::Report
|
|
|
32
32
|
field :y, :type => Float
|
|
33
33
|
field :z, :type => Float
|
|
34
34
|
|
|
35
|
-
belongs_to :author, class_name: 'Wco::Profile'
|
|
35
|
+
belongs_to :author, class_name: 'Wco::Profile', optional: true
|
|
36
36
|
|
|
37
37
|
has_one :image_thumb, class_name: 'Wco::Photo', inverse_of: :report, dependent: :destroy
|
|
38
38
|
accepts_nested_attributes_for :image_thumb
|
data/app/models/wco/site.rb
CHANGED
|
@@ -18,7 +18,7 @@ class Wco::Site
|
|
|
18
18
|
has_many :logs, inverse_of: :obj
|
|
19
19
|
has_many :publishers # , class_name: 'Wco::Publisher'
|
|
20
20
|
has_many :sitemap_paths, class_name: 'Wco::SitemapPath'
|
|
21
|
-
has_many :tags, class_name: 'Wco::Tag'
|
|
21
|
+
has_many :tags, class_name: 'Wco::Tag', inverse_of: :site
|
|
22
22
|
|
|
23
23
|
field :slug
|
|
24
24
|
validates :slug, presence: true, uniqueness: true
|
|
@@ -34,78 +34,12 @@ class Wco::Site
|
|
|
34
34
|
|
|
35
35
|
def to_s
|
|
36
36
|
slug
|
|
37
|
-
# origin
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
def self.list
|
|
41
40
|
[[nil,nil]] + all.map { |s| [ s.slug, s.id ] }
|
|
42
41
|
end
|
|
43
42
|
|
|
44
|
-
def body
|
|
45
|
-
{
|
|
46
|
-
"_links": {
|
|
47
|
-
"type":{"href":"http://pi.local/rest/type/node/article"}
|
|
48
|
-
},
|
|
49
|
-
"title":[{"value":"Node +++ 123 bac +++" }],
|
|
50
|
-
"body":[{"value": "<b>hello, wor</b>ld!", "format": "full_html" }],
|
|
51
|
-
"type":[{"target_id":"article"}],
|
|
52
|
-
"status": [{"value": 1}],
|
|
53
|
-
"_embedded": {
|
|
54
|
-
"http://pi.local/rest/relation/node/article/field_issue": [
|
|
55
|
-
{ "uuid": [{ "value": "56229a95-d675-43e1-99b1-f9e11b5579c5" }] }
|
|
56
|
-
],
|
|
57
|
-
"http://pi.local/rest/relation/node/article/field_tags": [
|
|
58
|
-
{ "uuid": [{ "value": "45646a7d-1a16-42e8-b758-f6e1c8d976f7" }] },
|
|
59
|
-
{ "uuid": [{ "value": "834e34e2-05ae-498d-b876-453798872ce1" }] }
|
|
60
|
-
]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def do_post
|
|
67
|
-
HTTParty.post( post_url,
|
|
68
|
-
body: JSON.generate( body ),
|
|
69
|
-
headers: { 'Content-Type' => 'application/hal+json' },
|
|
70
|
-
basic_auth: { username: username, password: password },
|
|
71
|
-
)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def wp_import
|
|
75
|
-
site = self
|
|
76
|
-
|
|
77
|
-
root_tag = Wco::Tag.find_or_create_by slug: "#{site.slug}_wp-import", site_id: site.id
|
|
78
|
-
url = "#{site.origin}/wp-json/wp/v2/posts"
|
|
79
|
-
pi_admin = Wco::Profile.find_or_create_by email: 'admin@piousbox.com'
|
|
80
|
-
n_pages = 12
|
|
81
|
-
per_page = 100
|
|
82
|
-
|
|
83
|
-
(1..n_pages).each do |page|
|
|
84
|
-
print "Page #{page}"
|
|
85
|
-
|
|
86
|
-
posts = HTTParty.get url, query: { per_page: per_page, page: page }
|
|
87
|
-
posts.each do |post|
|
|
88
|
-
report = Wco::Report.new({
|
|
89
|
-
legacy_id: post['id'],
|
|
90
|
-
created_at: post['date'],
|
|
91
|
-
slug: post['link'].sub(site.origin, ''),
|
|
92
|
-
title: post['title']['rendered'],
|
|
93
|
-
subtitle: post['excerpt']['rendered'],
|
|
94
|
-
body: post['content']['rendered'],
|
|
95
|
-
author: pi_admin,
|
|
96
|
-
tag_ids: ( [ root_tag ] + site.tags.where( :legacy_id.in => post['categories'] ) ).map(&:id),
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
if report.save
|
|
100
|
-
print '^'
|
|
101
|
-
else
|
|
102
|
-
puts report.errors.messages
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
puts "ok"
|
|
107
|
-
end
|
|
108
|
-
|
|
109
43
|
def check_sitemap
|
|
110
44
|
@results = []
|
|
111
45
|
@total_count = 0
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
|
|
2
|
+
def body
|
|
3
|
+
{
|
|
4
|
+
"_links": {
|
|
5
|
+
"type":{"href":"http://pi.local/rest/type/node/article"}
|
|
6
|
+
},
|
|
7
|
+
"title":[{"value":"Node +++ 123 bac +++" }],
|
|
8
|
+
"body":[{"value": "<b>hello, wor</b>ld!", "format": "full_html" }],
|
|
9
|
+
"type":[{"target_id":"article"}],
|
|
10
|
+
"status": [{"value": 1}],
|
|
11
|
+
"_embedded": {
|
|
12
|
+
"http://pi.local/rest/relation/node/article/field_issue": [
|
|
13
|
+
{ "uuid": [{ "value": "56229a95-d675-43e1-99b1-f9e11b5579c5" }] }
|
|
14
|
+
],
|
|
15
|
+
"http://pi.local/rest/relation/node/article/field_tags": [
|
|
16
|
+
{ "uuid": [{ "value": "45646a7d-1a16-42e8-b758-f6e1c8d976f7" }] },
|
|
17
|
+
{ "uuid": [{ "value": "834e34e2-05ae-498d-b876-453798872ce1" }] }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def do_post
|
|
25
|
+
HTTParty.post( post_url,
|
|
26
|
+
body: JSON.generate( body ),
|
|
27
|
+
headers: { 'Content-Type' => 'application/hal+json' },
|
|
28
|
+
basic_auth: { username: username, password: password },
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def wp_import
|
|
33
|
+
site = self
|
|
34
|
+
|
|
35
|
+
root_tag = Wco::Tag.find_or_create_by slug: "#{site.slug}_wp-import", site_id: site.id
|
|
36
|
+
url = "#{site.origin}/wp-json/wp/v2/posts"
|
|
37
|
+
pi_admin = Wco::Profile.find_or_create_by email: 'admin@piousbox.com'
|
|
38
|
+
n_pages = 12
|
|
39
|
+
per_page = 100
|
|
40
|
+
|
|
41
|
+
(1..n_pages).each do |page|
|
|
42
|
+
print "Page #{page}"
|
|
43
|
+
|
|
44
|
+
posts = HTTParty.get url, query: { per_page: per_page, page: page }
|
|
45
|
+
posts.each do |post|
|
|
46
|
+
report = Wco::Report.new({
|
|
47
|
+
legacy_id: post['id'],
|
|
48
|
+
created_at: post['date'],
|
|
49
|
+
slug: post['link'].sub(site.origin, ''),
|
|
50
|
+
title: post['title']['rendered'],
|
|
51
|
+
subtitle: post['excerpt']['rendered'],
|
|
52
|
+
body: post['content']['rendered'],
|
|
53
|
+
author: pi_admin,
|
|
54
|
+
tag_ids: ( [ root_tag ] + site.tags.where( :legacy_id.in => post['categories'] ) ).map(&:id),
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
if report.save
|
|
58
|
+
print '^'
|
|
59
|
+
else
|
|
60
|
+
puts report.errors.messages
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
puts "ok"
|
|
65
|
+
end
|
data/app/models/wco/tag.rb
CHANGED
|
@@ -9,15 +9,17 @@ class Wco::Tag
|
|
|
9
9
|
index({ slug: -1 })
|
|
10
10
|
|
|
11
11
|
field :weight, type: :string, default: 'jjj'
|
|
12
|
+
field :external_id, type: :string
|
|
13
|
+
def eid; external_id; end
|
|
12
14
|
|
|
13
15
|
belongs_to :parent, class_name: '::Wco::Tag', inverse_of: :sons, optional: true
|
|
14
16
|
has_many :sons, class_name: '::Wco::Tag', inverse_of: :parent
|
|
15
17
|
|
|
16
|
-
belongs_to :site,
|
|
17
|
-
belongs_to :sidebar_profile, class_name: 'Wco::Profile',
|
|
18
|
-
has_many :email_filters,
|
|
19
|
-
has_many :email_templates,
|
|
20
|
-
has_many :ajects,
|
|
18
|
+
belongs_to :site, class_name: '::Wco::Site', optional: true, inverse_of: :tags
|
|
19
|
+
belongs_to :sidebar_profile, class_name: 'Wco::Profile', optional: true
|
|
20
|
+
has_many :email_filters, class_name: '::WcoEmail::EmailFilter', inverse_of: :tag
|
|
21
|
+
has_many :email_templates, class_name: '::WcoEmail::EmailTemplate', inverse_of: :tag
|
|
22
|
+
has_many :ajects, class_name: '::WcoEmail::EmailFilterAction', inverse_of: :aject
|
|
21
23
|
|
|
22
24
|
has_and_belongs_to_many :conversations, class_name: '::WcoEmail::Conversation', index: true
|
|
23
25
|
has_and_belongs_to_many :galleries, class_name: '::Wco::Gallery'
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
= link_to oat.slug, office_action_template_path(oat)
|
|
17
17
|
|
|
18
|
-
= button_to '
|
|
18
|
+
= button_to 'Perform', oat_perform_path(oat), data: { confirm: 'Are you sure?' }
|
|
19
19
|
.col-6
|
|
20
20
|
= render '/wco/office_action_templates/ties', ties: oat.ties, oat: oat
|
|
21
21
|
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
%h5 Office Action
|
|
4
4
|
.d-inline-block
|
|
5
5
|
= select_tag :office_action_template, options_for_select(@office_action_templates_list), class: 'select2'
|
|
6
|
-
%a.btn.office-action-templates-perform-btn{ href: "javascript: void(0)", data: { url: wco.
|
|
6
|
+
%a.btn.office-action-templates-perform-btn{ href: "javascript: void(0)", data: { url: wco.oats_perform_path } }
|
|
7
7
|
Perform
|
|
@@ -20,11 +20,15 @@
|
|
|
20
20
|
.d-flex
|
|
21
21
|
%label post_path
|
|
22
22
|
= f.text_field :post_path, class: 'w-100'
|
|
23
|
-
.field
|
|
23
|
+
.field.d-flex.flex-column
|
|
24
24
|
%label.d-block context_eval
|
|
25
|
+
.descr
|
|
26
|
+
@headers, @props
|
|
25
27
|
= f.text_area :context_eval, class: 'monospace'
|
|
26
|
-
.field
|
|
28
|
+
.field.d-flex.flex-column
|
|
27
29
|
%label.d-block post_body_tmpl
|
|
30
|
+
.descr
|
|
31
|
+
@headers, @props and #context_eval
|
|
28
32
|
= f.text_area :post_body_tmpl, class: 'monospace'
|
|
29
33
|
.field
|
|
30
34
|
%label.d-block after_eval
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
-# %th kind
|
|
12
12
|
%th origin
|
|
13
13
|
-# %th post_path
|
|
14
|
+
%th tags
|
|
14
15
|
- @sites.each do |site|
|
|
15
16
|
%tr
|
|
16
17
|
%td
|
|
@@ -22,3 +23,8 @@
|
|
|
22
23
|
-# %td= site.kind
|
|
23
24
|
%td= site.origin
|
|
24
25
|
-# %td= site.post_path
|
|
26
|
+
%td
|
|
27
|
+
- site.tags.map do |t|
|
|
28
|
+
= link_to t.slug, tag_path(t)
|
|
29
|
+
,
|
|
30
|
+
|
data/config/routes.rb
CHANGED
|
@@ -95,8 +95,8 @@ Wco::Engine.routes.draw do
|
|
|
95
95
|
|
|
96
96
|
resources :obfuscated_redirects
|
|
97
97
|
|
|
98
|
-
post 'office_action_templates',
|
|
99
|
-
post 'office_action_templates/perform',
|
|
98
|
+
post 'office_action_templates', to: 'office_action_templates#update'
|
|
99
|
+
post 'office_action_templates/perform', to: 'office_action_templates#perform', as: :oats_perform ## from the mailbox, the oat id is passed as a body param.
|
|
100
100
|
post 'office_action_templates/:id/perform', to: 'office_action_templates#perform', as: :oat_perform
|
|
101
101
|
get 'office_action_templates/:id/perform', to: 'office_action_templates#perform'
|
|
102
102
|
resources :office_action_templates
|
data/lib/wco_models.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wco_models
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.4.0.
|
|
4
|
+
version: 3.4.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Victor Pudeyev
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-s3
|
|
@@ -544,6 +544,7 @@ files:
|
|
|
544
544
|
- app/models/wco/report.rb
|
|
545
545
|
- app/models/wco/setting.rb
|
|
546
546
|
- app/models/wco/site.rb
|
|
547
|
+
- app/models/wco/site.rb-trash
|
|
547
548
|
- app/models/wco/sitemap_path.rb
|
|
548
549
|
- app/models/wco/subscription.rb
|
|
549
550
|
- app/models/wco/tag.rb
|