wco_models 3.1.0.249 → 3.1.0.250
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 +9 -1
- data/app/mailers/wco_email/application_mailer.rb +14 -3
- data/app/models/wco/lead.rb +4 -2
- data/app/models/wco/office_action.rb +17 -15
- data/app/models/wco/office_action_template.rb +2 -0
- data/app/models/wco/tag.rb +2 -2
- data/app/models/wco_email/conversation.rb +4 -0
- data/app/models/wco_email/email_action_template.rb +2 -0
- data/app/models/wco_email/email_filter.rb +17 -13
- data/app/models/wco_email/email_filter_action.rb +29 -28
- data/app/models/wco_email/email_filter_condition.rb +24 -12
- data/app/models/wco_email/email_template.rb +2 -1
- data/app/models/wco_email/message_stub.rb +1 -1
- data/app/views/wco/leads/_list.haml +8 -0
- data/app/views/wco/leads/show.haml +4 -0
- data/app/views/wco/office_action_templates/_form.haml +1 -1
- data/app/views/wco/office_action_templates/index.haml +14 -13
- data/app/views/wco/tags/_index_table.haml +2 -2
- data/lib/20260402_tmp.rb +125 -0
- data/lib/tasks/office_tasks.rake +1 -1
- data/lib/wco_models.rb +1 -23
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5d5d8a2f6c49b59221969a2316d3d67b5ae66c1e05583557ae37dd699154678
|
|
4
|
+
data.tar.gz: 7118d503e0ebbdc81ab6c43530982fc25577adc45f99a24fcf64b086ffba4d3a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 844d93fa80db62810740823375f8f7aa7212867b0e06b48e61a2b40c486183ee0f8b991423019f93e5c3b374f04a607625b426f541bdcd718736ca0500926c92
|
|
7
|
+
data.tar.gz: 07fdc6450dc423173adfe7649978c3129abfb7dba440818f656c1625900f235add1a7fce531b5129d41beda7aa91d7dba182265e3c03293f7845e2738e1cfab7
|
|
@@ -199,7 +199,8 @@ input[type=file] {
|
|
|
199
199
|
/* M */
|
|
200
200
|
|
|
201
201
|
.maxwidth {
|
|
202
|
-
|
|
202
|
+
width: 1200px;
|
|
203
|
+
max-width: 1200px; /* @TODO: this would be responsive by-breakpoint _vp_ 2024-04-23 */
|
|
203
204
|
margin: auto;
|
|
204
205
|
}
|
|
205
206
|
|
|
@@ -229,6 +230,13 @@ input[type=file] {
|
|
|
229
230
|
margin: 15px; // bootstrap has 15px gutters
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
table pre {
|
|
234
|
+
max-width: 50vw;
|
|
235
|
+
max-height: 50vh;
|
|
236
|
+
border: 1px solid #ccc;
|
|
237
|
+
padding: 1em;
|
|
238
|
+
}
|
|
239
|
+
|
|
232
240
|
/* R */
|
|
233
241
|
|
|
234
242
|
.red {
|
|
@@ -14,6 +14,17 @@ class WcoEmail::ApplicationMailer < ActionMailer::Base
|
|
|
14
14
|
subject: "POX::#{@msg.subject}" )
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def notify_self params
|
|
18
|
+
subject = params[:subject] || 'default subject'
|
|
19
|
+
body = params[:body] || 'default body'
|
|
20
|
+
mail( from: DEFAULT_FROM,
|
|
21
|
+
to: DEFAULT_RECIPIENT,
|
|
22
|
+
subject: subject,
|
|
23
|
+
body: body,
|
|
24
|
+
content_type: "text/text",
|
|
25
|
+
);
|
|
26
|
+
end
|
|
27
|
+
|
|
17
28
|
def option_alert option
|
|
18
29
|
@option = option
|
|
19
30
|
mail({
|
|
@@ -53,10 +64,10 @@ class WcoEmail::ApplicationMailer < ActionMailer::Base
|
|
|
53
64
|
|
|
54
65
|
profile = Wco::Profile.find_by email: @ctx.from_email
|
|
55
66
|
delivery_options = {
|
|
67
|
+
address: profile.smtp_host,
|
|
68
|
+
password: profile.smtp_password,
|
|
69
|
+
port: profile.smtp_port,
|
|
56
70
|
user_name: profile.smtp_username,
|
|
57
|
-
password: profile.smtp_password,
|
|
58
|
-
address: profile.smtp_host,
|
|
59
|
-
post: profile.smtp_port,
|
|
60
71
|
};
|
|
61
72
|
|
|
62
73
|
mail( from: @ctx.from_email,
|
data/app/models/wco/lead.rb
CHANGED
|
@@ -14,7 +14,8 @@ class Wco::Lead
|
|
|
14
14
|
field :name
|
|
15
15
|
field :phone
|
|
16
16
|
field :address
|
|
17
|
-
field :comment
|
|
17
|
+
field :comment ## _TODO: replace with log?
|
|
18
|
+
field :memory, type: Hash, default: {}
|
|
18
19
|
|
|
19
20
|
belongs_to :leadset, class_name: 'Wco::Leadset'
|
|
20
21
|
before_validation :set_leadset, on: :create
|
|
@@ -81,7 +82,8 @@ class Wco::Lead
|
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
def to_s
|
|
84
|
-
"
|
|
85
|
+
# "`#{name}` <#{email}>"
|
|
86
|
+
email
|
|
85
87
|
end
|
|
86
88
|
def self.list
|
|
87
89
|
[[nil,nil]] + all.map { |p| [ p.email, p.id ] }
|
|
@@ -20,31 +20,33 @@ class Wco::OfficeAction
|
|
|
20
20
|
STATUSS = [ STATUS_ACTIVE, STATUS_INACTIVE ]
|
|
21
21
|
field :status, type: :string
|
|
22
22
|
scope :active, ->{ where( status: STATUS_ACTIVE ) }
|
|
23
|
+
attr_accessor :deactivate
|
|
23
24
|
|
|
24
25
|
field :perform_at, type: :time
|
|
25
26
|
|
|
26
27
|
def do_run
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
@oa = self
|
|
29
|
+
@oa.update!({ status: STATUS_INACTIVE })
|
|
29
30
|
|
|
30
31
|
begin
|
|
31
|
-
eval(
|
|
32
|
+
eval( @oa.tmpl.action_exe )
|
|
32
33
|
rescue => err
|
|
33
34
|
puts! err, "Wco::OfficeAction#do_run"
|
|
34
|
-
::ExceptionNotifier.notify_exception(
|
|
35
|
-
err,
|
|
36
|
-
data: { office_action: self }
|
|
37
|
-
)
|
|
35
|
+
::ExceptionNotifier.notify_exception( err, data: { office_action: self } )
|
|
38
36
|
end
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
if @oa.deactivate
|
|
39
|
+
; # nothing
|
|
40
|
+
else
|
|
41
|
+
# schedule next actions & update the action
|
|
42
|
+
@oa.tmpl.ties.each do |tie|
|
|
43
|
+
next_oa = self.class.find_or_initialize_by({
|
|
44
|
+
office_action_template_id: tie.next_tmpl.id,
|
|
45
|
+
})
|
|
46
|
+
next_oa.perform_at = eval(tie.next_at_exe)
|
|
47
|
+
next_oa.status = STATUS_ACTIVE
|
|
48
|
+
next_oa.save!
|
|
49
|
+
end
|
|
48
50
|
end
|
|
49
51
|
end
|
|
50
52
|
|
|
@@ -33,6 +33,8 @@ class Wco::OfficeActionTemplate
|
|
|
33
33
|
# has_and_belongs_to_many :email_filters, class_name: WcoEmail::EmailFilter
|
|
34
34
|
has_many :email_filters, class_name: '::WcoEmail::EmailFilter', inverse_of: :office_action_template
|
|
35
35
|
|
|
36
|
+
has_many :ajects, inverse_of: :aject ## email action object
|
|
37
|
+
|
|
36
38
|
def to_s
|
|
37
39
|
"#{slug}"
|
|
38
40
|
end
|
data/app/models/wco/tag.rb
CHANGED
|
@@ -15,13 +15,13 @@ class Wco::Tag
|
|
|
15
15
|
belongs_to :site, class_name: '::Wco::Site', optional: true
|
|
16
16
|
has_many :email_filters, class_name: '::WcoEmail::EmailFilter', inverse_of: :tag
|
|
17
17
|
has_many :email_templates, class_name: '::WcoEmail::EmailTemplate', inverse_of: :tag
|
|
18
|
+
has_many :ajects, class_name: '::WcoEmail::EmailFilterAction', inverse_of: :aject
|
|
18
19
|
|
|
19
20
|
has_and_belongs_to_many :conversations, class_name: '::WcoEmail::Conversation', index: true
|
|
20
21
|
has_and_belongs_to_many :galleries, class_name: '::Wco::Gallery'
|
|
21
|
-
has_and_belongs_to_many :headlines # , class_name: 'Headline'
|
|
22
22
|
has_and_belongs_to_many :leads, class_name: '::Wco::Lead', index: true
|
|
23
23
|
has_and_belongs_to_many :leadsets, class_name: '::Wco::Leadset'
|
|
24
|
-
|
|
24
|
+
has_many :logs, inverse_of: :obj
|
|
25
25
|
has_and_belongs_to_many :message_stubs, class_name: '::WcoEmail::MessageStub'
|
|
26
26
|
has_and_belongs_to_many :newsvideos, class_name: '::Wco::Newsvideo'
|
|
27
27
|
has_and_belongs_to_many :reports, class_name: '::Wco::Report'
|
|
@@ -35,6 +35,10 @@ class WcoEmail::Conversation
|
|
|
35
35
|
|
|
36
36
|
belongs_to :filter, class_name: 'WcoEmail::EmailFilter', inverse_of: :conversations, optional: true
|
|
37
37
|
|
|
38
|
+
=begin
|
|
39
|
+
current_profile = OpenStruct.new per_page: 25
|
|
40
|
+
params = { tagname: 'inbox' }
|
|
41
|
+
=end
|
|
38
42
|
def self.load_conversations_messages_tag_by_params_and_profile params, current_profile
|
|
39
43
|
@conversations = WcoEmail::Conversation.all
|
|
40
44
|
|
|
@@ -15,6 +15,8 @@ class WcoEmail::EmailActionTemplate
|
|
|
15
15
|
|
|
16
16
|
belongs_to :email_template, class_name: 'EmailTemplate'
|
|
17
17
|
|
|
18
|
+
has_many :ajects, inverse_of: :aject ## email action object
|
|
19
|
+
|
|
18
20
|
has_many :email_actions, class_name: 'EmailAction'
|
|
19
21
|
|
|
20
22
|
has_many :ties, class_name: '::WcoEmail::EmailActionTemplateTie', inverse_of: :tmpl
|
|
@@ -5,12 +5,11 @@ class WcoEmail::EmailFilter
|
|
|
5
5
|
include Mongoid::Paranoia
|
|
6
6
|
store_in collection: 'office_email_filters' ## 'wco_email_email_filters'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
FIELD_OPTS = [ 'subject', 'from', 'to', 'to_and_cc', 'body', ] ## 'lead_tag_id'
|
|
11
|
-
MATCHTYPE_OPTS = [ 'regex', 'exact_insensitive' ]
|
|
8
|
+
field :descr, type: :string
|
|
12
9
|
|
|
10
|
+
PAGE_PARAM_NAME = :filters_page
|
|
13
11
|
|
|
12
|
+
## @deprecated, use email_filter_conditions
|
|
14
13
|
field :from_regex
|
|
15
14
|
field :from_exact
|
|
16
15
|
field :subject_regex
|
|
@@ -22,8 +21,13 @@ class WcoEmail::EmailFilter
|
|
|
22
21
|
field :skip_from_regex
|
|
23
22
|
field :skip_to_exact
|
|
24
23
|
|
|
24
|
+
STATUS_ACTIVE = 'active'
|
|
25
|
+
STATUS_INACTIVE = 'inactive'
|
|
26
|
+
field :status, type: :string, default: STATUS_ACTIVE
|
|
27
|
+
def self.active; where( :status.in => [ nil, STATUS_ACTIVE ] ); end
|
|
28
|
+
|
|
25
29
|
has_many :actions, class_name: '::WcoEmail::EmailFilterAction', inverse_of: :email_filter
|
|
26
|
-
accepts_nested_attributes_for :actions, allow_destroy: true
|
|
30
|
+
accepts_nested_attributes_for :actions, allow_destroy: true, reject_if: :all_blank
|
|
27
31
|
# validate :validate_actions
|
|
28
32
|
def validate_actions
|
|
29
33
|
if actions.length == 0
|
|
@@ -33,11 +37,11 @@ class WcoEmail::EmailFilter
|
|
|
33
37
|
|
|
34
38
|
## 'and' - all conditions must match, for filter to match
|
|
35
39
|
has_many :conditions, class_name: '::WcoEmail::EmailFilterCondition', inverse_of: :email_filter
|
|
36
|
-
accepts_nested_attributes_for :conditions, allow_destroy: true
|
|
40
|
+
accepts_nested_attributes_for :conditions, allow_destroy: true, reject_if: :all_blank
|
|
37
41
|
|
|
38
42
|
## 'and' - all conditions must match, for filter to match
|
|
39
43
|
has_many :skip_conditions, class_name: '::WcoEmail::EmailFilterCondition', inverse_of: :email_skip_filter
|
|
40
|
-
accepts_nested_attributes_for :skip_conditions, allow_destroy: true
|
|
44
|
+
accepts_nested_attributes_for :skip_conditions, allow_destroy: true, reject_if: :all_blank
|
|
41
45
|
|
|
42
46
|
# validate :validate_conditions
|
|
43
47
|
def validate_conditions
|
|
@@ -48,7 +52,7 @@ class WcoEmail::EmailFilter
|
|
|
48
52
|
|
|
49
53
|
has_and_belongs_to_many :leadsets, class_name: '::Wco::Leadset'
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
## @deprecated 2026-04-02
|
|
52
56
|
KIND_AUTORESPOND_TMPL = 'autorespond-template'
|
|
53
57
|
KIND_AUTORESPOND_EACT = 'autorespond-email-action'
|
|
54
58
|
KIND_REMOVE_TAG = 'remove-tag'
|
|
@@ -61,8 +65,8 @@ class WcoEmail::EmailFilter
|
|
|
61
65
|
KIND_DELETE = 'delete' ## @deprecated, use add-tag
|
|
62
66
|
KIND_SKIP_INBOX = 'skip-inbox' ## @deprecated, use remove-tag
|
|
63
67
|
|
|
64
|
-
KINDS = [ nil, KIND_OAT, KIND_AUTORESPOND_TMPL, KIND_AUTORESPOND_EACT, KIND_ADD_TAG, KIND_REMOVE_TAG, KIND_DESTROY_SCHS]
|
|
65
|
-
field :kind
|
|
68
|
+
KINDS = [ nil, KIND_OAT, KIND_AUTORESPOND_TMPL, KIND_AUTORESPOND_EACT, KIND_ADD_TAG, KIND_REMOVE_TAG, KIND_DESTROY_SCHS ]
|
|
69
|
+
field :kind ## @deprecated, use filter.action.aject.kind 2026-04-02
|
|
66
70
|
|
|
67
71
|
|
|
68
72
|
belongs_to :email_template, class_name: '::WcoEmail::EmailTemplate', optional: true
|
|
@@ -71,7 +75,7 @@ class WcoEmail::EmailFilter
|
|
|
71
75
|
## no habtm please
|
|
72
76
|
# has_and_belongs_to_many :action_tmpls, class_name: '::Wco::OfficeActionTemplate'
|
|
73
77
|
belongs_to :office_action_template, class_name: '::Wco::OfficeActionTemplate', optional: true
|
|
74
|
-
belongs_to :tag, class_name: '::Wco::Tag',
|
|
78
|
+
belongs_to :tag, class_name: '::Wco::Tag', optional: true, inverse_of: :email_filters
|
|
75
79
|
|
|
76
80
|
## @TODO: change to has_and_belongs_to_many, test-driven.
|
|
77
81
|
has_many :conversations, class_name: '::WcoEmail::Conversation', inverse_of: :filter
|
|
@@ -84,11 +88,11 @@ class WcoEmail::EmailFilter
|
|
|
84
88
|
# inn = "#{inn}#{conditions.map { |c| c.to_s_full }.join }" if conditions.present?
|
|
85
89
|
# inn = "#{inn}#{skip_conditions.map { |c| c.to_s_full }.join }" if skip_conditions.present?
|
|
86
90
|
out =<<-AOL
|
|
87
|
-
<EmailFilter
|
|
91
|
+
<EmailFilter >
|
|
88
92
|
#{conditions.map { |c| c.to_s_full( indent: 2) }.join }
|
|
89
93
|
#{skip_conditions.map { |c| c.to_s_full( indent: 2) }.join }
|
|
90
94
|
#{actions.map { |c| c.to_s_full( indent: 2) }.join }
|
|
91
|
-
</EmailFilter>
|
|
95
|
+
</EmailFilter>
|
|
92
96
|
AOL
|
|
93
97
|
while out.match(/\n\n/) do
|
|
94
98
|
out = out.gsub(/\n\n/, "\n")
|
|
@@ -6,42 +6,43 @@ class WcoEmail::EmailFilterAction
|
|
|
6
6
|
|
|
7
7
|
belongs_to :email_filter
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
KIND_ADD_TAG =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
KIND_AUTORESPOND = 'autorespond-template'
|
|
10
|
+
# KIND_EXE_RB = 'exe-rb'
|
|
11
|
+
KIND_ADD_TAG = 'add-tag'
|
|
12
|
+
KIND_RM_TAG = 'remove-tag'
|
|
13
|
+
KIND_EAT = 'autorespond-email-action'
|
|
14
|
+
KIND_RM_EAT = 'rm-email-action'
|
|
15
|
+
KIND_OAT = 'office-action-template'
|
|
16
|
+
KIND_RM_OAT = 'rm-office-action-template'
|
|
17
|
+
KINDS = [ KIND_ADD_TAG, KIND_RM_TAG, KIND_AUTORESPOND, KIND_OAT, KIND_EAT, KIND_RM_EAT ]
|
|
15
18
|
field :kind
|
|
16
|
-
validates :kind, inclusion:
|
|
19
|
+
validates :kind, inclusion: KINDS
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
## for exe_rb only. otherwise, use aject
|
|
22
|
+
field :value
|
|
19
23
|
|
|
24
|
+
belongs_to :aject, polymorphic: true # , optional: true # eg tag, EAT, OAT
|
|
25
|
+
# validates :aject_id, presence: true
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
27
|
+
## 2026-04-02 not anymore.
|
|
28
|
+
# before_validation :check_value
|
|
29
|
+
# def check_value
|
|
30
|
+
# case kind
|
|
31
|
+
# when KIND_AUTORESPOND
|
|
32
|
+
# existing = WcoEmail::EmailTemplate.where({ id: value }).first
|
|
33
|
+
# if !existing
|
|
34
|
+
# errors.add( :base, 'missing EmailTemplate id when creating an EmailFilterAction' )
|
|
35
|
+
# throw :abort
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
32
39
|
|
|
33
40
|
|
|
34
41
|
def to_s
|
|
35
|
-
"<
|
|
42
|
+
"<EFAction #{kind} #{aject} />\n"
|
|
36
43
|
end
|
|
37
44
|
def to_s_full indent: 0
|
|
38
|
-
|
|
39
|
-
if [ KIND_ADD_TAG, KIND_REMOVE_TAG ].include?( kind )
|
|
40
|
-
_value = Wco::Tag.find( value )
|
|
41
|
-
end
|
|
42
|
-
if [ KIND_AUTORESPOND ].include?( kind )
|
|
43
|
-
_value = WcoEmail::EmailTemplate.find( value )
|
|
44
|
-
end
|
|
45
|
-
"#{" " * indent }<EFAction #{kind} `#{_value}` />\n"
|
|
45
|
+
"#{" " * indent }<EFAction #{kind} `#{aject}` />\n"
|
|
46
46
|
end
|
|
47
|
+
|
|
47
48
|
end
|
|
@@ -8,18 +8,33 @@ class WcoEmail::EmailFilterCondition
|
|
|
8
8
|
belongs_to :email_filter, class_name: '::WcoEmail::EmailFilter', inverse_of: :conditions, optional: true
|
|
9
9
|
belongs_to :email_skip_filter, class_name: '::WcoEmail::EmailFilter', inverse_of: :skip_conditions, optional: true
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
FIELD_BODY = 'body'
|
|
12
|
+
FIELD_FROM = 'from'
|
|
13
|
+
FIELD_TAGGED = 'leadset-tagged'
|
|
14
|
+
FIELD_NOT_TAGGED = 'leadset-not-tagged'
|
|
15
|
+
FIELD_SUBJECT = 'subject'
|
|
16
|
+
# FIELD_TO = 'to'
|
|
17
|
+
FIELD_TO_OR_CC = 'to-or-cc'
|
|
18
|
+
FIELD_OPTS = [ FIELD_SUBJECT, FIELD_FROM, FIELD_TO_OR_CC, FIELD_TAGGED, FIELD_NOT_TAGGED, FIELD_BODY ]
|
|
12
19
|
field :field
|
|
13
|
-
validates :field, presence: true
|
|
20
|
+
validates :field, presence: true, inclusion: FIELD_OPTS
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
OPERATOR_EQUALS = 'eq-i'
|
|
23
|
+
# OPERATOR_HAS_TAG = 'has-tag'
|
|
24
|
+
# OPERATOR_NOT_HAS_TAG = 'not-has-tag'
|
|
25
|
+
OPERATOR_REGEX = 'regex'
|
|
26
|
+
OPERATOR_MATCH = 'match-i'
|
|
27
|
+
OPERATOR__ID = '_id'
|
|
28
|
+
OPERATOR_SLUG = 'slug'
|
|
29
|
+
OPERATOR_OPTS = [ OPERATOR_REGEX, OPERATOR_MATCH, OPERATOR__ID, OPERATOR_SLUG ]
|
|
30
|
+
field :operator
|
|
31
|
+
validates :operator, presence: true, inclusion: OPERATOR_OPTS
|
|
19
32
|
|
|
20
33
|
field :value
|
|
21
34
|
validates :value, presence: true
|
|
22
35
|
|
|
36
|
+
index({ email_filter_id: 1, field: 1, operator: 1, value: 1 }, unique: true )
|
|
37
|
+
|
|
23
38
|
def apply leadset:, message:
|
|
24
39
|
cond = self
|
|
25
40
|
reason = nil
|
|
@@ -43,14 +58,11 @@ class WcoEmail::EmailFilterCondition
|
|
|
43
58
|
|
|
44
59
|
|
|
45
60
|
def to_s
|
|
46
|
-
"<
|
|
61
|
+
"<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{operator} `#{value}` />"
|
|
47
62
|
end
|
|
48
63
|
def to_s_full indent: 0
|
|
49
|
-
|
|
50
|
-
if [ ::WcoEmail::OPERATOR_HAS_TAG, ::WcoEmail::OPERATOR_NOT_HAS_TAG ].include?( matchtype )
|
|
51
|
-
_value = Wco::Tag.find( value )
|
|
52
|
-
end
|
|
53
|
-
"#{" " * indent }<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{matchtype} `#{_value}` />\n"
|
|
64
|
+
"#{" " * indent }<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{operator} `#{value}` />\n"
|
|
54
65
|
end
|
|
66
|
+
|
|
55
67
|
end
|
|
56
68
|
|
|
@@ -11,7 +11,7 @@ class WcoEmail::EmailTemplate
|
|
|
11
11
|
validates :slug, presence: true, uniqueness: true
|
|
12
12
|
index({ slug: 1 }, { unique: true, name: "slug_idx" })
|
|
13
13
|
def to_s
|
|
14
|
-
"
|
|
14
|
+
"#{slug}"
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
field :preview_str, type: :string
|
|
@@ -127,6 +127,7 @@ class WcoEmail::EmailTemplate
|
|
|
127
127
|
has_many :email_contexts, class_name: '::WcoEmail::Context'
|
|
128
128
|
has_many :email_filters, class_name: '::WcoEmail::EmailFilter'
|
|
129
129
|
has_many :unsubscribes, class_name: '::WcoEmail::Unsubscribe'
|
|
130
|
+
has_many :ajects, inverse_of: :aject ## email action object
|
|
130
131
|
|
|
131
132
|
belongs_to :tag, class_name: '::Wco::Tag', inverse_of: :email_templates, optional: true
|
|
132
133
|
|
|
@@ -117,7 +117,7 @@ class WcoEmail::MessageStub
|
|
|
117
117
|
|
|
118
118
|
@conv.update_attributes({
|
|
119
119
|
status: WcoEmail::Conversation::STATUS_UNREAD,
|
|
120
|
-
latest_at: json['date'].to_s || Time.now.to_datetime,
|
|
120
|
+
latest_at: json['date'].to_time.to_s || Time.now.to_datetime,
|
|
121
121
|
from_emails: ( @conv.from_emails + [ from ]).uniq,
|
|
122
122
|
preview: @message.preview_str,
|
|
123
123
|
})
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
%label action_type
|
|
14
14
|
= f.select :action_type, options_for_select( [ nil, 'js', 'rb', 'sh' ], selected: oat.action_type )
|
|
15
15
|
.descr
|
|
16
|
-
rb available vars: @conversations , @oat ,
|
|
16
|
+
rb available vars: @conversations , @oat , @oa ,
|
|
17
17
|
.field
|
|
18
18
|
%label action_exe
|
|
19
19
|
= f.text_area :action_exe, class: :monospace
|
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
.header
|
|
4
4
|
%h5.title Office Action Templates
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
.a
|
|
7
7
|
- @oats.each do |oat|
|
|
8
|
-
|
|
9
|
-
.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
.Oat.descr
|
|
9
|
+
.row
|
|
10
|
+
.col-6
|
|
11
|
+
.d-flex
|
|
12
|
+
= link_to '[~]', edit_office_action_template_path(oat)
|
|
13
|
+
|
|
14
|
+
= button_to 'x', office_action_template_path(oat), method: :delete, data: { confirm: 'Are you sure?' }
|
|
15
|
+
|
|
16
|
+
= link_to oat.slug, office_action_template_path(oat)
|
|
17
|
+
|
|
18
|
+
= button_to 'Run w/convos', oat_perform_with_conversations_path(oat), data: { confirm: 'Are you sure?' }
|
|
19
|
+
.col-6
|
|
20
|
+
= render '/wco/office_action_templates/ties', ties: oat.ties, oat: oat
|
|
20
21
|
|
|
21
22
|
%hr
|
|
22
23
|
= render 'form', oat: @new_oat
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
%th N Conv
|
|
7
7
|
%th N Stubs
|
|
8
8
|
|
|
9
|
-
%th N Headlines
|
|
9
|
+
-# %th N Headlines
|
|
10
10
|
|
|
11
11
|
%th N Galleries
|
|
12
12
|
%th N Reports
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
= link_to tag.slug, tag_path(tag)
|
|
25
25
|
%td= tag.conversations.length
|
|
26
26
|
%td= tag.message_stubs.length
|
|
27
|
-
%td= tag.headlines.length
|
|
27
|
+
-# %td= tag.headlines.length
|
|
28
28
|
%td= tag.galleries.length
|
|
29
29
|
%td= tag.reports.length
|
|
30
30
|
%td= tag.videos.length
|
data/lib/20260402_tmp.rb
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
|
|
2
|
+
##
|
|
3
|
+
## skip: careers@wasya.co
|
|
4
|
+
## skip: mishellduvrazka2023|wasteplacellc|smttest42|robincroom|acelec|rleer24|statusunknown03|claricefth|abogadooctavioarango|claudenicefh|email4gregory|morishitaarata|314658|alisa406|dawnmeverly|faizana1298|jandrews555|midwestksp|mj8712|msohaibhere|piousbox|poxlovi|snehagophane99|stephenkim79
|
|
5
|
+
##
|
|
6
|
+
## exceptions: finradrnm@finra.org
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
filter = nil
|
|
10
|
+
WcoEmail::EmailFilter.active.each do |_filter|
|
|
11
|
+
filter = _filter
|
|
12
|
+
case filter.kind
|
|
13
|
+
when WcoEmail::EmailFilter::KIND_ADD_TAG,
|
|
14
|
+
WcoEmail::EmailFilter::KIND_REMOVE_TAG,
|
|
15
|
+
WcoEmail::EmailFilter::KIND_AUTORESPOND_TMPL,
|
|
16
|
+
WcoEmail::EmailFilter::KIND_AUTORESPOND_EACT
|
|
17
|
+
|
|
18
|
+
aject_id = case filter.kind
|
|
19
|
+
when WcoEmail::EmailFilter::KIND_ADD_TAG,
|
|
20
|
+
WcoEmail::EmailFilter::KIND_REMOVE_TAG
|
|
21
|
+
filter.tag_id
|
|
22
|
+
when WcoEmail::EmailFilter::KIND_AUTORESPOND_TMPL
|
|
23
|
+
filter.email_template_id
|
|
24
|
+
when WcoEmail::EmailFilter::KIND_AUTORESPOND_EACT
|
|
25
|
+
filter.email_action_template_id
|
|
26
|
+
end
|
|
27
|
+
# puts! aject_id, 'aject_id'
|
|
28
|
+
|
|
29
|
+
aject_type = case filter.kind
|
|
30
|
+
when WcoEmail::EmailFilter::KIND_ADD_TAG,
|
|
31
|
+
WcoEmail::EmailFilter::KIND_REMOVE_TAG
|
|
32
|
+
'Wco::Tag'
|
|
33
|
+
when WcoEmail::EmailFilter::KIND_AUTORESPOND_TMPL
|
|
34
|
+
'WcoEmail::EmailTemplate'
|
|
35
|
+
when WcoEmail::EmailFilter::KIND_AUTORESPOND_EACT
|
|
36
|
+
'WcoEmail::EmailActionTemplate'
|
|
37
|
+
end
|
|
38
|
+
# puts! aject_type, 'aject_type'
|
|
39
|
+
|
|
40
|
+
aject_kind = filter.kind
|
|
41
|
+
# aject_kind = case filter.kind
|
|
42
|
+
# when WcoEmail::EmailFilter::KIND_AUTORESPOND_EACT
|
|
43
|
+
# filter.kind
|
|
44
|
+
# else
|
|
45
|
+
# filter.kind
|
|
46
|
+
# end
|
|
47
|
+
# puts! aject_kind, 'aject_kind'
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
action_ids = WcoEmail::EmailFilterAction.where({
|
|
51
|
+
kind: filter.kind,
|
|
52
|
+
aject_id: aject_id,
|
|
53
|
+
}).distinct(:email_filter_id)
|
|
54
|
+
new_filter = WcoEmail::EmailFilter.where( :id.in => action_ids ).first
|
|
55
|
+
|
|
56
|
+
if new_filter
|
|
57
|
+
puts "+++ filter exists"
|
|
58
|
+
else
|
|
59
|
+
new_filter = WcoEmail::EmailFilter.new({
|
|
60
|
+
actions_attributes: [{
|
|
61
|
+
kind: aject_kind,
|
|
62
|
+
aject_type: aject_type,
|
|
63
|
+
aject_id: aject_id,
|
|
64
|
+
}] })
|
|
65
|
+
|
|
66
|
+
new_filter.save!
|
|
67
|
+
puts "+++ created new filter #{new_filter.id}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
cond_field = WcoEmail::EmailFilterCondition::FIELD_FROM
|
|
71
|
+
cond_op = WcoEmail::EmailFilterCondition::OPERATOR_MATCH
|
|
72
|
+
cond_value = filter.from_exact
|
|
73
|
+
if cond_value.blank?
|
|
74
|
+
cond_field = WcoEmail::EmailFilterCondition::FIELD_SUBJECT
|
|
75
|
+
cond_value = filter.subject_exact
|
|
76
|
+
end
|
|
77
|
+
if cond_value.blank?
|
|
78
|
+
cond_field = WcoEmail::EmailFilterCondition::FIELD_FROM
|
|
79
|
+
cond_op = WcoEmail::EmailFilterCondition::OPERATOR_REGEX
|
|
80
|
+
cond_value = filter.from_regex
|
|
81
|
+
end
|
|
82
|
+
if cond_value.blank?
|
|
83
|
+
cond_field = WcoEmail::EmailFilterCondition::FIELD_SUBJECT
|
|
84
|
+
cond_op = WcoEmail::EmailFilterCondition::OPERATOR_REGEX
|
|
85
|
+
cond_value = filter.subject_regex
|
|
86
|
+
end
|
|
87
|
+
if cond_value.blank?
|
|
88
|
+
cond_field = WcoEmail::EmailFilterCondition::FIELD_BODY
|
|
89
|
+
cond_op = WcoEmail::EmailFilterCondition::OPERATOR_MATCH
|
|
90
|
+
cond_value = filter.body_exact
|
|
91
|
+
end
|
|
92
|
+
if cond_value.blank?
|
|
93
|
+
throw '+++ cond_value cannot be blank'
|
|
94
|
+
end
|
|
95
|
+
# puts! cond_field, 'cond_field'
|
|
96
|
+
# puts! cond_value, 'cond_value'
|
|
97
|
+
|
|
98
|
+
new_condition = WcoEmail::EmailFilterCondition.where({
|
|
99
|
+
email_filter_id: new_filter.id,
|
|
100
|
+
field: cond_field,
|
|
101
|
+
operator: cond_op,
|
|
102
|
+
value: cond_value,
|
|
103
|
+
}).first
|
|
104
|
+
if new_condition
|
|
105
|
+
puts "+++ condition exists"
|
|
106
|
+
else
|
|
107
|
+
new_condition = WcoEmail::EmailFilterCondition.new({
|
|
108
|
+
email_filter_id: new_filter.id,
|
|
109
|
+
field: cond_field,
|
|
110
|
+
operator: cond_op,
|
|
111
|
+
value: cond_value,
|
|
112
|
+
})
|
|
113
|
+
new_condition.save!
|
|
114
|
+
puts "+++ created new condition #{new_condition.id}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
filter.conversations.update_all( filter_id: new_filter.id )
|
|
118
|
+
filter.update( status: 'inactive' )
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
data/lib/tasks/office_tasks.rake
CHANGED
|
@@ -7,7 +7,7 @@ namespace :wco do
|
|
|
7
7
|
|
|
8
8
|
desc 'run office actions'
|
|
9
9
|
task run_office_actions: :environment do
|
|
10
|
-
puts! "Starting wco_email:run_office_actions..."
|
|
10
|
+
puts! "Starting wco_email:run_office_actions in #{Rails.env}..."
|
|
11
11
|
while true do
|
|
12
12
|
|
|
13
13
|
schs = Wco::OfficeAction.active.where({ :perform_at.lte => Time.now })
|
data/lib/wco_models.rb
CHANGED
|
@@ -34,29 +34,7 @@ module Iro; end
|
|
|
34
34
|
module Tda; end
|
|
35
35
|
module Wco; end
|
|
36
36
|
|
|
37
|
-
module WcoEmail
|
|
38
|
-
ACTION_ADD_TAG = 'add-tag'
|
|
39
|
-
ACTION_AUTORESPOND = 'autorespond-template'
|
|
40
|
-
ACTION_EXE = 'exe'
|
|
41
|
-
ACTION_SCHEDULE_EMAIL_ACTION = 'autorespond-email-action'
|
|
42
|
-
ACTION_REMOVE_EMAIL_ACTION = 'remove-email-action'
|
|
43
|
-
ACTION_REMOVE_TAG = 'remove-tag'
|
|
44
|
-
ACTIONS = [ 'add-tag', 'autorespond-email-action', 'autorespond-template', 'exe', 'remove-email-action', 'remove-tag' ]
|
|
45
|
-
|
|
46
|
-
FIELD_BODY = 'body'
|
|
47
|
-
FIELD_EXE = 'exe'
|
|
48
|
-
FIELD_FROM = 'from'
|
|
49
|
-
FIELD_LEADSET = 'leadset_id'
|
|
50
|
-
FIELD_SUBJECT = 'subject'
|
|
51
|
-
FIELD_TO = 'to'
|
|
52
|
-
|
|
53
|
-
OPERATOR_EQUALS = 'equals'
|
|
54
|
-
OPERATOR_HAS_TAG = 'has-tag'
|
|
55
|
-
OPERATOR_NOT_HAS_TAG = 'not-has-tag'
|
|
56
|
-
OPERATOR_TEXT_INPUT = 'text-input'
|
|
57
|
-
OPERATORS = [ 'equals', 'has-tag', 'not-has-tag', 'text-input' ]
|
|
58
|
-
end
|
|
59
|
-
|
|
37
|
+
module WcoEmail; end
|
|
60
38
|
module WcoHosting; end
|
|
61
39
|
|
|
62
40
|
class Wco::HTTParty
|
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.250
|
|
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-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ahoy_matey
|
|
@@ -591,6 +591,7 @@ files:
|
|
|
591
591
|
- app/views/wco/leads/_header.haml
|
|
592
592
|
- app/views/wco/leads/_index.haml
|
|
593
593
|
- app/views/wco/leads/_index_chips.haml
|
|
594
|
+
- app/views/wco/leads/_list.haml
|
|
594
595
|
- app/views/wco/leads/_table.haml
|
|
595
596
|
- app/views/wco/leads/edit.haml
|
|
596
597
|
- app/views/wco/leads/index.haml
|
|
@@ -767,6 +768,7 @@ files:
|
|
|
767
768
|
- config/initializers/ahoy.rb
|
|
768
769
|
- config/initializers/assets.rb
|
|
769
770
|
- config/routes.rb
|
|
771
|
+
- lib/20260402_tmp.rb
|
|
770
772
|
- lib/shortcuts.rb
|
|
771
773
|
- lib/tasks/db_tasks.rake
|
|
772
774
|
- lib/tasks/migrate_tasks.rake
|