Compare commits
296 Commits
develop
...
stable-2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd5e64f7db | ||
|
|
1a9af7dbe6 | ||
|
|
de51dedcbd | ||
|
|
f99f30e61e | ||
|
|
428136120f | ||
|
|
4ceeffcc4c | ||
|
|
fe3a739a58 | ||
|
|
5c983f69e8 | ||
|
|
dfa8f805cb | ||
|
|
db19f30961 | ||
|
|
80341b90f9 | ||
|
|
5604e5fe8c | ||
|
|
fc499909ce | ||
|
|
1c2ff2a514 | ||
|
|
0e8203fff4 | ||
|
|
d2d6945a8f | ||
|
|
dbad0f53cb | ||
|
|
b7e9b97a13 | ||
|
|
c44ebc166a | ||
|
|
47a1bb76a6 | ||
|
|
db6eadce9f | ||
|
|
535ce06efd | ||
|
|
8d79744bc5 | ||
|
|
7884d86480 | ||
|
|
2036235d55 | ||
|
|
8200862127 | ||
|
|
0736061008 | ||
|
|
626911e52c | ||
|
|
0bac6f5e5f | ||
|
|
cc5a34df97 | ||
|
|
7209b85c16 | ||
|
|
66c0975877 | ||
|
|
76efb008a8 | ||
|
|
abc0541244 | ||
|
|
c9f8022f83 | ||
|
|
dfc757968e | ||
|
|
52bc45c0f8 | ||
|
|
cbc8ba5467 | ||
|
|
5f071e7d7f | ||
|
|
1dcd6a243c | ||
|
|
679deb1cf3 | ||
|
|
6f6ac44978 | ||
|
|
0bb341cb7e | ||
|
|
6c122e046b | ||
|
|
57c2dad0a3 | ||
|
|
faefd529b4 | ||
|
|
1481a12035 | ||
|
|
2bf0635e0d | ||
|
|
2211274bc5 | ||
|
|
c229c42838 | ||
|
|
a3c71f6558 | ||
|
|
db8b85f767 | ||
|
|
f1664c3841 | ||
|
|
151c298056 | ||
|
|
38f51ce6b2 | ||
|
|
434f3e963e | ||
|
|
b853dd1597 | ||
|
|
3b5b6f612f | ||
|
|
962043c520 | ||
|
|
8394be87ed | ||
|
|
5b547ceb3c | ||
|
|
789ee08485 | ||
|
|
490937859a | ||
|
|
dfc306a2ac | ||
|
|
dea06015a1 | ||
|
|
2711e3392d | ||
|
|
f5e1fe0c2f | ||
|
|
dbbb4ac7a1 | ||
|
|
8ec2ffdde1 | ||
|
|
b76664e7ae | ||
|
|
704c537749 | ||
|
|
633c99bb72 | ||
|
|
44051d8023 | ||
|
|
50dc143c1b | ||
|
|
6d44275869 | ||
|
|
b1b3bf6d3c | ||
|
|
77081ecd4d | ||
|
|
b823b960d8 | ||
|
|
e08f634125 | ||
|
|
ab5e8d9338 | ||
|
|
9a29ea8f14 | ||
|
|
cf87e00b21 | ||
|
|
6233b0a9ec | ||
|
|
04b1bc638c | ||
|
|
a78938f7c2 | ||
|
|
1d23308454 | ||
|
|
6bc9c00ab8 | ||
|
|
bc131742be | ||
|
|
5a12aa0167 | ||
|
|
b3ab9d0055 | ||
|
|
1bde8f91bc | ||
|
|
47ef1b7e5d | ||
|
|
88c7816f5c | ||
|
|
82339c6c18 | ||
|
|
04a609c3a8 | ||
|
|
60430139aa | ||
|
|
7d1c655ee3 | ||
|
|
e34c1c9b79 | ||
|
|
3c430b35ef | ||
|
|
7ad3c70311 | ||
|
|
c270bc1e67 | ||
|
|
3d19bfdcf7 | ||
|
|
dc4a55cc5c | ||
|
|
6e8886277d | ||
|
|
74e96e92b2 | ||
|
|
287b1f0d01 | ||
|
|
feee46e29b | ||
|
|
991efe36e4 | ||
|
|
a2aacb20fa | ||
|
|
592e978062 | ||
|
|
a4769c8bc7 | ||
|
|
d1378d53f1 | ||
|
|
f0b91d3269 | ||
|
|
48c77dd688 | ||
|
|
d86d904395 | ||
|
|
5efc455f0c | ||
|
|
be3bbeba20 | ||
|
|
31ab1b614c | ||
|
|
4bc5fa4693 | ||
|
|
418a64f401 | ||
|
|
abe46270a6 | ||
|
|
1249a77150 | ||
|
|
cfa6b9ed16 | ||
|
|
aa2303f999 | ||
|
|
d5616684f8 | ||
|
|
0f75ba57bd | ||
|
|
c83675bbba | ||
|
|
17d16d405c | ||
|
|
76795ca302 | ||
|
|
5d145bd09f | ||
|
|
82471552a8 | ||
|
|
dc60574129 | ||
|
|
d33a96dee2 | ||
|
|
0098d4ab82 | ||
|
|
bb03b5eab8 | ||
|
|
17eb0f84ec | ||
|
|
56d0523c1f | ||
|
|
9fa18758bc | ||
|
|
d2f2c55b06 | ||
|
|
f4a409bd6e | ||
|
|
971b724d4c | ||
|
|
3263c6f2ba | ||
|
|
359b026535 | ||
|
|
c63518fd3e | ||
|
|
24ba3cff44 | ||
|
|
f7066e1995 | ||
|
|
6844499309 | ||
|
|
afa3e47eab | ||
|
|
5f3e9298f1 | ||
|
|
e4dd303357 | ||
|
|
2fa06eee3d | ||
|
|
dc0ac03334 | ||
|
|
c5a1d69ec5 | ||
|
|
9891981f92 | ||
|
|
2c721f71e7 | ||
|
|
0b4a4be0b7 | ||
|
|
b13bb2fcaf | ||
|
|
d9ba369fcf | ||
|
|
3adece0db5 | ||
|
|
7101ffc277 | ||
|
|
19a7a439b8 | ||
|
|
e728320241 | ||
|
|
1bc17afc53 | ||
|
|
ee5c58f53a | ||
|
|
9bdf6d7b81 | ||
|
|
5754fdccdd | ||
|
|
4901050d57 | ||
|
|
7980c8cb93 | ||
|
|
7e7088388d | ||
|
|
2f6e52d63d | ||
|
|
bde8babb43 | ||
|
|
d6d68fb363 | ||
|
|
814ffed0f0 | ||
|
|
b013fb8cbc | ||
|
|
fbd8e63592 | ||
|
|
e8ad3965d7 | ||
|
|
e00981ee23 | ||
|
|
4e74c6beda | ||
|
|
2d09e556d7 | ||
|
|
8cd39398d6 | ||
|
|
94c616ffe3 | ||
|
|
57649bb888 | ||
|
|
7e9442ec4a | ||
|
|
521e6265fd | ||
|
|
a42a9689fc | ||
|
|
d9ffb8001d | ||
|
|
ec86d26ae6 | ||
|
|
e00efc821a | ||
|
|
f04be8ca93 | ||
|
|
c7ff6a323a | ||
|
|
34833416bc | ||
|
|
d7a6e28d81 | ||
|
|
c13531d720 | ||
|
|
4a40cced7d | ||
|
|
450de10cc7 | ||
|
|
5e587a455c | ||
|
|
04aef9b258 | ||
|
|
9b72557d13 | ||
|
|
a5e0bc30c1 | ||
|
|
458c166e9f | ||
|
|
3373e5d141 | ||
|
|
8f6b8de617 | ||
|
|
22b21a82e7 | ||
|
|
b4151b299f | ||
|
|
e969fca8c4 | ||
|
|
e59993a5d6 | ||
|
|
3adc9d4cf1 | ||
|
|
c1153250cb | ||
|
|
7718dc28d3 | ||
|
|
1894580ae6 | ||
|
|
11df714bbf | ||
|
|
72adee37a8 | ||
|
|
0e8f460d73 | ||
|
|
4e62d5d0d2 | ||
|
|
004e5ba457 | ||
|
|
f1a8a8da6f | ||
|
|
bfb44d1189 | ||
|
|
d64afd8d97 | ||
|
|
97cfdb9c4c | ||
|
|
bb336f63f1 | ||
|
|
80da08f447 | ||
|
|
a6db2b7c90 | ||
|
|
e1c3f83324 | ||
|
|
8545a44ad1 | ||
|
|
cfbe7510a2 | ||
|
|
1479c32edb | ||
|
|
a9d428bf5a | ||
|
|
3a62eb11da | ||
|
|
2df5f81029 | ||
|
|
b88c23bc92 | ||
|
|
4144fbaf5b | ||
|
|
86ddc93f52 | ||
|
|
8a1b583535 | ||
|
|
7623628b86 | ||
|
|
f753bc203f | ||
|
|
ff9ba10705 | ||
|
|
fdc25bdc26 | ||
|
|
d154a587ad | ||
|
|
a9cc4f037b | ||
|
|
50d6679189 | ||
|
|
b82cf4e1d6 | ||
|
|
fa6eaa6710 | ||
|
|
2ca17ac1bd | ||
|
|
862ecd7d36 | ||
|
|
e38b72593b | ||
|
|
81883cae8f | ||
|
|
63770c9cbf | ||
|
|
aaf5da55a0 | ||
|
|
8455d9ae17 | ||
|
|
839a8e8eb4 | ||
|
|
7aa3f6eaee | ||
|
|
219abc69a3 | ||
|
|
595822c928 | ||
|
|
32112937b1 | ||
|
|
a0889c5b99 | ||
|
|
4bc281bfb0 | ||
|
|
e12ec607d7 | ||
|
|
545f393293 | ||
|
|
4efa152e93 | ||
|
|
0ebda4f32a | ||
|
|
b94f54799f | ||
|
|
99f0b4e2e2 | ||
|
|
53cb906733 | ||
|
|
2c31fe8a84 | ||
|
|
6c5e673a2c | ||
|
|
574b891a33 | ||
|
|
9ef1d3f58b | ||
|
|
8b3f432746 | ||
|
|
14a9df261e | ||
|
|
5620a2847b | ||
|
|
13aaae3835 | ||
|
|
2d4fcd3a4f | ||
|
|
f4f70b0bc2 | ||
|
|
1d279bb88f | ||
|
|
fe4757cbf9 | ||
|
|
1d476f163e | ||
|
|
513701b6d2 | ||
|
|
1a1b661714 | ||
|
|
6081a98279 | ||
|
|
157991c33d | ||
|
|
ef67be9170 | ||
|
|
39f3819303 | ||
|
|
7a676bd563 | ||
|
|
80c54daa03 | ||
|
|
99c88cde62 | ||
|
|
17d113ca20 | ||
|
|
2fbf4324a7 | ||
|
|
b46c390d30 | ||
|
|
3c3651bc52 | ||
|
|
abeeb5e66d | ||
|
|
09d61ce4c8 | ||
|
|
cc1c4495b2 | ||
|
|
7b1ec4d17f | ||
|
|
99b3201ccf | ||
|
|
d4205d9ba6 | ||
|
|
8d57633390 |
16
.github/ISSUE_TEMPLATE.md
vendored
16
.github/ISSUE_TEMPLATE.md
vendored
@@ -25,24 +25,26 @@ Note: We always do our best. Unfortunately, sometimes there are too many request
|
||||
|
||||
### Infos:
|
||||
|
||||
* Used Zammad version:
|
||||
* Used Zammad installation source: (source, package, ...)
|
||||
* Operating system:
|
||||
* Used Zammad version:
|
||||
* Installation method (source, package, ..):
|
||||
* Operating system:
|
||||
* Database + version:
|
||||
* Elasticsearch version:
|
||||
* Browser + version:
|
||||
|
||||
|
||||
### Expected behavior:
|
||||
|
||||
*
|
||||
*
|
||||
|
||||
|
||||
### Actual behavior:
|
||||
|
||||
*
|
||||
*
|
||||
|
||||
|
||||
### Steps to reproduce the behavior:
|
||||
|
||||
*
|
||||
*
|
||||
|
||||
Yes I'm sure this is a bug and no feature request or a general question.
|
||||
Yes I'm sure this is a bug and no feature request or a general question.
|
||||
|
||||
@@ -62,3 +62,4 @@ script:
|
||||
after_success:
|
||||
- if [ "${DB}" = "mysql" ]; then contrib/travis-ci.org/trigger-docker-build.sh; fi
|
||||
- if [ "${DB}" = "mysql" ]; then contrib/travis-ci.org/trigger-docker-compose-build.sh; fi
|
||||
- if [ "${DB}" = "mysql" ]; then contrib/travis-ci.org/trigger-docker-univention-build.sh; fi
|
||||
|
||||
53
CHANGELOG.md
53
CHANGELOG.md
@@ -1,16 +1,55 @@
|
||||
# Change Log
|
||||
|
||||
## [2.2.0](https://github.com/zammad/zammad/tree/2.2.0) (2017-xx-xx)
|
||||
## [2.2.2](https://github.com/zammad/zammad/tree/2.2.2) (2018-03-29)
|
||||
[Full Changelog](https://github.com/zammad/zammad/compare/2.2.1...2.2.2)
|
||||
|
||||
**Fixed bugs:**
|
||||
- The column widths of a table are shifted after manual change and use of pagination. [\#1829](https://github.com/zammad/zammad/issues/1829) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- XSS issue in ticket overview [\#1869](https://github.com/zammad/zammad/issues/1869) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
|
||||
## [2.2.1](https://github.com/zammad/zammad/tree/2.2.0) (2018-01-30)
|
||||
[Full Changelog](https://github.com/zammad/zammad/compare/2.2.0...2.2.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
- Generated excel report fails to create for special strings in ticket titles \(also: CSV formula injection possible\) [\#1756](https://github.com/zammad/zammad/issues/1756) [[bug](https://github.com/zammad/zammad/labels/bug)] [[reporting](https://github.com/zammad/zammad/labels/reporting)]
|
||||
- Need data\_option\[:null\] - Ticket Object Manager [\#1742](https://github.com/zammad/zammad/issues/1742) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Ticket search fails for limit exceeding 100 with internal server error [\#1753](https://github.com/zammad/zammad/issues/1753) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Unable to send auto reply if from contains 2 or more senders with invalid email address [\#1749](https://github.com/zammad/zammad/issues/1749) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Report for Created tickets should not have "merged" tickets [\#1741](https://github.com/zammad/zammad/issues/1741) [[bug](https://github.com/zammad/zammad/labels/bug)] [[reporting](https://github.com/zammad/zammad/labels/reporting)]
|
||||
- Wrong ticket number count in preview [\#1723](https://github.com/zammad/zammad/issues/1723) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Zammad Api for idoit.object\_ids broken [\#1711](https://github.com/zammad/zammad/issues/1711) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Unable to login with Office365 [\#1710](https://github.com/zammad/zammad/issues/1710) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- No user preference for out-of-office available [\#1699](https://github.com/zammad/zammad/issues/1699) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- SipgateController - undefined method `each' for nil:NilClass \(NoMethodError\) [\#1698](https://github.com/zammad/zammad/issues/1698) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
|
||||
## [2.2.0](https://github.com/zammad/zammad/tree/2.2.0) (2017-12-06)
|
||||
[Full Changelog](https://github.com/zammad/zammad/compare/2.1.0...2.2.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
|
||||
|
||||
- email forward of article \(like regular email client forward - e. g. forward customers message to third party contact\) [\#573](https://github.com/zammad/zammad/issues/573) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Take over attachment on ticket split [\#195](https://github.com/zammad/zammad/issues/195) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Enable state "merged" for admin overviews, triggers and jobs [\#1689](https://github.com/zammad/zammad/issues/1689) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Elasticsearchs mapper-attachments plugin has been deprecated, use ingest-attachment now [\#599](https://github.com/zammad/zammad/issues/599) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Improve i-doit filtering \(without type\) [\#1571](https://github.com/zammad/zammad/issues/1571) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Reset customer selection in ticket create screen if input field cleared [\#1670](https://github.com/zammad/zammad/issues/1670) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Add config option for intelligent customer selection of incoming emails of agents [\#1671](https://github.com/zammad/zammad/issues/1671) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Twitter: Allow tweet articles to be 280 chars long [\#1628](https://github.com/zammad/zammad/issues/1628) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Chat language setting or behaviour in dutch [\#1618](https://github.com/zammad/zammad/issues/1618) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- leading and tailing utf8 spaces are not removed for email addresses are not removed [\#1579](https://github.com/zammad/zammad/issues/1579) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Import emails with same message\_id but target was different channels [\#1578](https://github.com/zammad/zammad/issues/1578) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
|
||||
|
||||
- Webform isn´t available | 401 Unauthorized [\#1604](https://github.com/zammad/zammad/issues/1604) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- TimeAccounting ticket condition prevents submit of Zoom [\#1513](https://github.com/zammad/zammad/issues/1513) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Unable to re-order overviews in admin interface with over 100 overviews [\#1681](https://github.com/zammad/zammad/issues/1681) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Unable to open trigger in admin interface [\#1666](https://github.com/zammad/zammad/issues/1666) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Users mail\_delivery\_failed is not removed after changing the email address [\#1661](https://github.com/zammad/zammad/issues/1661) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Tickets are deleted but database is still the same size [\#1649](https://github.com/zammad/zammad/issues/1649) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Translation for form widget in Dutch [\#1623](https://github.com/zammad/zammad/issues/1623) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
|
||||
- Exchange Integration SSL Error with self-signed root certificate authority [\#1442](https://github.com/zammad/zammad/issues/1442) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- Unable to sort overview by priority [\#1595](https://github.com/zammad/zammad/issues/1595) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- LDAP Integration: Comprehensive configuration cause the import to fail [\#1457](https://github.com/zammad/zammad/issues/1457) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- {"error":"Role Customer conflicts with Admin"} [\#1509](https://github.com/zammad/zammad/issues/1509) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
- prevent admin from locking out [\#1563](https://github.com/zammad/zammad/issues/1563) [[bug](https://github.com/zammad/zammad/labels/bug)]
|
||||
|
||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
||||
@@ -213,7 +213,7 @@ GEM
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
loofah (2.1.1)
|
||||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
lumberjack (1.0.12)
|
||||
@@ -235,7 +235,7 @@ GEM
|
||||
net-ldap (0.16.1)
|
||||
netrc (0.11.0)
|
||||
nio4r (2.1.0)
|
||||
nokogiri (1.8.1)
|
||||
nokogiri (1.8.2)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
nori (2.6.0)
|
||||
notiffany (0.1.1)
|
||||
@@ -318,8 +318,8 @@ GEM
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
rails-observers (0.1.5)
|
||||
activemodel (>= 4.0)
|
||||
railties (5.1.4)
|
||||
|
||||
@@ -192,8 +192,8 @@ class App.ControllerTable extends App.Controller
|
||||
el.filter('.js-pager').html('')
|
||||
return
|
||||
pager = App.view('generic/table_pager')(
|
||||
page: @shownPage
|
||||
pages: pages
|
||||
page: @shownPage
|
||||
pages: pages
|
||||
)
|
||||
if find
|
||||
el.find('.js-pager').html(pager)
|
||||
@@ -839,13 +839,21 @@ class App.ControllerTable extends App.Controller
|
||||
# update store and runtime @headerWidth
|
||||
@preferencesStore('headerWidth', leftColumnKey, leftWidth)
|
||||
@headerWidth[leftColumnKey] = leftWidth
|
||||
_.find(@headers, (column) -> column.name is leftColumnKey).displayWidth = leftWidth
|
||||
|
||||
# set header at runtime
|
||||
for header in @headers
|
||||
if header.name is leftColumnKey
|
||||
header.displayWidth = @resizeTargetLeft.outerWidth()
|
||||
|
||||
# update store and runtime @headerWidth
|
||||
if rightColumnKey
|
||||
@preferencesStore('headerWidth', rightColumnKey, rightWidth)
|
||||
@headerWidth[rightColumnKey] = rightWidth
|
||||
_.find(@headers, (column) -> column.name is rightColumnKey).displayWidth = rightWidth
|
||||
|
||||
# set header at runtime
|
||||
for header in @headers
|
||||
if header.name is rightColumnKey
|
||||
header.displayWidth = @resizeTargetRight.outerWidth()
|
||||
|
||||
sortByColumn: (event) =>
|
||||
column = $(event.currentTarget).closest('[data-column-key]').attr('data-column-key')
|
||||
|
||||
@@ -42,7 +42,7 @@ class App.SettingsAreaTicketNumber extends App.Controller
|
||||
number = "#{App.Config.get('ticket_hook')}#{App.Config.get('system_id')}"
|
||||
counter = '1'
|
||||
if paramsItem.min_size
|
||||
minSize = parseInt(paramsItem.min_size)
|
||||
minSize = parseInt(paramsItem.min_size) - "#{App.Config.get('system_id')}".length
|
||||
if paramsItem.checksum
|
||||
minSize -= 1
|
||||
if minSize > 1
|
||||
|
||||
@@ -151,7 +151,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
||||
icon: 'twitter'
|
||||
attributes: []
|
||||
internal: false,
|
||||
features: ['body:limit', 'body:initials']
|
||||
features: attributes
|
||||
maxTextLength: 280
|
||||
warningTextLength: 30
|
||||
}
|
||||
@@ -164,7 +164,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
||||
icon: 'twitter'
|
||||
attributes: ['to']
|
||||
internal: false,
|
||||
features: ['body:limit', 'body:initials']
|
||||
features: attributes
|
||||
maxTextLength: 10000
|
||||
warningTextLength: 500
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<div class="signup fullscreen">
|
||||
<div class="fullscreen-center">
|
||||
<div class="hero-unit fullscreen-body">
|
||||
<h1><%- @T( 'Join' ) %> <%= @C( 'product_name' ) %></h1>
|
||||
<h1><%- @T('Join %s', @C('product_name')) %></h1>
|
||||
<form>
|
||||
<div class="form-controls">
|
||||
<a class="btn btn--text btn--subtle js-cancel" href="#login"><%- @T( 'Cancel & Go Back' ) %></a>
|
||||
<button class="btn btn--primary js-submit align-right"><%- @T( 'Create my account' ) %></button>
|
||||
<a class="btn btn--text btn--subtle js-cancel" href="#login"><%- @T('Cancel & Go Back') %></a>
|
||||
<button class="btn btn--primary js-submit align-right"><%- @T('Create my account') %></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -43,8 +43,13 @@ class Integration::SipgateController < ApplicationController
|
||||
|
||||
# set caller id of outbound call
|
||||
def out
|
||||
config_outbound = config_integration[:outbound][:routing_table]
|
||||
default_caller_id = config_integration[:outbound][:default_caller_id]
|
||||
config_outbound = config_integration[:outbound]
|
||||
routing_table = nil
|
||||
default_caller_id = nil
|
||||
if config_outbound.present?
|
||||
routing_table = config_outbound[:routing_table]
|
||||
default_caller_id = config_outbound[:default_caller_id]
|
||||
end
|
||||
|
||||
xml = Builder::XmlMarkup.new(indent: 2)
|
||||
xml.instruct!
|
||||
@@ -53,8 +58,8 @@ class Integration::SipgateController < ApplicationController
|
||||
content = nil
|
||||
to = params[:to]
|
||||
from = nil
|
||||
if to
|
||||
config_outbound.each do |row|
|
||||
if to && routing_table.present?
|
||||
routing_table.each do |row|
|
||||
dest = row[:dest].gsub(/\*/, '.+?')
|
||||
next if to !~ /^#{dest}$/
|
||||
from = row[:caller_id]
|
||||
@@ -63,7 +68,7 @@ class Integration::SipgateController < ApplicationController
|
||||
end
|
||||
break
|
||||
end
|
||||
if !content && default_caller_id
|
||||
if !content && default_caller_id.present?
|
||||
from = default_caller_id
|
||||
content = xml.Response(onHangup: url, onAnswer: url) do
|
||||
xml.Dial(callerId: default_caller_id) { xml.Number(params[:to]) }
|
||||
@@ -73,8 +78,8 @@ class Integration::SipgateController < ApplicationController
|
||||
content = xml.Response(onHangup: url, onAnswer: url)
|
||||
end
|
||||
|
||||
send_data content, type: 'application/xml; charset=UTF-8;'
|
||||
if from
|
||||
send_data(content, type: 'application/xml; charset=UTF-8;')
|
||||
if from.present?
|
||||
params['from'] = from
|
||||
end
|
||||
Cti::Log.process(params)
|
||||
@@ -89,7 +94,7 @@ class Integration::SipgateController < ApplicationController
|
||||
xml_error('Feature is disable, please contact your admin to enable it!')
|
||||
return
|
||||
end
|
||||
if !config_integration || !config_integration[:inbound] || !config_integration[:outbound]
|
||||
if config_integration.blank? || config_integration[:inbound].blank? || config_integration[:outbound].blank?
|
||||
xml_error('Feature not configured, please contact your admin!')
|
||||
return
|
||||
end
|
||||
|
||||
@@ -32,6 +32,7 @@ class ObjectManagerAttributesController < ApplicationController
|
||||
raise Exceptions::UnprocessableEntity, 'already exists' if exists
|
||||
|
||||
local_params = params.permit!.to_h
|
||||
local_params[:data_option][:null] = true # set data option which can be null
|
||||
begin
|
||||
object_manager_attribute = ObjectManager::Attribute.add(
|
||||
object: local_params[:object],
|
||||
@@ -110,12 +111,33 @@ class ObjectManagerAttributesController < ApplicationController
|
||||
# rubocop:enable Lint/BooleanSymbol
|
||||
end
|
||||
end
|
||||
if params[:data_option] && !params[:data_option].key?(:default)
|
||||
params[:data_option][:default] = if params[:data_type].match?(/^(input|select|tree_select)$/)
|
||||
''
|
||||
end
|
||||
|
||||
if params[:data_option]
|
||||
|
||||
if !params[:data_option].key?(:default)
|
||||
params[:data_option][:default] = if params[:data_type].match?(/^(input|select|tree_select)$/)
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
if params[:data_option][:null].nil?
|
||||
params[:data_option][:null] = true
|
||||
end
|
||||
|
||||
if params[:data_option][:options].nil?
|
||||
params[:data_option][:options] = ''
|
||||
end
|
||||
|
||||
if params[:data_option][:relation].nil?
|
||||
params[:data_option][:relation] = ''
|
||||
end
|
||||
else
|
||||
params[:data_option] = {
|
||||
default: '',
|
||||
options: '',
|
||||
relation: '',
|
||||
null: true
|
||||
}
|
||||
end
|
||||
return if !params[:data_option][:null].nil?
|
||||
params[:data_option][:null] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -234,7 +234,7 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
|
||||
end
|
||||
|
||||
if params[:limit] && params[:limit].to_i > 500
|
||||
params[:limit].to_i = 500
|
||||
params[:limit] = 500
|
||||
end
|
||||
|
||||
query = params[:query]
|
||||
|
||||
@@ -187,46 +187,50 @@ class ReportsController < ApplicationController
|
||||
worksheet.set_row(0, 0, 6)
|
||||
|
||||
# Write a formatted and unformatted string, row and column notation.
|
||||
worksheet.write(0, 0, "Tickets: #{profile.name} (#{title})", format)
|
||||
worksheet.write_string(0, 0, "Tickets: #{profile.name} (#{title})", format)
|
||||
|
||||
format_header = workbook.add_format
|
||||
format_header.set_italic
|
||||
format_header.set_bg_color('gray')
|
||||
format_header.set_color('white')
|
||||
|
||||
worksheet.write(2, 0, '#', format_header)
|
||||
worksheet.write(2, 1, 'Title', format_header)
|
||||
worksheet.write(2, 2, 'State', format_header)
|
||||
worksheet.write(2, 3, 'Priority', format_header)
|
||||
worksheet.write(2, 4, 'Group', format_header)
|
||||
worksheet.write(2, 5, 'Owner', format_header)
|
||||
worksheet.write(2, 6, 'Customer', format_header)
|
||||
worksheet.write(2, 7, 'Organization', format_header)
|
||||
worksheet.write(2, 8, 'Create Channel', format_header)
|
||||
worksheet.write(2, 9, 'Sender', format_header)
|
||||
worksheet.write(2, 10, 'Tags', format_header)
|
||||
worksheet.write(2, 11, 'Created at', format_header)
|
||||
worksheet.write(2, 12, 'Updated at', format_header)
|
||||
worksheet.write(2, 13, 'Closed at', format_header)
|
||||
worksheet.write_string(2, 0, '#', format_header)
|
||||
worksheet.write_string(2, 1, 'Title', format_header)
|
||||
worksheet.write_string(2, 2, 'State', format_header)
|
||||
worksheet.write_string(2, 3, 'Priority', format_header)
|
||||
worksheet.write_string(2, 4, 'Group', format_header)
|
||||
worksheet.write_string(2, 5, 'Owner', format_header)
|
||||
worksheet.write_string(2, 6, 'Customer', format_header)
|
||||
worksheet.write_string(2, 7, 'Organization', format_header)
|
||||
worksheet.write_string(2, 8, 'Create Channel', format_header)
|
||||
worksheet.write_string(2, 9, 'Sender', format_header)
|
||||
worksheet.write_string(2, 10, 'Tags', format_header)
|
||||
worksheet.write_string(2, 11, 'Created at', format_header)
|
||||
worksheet.write_string(2, 12, 'Updated at', format_header)
|
||||
worksheet.write_string(2, 13, 'Closed at', format_header)
|
||||
|
||||
row = 2
|
||||
result[:ticket_ids].each do |ticket_id|
|
||||
ticket = Ticket.lookup(id: ticket_id)
|
||||
row += 1
|
||||
worksheet.write(row, 0, ticket.number)
|
||||
worksheet.write(row, 1, ticket.title)
|
||||
worksheet.write(row, 2, ticket.state.name)
|
||||
worksheet.write(row, 3, ticket.priority.name)
|
||||
worksheet.write(row, 4, ticket.group.name)
|
||||
worksheet.write(row, 5, ticket.owner.fullname)
|
||||
worksheet.write(row, 6, ticket.customer.fullname)
|
||||
worksheet.write(row, 7, ticket.try(:organization).try(:name))
|
||||
worksheet.write(row, 8, ticket.create_article_type.name)
|
||||
worksheet.write(row, 9, ticket.create_article_sender.name)
|
||||
worksheet.write(row, 10, ticket.tag_list.join(','))
|
||||
worksheet.write(row, 11, ticket.created_at)
|
||||
worksheet.write(row, 12, ticket.updated_at)
|
||||
worksheet.write(row, 13, ticket.close_at)
|
||||
begin
|
||||
ticket = Ticket.lookup(id: ticket_id)
|
||||
row += 1
|
||||
worksheet.write_string(row, 0, ticket.number)
|
||||
worksheet.write_string(row, 1, ticket.title)
|
||||
worksheet.write_string(row, 2, ticket.state.name)
|
||||
worksheet.write_string(row, 3, ticket.priority.name)
|
||||
worksheet.write_string(row, 4, ticket.group.name)
|
||||
worksheet.write_string(row, 5, ticket.owner.fullname)
|
||||
worksheet.write_string(row, 6, ticket.customer.fullname)
|
||||
worksheet.write_string(row, 7, ticket.try(:organization).try(:name))
|
||||
worksheet.write_string(row, 8, ticket.create_article_type.name)
|
||||
worksheet.write_string(row, 9, ticket.create_article_sender.name)
|
||||
worksheet.write_string(row, 10, ticket.tag_list.join(','))
|
||||
worksheet.write_date_time(row, 11, ticket.created_at.to_time.iso8601)
|
||||
worksheet.write_date_time(row, 12, ticket.updated_at.to_time.iso8601)
|
||||
worksheet.write_date_time(row, 13, ticket.close_at.to_time.iso8601)
|
||||
rescue => e
|
||||
Rails.logger.error "SKIP: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
workbook.close
|
||||
|
||||
@@ -388,7 +388,7 @@ class TicketsController < ApplicationController
|
||||
end
|
||||
|
||||
if params[:limit] && params[:limit].to_i > 100
|
||||
params[:limit].to_i = 100
|
||||
params[:limit] = 100
|
||||
end
|
||||
|
||||
query = params[:query]
|
||||
|
||||
@@ -382,7 +382,7 @@ class TimeAccountingsController < ApplicationController
|
||||
worksheet.set_row(0, 0, header.count)
|
||||
|
||||
# Write a formatted and unformatted string, row and column notation.
|
||||
worksheet.write(0, 0, title, format)
|
||||
worksheet.write_string(0, 0, title, format)
|
||||
|
||||
format_header = workbook.add_format # Add a format
|
||||
format_header.set_italic
|
||||
@@ -393,7 +393,7 @@ class TimeAccountingsController < ApplicationController
|
||||
if item[:width]
|
||||
worksheet.set_column(count, count, item[:width])
|
||||
end
|
||||
worksheet.write(2, count, item[:name], format_header)
|
||||
worksheet.write_string(2, count, item[:name], format_header)
|
||||
count += 1
|
||||
end
|
||||
|
||||
@@ -402,7 +402,11 @@ class TimeAccountingsController < ApplicationController
|
||||
row_count += 1
|
||||
row_item_count = 0
|
||||
row.each do |item|
|
||||
worksheet.write(row_count, row_item_count, item)
|
||||
if item.acts_like?(:date)
|
||||
worksheet.write_date_time(row_count, row_item_count, item.to_time.iso8601)
|
||||
else
|
||||
worksheet.write_string(row_count, row_item_count, item)
|
||||
end
|
||||
row_item_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -360,7 +360,7 @@ class UsersController < ApplicationController
|
||||
end
|
||||
|
||||
if params[:limit] && params[:limit].to_i > 500
|
||||
params[:limit].to_i = 500
|
||||
params[:limit] = 500
|
||||
end
|
||||
|
||||
query = params[:query]
|
||||
|
||||
@@ -105,22 +105,41 @@ add avatar by url
|
||||
|
||||
# fetch image based on http url
|
||||
if data[:url].present?
|
||||
if data[:url].match?(/^http/)
|
||||
if data[:url].class == Tempfile
|
||||
logger.info "Reading image from tempfile '#{data[:url].inspect}'"
|
||||
content = data[:url].read
|
||||
filename = data[:url].path
|
||||
mime_type = 'image'
|
||||
if filename.match?(/\.png/i)
|
||||
mime_type = 'image/png'
|
||||
end
|
||||
if filename.match?(/\.(jpg|jpeg)/i)
|
||||
mime_type = 'image/jpeg'
|
||||
end
|
||||
data[:resize] ||= {}
|
||||
data[:resize][:content] = content
|
||||
data[:resize][:mime_type] = mime_type
|
||||
data[:full] ||= {}
|
||||
data[:full][:content] = content
|
||||
data[:full][:mime_type] = mime_type
|
||||
|
||||
elsif data[:url].to_s.match?(/^http/)
|
||||
url = data[:url].to_s
|
||||
|
||||
# check if source ist already updated within last 2 minutes
|
||||
if avatar_already_exists&.source_url == data[:url]
|
||||
if avatar_already_exists&.source_url == url
|
||||
return if avatar_already_exists.updated_at > 2.minutes.ago
|
||||
end
|
||||
|
||||
# twitter workaround to get bigger avatar images
|
||||
# see also https://dev.twitter.com/overview/general/user-profile-images-and-banners
|
||||
if data[:url].match?(%r{//pbs.twimg.com/}i)
|
||||
data[:url].sub!(/normal\.(png|jpg|gif)$/, 'bigger.\1')
|
||||
if url.match?(%r{//pbs.twimg.com/}i)
|
||||
url.sub!(/normal\.(png|jpg|gif)$/, 'bigger.\1')
|
||||
end
|
||||
|
||||
# fetch image
|
||||
response = UserAgent.get(
|
||||
data[:url],
|
||||
url,
|
||||
{},
|
||||
{
|
||||
open_timeout: 4,
|
||||
@@ -129,20 +148,19 @@ add avatar by url
|
||||
},
|
||||
)
|
||||
if !response.success?
|
||||
logger.info "Can't fetch '#{data[:url]}' (maybe no avatar available), http code: #{response.code}"
|
||||
logger.info "Can't fetch '#{url}' (maybe no avatar available), http code: #{response.code}"
|
||||
return
|
||||
end
|
||||
logger.info "Fetchd image '#{data[:url]}', http code: #{response.code}"
|
||||
logger.info "Fetchd image '#{url}', http code: #{response.code}"
|
||||
mime_type = 'image'
|
||||
if data[:url].match?(/\.png/i)
|
||||
if url.match?(/\.png/i)
|
||||
mime_type = 'image/png'
|
||||
end
|
||||
if data[:url].match?(/\.(jpg|jpeg)/i)
|
||||
if url.match?(/\.(jpg|jpeg)/i)
|
||||
mime_type = 'image/jpeg'
|
||||
end
|
||||
if !data[:resize]
|
||||
data[:resize] = {}
|
||||
end
|
||||
|
||||
data[:resize] ||= {}
|
||||
data[:resize][:content] = response.body
|
||||
data[:resize][:mime_type] = mime_type
|
||||
data[:full] ||= {}
|
||||
@@ -150,15 +168,16 @@ add avatar by url
|
||||
data[:full][:mime_type] = mime_type
|
||||
|
||||
# try zammad backend to find image based on email
|
||||
elsif data[:url].match?(/@/)
|
||||
elsif data[:url].to_s.match?(/@/)
|
||||
url = data[:url].to_s
|
||||
|
||||
# check if source ist already updated within last 3 minutes
|
||||
if avatar_already_exists&.source_url == data[:url]
|
||||
if avatar_already_exists&.source_url == url
|
||||
return if avatar_already_exists.updated_at > 2.minutes.ago
|
||||
end
|
||||
|
||||
# fetch image
|
||||
image = Service::Image.user(data[:url])
|
||||
image = Service::Image.user(url)
|
||||
return if !image
|
||||
data[:resize] ||= {}
|
||||
data[:resize] = image
|
||||
@@ -337,7 +356,7 @@ returns:
|
||||
store_hash: hash,
|
||||
)
|
||||
return if !avatar
|
||||
file = Store.find(avatar.store_resize_id)
|
||||
Store.find(avatar.store_resize_id)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
@@ -95,16 +95,19 @@ module Channel::Filter::IdentifySender
|
||||
max_count = 40
|
||||
current_count = 0
|
||||
['raw-to', 'raw-cc'].each do |item|
|
||||
next if !mail[item.to_sym]
|
||||
next if mail[item.to_sym].blank?
|
||||
begin
|
||||
next if !mail[item.to_sym].addrs
|
||||
items = mail[item.to_sym].addrs
|
||||
next if items.blank?
|
||||
items.each do |address_data|
|
||||
next if address_data.address.blank?
|
||||
email_address = address_data.address
|
||||
next if email_address.blank?
|
||||
next if email_address !~ /@/
|
||||
next if email_address.match?(/\s/)
|
||||
user_create(
|
||||
firstname: address_data.display_name,
|
||||
lastname: '',
|
||||
email: address_data.address,
|
||||
email: email_address,
|
||||
)
|
||||
current_count += 1
|
||||
return false if current_count == max_count
|
||||
@@ -126,6 +129,8 @@ module Channel::Filter::IdentifySender
|
||||
display_name = $1
|
||||
end
|
||||
next if address.blank?
|
||||
next if address !~ /@/
|
||||
next if address.match?(/\s/)
|
||||
user_create(
|
||||
firstname: display_name,
|
||||
lastname: '',
|
||||
@@ -176,7 +181,7 @@ module Channel::Filter::IdentifySender
|
||||
data[:updated_by_id] = 1
|
||||
data[:created_by_id] = 1
|
||||
|
||||
user = User.create(data)
|
||||
user = User.create!(data)
|
||||
user.update!(
|
||||
updated_by_id: user.id,
|
||||
created_by_id: user.id,
|
||||
|
||||
@@ -22,6 +22,12 @@ class Report
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: { field: 'created_at' },
|
||||
condition: {
|
||||
'state' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'closed',
|
||||
@@ -30,6 +36,12 @@ class Report
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: { field: 'close_at' },
|
||||
condition: {
|
||||
'state' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'backlog',
|
||||
@@ -37,6 +49,12 @@ class Report
|
||||
selected: true,
|
||||
dataDownload: false,
|
||||
adapter: Report::TicketBacklog,
|
||||
condition: {
|
||||
'state' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'first_solution',
|
||||
@@ -44,6 +62,12 @@ class Report
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketFirstSolution,
|
||||
condition: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'reopened',
|
||||
@@ -51,6 +75,12 @@ class Report
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketReopened,
|
||||
condition: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'movedin',
|
||||
@@ -59,6 +89,12 @@ class Report
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketMoved,
|
||||
params: { type: 'in' },
|
||||
condition: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'movedout',
|
||||
@@ -67,6 +103,12 @@ class Report
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketMoved,
|
||||
params: { type: 'out' },
|
||||
condition: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
config[:metric][:count][:backend] = backend
|
||||
|
||||
@@ -185,7 +185,7 @@ returns
|
||||
|
||||
def last_admin_check_admin_count
|
||||
admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).where.not(id: id).pluck(:id)
|
||||
User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).count
|
||||
User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).distinct().count
|
||||
end
|
||||
|
||||
def validate_agent_limit_by_attributes
|
||||
@@ -194,8 +194,8 @@ returns
|
||||
return true if active != true
|
||||
return true if !with_permission?('ticket.agent')
|
||||
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
|
||||
currents = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).pluck(:id)
|
||||
news = User.joins(:roles).where(roles: { id: id }, users: { active: true }).pluck(:id)
|
||||
currents = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().pluck(:id)
|
||||
news = User.joins(:roles).where(roles: { id: id }, users: { active: true }).distinct().pluck(:id)
|
||||
count = currents.concat(news).uniq.count
|
||||
raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
|
||||
true
|
||||
@@ -208,7 +208,7 @@ returns
|
||||
return true if permission.name != 'ticket.agent'
|
||||
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent' }, roles: { active: true }).pluck(:id)
|
||||
ticket_agent_role_ids.push(id)
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count
|
||||
raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
|
||||
true
|
||||
end
|
||||
|
||||
@@ -528,6 +528,9 @@ condition example
|
||||
elsif selector[0] == 'article'
|
||||
tables += ', ticket_articles articles'
|
||||
query += 'tickets.id = articles.ticket_id'
|
||||
elsif selector[0] == 'ticket_state'
|
||||
tables += ', ticket_states'
|
||||
query += 'tickets.state_id = ticket_states.id'
|
||||
else
|
||||
raise "invalid selector #{attribute.inspect}->#{selector.inspect}"
|
||||
end
|
||||
@@ -881,14 +884,25 @@ perform changes on ticket
|
||||
next if skip_user
|
||||
|
||||
# send notifications only to email adresses
|
||||
next if !recipient_email
|
||||
next if recipient_email.blank?
|
||||
next if recipient_email !~ /@/
|
||||
|
||||
# check if address is valid
|
||||
begin
|
||||
recipient_email = Mail::Address.new(recipient_email).address
|
||||
Mail::AddressList.new(recipient_email).addresses.each do |address|
|
||||
recipient_email = address.address
|
||||
break if recipient_email.present? && recipient_email =~ /@/ && !recipient_email.match?(/\s/)
|
||||
end
|
||||
rescue
|
||||
next # because unable to parse
|
||||
if recipient_email.present?
|
||||
if recipient_email !~ /^(.+?)<(.+?)@(.+?)>$/
|
||||
next # no usable format found
|
||||
end
|
||||
recipient_email = "#{$2}@#{$3}"
|
||||
end
|
||||
next if recipient_email.blank?
|
||||
next if recipient_email !~ /@/
|
||||
next if recipient_email.match?(/\s/)
|
||||
end
|
||||
|
||||
# do not sent notifications to this recipients
|
||||
|
||||
@@ -81,6 +81,10 @@ module Ticket::Number::Date
|
||||
ticket_hook_divider = Setting.get('ticket_hook_divider') || ''
|
||||
ticket = nil
|
||||
|
||||
if Setting.get('ticket_number_ignore_system_id') == true
|
||||
system_id = ''
|
||||
end
|
||||
|
||||
# probe format
|
||||
string.scan(/#{Regexp.quote(ticket_hook)}#{Regexp.quote(ticket_hook_divider)}(\d{4,10}#{system_id}\d{2,40})/i) do
|
||||
ticket = Ticket.find_by(number: $1)
|
||||
|
||||
@@ -78,6 +78,10 @@ module Ticket::Number::Increment
|
||||
ticket_hook_divider = Setting.get('ticket_hook_divider') || ''
|
||||
ticket = nil
|
||||
|
||||
if Setting.get('ticket_number_ignore_system_id') == true
|
||||
system_id = ''
|
||||
end
|
||||
|
||||
# probe format
|
||||
string.scan(/#{Regexp.quote(ticket_hook)}#{Regexp.quote(ticket_hook_divider)}(#{system_id}\d{2,48})/i) do
|
||||
ticket = Ticket.find_by(number: $1)
|
||||
|
||||
@@ -99,7 +99,7 @@ returns
|
||||
end
|
||||
|
||||
# try search index backend
|
||||
if !condition && SearchIndexBackend.enabled?
|
||||
if condition.blank? && SearchIndexBackend.enabled?
|
||||
query_extention = {}
|
||||
query_extention['bool'] = {}
|
||||
query_extention['bool']['must'] = []
|
||||
|
||||
@@ -1018,7 +1018,7 @@ raise 'Minimum one user need to have admin permissions'
|
||||
|
||||
def last_admin_check_admin_count
|
||||
admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).pluck(:id)
|
||||
User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).count - 1
|
||||
User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).distinct().count - 1
|
||||
end
|
||||
|
||||
def validate_agent_limit_by_attributes
|
||||
@@ -1027,7 +1027,7 @@ raise 'Minimum one user need to have admin permissions'
|
||||
return true if active != true
|
||||
return true if !permissions?('ticket.agent')
|
||||
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count + 1
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count + 1
|
||||
raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
|
||||
true
|
||||
end
|
||||
@@ -1038,7 +1038,7 @@ raise 'Minimum one user need to have admin permissions'
|
||||
return true if role.active != true
|
||||
return true if !role.with_permission?('ticket.agent')
|
||||
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count
|
||||
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count
|
||||
|
||||
# if new added role is a ticket.agent role
|
||||
if ticket_agent_role_ids.include?(role.id)
|
||||
|
||||
18
contrib/travis-ci.org/trigger-docker-univention-build.sh
Executable file
18
contrib/travis-ci.org/trigger-docker-univention-build.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# trigger build of https://github.com/zammad/zammad-docker-univention on https://travis-ci.org/zammad/zammad-docker-univention and upload it to https://hub.docker.com/r/zammad/zammad-docker-univention
|
||||
#
|
||||
|
||||
REPO_USER="zammad"
|
||||
REPO="zammad-docker-univention"
|
||||
BRANCH="master"
|
||||
|
||||
if [ "${TRAVIS_BRANCH}" == 'stable' ]; then
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Travis-API-Version: 3" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: token ${TRAVIS_API_TOKEN}" \
|
||||
-d '{"request":{ "message": "'"${TRAVIS_COMMIT_MESSAGE}"'","branch":"'${BRANCH}'","config":{"env":{"ZAMMAD_VERSION":"'${ZAMMAD_VERSION}'"}}}}' \
|
||||
"https://api.travis-ci.org/repo/${REPO_USER}%2F${REPO}/requests"
|
||||
fi
|
||||
@@ -201,7 +201,7 @@ class CreateBase < ActiveRecord::Migration[4.2]
|
||||
create_table :authorizations do |t|
|
||||
t.string :provider, limit: 250, null: false
|
||||
t.string :uid, limit: 250, null: false
|
||||
t.string :token, limit: 250, null: true
|
||||
t.string :token, limit: 2500, null: true
|
||||
t.string :secret, limit: 250, null: true
|
||||
t.string :username, limit: 250, null: true
|
||||
t.references :user, null: false
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
class PermissionUserPreferencesOutOfOffice < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
Permission.create_if_not_exists(
|
||||
name: 'user_preferences.out_of_office',
|
||||
note: 'Change %s',
|
||||
preferences: {
|
||||
translations: ['Out of Office'],
|
||||
required: ['ticket.agent'],
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
10
db/migrate/20171213000001_change_authorization_token_size.rb
Normal file
10
db/migrate/20171213000001_change_authorization_token_size.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
class ChangeAuthorizationTokenSize < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
# return if it's a new setup to avoid running the migration
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
change_column :authorizations, :token, :string, limit: 2500
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
class SettingTicketNumberIgnoreSystemIdSupport < ActiveRecord::Migration[4.2]
|
||||
def up
|
||||
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Ticket Number ignore system_id',
|
||||
name: 'ticket_number_ignore_system_id',
|
||||
area: 'Ticket::Core',
|
||||
description: '-',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: 'Ignore system_id',
|
||||
null: true,
|
||||
name: 'ticket_number_ignore_system_id',
|
||||
tag: 'boolean',
|
||||
options: {
|
||||
true => 'yes',
|
||||
false => 'no',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
state: {
|
||||
ticket_number_ignore_system_id: false
|
||||
},
|
||||
preferences: {
|
||||
permission: ['admin.ticket'],
|
||||
hidden: true,
|
||||
},
|
||||
frontend: false
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -283,6 +283,14 @@ Permission.create_if_not_exists(
|
||||
required: ['ticket.agent'],
|
||||
},
|
||||
)
|
||||
Permission.create_if_not_exists(
|
||||
name: 'user_preferences.out_of_office',
|
||||
note: 'Change %s',
|
||||
preferences: {
|
||||
translations: ['Out of Office'],
|
||||
required: ['ticket.agent'],
|
||||
},
|
||||
)
|
||||
|
||||
Permission.create_if_not_exists(
|
||||
name: 'report',
|
||||
|
||||
@@ -1672,6 +1672,34 @@ Setting.create_if_not_exists(
|
||||
},
|
||||
frontend: false
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Ticket Number ignore system_id',
|
||||
name: 'ticket_number_ignore_system_id',
|
||||
area: 'Ticket::Core',
|
||||
description: '-',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: 'Ignore system_id',
|
||||
null: true,
|
||||
name: 'ticket_number_ignore_system_id',
|
||||
tag: 'boolean',
|
||||
options: {
|
||||
true => 'yes',
|
||||
false => 'no',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
state: {
|
||||
ticket_number_ignore_system_id: false
|
||||
},
|
||||
preferences: {
|
||||
permission: ['admin.ticket'],
|
||||
hidden: true,
|
||||
},
|
||||
frontend: false
|
||||
)
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Enable Ticket creation',
|
||||
|
||||
@@ -68,6 +68,7 @@ module Import
|
||||
mapped[:created_at] ||= DateTime.current
|
||||
mapped[:updated_at] ||= DateTime.current
|
||||
mapped[:email].downcase!
|
||||
mapped[:login].downcase!
|
||||
mapped
|
||||
end
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ module Import
|
||||
def map(user)
|
||||
mapped = map_default(user)
|
||||
mapped[:email].downcase!
|
||||
mapped[:login].downcase!
|
||||
mapped
|
||||
end
|
||||
|
||||
@@ -95,6 +96,7 @@ module Import
|
||||
queues.each do |queue|
|
||||
|
||||
permissions = user['GroupIDs'][ queue['GroupID'] ]
|
||||
permissions ||= user['GroupIDs'][ queue['GroupID'].to_s ]
|
||||
|
||||
next if !permissions
|
||||
next if !permissions.include?('rw')
|
||||
@@ -143,6 +145,7 @@ module Import
|
||||
|
||||
def groups_from_otrs_group(role_object, group)
|
||||
result = []
|
||||
return result if role_object.blank?
|
||||
return result if role_object['GroupIDs'].blank?
|
||||
permissions = role_object['GroupIDs'][ group['ID'] ]
|
||||
|
||||
@@ -164,7 +167,7 @@ module Import
|
||||
roles = Import::OTRS::Requester.load('Role')
|
||||
roles.each do |role|
|
||||
next if !user['RoleIDs'].include?(role['ID'])
|
||||
result += groups_from_otrs_groups(role['GroupIDs'])
|
||||
result += groups_from_otrs_groups(role)
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
@@ -461,7 +461,7 @@ get count of tickets and tickets which match on selector
|
||||
elsif data['operator'] == 'contains not'
|
||||
query_must_not.push t
|
||||
else
|
||||
raise "unknown operator '#{data['operator']}'"
|
||||
raise "unknown operator '#{data['operator']}' for #{key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -71,8 +71,11 @@
|
||||
height: 100%;
|
||||
width: 3.4em;
|
||||
text-align: center;
|
||||
line-height: 3.5em;
|
||||
line-height: 3.4em;
|
||||
cursor: pointer; }
|
||||
.zammad-chat-header-icon:before {
|
||||
content: "";
|
||||
display: inline-block; }
|
||||
|
||||
.zammad-chat-header-icon-open,
|
||||
.zammad-chat-header-icon-close {
|
||||
@@ -107,7 +110,7 @@
|
||||
font-weight: bold; }
|
||||
|
||||
.zammad-chat-agent-status {
|
||||
margin: 0 1em;
|
||||
margin: 0.25em 1em;
|
||||
display: inline-block;
|
||||
line-height: 2em;
|
||||
padding: 0 .7em;
|
||||
|
||||
@@ -80,8 +80,13 @@
|
||||
height: 100%;
|
||||
width: 3.4em;
|
||||
text-align: center;
|
||||
line-height: 3.5em;
|
||||
line-height: 3.4em;
|
||||
cursor: pointer;
|
||||
|
||||
&:before { // force the icon to align to center
|
||||
content: "";
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.zammad-chat-header-icon-open,
|
||||
@@ -125,7 +130,7 @@
|
||||
}
|
||||
|
||||
.zammad-chat-agent-status {
|
||||
margin: 0 1em;
|
||||
margin: 0.25em 1em;
|
||||
display: inline-block;
|
||||
line-height: 2em;
|
||||
padding: 0 .7em;
|
||||
|
||||
348
spec/fixtures/import/otrs/customer_user/camel_case_login.json
vendored
Normal file
348
spec/fixtures/import/otrs/customer_user/camel_case_login.json
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
{
|
||||
"CustomerCompanyCity": "test712259",
|
||||
"Config": {
|
||||
"CustomerUserEmailUniqCheck": 1,
|
||||
"CustomerUserSearchListLimit": 250,
|
||||
"CustomerCompanySupport": 1,
|
||||
"CustomerValid": "valid_id",
|
||||
"CustomerUserSearchFields": [
|
||||
"login",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"customer_id"
|
||||
],
|
||||
"CustomerUserSearchPrefix": "*",
|
||||
"Params": {
|
||||
"Table": "customer_user",
|
||||
"CaseSensitive": 0
|
||||
},
|
||||
"CustomerUserListFields": [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"email"
|
||||
],
|
||||
"Map": [
|
||||
[
|
||||
"UserTitle",
|
||||
"Title",
|
||||
"title",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserFirstname",
|
||||
"Firstname",
|
||||
"first_name",
|
||||
1,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserLastname",
|
||||
"Lastname",
|
||||
"last_name",
|
||||
1,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserLogin",
|
||||
"Username",
|
||||
"login",
|
||||
1,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserPassword",
|
||||
"Password",
|
||||
"pw",
|
||||
0,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserEmail",
|
||||
"Email",
|
||||
"email",
|
||||
1,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserCustomerID",
|
||||
"CustomerID",
|
||||
"customer_id",
|
||||
0,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserPhone",
|
||||
"Phone",
|
||||
"phone",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserFax",
|
||||
"Fax",
|
||||
"fax",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserMobile",
|
||||
"Mobile",
|
||||
"mobile",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserStreet",
|
||||
"Street",
|
||||
"street",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserZip",
|
||||
"Zip",
|
||||
"zip",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserCity",
|
||||
"City",
|
||||
"city",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserCountry",
|
||||
"Country",
|
||||
"country",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"UserComment",
|
||||
"Comment",
|
||||
"comments",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"ValidID",
|
||||
"Valid",
|
||||
"valid_id",
|
||||
0,
|
||||
1,
|
||||
"int",
|
||||
"",
|
||||
0
|
||||
]
|
||||
],
|
||||
"CustomerKey": "login",
|
||||
"CustomerUserSearchSuffix": "*",
|
||||
"Module": "Kernel::System::CustomerUser::DB",
|
||||
"CacheTTL": 86400,
|
||||
"Selections": {},
|
||||
"CustomerID": "customer_id",
|
||||
"Name": "Database Backend",
|
||||
"CustomerUserPostMasterSearchFields": [
|
||||
"email"
|
||||
],
|
||||
"CustomerUserNameFields": [
|
||||
"title",
|
||||
"first_name",
|
||||
"last_name"
|
||||
]
|
||||
},
|
||||
"UserCustomerID": "test712259",
|
||||
"CustomerCompanyComment": "test712259",
|
||||
"Source": "CustomerUser",
|
||||
"UserTitle": "",
|
||||
"CompanyConfig": {
|
||||
"CustomerCompanySearchFields": [
|
||||
"customer_id",
|
||||
"name"
|
||||
],
|
||||
"CustomerCompanyListFields": [
|
||||
"customer_id",
|
||||
"name"
|
||||
],
|
||||
"Module": "Kernel::System::CustomerCompany::DB",
|
||||
"CustomerCompanyKey": "customer_id",
|
||||
"CustomerCompanySearchSuffix": "*",
|
||||
"CacheTTL": 86400,
|
||||
"CustomerCompanySearchListLimit": 250,
|
||||
"CustomerCompanySearchPrefix": "",
|
||||
"CustomerCompanyValid": "valid_id",
|
||||
"Params": {
|
||||
"Table": "customer_company",
|
||||
"CaseSensitive": 0
|
||||
},
|
||||
"Map": [
|
||||
[
|
||||
"CustomerID",
|
||||
"CustomerID",
|
||||
"customer_id",
|
||||
0,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyName",
|
||||
"Customer",
|
||||
"name",
|
||||
1,
|
||||
1,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyStreet",
|
||||
"Street",
|
||||
"street",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyZIP",
|
||||
"Zip",
|
||||
"zip",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyCity",
|
||||
"City",
|
||||
"city",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyCountry",
|
||||
"Country",
|
||||
"country",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyURL",
|
||||
"URL",
|
||||
"url",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"[% Data.CustomerCompanyURL | html %]",
|
||||
0
|
||||
],
|
||||
[
|
||||
"CustomerCompanyComment",
|
||||
"Comment",
|
||||
"comments",
|
||||
1,
|
||||
0,
|
||||
"var",
|
||||
"",
|
||||
0
|
||||
],
|
||||
[
|
||||
"ValidID",
|
||||
"Valid",
|
||||
"valid_id",
|
||||
0,
|
||||
1,
|
||||
"int",
|
||||
"",
|
||||
0
|
||||
]
|
||||
],
|
||||
"Name": "Database Backend"
|
||||
},
|
||||
"UserZip": null,
|
||||
"UserLastname": "test669673",
|
||||
"ChangeBy": "1",
|
||||
"CreateTime": "2014-06-07 02:31:31",
|
||||
"UserLogin": "TeSt669673",
|
||||
"UserPhone": null,
|
||||
"CustomerID": "test712259",
|
||||
"CustomerCompanyValidID": "1",
|
||||
"CustomerCompanyZIP": "test712259",
|
||||
"UserCountry": null,
|
||||
"UserPassword": "f8be19af2f25837a31eff9131b0e47a5173290652c04a48b49b86474d48825ee",
|
||||
"ValidID": "1",
|
||||
"UserRefreshTime": "0",
|
||||
"UserEmail": "QA100@t-Online.de",
|
||||
"UserComment": "",
|
||||
"UserID": "test669673",
|
||||
"UserFirstname": "test669673",
|
||||
"CustomerCompanyCountry": "test712259",
|
||||
"UserFax": null,
|
||||
"CreateBy": "1",
|
||||
"ChangeTime": "2014-06-07 02:31:31",
|
||||
"UserShowTickets": "25",
|
||||
"UserStreet": null,
|
||||
"CustomerCompanyURL": "test712259",
|
||||
"CustomerCompanyName": "test712259",
|
||||
"UserMobile": null,
|
||||
"CustomerCompanyStreet": "test712259",
|
||||
"UserCity": null
|
||||
}
|
||||
135
spec/fixtures/import/otrs/user/camel_case_login.json
vendored
Normal file
135
spec/fixtures/import/otrs/user/camel_case_login.json
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"OutOfOffice": "1",
|
||||
"OutOfOfficeStartMonth": "9",
|
||||
"UserStoredFilterColumns-AgentTicketLockedView": "{}",
|
||||
"UserTicketOverviewSmallPageShown": "35",
|
||||
"UserCreateWorkOrderNextMask": "AgentITSMWorkOrderZoom",
|
||||
"OutOfOfficeEndYear": "2014",
|
||||
"UserDashboardTicketGenericFilter0110-TicketEscalation": "All",
|
||||
"UserDashboardPref0120-TicketNew-Columns": "{\"Columns\":{\"Changed\":0,\"CustomerID\":0,\"CustomerName\":0,\"CustomerUserID\":0,\"DynamicField_CustomerLocation\":0,\"EscalationResponseTime\":0,\"EscalationSolutionTime\":0,\"EscalationTime\":0,\"EscalationUpdateTime\":0,\"Lock\":0,\"Owner\":0,\"PendingTime\":0,\"Priority\":0,\"Responsible\":0,\"SLA\":0,\"State\":0,\"Type\":0,\"Age\":1,\"Title\":1,\"Queue\":1,\"Service\":1,\"TicketNumber\":1},\"Order\":[\"Age\",\"Title\",\"Queue\",\"Service\",\"TicketNumber\"]}",
|
||||
"UserLastUsedZoomViewType": "",
|
||||
"OutOfOfficeStartDay": "10",
|
||||
"UserStoredFilterColumns-AgentTicketStatusView": "{}",
|
||||
"UserTitle": null,
|
||||
"UserLastname": "OTRS",
|
||||
"UserTicketOverviewMediumPageShown": "20",
|
||||
"OutOfOfficeEndDay": "12",
|
||||
"CreateTime": "2014-04-28 10:53:18",
|
||||
"UserTicketOverviewPreviewPageShown": "15",
|
||||
"UserLogin": "rOoT@LoCaLhOsT",
|
||||
"UserFilterColumnsEnabled-AgentTicketEscalationView": "[\"TicketNumber\",\"Age\",\"EscalationTime\",\"EscalationResponseTime\",\"EscalationSolutionTime\",\"EscalationUpdateTime\",\"Title\",\"State\",\"Lock\",\"Queue\",\"Owner\",\"CustomerID\"]",
|
||||
"UserLanguage": "de",
|
||||
"UserDashboardPref0110-TicketEscalation-Columns": "{\"Columns\":{\"Changed\":0,\"CustomerID\":0,\"CustomerUserID\":0,\"EscalationResponseTime\":0,\"EscalationSolutionTime\":0,\"EscalationTime\":0,\"EscalationUpdateTime\":0,\"Lock\":0,\"Owner\":0,\"PendingTime\":0,\"Priority\":0,\"Queue\":0,\"Responsible\":0,\"SLA\":0,\"Service\":0,\"State\":0,\"Type\":0,\"Age\":1,\"Title\":1,\"CustomerName\":1,\"TicketNumber\":1},\"Order\":[\"Age\",\"Title\",\"CustomerName\",\"TicketNumber\"]}",
|
||||
"OutOfOfficeStartYear": "2014",
|
||||
"UserDashboardPref0120-TicketNew-Shown": "10",
|
||||
"UserFullname": "Admin OTRS",
|
||||
"UserLastLoginTimestamp": "2016-08-10 19:37:44",
|
||||
"UserLastLogin": "1470850664",
|
||||
"UserMarkTicketUnseenRedirectURL": "Action=AgentTicketZoom;TicketID=###TicketID####1",
|
||||
"AdminDynamicFieldsOverviewPageShown": "35",
|
||||
"UserChangeOverviewSmallPageShown": "25",
|
||||
"RoleIDs": [],
|
||||
"ValidID": "1",
|
||||
"UserStoredFilterColumns-AgentTicketQueue": "{}",
|
||||
"UserEmail": "ROOT@loCalhosT",
|
||||
"UserRefreshTime": "0",
|
||||
"UserDashboardPref0130-TicketOpen-Shown": "10",
|
||||
"UserTicketOverviewAgentTicketQueue": "Small",
|
||||
"UserID": "1",
|
||||
"UserDashboardTicketGenericColumnFiltersRealKeys0120-TicketNew": "{\"QueueIDs\":[\"1\"]}",
|
||||
"wpt22": "1",
|
||||
"UserMarkTicketSeenRedirectURL": "Action=AgentTicketZoom;TicketID=###TicketID####1",
|
||||
"UserStoredFilterColumns-AgentTicketEscalationView": "{}",
|
||||
"UserDashboardTicketGenericFilter0120-TicketNew": "MyQueues",
|
||||
"UserCreateNextMask": "",
|
||||
"UserFirstname": "Admin",
|
||||
"UserPw": "9faaba2ab242a99bbb6992e9424386375f6757c17e6484ae570f39d9cad9f28ea",
|
||||
"UserDashboardPref0110-TicketEscalation-Shown": "10",
|
||||
"UserFilterColumnsEnabled-AgentTicketQueue": "[\"TicketNumber\",\"Age\",\"Title\",\"State\",\"Lock\",\"DynamicField_CustomerLocation\",\"Queue\",\"Owner\",\"CustomerID\",\"DynamicField_Hostname\"]",
|
||||
"OutOfOfficeEndMonth": "9",
|
||||
"ChangeTime": "2014-04-28 10:53:18",
|
||||
"UserDashboardPref0130-TicketOpen-Columns": "{\"Columns\":{\"Changed\":0,\"CustomerID\":0,\"CustomerUserID\":0,\"EscalationResponseTime\":0,\"EscalationTime\":0,\"EscalationUpdateTime\":0,\"Lock\":0,\"Owner\":0,\"PendingTime\":0,\"Priority\":0,\"Queue\":0,\"Responsible\":0,\"SLA\":0,\"Service\":0,\"State\":0,\"Type\":0,\"Age\":1,\"DynamicField_CustomerLocation\":1,\"Title\":1,\"CustomerName\":1,\"EscalationSolutionTime\":1,\"TicketNumber\":1},\"Order\":[\"Age\",\"DynamicField_CustomerLocation\",\"Title\",\"CustomerName\",\"EscalationSolutionTime\",\"TicketNumber\"]}",
|
||||
"UserTicketOverviewAgentTicketSearch": "Small",
|
||||
"UserTicketOverviewAgentCustomerSearch": "Small",
|
||||
"UserDashboardTicketGenericColumnFilters0120-TicketNew": "{\"Queue\":\"1\"}",
|
||||
"GroupIDs": {
|
||||
"6": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"3": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"7": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"2": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"8": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"1": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"4": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
],
|
||||
"5": [
|
||||
"ro",
|
||||
"move_into",
|
||||
"create",
|
||||
"note",
|
||||
"owner",
|
||||
"priority",
|
||||
"rw"
|
||||
]
|
||||
},
|
||||
"UserConfigItemOverviewSmallPageShown": "25",
|
||||
"UserAuthBackend": "",
|
||||
"UserTicketOverviewAgentTicketLockedView": "Small",
|
||||
"UserTicketOverviewAgentTicketEscalationView": "Small",
|
||||
"UserTicketOverviewAgentTicketStatusView": "Small",
|
||||
"UserLoginFailed": "0"
|
||||
}
|
||||
@@ -158,4 +158,42 @@ RSpec.describe Import::OTRS::CustomerUser do
|
||||
updates_with(zammad_structure)
|
||||
end
|
||||
end
|
||||
|
||||
context 'regular user with camelcase login' do
|
||||
|
||||
let(:object_structure) { load_customer_json('camel_case_login') }
|
||||
let(:zammad_structure) do
|
||||
{
|
||||
created_by_id: '1',
|
||||
updated_by_id: '1',
|
||||
active: true,
|
||||
source: 'OTRS Import',
|
||||
organization_id: 1337,
|
||||
role_ids: [3],
|
||||
updated_at: '2014-06-07 02:31:31',
|
||||
created_at: '2014-06-07 02:31:31',
|
||||
note: '',
|
||||
email: 'qa100@t-online.de',
|
||||
firstname: 'test669673',
|
||||
lastname: 'test669673',
|
||||
login: 'test669673',
|
||||
password: 'f8be19af2f25837a31eff9131b0e47a5173290652c04a48b49b86474d48825ee',
|
||||
phone: nil,
|
||||
fax: nil,
|
||||
mobile: nil,
|
||||
street: nil,
|
||||
zip: nil,
|
||||
city: nil,
|
||||
country: nil
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates' do
|
||||
creates_with(zammad_structure)
|
||||
end
|
||||
|
||||
it 'updates' do
|
||||
updates_with(zammad_structure)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -166,4 +166,38 @@ RSpec.describe Import::OTRS::User do
|
||||
updates_with(zammad_structure)
|
||||
end
|
||||
end
|
||||
|
||||
context 'regular user with camel case login' do
|
||||
|
||||
let(:object_structure) { load_user_json('camel_case_login') }
|
||||
let(:zammad_structure) do
|
||||
{
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
active: true,
|
||||
source: 'OTRS Import',
|
||||
role_ids: [2, 1],
|
||||
group_ids: ['1'],
|
||||
password: '{sha2}9faaba2ab242a99bbb6992e9424386375f6757c17e6484ae570f39d9cad9f28ea',
|
||||
updated_at: '2014-04-28 10:53:18',
|
||||
created_at: '2014-04-28 10:53:18',
|
||||
id: '1',
|
||||
email: 'root@localhost',
|
||||
firstname: 'Admin',
|
||||
lastname: 'OTRS',
|
||||
login: 'root@localhost'
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates' do
|
||||
prepare_expectations
|
||||
creates_with(zammad_structure)
|
||||
end
|
||||
|
||||
it 'updates' do
|
||||
prepare_expectations
|
||||
updates_with(zammad_structure)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
17
test/fixtures/mail65.box
vendored
Normal file
17
test/fixtures/mail65.box
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
From: =?iso-8859-1?Q?B=FCrling,=20Andreas?= <smith@example.com>
|
||||
Content-Type: text/plain;
|
||||
charset=iso-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Subject: =?iso-8859-1?Q?aa=E4=F6=FC=DFad_asd?=
|
||||
X-Universally-Unique-Identifier: d12c15d2-e6d6-4ccd-86c7-abc2c3d0a2a2
|
||||
Date: Fri, 4 May 2012 14:01:03 +0200
|
||||
Message-Id: <BC182994-03FA-4DC5-8202-98CBFACA0887@example.com>
|
||||
To: metest@znuny.com
|
||||
Mime-Version: 1.0 (Apple Message framework v1257)
|
||||
|
||||
=E4=F6=FC=DF ad asd
|
||||
|
||||
-Martin
|
||||
|
||||
--
|
||||
Old programmers never die. They just branch to a new address.
|
||||
@@ -136,8 +136,8 @@ class ReportTest < ActiveSupport::TestCase
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
close_at: '2015-10-28 11:30:00 UTC',
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
created_at: '2015-10-28 10:30:01 UTC',
|
||||
updated_at: '2015-10-28 10:30:01 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
@@ -151,8 +151,8 @@ class ReportTest < ActiveSupport::TestCase
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Customer').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
created_at: '2015-10-28 10:30:01 UTC',
|
||||
updated_at: '2015-10-28 10:30:01 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
@@ -245,6 +245,34 @@ class ReportTest < ActiveSupport::TestCase
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
@ticket8 = Ticket.create!(
|
||||
title: 'test 8',
|
||||
group: group1,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'merged'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
close_at: '2015-11-02 12:30:00 UTC',
|
||||
created_at: '2015-11-02 12:30:00 UTC',
|
||||
updated_at: '2015-11-02 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: @ticket8.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_outbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Agent').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-11-02 12:30:00 UTC',
|
||||
updated_at: '2015-11-02 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
# execute background jobs
|
||||
Scheduler.worker(true)
|
||||
|
||||
@@ -276,7 +304,7 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(2, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(2, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
@@ -289,7 +317,8 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(@ticket6.id, result[:ticket_ids][1])
|
||||
assert_equal(@ticket7.id, result[:ticket_ids][2])
|
||||
assert_nil(result[:ticket_ids][3])
|
||||
assert_equal(@ticket8.id, result[:ticket_ids][3])
|
||||
assert_nil(result[:ticket_ids][4])
|
||||
|
||||
# month - with selector #1
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
@@ -332,6 +361,47 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][0])
|
||||
assert_nil(result[:ticket_ids][1])
|
||||
|
||||
# month - with merged tickets selector
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(2, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][0])
|
||||
assert_nil(result[:ticket_ids][3])
|
||||
|
||||
# month - with selector #2
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
@@ -355,7 +425,7 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(2, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
@@ -372,7 +442,8 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert(result)
|
||||
assert_equal(@ticket6.id, result[:ticket_ids][0])
|
||||
assert_equal(@ticket7.id, result[:ticket_ids][1])
|
||||
assert_nil(result[:ticket_ids][2])
|
||||
assert_equal(@ticket8.id, result[:ticket_ids][2])
|
||||
assert_nil(result[:ticket_ids][3])
|
||||
|
||||
# week
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
@@ -611,6 +682,94 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert(result)
|
||||
assert_nil(result[:ticket_ids][0])
|
||||
|
||||
# month - reopened with merge selector
|
||||
result = Report::TicketReopened.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
result = Report::TicketReopened.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][0])
|
||||
assert_nil(result[:ticket_ids][1])
|
||||
|
||||
# move in/out without merged status
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'in',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(0, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
result = Report::TicketMoved.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.group_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Group.lookup(name: 'Users').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'in',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(@ticket1.id, result[:ticket_ids][0])
|
||||
assert_nil(result[:ticket_ids][1])
|
||||
|
||||
# move in/out
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
@@ -658,6 +817,52 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(@ticket1.id, result[:ticket_ids][0])
|
||||
assert_nil(result[:ticket_ids][1])
|
||||
|
||||
# out without merged tickets
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'out',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(0, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
result = Report::TicketMoved.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket_state.name' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged',
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'out',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_nil(result[:ticket_ids][0])
|
||||
|
||||
# out
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
@@ -724,7 +929,7 @@ class ReportTest < ActiveSupport::TestCase
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(6, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(2, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
@@ -735,12 +940,62 @@ class ReportTest < ActiveSupport::TestCase
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(@ticket8.id, result[:ticket_ids][0].to_i)
|
||||
assert_equal(@ticket7.id, result[:ticket_ids][1].to_i)
|
||||
assert_equal(@ticket6.id, result[:ticket_ids][2].to_i)
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][3].to_i)
|
||||
assert_equal(@ticket4.id, result[:ticket_ids][4].to_i)
|
||||
assert_equal(@ticket3.id, result[:ticket_ids][5].to_i)
|
||||
assert_equal(@ticket2.id, result[:ticket_ids][6].to_i)
|
||||
assert_equal(@ticket1.id, result[:ticket_ids][7].to_i)
|
||||
assert_nil(result[:ticket_ids][8])
|
||||
|
||||
# create at - selector with merge
|
||||
result = Report::TicketGenericTime.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'state' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(6, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_nil(result[12])
|
||||
|
||||
result = Report::TicketGenericTime.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'state' => {
|
||||
'operator' => 'is not',
|
||||
'value' => 'merged'
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
|
||||
assert(result)
|
||||
assert_equal(@ticket7.id, result[:ticket_ids][0].to_i)
|
||||
assert_equal(@ticket6.id, result[:ticket_ids][1].to_i)
|
||||
assert_equal(@ticket5.id, result[:ticket_ids][2].to_i)
|
||||
assert_equal(@ticket3.id, result[:ticket_ids][3].to_i)
|
||||
assert_equal(@ticket4.id, result[:ticket_ids][4].to_i)
|
||||
assert_equal(@ticket4.id, result[:ticket_ids][3].to_i)
|
||||
assert_equal(@ticket3.id, result[:ticket_ids][4].to_i)
|
||||
assert_equal(@ticket2.id, result[:ticket_ids][5].to_i)
|
||||
assert_equal(@ticket1.id, result[:ticket_ids][6].to_i)
|
||||
assert_nil(result[:ticket_ids][7])
|
||||
|
||||
@@ -203,6 +203,74 @@ Some Text",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
data: "From: sender@example.com
|
||||
To: some_new_customer423@example.com
|
||||
Cc: some recipient <some with invalid@example.com>, max <somebody_else@example.com>
|
||||
Subject: abc some subject2
|
||||
|
||||
Some Text",
|
||||
success: true,
|
||||
result: {
|
||||
0 => {
|
||||
priority: '2 normal',
|
||||
title: 'abc some subject2',
|
||||
},
|
||||
1 => {
|
||||
body: 'Some Text',
|
||||
sender: 'Customer',
|
||||
type: 'email',
|
||||
internal: false,
|
||||
},
|
||||
},
|
||||
verify: {
|
||||
users: [
|
||||
{
|
||||
firstname: 'max',
|
||||
lastname: '',
|
||||
fullname: 'max',
|
||||
email: 'somebody_else@example.com',
|
||||
},
|
||||
{
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
fullname: 'some_new_customer423@example.com',
|
||||
email: 'some_new_customer423@example.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
data: "From: sender@example.com
|
||||
To: some_new_customer424@example.com
|
||||
Subject: abc some subject3
|
||||
Reply-To: some user <no-reply-with invalid-spaces@example.com>
|
||||
|
||||
Some Text",
|
||||
success: true,
|
||||
result: {
|
||||
0 => {
|
||||
priority: '2 normal',
|
||||
title: 'abc some subject3',
|
||||
},
|
||||
1 => {
|
||||
body: 'Some Text',
|
||||
sender: 'Customer',
|
||||
type: 'email',
|
||||
internal: false,
|
||||
},
|
||||
},
|
||||
verify: {
|
||||
users: [
|
||||
{
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
fullname: 'some_new_customer424@example.com',
|
||||
email: 'some_new_customer424@example.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
data: "From: me@example.com
|
||||
To: Alexander Ha <service-d1@example.com>,
|
||||
@@ -2601,6 +2669,38 @@ Some Text',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
data: IO.binread('test/fixtures/mail65.box'),
|
||||
success: true,
|
||||
result: {
|
||||
0 => {
|
||||
priority: '2 normal',
|
||||
title: 'aaäöüßad asd',
|
||||
},
|
||||
1 => {
|
||||
from: '=?iso-8859-1?Q?B=FCrling, =20Andreas?= <smith@example.com>',
|
||||
sender: 'Customer',
|
||||
type: 'email',
|
||||
body: 'äöüß ad asd
|
||||
|
||||
-Martin
|
||||
|
||||
--
|
||||
Old programmers never die. They just branch to a new address.
|
||||
',
|
||||
},
|
||||
},
|
||||
verify: {
|
||||
users: [
|
||||
{
|
||||
firstname: '=20Andreas?=',
|
||||
lastname: '',
|
||||
fullname: '=20Andreas?=',
|
||||
email: 'smith@example.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
assert_process(files)
|
||||
end
|
||||
@@ -2812,9 +2912,9 @@ Some Text',
|
||||
# verify if users are created
|
||||
if file[:verify][:users]
|
||||
file[:verify][:users].each { |user_result|
|
||||
user = User.where(email: user_result[:email]).first
|
||||
user = User.where(email: user_result[:email].downcase).first
|
||||
if !user
|
||||
assert(false, "No user '#{user_result[:email]}' found!")
|
||||
assert(false, "No user '#{user_result[:email].downcase}' found!")
|
||||
return
|
||||
end
|
||||
user_result.each { |key, value|
|
||||
|
||||
@@ -73,9 +73,9 @@ class RoleValidateAgentLimit < ActiveSupport::TestCase
|
||||
|
||||
test 'role validate agent limit - 1 user 2 ticket.agent roles' do
|
||||
|
||||
agent_max = User.with_permissions('ticket.agent').count
|
||||
current_agent_max = User.with_permissions('ticket.agent').count + 1
|
||||
UserInfo.current_user_id = 1
|
||||
Setting.set('system_agent_limit', agent_max + 1)
|
||||
Setting.set('system_agent_limit', current_agent_max)
|
||||
|
||||
permission_ticket_agent = Permission.find_by(name: 'ticket.agent')
|
||||
|
||||
@@ -107,6 +107,8 @@ class RoleValidateAgentLimit < ActiveSupport::TestCase
|
||||
|
||||
user1.role_ids = [Role.find_by(name: 'Agent').id, role_agent_limit1.id]
|
||||
|
||||
user1.role_ids = [Role.find_by(name: 'Agent').id, role_agent_limit1.id, role_agent_limit2.id]
|
||||
|
||||
assert_raises(Exceptions::UnprocessableEntity) do
|
||||
user2 = User.create!(
|
||||
firstname: 'Firstname2',
|
||||
@@ -118,6 +120,20 @@ class RoleValidateAgentLimit < ActiveSupport::TestCase
|
||||
)
|
||||
end
|
||||
|
||||
assert_equal(current_agent_max, User.with_permissions('ticket.agent').count)
|
||||
|
||||
current_agent_max = User.with_permissions('ticket.agent').count + 1
|
||||
Setting.set('system_agent_limit', current_agent_max)
|
||||
|
||||
user3 = User.create!(
|
||||
firstname: 'Firstname',
|
||||
lastname: 'Lastname',
|
||||
email: 'some-agentlimit-role-3@example.com',
|
||||
login: 'some-agentlimit-role-3@example.com',
|
||||
role_ids: [Role.find_by(name: 'Agent').id],
|
||||
active: true,
|
||||
)
|
||||
|
||||
role_agent_limit1.destroy!
|
||||
role_agent_limit2.destroy!
|
||||
Setting.set('system_agent_limit', nil)
|
||||
|
||||
162
test/unit/ticket_number_test.rb
Normal file
162
test/unit/ticket_number_test.rb
Normal file
@@ -0,0 +1,162 @@
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class TicketNumberTest < ActiveSupport::TestCase
|
||||
test 'number' do
|
||||
Setting.set('ticket_number_increment', { checksum: false, min_size: 5 })
|
||||
Setting.set('system_id', 1)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 5)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: false, min_size: 10 })
|
||||
Setting.set('system_id', 1)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 10)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: true, min_size: 5 })
|
||||
Setting.set('system_id', 1)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 5)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: true, min_size: 10 })
|
||||
Setting.set('system_id', 1)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 10)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: false, min_size: 5 })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 5)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: false, min_size: 10 })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 10)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: true, min_size: 5 })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 5)
|
||||
|
||||
Setting.set('ticket_number_increment', { checksum: true, min_size: 10 })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 10)
|
||||
|
||||
150.times do
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 10)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
test 'number check' do
|
||||
Setting.set('ticket_number_increment', { checksum: false, min_size: 5 })
|
||||
ticket = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
subject = ticket.subject_build(ticket.title)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_equal(ticket.id, ticket_check.id)
|
||||
|
||||
Setting.set('system_id', 999)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_not(ticket_check)
|
||||
|
||||
Setting.set('ticket_number_ignore_system_id', true)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_equal(ticket.id, ticket_check.id)
|
||||
end
|
||||
|
||||
test 'date' do
|
||||
Setting.set('ticket_number', 'Ticket::Number::Date')
|
||||
Setting.set('ticket_number_date', { checksum: false })
|
||||
Setting.set('system_id', 1)
|
||||
system_id = Setting.get('system_id')
|
||||
number_prefix = "#{Time.zone.now.strftime('%Y%m%d')}#{system_id}"
|
||||
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 13)
|
||||
assert_match(/#{number_prefix}/, number.to_s)
|
||||
|
||||
Setting.set('ticket_number_date', { checksum: false })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
system_id = Setting.get('system_id')
|
||||
number_prefix = "#{Time.zone.now.strftime('%Y%m%d')}#{system_id}"
|
||||
assert_equal(number.to_s.length, 14)
|
||||
assert_match(/#{number_prefix}/, number.to_s)
|
||||
|
||||
Setting.set('ticket_number_date', { checksum: true })
|
||||
Setting.set('system_id', 1)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
system_id = Setting.get('system_id')
|
||||
number_prefix = "#{Time.zone.now.strftime('%Y%m%d')}#{system_id}"
|
||||
assert_equal(number.to_s.length, 14)
|
||||
assert_match(/#{number_prefix}/, number.to_s)
|
||||
|
||||
Setting.set('ticket_number_date', { checksum: true })
|
||||
Setting.set('system_id', 88)
|
||||
|
||||
number = Ticket::Number.generate
|
||||
system_id = Setting.get('system_id')
|
||||
number_prefix = "#{Time.zone.now.strftime('%Y%m%d')}#{system_id}"
|
||||
assert_equal(number.to_s.length, 15)
|
||||
assert_match(/#{number_prefix}/, number.to_s)
|
||||
|
||||
150.times do
|
||||
number = Ticket::Number.generate
|
||||
assert_equal(number.to_s.length, 15)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
test 'date check' do
|
||||
Setting.set('ticket_number', 'Ticket::Number::Date')
|
||||
Setting.set('ticket_number_date', { checksum: false })
|
||||
|
||||
ticket = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
subject = ticket.subject_build(ticket.title)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_equal(ticket.id, ticket_check.id)
|
||||
|
||||
Setting.set('system_id', 999)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_not(ticket_check)
|
||||
|
||||
Setting.set('ticket_number_ignore_system_id', true)
|
||||
|
||||
ticket_check = Ticket::Number.check(subject)
|
||||
assert_equal(ticket.id, ticket_check.id)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3480,4 +3480,549 @@ class TicketTriggerTest < ActiveSupport::TestCase
|
||||
|
||||
end
|
||||
|
||||
test '4 tag based auto response' do
|
||||
trigger1 = Trigger.create_or_update(
|
||||
name: '100 add tag if sender 1',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'article.from' => {
|
||||
'operator' => 'contains',
|
||||
'value' => 'sender1',
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'ticket.tags' => {
|
||||
'operator' => 'add',
|
||||
'value' => 'sender1',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
trigger2 = Trigger.create_or_update(
|
||||
name: '200 add tag if sender 2',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'article.from' => {
|
||||
'operator' => 'contains',
|
||||
'value' => 'sender2',
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'ticket.tags' => {
|
||||
'operator' => 'add',
|
||||
'value' => 'sender2',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
trigger3 = Trigger.create_or_update(
|
||||
name: '300 auto reply',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::State.lookup(name: 'new').id.to_s,
|
||||
},
|
||||
'ticket.tags' => {
|
||||
#'operator' => 'contains one not',
|
||||
'operator' => 'contains all not',
|
||||
'value' => 'sender1, sender2',
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'notification.email' => {
|
||||
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
|
||||
'recipient' => 'ticket_customer',
|
||||
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket1.id,
|
||||
from: 'sender1@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: "some message <b>note</b>\nnew line",
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
|
||||
type: Ticket::Article::Type.find_by(name: 'email'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
|
||||
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
|
||||
assert_equal([], ticket1.tag_list)
|
||||
Observer::Transaction.commit
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
|
||||
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
|
||||
assert_equal(%w[sender1], ticket1.tag_list)
|
||||
|
||||
ticket2 = Ticket.create!(
|
||||
title: 'test 2',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket2.id,
|
||||
from: 'sender2@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: "some message <b>note</b>\nnew line",
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
|
||||
type: Ticket::Article::Type.find_by(name: 'email'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket2.reload
|
||||
assert_equal('test 2', ticket2.title, 'ticket2.title verify')
|
||||
assert_equal('Users', ticket2.group.name, 'ticket2.group verify')
|
||||
assert_equal('new', ticket2.state.name, 'ticket2.state verify')
|
||||
assert_equal('2 normal', ticket2.priority.name, 'ticket2.priority verify')
|
||||
assert_equal(1, ticket2.articles.count, 'ticket2.articles verify')
|
||||
assert_equal([], ticket2.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket2.reload
|
||||
assert_equal('test 2', ticket2.title, 'ticket2.title verify')
|
||||
assert_equal('Users', ticket2.group.name, 'ticket2.group verify')
|
||||
assert_equal('new', ticket2.state.name, 'ticket2.state verify')
|
||||
assert_equal('2 normal', ticket2.priority.name, 'ticket2.priority verify')
|
||||
assert_equal(1, ticket2.articles.count, 'ticket2.articles verify')
|
||||
assert_equal(%w[sender2], ticket2.tag_list)
|
||||
|
||||
ticket3 = Ticket.create!(
|
||||
title: 'test 3',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
assert(ticket3, 'ticket3 created')
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket3.id,
|
||||
from: 'sender0@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: "some message <b>note</b>\nnew line",
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
|
||||
type: Ticket::Article::Type.find_by(name: 'email'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket3.reload
|
||||
assert_equal('test 3', ticket3.title, 'ticket3.title verify')
|
||||
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
|
||||
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
|
||||
assert_equal('2 normal', ticket3.priority.name, 'ticket3.priority verify')
|
||||
assert_equal(1, ticket3.articles.count, 'ticket3.articles verify')
|
||||
assert_equal([], ticket3.tag_list)
|
||||
Observer::Transaction.commit
|
||||
ticket3.reload
|
||||
assert_equal('test 3', ticket3.title, 'ticket3.title verify')
|
||||
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
|
||||
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
|
||||
assert_equal('2 normal', ticket3.priority.name, 'ticket3.priority verify')
|
||||
assert_equal(2, ticket3.articles.count, 'ticket3.articles verify')
|
||||
assert_equal([], ticket3.tag_list)
|
||||
article1 = ticket3.articles.last
|
||||
|
||||
end
|
||||
|
||||
test 'article.body' do
|
||||
trigger1 = Trigger.create_or_update(
|
||||
name: 'auto reply',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::State.lookup(name: 'new').id.to_s,
|
||||
},
|
||||
'article.body' => {
|
||||
'operator' => 'contains',
|
||||
'value' => 'hello',
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'notification.email' => {
|
||||
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
|
||||
'recipient' => 'ticket_customer',
|
||||
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
|
||||
},
|
||||
'ticket.tags' => {
|
||||
'operator' => 'add',
|
||||
'value' => 'aa, kk',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket1.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message <b>note</b> hello ',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
|
||||
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
|
||||
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
|
||||
assert_equal([], ticket1.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
|
||||
assert_equal(%w[aa kk], ticket1.tag_list)
|
||||
article1 = ticket1.articles.last
|
||||
assert_match('Zammad <zammad@localhost>', article1.from)
|
||||
assert_match('nicole.braun@zammad.org', article1.to)
|
||||
assert_match('Thanks for your inquiry (test 1)!', article1.subject)
|
||||
assert_match('some message', article1.body)
|
||||
assert_match('> some message <b>note</b> hello', article1.body)
|
||||
assert_equal('text/html', article1.content_type)
|
||||
|
||||
ticket2 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket2.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message <b>note</b>',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
|
||||
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket2.reload
|
||||
assert_equal('test 1', ticket2.title, 'ticket2.title verify')
|
||||
assert_equal('Users', ticket2.group.name, 'ticket2.group verify')
|
||||
assert_equal('new', ticket2.state.name, 'ticket2.state verify')
|
||||
assert_equal('2 normal', ticket2.priority.name, 'ticket2.priority verify')
|
||||
assert_equal(1, ticket2.articles.count, 'ticket2.articles verify')
|
||||
assert_equal([], ticket2.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket2.reload
|
||||
assert_equal('test 1', ticket2.title, 'ticket2.title verify')
|
||||
assert_equal('Users', ticket2.group.name, 'ticket2.group verify')
|
||||
assert_equal('new', ticket2.state.name, 'ticket2.state verify')
|
||||
assert_equal(1, ticket2.articles.count, 'ticket2.articles verify')
|
||||
assert_equal(%w[], ticket2.tag_list)
|
||||
|
||||
trigger1 = Trigger.create_or_update(
|
||||
name: 'auto reply',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::State.lookup(name: 'new').id.to_s,
|
||||
},
|
||||
'article.body' => {
|
||||
'operator' => 'contains not',
|
||||
'value' => 'hello',
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'notification.email' => {
|
||||
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
|
||||
'recipient' => 'ticket_customer',
|
||||
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
|
||||
},
|
||||
'ticket.tags' => {
|
||||
'operator' => 'add',
|
||||
'value' => 'aa, kk',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
ticket3 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket3.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message <b>note</b> hello ',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
|
||||
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket3.reload
|
||||
assert_equal('test 1', ticket3.title, 'ticket3.title verify')
|
||||
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
|
||||
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
|
||||
assert_equal('2 normal', ticket3.priority.name, 'ticket3.priority verify')
|
||||
assert_equal(1, ticket3.articles.count, 'ticket3.articles verify')
|
||||
assert_equal([], ticket3.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket3.reload
|
||||
assert_equal('test 1', ticket3.title, 'ticket3.title verify')
|
||||
assert_equal('Users', ticket3.group.name, 'ticket3.group verify')
|
||||
assert_equal('new', ticket3.state.name, 'ticket3.state verify')
|
||||
assert_equal(1, ticket3.articles.count, 'ticket3.articles verify')
|
||||
assert_equal(%w[], ticket3.tag_list)
|
||||
|
||||
ticket4 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket4.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message <b>note</b> 2',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Agent'),
|
||||
type: Ticket::Article::Type.find_by(name: 'note'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket4.reload
|
||||
assert_equal('test 1', ticket4.title, 'ticket4.title verify')
|
||||
assert_equal('Users', ticket4.group.name, 'ticket4.group verify')
|
||||
assert_equal('new', ticket4.state.name, 'ticket4.state verify')
|
||||
assert_equal('2 normal', ticket4.priority.name, 'ticket4.priority verify')
|
||||
assert_equal(1, ticket4.articles.count, 'ticket4.articles verify')
|
||||
assert_equal([], ticket4.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket4.reload
|
||||
assert_equal('test 1', ticket4.title, 'ticket4.title verify')
|
||||
assert_equal('Users', ticket4.group.name, 'ticket4.group verify')
|
||||
assert_equal('new', ticket4.state.name, 'ticket4.state verify')
|
||||
assert_equal(2, ticket4.articles.count, 'ticket4.articles verify')
|
||||
assert_equal(%w[aa kk], ticket4.tag_list)
|
||||
article4 = ticket4.articles.last
|
||||
assert_match('Zammad <zammad@localhost>', article4.from)
|
||||
assert_match('nicole.braun@zammad.org', article4.to)
|
||||
assert_match('Thanks for your inquiry (test 1)!', article4.subject)
|
||||
assert_match('some message', article4.body)
|
||||
assert_match('> some message <b>note</b> 2', article4.body)
|
||||
assert_equal('text/html', article4.content_type)
|
||||
|
||||
end
|
||||
|
||||
test 'trigger auto reply with umlaut in form' do
|
||||
trigger1 = Trigger.create_or_update(
|
||||
name: 'auto reply',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::State.lookup(name: 'new').id.to_s,
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'notification.email' => {
|
||||
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
|
||||
'recipient' => 'article_last_sender',
|
||||
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1 = Ticket.create!(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer: User.lookup(email: 'nicole.braun@zammad.org'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Ticket::Article.create!(
|
||||
ticket_id: ticket1.id,
|
||||
from: 'Sabine Schütz <some_sender@example.com>',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message <b>note</b> hello ',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.find_by(name: 'Customer'),
|
||||
type: Ticket::Article::Type.find_by(name: 'email'),
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify')
|
||||
assert_equal(1, ticket1.articles.count, 'ticket1.articles verify')
|
||||
assert_equal('Sabine Schütz <some_sender@example.com>', ticket1.articles.first.from, 'ticket1.articles.first.from verify')
|
||||
assert_equal([], ticket1.tag_list)
|
||||
|
||||
Observer::Transaction.commit
|
||||
|
||||
ticket1.reload
|
||||
assert_equal('test 1', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
|
||||
article1 = ticket1.articles.last
|
||||
assert_match('Zammad <zammad@localhost>', article1.from)
|
||||
assert_match('some_sender@example.com', article1.to)
|
||||
assert_match('Thanks for your inquiry (test 1)!', article1.subject)
|
||||
assert_match('some message', article1.body)
|
||||
assert_match('> some message <b>note</b> hello', article1.body)
|
||||
assert_equal('text/html', article1.content_type)
|
||||
|
||||
end
|
||||
|
||||
test 'trigger auto reply with 2 sender addresses in form' do
|
||||
trigger1 = Trigger.create_or_update(
|
||||
name: 'auto reply',
|
||||
condition: {
|
||||
'ticket.action' => {
|
||||
'operator' => 'is',
|
||||
'value' => 'create',
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::State.lookup(name: 'new').id.to_s,
|
||||
},
|
||||
},
|
||||
perform: {
|
||||
'notification.email' => {
|
||||
'body' => 'some text<br>#{ticket.customer.lastname}<br>#{ticket.title}<br>#{article.body}',
|
||||
'recipient' => 'article_last_sender',
|
||||
'subject' => 'Thanks for your inquiry (#{ticket.title})!',
|
||||
},
|
||||
},
|
||||
disable_notification: true,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
ticket1, article1, user, mail = Channel::EmailParser.new.process({}, IO.binread('test/fixtures/mail65.box'))
|
||||
|
||||
assert_equal('aaäöüßad asd', ticket1.title, 'ticket1.title verify')
|
||||
assert_equal('Users', ticket1.group.name, 'ticket1.group verify')
|
||||
assert_equal('new', ticket1.state.name, 'ticket1.state verify')
|
||||
assert_equal(2, ticket1.articles.count, 'ticket1.articles verify')
|
||||
article1 = ticket1.articles.last
|
||||
assert_match('Zammad <zammad@localhost>', article1.from)
|
||||
assert_match('smith@example.com', article1.to)
|
||||
assert_match('Thanks for your inquiry (aaäöüßad asd)!', article1.subject)
|
||||
assert_match('some text<br><br>aaäöüßad asd', article1.body)
|
||||
assert_equal('text/html', article1.content_type)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user