wco_models 3.1.0.264 → 3.1.0.265
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 +31 -10
- data/app/helpers/wco/application_helper.rb +2 -2
- data/app/models/iro/position.rb +20 -22
- data/app/models/iro/purse.rb +0 -29
- data/app/models/iro/strategy.rb +36 -29
- data/app/models/tda/order.rb +4 -3
- data/app/models/wco_email/config.rb +15 -0
- data/app/views/wco/profiles/_form.haml +5 -0
- 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: 327c2ab838cce926d5afd9e979b7acb2979aa8e78d1745470ea29ccac2e81197
|
|
4
|
+
data.tar.gz: 42615e28beeb55afbdf91eb592c58b22dae4a89d168e2ba17ce9046a7ac68857
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ca18a2f3190d96d1c8a2d9b62823886b8bb77870b22246a4af13f1f55081c65dd8bfc7b15e0db9fd232d0efc0968c7c4dd0ac8c9e0da1063c486b08fe2c5d9c
|
|
7
|
+
data.tar.gz: 8c4c8a85bcd9087b837e6c70b42082967c9b2d502c9cc12651a946cceab10c6d85ca1d18646fa18f6b56862b51cd8436e9071a7eaa8bda059dbd6a1252cd65b3
|
|
@@ -70,16 +70,6 @@ table.bordered {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
table.sticky thead,
|
|
74
|
-
table thead.sticky {
|
|
75
|
-
background: #ccc;
|
|
76
|
-
|
|
77
|
-
th {
|
|
78
|
-
position: sticky;
|
|
79
|
-
top: 0;
|
|
80
|
-
z-index: 10;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
73
|
|
|
84
74
|
/* C */
|
|
85
75
|
|
|
@@ -93,6 +83,11 @@ textarea.monospace {
|
|
|
93
83
|
padding: 0.6em;
|
|
94
84
|
}
|
|
95
85
|
|
|
86
|
+
.crossed,
|
|
87
|
+
.crossout {
|
|
88
|
+
text-decoration: line-through;
|
|
89
|
+
}
|
|
90
|
+
|
|
96
91
|
/* D */
|
|
97
92
|
|
|
98
93
|
.d-flex {
|
|
@@ -250,10 +245,36 @@ label.required {
|
|
|
250
245
|
|
|
251
246
|
|
|
252
247
|
/* S */
|
|
248
|
+
|
|
253
249
|
.spacer-small {
|
|
254
250
|
height: 20px;
|
|
255
251
|
}
|
|
256
252
|
|
|
253
|
+
div.sticky,
|
|
254
|
+
h2.sticky,
|
|
255
|
+
h3.sticky,
|
|
256
|
+
h4.sticky,
|
|
257
|
+
h5.sticky {
|
|
258
|
+
position: sticky;
|
|
259
|
+
top: 0.5em;
|
|
260
|
+
z-index: 10;
|
|
261
|
+
|
|
262
|
+
border-radius: 0.5em;
|
|
263
|
+
padding: 0.5em;
|
|
264
|
+
background: rgba(255,255,255, 0.5);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
table.sticky thead,
|
|
268
|
+
table thead.sticky {
|
|
269
|
+
background: #ccc;
|
|
270
|
+
|
|
271
|
+
th {
|
|
272
|
+
position: sticky;
|
|
273
|
+
top: 0;
|
|
274
|
+
z-index: 10;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
257
278
|
/* T */
|
|
258
279
|
|
|
259
280
|
.title {
|
|
@@ -34,8 +34,8 @@ module Wco::ApplicationHelper
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def pp_amount a, config = { precision: 2 }
|
|
37
|
-
return '
|
|
38
|
-
return '
|
|
37
|
+
return '___' if !a
|
|
38
|
+
return '___' if a.class == String
|
|
39
39
|
return number_to_currency a, precision: config[:precision]
|
|
40
40
|
# "$#{'%.2f' % a}"
|
|
41
41
|
end
|
data/app/models/iro/position.rb
CHANGED
|
@@ -5,12 +5,6 @@ class Iro::Position
|
|
|
5
5
|
include Mongoid::Paranoia
|
|
6
6
|
store_in collection: 'iro_positions'
|
|
7
7
|
|
|
8
|
-
## @trash, use next_gain_loss_amount instead
|
|
9
|
-
# field :prev_gain_loss_amount, type: :float
|
|
10
|
-
# def prev_gain_loss_amount
|
|
11
|
-
# out = autoprev.outer.end_price - autoprev.inner.end_price
|
|
12
|
-
# out += inner.begin_price - outer.begin_price
|
|
13
|
-
# end
|
|
14
8
|
field :next_gain_loss_amount, type: :float
|
|
15
9
|
|
|
16
10
|
|
|
@@ -231,33 +225,35 @@ class Iro::Position
|
|
|
231
225
|
# puts! outs, '#calc_nxt.outs -> 2'
|
|
232
226
|
|
|
233
227
|
## next_inner_strike
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if Iro::Strategy::
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
228
|
+
if strategy.next_inner_strike.present?
|
|
229
|
+
outs = outs.select do |out|
|
|
230
|
+
if Iro::Strategy::CREDIT == pos.credit_or_debit
|
|
231
|
+
if Iro::Strategy::SHORT == pos.long_or_short
|
|
232
|
+
## short credit call
|
|
233
|
+
out[:strikePrice] >= strategy.next_inner_strike
|
|
234
|
+
elsif Iro::Strategy::LONG == pos.long_or_short
|
|
235
|
+
## long credit put
|
|
236
|
+
out[:strikePrice] <= strategy.next_inner_strike
|
|
237
|
+
end
|
|
238
|
+
else
|
|
239
|
+
raise 'zt3 - @TODO: implement, debit spreads'
|
|
242
240
|
end
|
|
243
|
-
else
|
|
244
|
-
raise 'zt3 - @TODO: implement, debit spreads'
|
|
245
241
|
end
|
|
242
|
+
puts! outs[0][:strikePrice], 'after calc next_inner_strike'
|
|
243
|
+
# puts! outs, 'outs'
|
|
246
244
|
end
|
|
247
|
-
puts! outs[0][:strikePrice], 'after calc next_inner_strike'
|
|
248
|
-
# puts! outs, 'outs'
|
|
249
245
|
|
|
250
|
-
##
|
|
246
|
+
## next_usd_above_mark
|
|
251
247
|
outs = outs.select do |out|
|
|
252
248
|
if Iro::Strategy::SHORT == pos.long_or_short
|
|
253
|
-
out[:strikePrice] > strategy.
|
|
249
|
+
out[:strikePrice] > strategy.next_usd_above_mark + strategy.stock.last
|
|
254
250
|
elsif Iro::Strategy::LONG == pos.long_or_short
|
|
255
|
-
out[:strikePrice] < strategy.stock.last - strategy.
|
|
251
|
+
out[:strikePrice] < strategy.stock.last - strategy.next_usd_above_mark
|
|
256
252
|
else
|
|
257
253
|
raise 'zt4 - this cannot happen'
|
|
258
254
|
end
|
|
259
255
|
end
|
|
260
|
-
puts! outs[0][:strikePrice], 'after calc
|
|
256
|
+
puts! outs[0][:strikePrice], 'after calc next_usd_above_mark'
|
|
261
257
|
puts! outs, 'outs'
|
|
262
258
|
|
|
263
259
|
## next_inner_delta
|
|
@@ -310,7 +306,9 @@ class Iro::Position
|
|
|
310
306
|
status: 'proposed',
|
|
311
307
|
stock: strategy.stock,
|
|
312
308
|
inner_strike: inner_attrs[:strike],
|
|
309
|
+
inner_attributes: inner_attrs,
|
|
313
310
|
outer_strike: outer_attrs[:strike],
|
|
311
|
+
outer_attributes: outer_attrs,
|
|
314
312
|
begin_on: Time.now.to_date,
|
|
315
313
|
expires_on: next_expires_on,
|
|
316
314
|
purse: purse,
|
data/app/models/iro/purse.rb
CHANGED
|
@@ -33,35 +33,6 @@ class Iro::Purse
|
|
|
33
33
|
available_amount
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# def balance
|
|
37
|
-
# 0.01
|
|
38
|
-
# end
|
|
39
|
-
|
|
40
|
-
def delta_wt_avg( begin_end, long_short, inner_outer )
|
|
41
|
-
max_loss_total = 0
|
|
42
|
-
|
|
43
|
-
out = positions.send( long_short ).map do |pos|
|
|
44
|
-
max_loss_total += pos.max_loss * pos.q
|
|
45
|
-
pos.max_loss * pos.q * pos.send( inner_outer ).send( "#{begin_end}_delta" )
|
|
46
|
-
end
|
|
47
|
-
# puts! out, 'delta_wt_avg 1'
|
|
48
|
-
out = out.reduce( &:+ ) / max_loss_total rescue 0
|
|
49
|
-
# puts! out, 'delta_wt_avg 2'
|
|
50
|
-
return out
|
|
51
|
-
end
|
|
52
|
-
## delta to plot percentage
|
|
53
|
-
## convert to normal between 0 and 3 std
|
|
54
|
-
def delta_to_plot_p( *args )
|
|
55
|
-
x = delta_wt_avg( *args ).abs
|
|
56
|
-
if x < 0.5
|
|
57
|
-
y = 1
|
|
58
|
-
else
|
|
59
|
-
y = 2 - 1/( 1.5 - x )
|
|
60
|
-
end
|
|
61
|
-
y_ = "#{ (y*100) .to_i}%"
|
|
62
|
-
return y_
|
|
63
|
-
end
|
|
64
|
-
|
|
65
36
|
def to_s
|
|
66
37
|
slug
|
|
67
38
|
end
|
data/app/models/iro/strategy.rb
CHANGED
|
@@ -79,7 +79,6 @@ class Iro::Strategy
|
|
|
79
79
|
|
|
80
80
|
field :threshold_usd_above_mark, type: :float
|
|
81
81
|
validates :threshold_usd_above_mark, presence: true
|
|
82
|
-
def buffer_above_water; threshold_usd_above_mark; end
|
|
83
82
|
|
|
84
83
|
field :threshold_pos_delta, type: :float # offensive: roll b/c markets are going my way
|
|
85
84
|
field :threshold_neg_delta, type: :float # defensive: roll b/c markets are going against me
|
|
@@ -206,6 +205,7 @@ class Iro::Strategy
|
|
|
206
205
|
## decisions
|
|
207
206
|
##
|
|
208
207
|
|
|
208
|
+
## do not use!
|
|
209
209
|
def calc_rollp_covered_call p
|
|
210
210
|
stock.reload
|
|
211
211
|
|
|
@@ -213,10 +213,10 @@ class Iro::Strategy
|
|
|
213
213
|
return [ 0.99, '0 DTE, must exit' ]
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
-
if ( stock.last -
|
|
216
|
+
if ( stock.last - threshold_usd_above_mark ) < p.inner.strike
|
|
217
217
|
return [ 0.98, "Last #{'%.2f' % stock.last} is " +
|
|
218
|
-
"#{'%.2f' % [p.inner.strike +
|
|
219
|
-
"below #{'%.2f' % [p.inner.strike +
|
|
218
|
+
"#{'%.2f' % [p.inner.strike + threshold_usd_above_mark - stock.last]} " +
|
|
219
|
+
"below #{'%.2f' % [p.inner.strike + threshold_usd_above_mark]} water" ]
|
|
220
220
|
end
|
|
221
221
|
|
|
222
222
|
if p.inner.end_delta < threshold_pos_delta
|
|
@@ -230,7 +230,7 @@ class Iro::Strategy
|
|
|
230
230
|
return [ 0.33, '-' ]
|
|
231
231
|
end
|
|
232
232
|
|
|
233
|
-
##
|
|
233
|
+
## do not use!
|
|
234
234
|
def calc_rollp_long_debit_call_spread p
|
|
235
235
|
stock.reload
|
|
236
236
|
|
|
@@ -241,10 +241,10 @@ class Iro::Strategy
|
|
|
241
241
|
return [ 0.99, '1 DTE, must exit' ]
|
|
242
242
|
end
|
|
243
243
|
|
|
244
|
-
if ( stock.last -
|
|
244
|
+
if ( stock.last - threshold_usd_above_mark ) < p.inner.strike
|
|
245
245
|
return [ 0.95, "Last #{'%.2f' % stock.last} is " +
|
|
246
|
-
"#{'%.2f' % [stock.last - p.inner.strike -
|
|
247
|
-
"below #{'%.2f' % [p.inner.strike +
|
|
246
|
+
"#{'%.2f' % [stock.last - p.inner.strike - threshold_usd_above_mark]} " +
|
|
247
|
+
"below #{'%.2f' % [p.inner.strike + threshold_usd_above_mark]} water" ]
|
|
248
248
|
end
|
|
249
249
|
|
|
250
250
|
if p.inner.end_delta < threshold_pos_delta
|
|
@@ -258,14 +258,15 @@ class Iro::Strategy
|
|
|
258
258
|
return [ 0.33, '-' ]
|
|
259
259
|
end
|
|
260
260
|
|
|
261
|
-
## 2025-10-12
|
|
261
|
+
## 2025-10-12 continue
|
|
262
|
+
## 2026-04-05 continue
|
|
262
263
|
def calc_rollp_long_credit_put_spread p
|
|
263
264
|
stock.reload
|
|
264
265
|
|
|
265
266
|
# puts! p, '#calc_rollp_long_credit_put_spread'
|
|
266
267
|
# puts! p.inner, 'p.inner'
|
|
267
|
-
puts! stock, 'stock'
|
|
268
|
-
puts! attributes, 'strategy attributes'
|
|
268
|
+
# puts! stock, 'stock'
|
|
269
|
+
# puts! attributes, 'strategy attributes'
|
|
269
270
|
|
|
270
271
|
if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
|
|
271
272
|
return [ 0.99, '0 DTE, must exit' ]
|
|
@@ -274,24 +275,28 @@ class Iro::Strategy
|
|
|
274
275
|
return [ 0.99, '1 DTE, must exit' ]
|
|
275
276
|
end
|
|
276
277
|
|
|
277
|
-
if ( stock.last -
|
|
278
|
-
return [ 0.95, "Last
|
|
279
|
-
|
|
280
|
-
"below #{'%.2f' % [p.inner.strike + buffer_above_water]} water" ]
|
|
278
|
+
if ( stock.last - threshold_usd_above_mark ) < p.inner.strike
|
|
279
|
+
return [ 0.95, ":threshold_usd_above_mark <br />Last $#{'%.2f' % stock.last} is " +
|
|
280
|
+
"#{'%.2f' % [stock.last - p.inner.strike]} near #{p.inner.strike} but should be greater than #{threshold_usd_above_mark} ." ]
|
|
281
281
|
end
|
|
282
282
|
|
|
283
|
-
if p.inner.end_delta < threshold_pos_delta
|
|
284
|
-
return [ 0.79, "
|
|
283
|
+
if p.inner.end_delta.abs < threshold_pos_delta
|
|
284
|
+
return [ 0.79, ":threshold_pos_delta <br />Offensive roll: delta #{p.inner.end_delta} is lower than #{threshold_pos_delta} ." ]
|
|
285
|
+
end
|
|
286
|
+
if p.inner.end_delta.abs > threshold_neg_delta
|
|
287
|
+
return [ 0.79, ":threshold_neg_delta <br />Defensive roll: delta #{p.inner.end_delta} is higher than #{threshold_neg_delta} ." ]
|
|
285
288
|
end
|
|
286
289
|
|
|
287
|
-
if
|
|
288
|
-
|
|
290
|
+
if threshold_netp.present?
|
|
291
|
+
if 1 - p.inner.end_price/p.inner.begin_price > threshold_netp
|
|
292
|
+
return [ 0.51, ":threshold_netp <br />made enough #{'%.02f' % [(1.0 - p.inner.end_price/p.inner.begin_price )*100]}% profit^" ]
|
|
293
|
+
end
|
|
289
294
|
end
|
|
290
295
|
|
|
291
296
|
return [ 0.33, '-' ]
|
|
292
297
|
end
|
|
293
298
|
|
|
294
|
-
##
|
|
299
|
+
## do not use!
|
|
295
300
|
def calc_rollp_short_debit_put_spread p
|
|
296
301
|
stock.reload
|
|
297
302
|
|
|
@@ -299,10 +304,10 @@ class Iro::Strategy
|
|
|
299
304
|
return [ 0.99, "< #{threshold_dte}DTE, must exit" ]
|
|
300
305
|
end
|
|
301
306
|
|
|
302
|
-
if stock.last +
|
|
307
|
+
if stock.last + threshold_usd_above_mark > p.inner.strike
|
|
303
308
|
return [ 0.98, "Last #{'%.2f' % stock.last} is " +
|
|
304
|
-
"#{'%.2f' % [stock.last +
|
|
305
|
-
"above #{'%.2f' % [p.inner.strike -
|
|
309
|
+
"#{'%.2f' % [stock.last + threshold_usd_above_mark - p.inner.strike]} " +
|
|
310
|
+
"above #{'%.2f' % [p.inner.strike - threshold_usd_above_mark]} water" ]
|
|
306
311
|
end
|
|
307
312
|
|
|
308
313
|
if p.inner.end_delta.abs < threshold_pos_delta.abs
|
|
@@ -317,6 +322,7 @@ class Iro::Strategy
|
|
|
317
322
|
end
|
|
318
323
|
|
|
319
324
|
## 2026-02-21 ok
|
|
325
|
+
## 2026-04-05 ok
|
|
320
326
|
def calc_rollp_short_credit_call_spread p
|
|
321
327
|
puts! p, 'calc_rollp_short_credit_call_spread...'
|
|
322
328
|
stock.reload
|
|
@@ -325,10 +331,9 @@ class Iro::Strategy
|
|
|
325
331
|
return [ 0.99, "< #{threshold_dte}DTE, must exit" ]
|
|
326
332
|
end
|
|
327
333
|
|
|
328
|
-
if stock.last +
|
|
329
|
-
return [ 0.95, "Last
|
|
330
|
-
"#{'%.2f' % [stock.last
|
|
331
|
-
"above #{'%.2f' % [p.inner.strike - buffer_above_water]} water" ]
|
|
334
|
+
if stock.last + threshold_usd_above_mark > p.inner.strike
|
|
335
|
+
return [ 0.95, ":threshold_usd_above_mark <br />Last $#{'%.2f' % stock.last} is " +
|
|
336
|
+
"#{'%.2f' % [p.inner.strike - stock.last]} near #{p.inner.strike} but should be greater than #{threshold_usd_above_mark} ." ]
|
|
332
337
|
end
|
|
333
338
|
|
|
334
339
|
## defensive
|
|
@@ -342,8 +347,10 @@ class Iro::Strategy
|
|
|
342
347
|
return [ 0.69, "Delta #{p.inner.end_delta} is lower than #{threshold_pos_delta} offensive threshold." ]
|
|
343
348
|
end
|
|
344
349
|
|
|
345
|
-
if
|
|
346
|
-
|
|
350
|
+
if threshold_netp.present?
|
|
351
|
+
if p.net_percent > threshold_netp
|
|
352
|
+
return [ 0.51, "made enough #{'%.0f' % [p.net_percent*100]}% > #{"%.2f" % [threshold_netp*100]}% profit," ]
|
|
353
|
+
end
|
|
347
354
|
end
|
|
348
355
|
|
|
349
356
|
return [ 0.33, '-' ]
|
data/app/models/tda/order.rb
CHANGED
|
@@ -33,6 +33,7 @@ class Tda::Order
|
|
|
33
33
|
puts! results, 'results'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
## obsolete, I don't do covered calls anymore?
|
|
36
37
|
def self.roll_covered_call_q pos
|
|
37
38
|
roll_price = pos.inner.begin_price - pos.autoprev.inner.end_price
|
|
38
39
|
query = {
|
|
@@ -67,12 +68,12 @@ class Tda::Order
|
|
|
67
68
|
return query
|
|
68
69
|
end
|
|
69
70
|
|
|
70
|
-
def self.
|
|
71
|
+
def self.roll_credit_call_spread_q pos
|
|
71
72
|
query = {
|
|
72
|
-
orderType:
|
|
73
|
+
orderType: pos.roll_price > 0 ? "NET_CREDIT" : "NET_DEBIT",
|
|
73
74
|
session: "NORMAL",
|
|
74
75
|
duration: "DAY",
|
|
75
|
-
price:
|
|
76
|
+
price: pos.roll_price.abs.to_s,
|
|
76
77
|
orderStrategyType: "SINGLE",
|
|
77
78
|
orderLegCollection: [
|
|
78
79
|
## close
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
class WcoEmail::Config
|
|
3
|
+
include Mongoid::Document
|
|
4
|
+
include Mongoid::Timestamps
|
|
5
|
+
store_in collection: 'wco_email_config'
|
|
6
|
+
|
|
7
|
+
field :key
|
|
8
|
+
validates :key, { presence: true, uniqueness: true }
|
|
9
|
+
|
|
10
|
+
field :value
|
|
11
|
+
validates :value, { presence: true }
|
|
12
|
+
|
|
13
|
+
field :descr
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
%hr
|
|
24
24
|
.row
|
|
25
25
|
.col-6
|
|
26
|
+
.field
|
|
27
|
+
%label schwab_account_hash
|
|
28
|
+
= f.text_field :schwab_account_hash
|
|
26
29
|
.field
|
|
27
30
|
%label schwab_access_token
|
|
28
31
|
= f.text_field :schwab_access_token
|
|
@@ -33,6 +36,8 @@
|
|
|
33
36
|
%label schwab_id_token
|
|
34
37
|
= f.text_field :schwab_id_token
|
|
35
38
|
.col-6
|
|
39
|
+
.field
|
|
40
|
+
%label
|
|
36
41
|
.field
|
|
37
42
|
%label schwab_exec_access_token
|
|
38
43
|
= f.text_field :schwab_exec_access_token
|
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.1.0.
|
|
4
|
+
version: 3.1.0.265
|
|
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-04-
|
|
11
|
+
date: 2026-04-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ahoy_matey
|
|
@@ -516,6 +516,7 @@ files:
|
|
|
516
516
|
- app/models/wco/utils.rb
|
|
517
517
|
- app/models/wco/video.rb
|
|
518
518
|
- app/models/wco_email/campaign.rb
|
|
519
|
+
- app/models/wco_email/config.rb
|
|
519
520
|
- app/models/wco_email/context.rb
|
|
520
521
|
- app/models/wco_email/conversation.rb
|
|
521
522
|
- app/models/wco_email/email_action.rb
|