keithsalisbury-subtrac 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/VERSION.yml +1 -1
  2. data/bin/subtrac +2 -0
  3. data/lib/subtrac.rb +85 -50
  4. data/lib/subtrac/config/config.yml +22 -19
  5. data/lib/subtrac/templates/location.erb +2 -2
  6. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +1 -1
  7. data/lib/subtrac/templates/trac.erb +1 -1
  8. data/lib/subtrac/templates/vhost.erb +6 -6
  9. metadata +1 -105
  10. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
  11. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +0 -419
  12. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +0 -3
  13. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +0 -20
  14. data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
  15. data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +0 -28
  16. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +0 -168
  17. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +0 -137
  18. data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +0 -91
  19. data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +0 -199
  20. data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +0 -105
  21. data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +0 -287
  22. data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +0 -71
  23. data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +0 -4
  24. data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +0 -135
  25. data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +0 -70
  26. data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +0 -142
  27. data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +0 -231
  28. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +0 -27
  29. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +0 -152
  30. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +0 -160
  31. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +0 -124
  32. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +0 -134
  33. data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +0 -132
  34. data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +0 -97
  35. data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +0 -161
  36. data/lib/subtrac/trac-plugins/clientsplugin/setup.py +0 -43
  37. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +0 -4
  38. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +0 -273
  39. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +0 -44
  40. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +0 -36
  41. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +0 -32
  42. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +0 -409
  43. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +0 -30
  44. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +0 -53
  45. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +0 -181
  46. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +0 -66
  47. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +0 -47
  48. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +0 -93
  49. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +0 -86
  50. data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +0 -20
  51. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +0 -23
  52. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +0 -128
  53. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +0 -40
  54. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +0 -285
  55. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +0 -173
  56. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
  57. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +0 -164
  58. data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +0 -69
  59. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +0 -1
  60. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +0 -292
  61. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +0 -172
  62. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +0 -178
  63. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +0 -25
  64. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +0 -6
  65. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +0 -356
  66. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +0 -100
  67. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +0 -84
  68. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +0 -1149
  69. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +0 -119
  70. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +0 -73
  71. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +0 -165
  72. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +0 -28
  73. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +0 -221
  74. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +0 -675
  75. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +0 -150
  76. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +0 -25
  77. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +0 -131
  78. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +0 -84
  79. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +0 -104
  80. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +0 -194
  81. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +0 -62
  82. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +0 -28
  83. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +0 -127
  84. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +0 -129
  85. data/lib/subtrac/trac-plugins/worklogplugin/setup.py +0 -29
  86. data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +0 -1
  87. data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +0 -187
  88. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +0 -40
  89. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +0 -67
  90. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +0 -12
  91. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +0 -7
  92. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +0 -40
  93. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +0 -208
  94. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +0 -1439
  95. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
  96. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
  97. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +0 -80
  98. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
  99. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
  100. data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +0 -336
  101. data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +0 -598
  102. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +0 -45
  103. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +0 -70
  104. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +0 -40
  105. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +0 -59
  106. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +0 -33
  107. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +0 -153
  108. data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +0 -96
  109. data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +0 -29
  110. data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +0 -31
  111. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +0 -47
  112. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +0 -174
  113. data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +0 -73
@@ -1,80 +0,0 @@
1
- #worklogmanual
2
- {
3
- display: block;
4
- float: right;
5
- }
6
- #worklog_comment
7
- {
8
- font-size: 70%;
9
- color: green;
10
- }
11
- #worklog_time_delta
12
- {
13
- font-size: 70%;
14
- color: green;
15
- }
16
- table#worklog_report
17
- {
18
- width: 99%;
19
- clear: both;
20
- }
21
- #content.worklog table th
22
- {
23
- background: #f7f7f7;
24
- border-bottom: 1px solid #d7d7d7;
25
- font-size: 105%;
26
- font-weight: bold;
27
- text-align: left;
28
- padding: 5px;
29
- }
30
- #content.worklog table td
31
- {
32
- padding: 5px;
33
- border: 1px solid #eee;
34
- }
35
- #content.worklog table td small
36
- {
37
- color: #999;
38
- }
39
- .message
40
- {
41
- font-weight:bold;
42
- color:#283;
43
- }
44
- dt.workstart, dt.workstart a
45
- {
46
- background-image: url(workstart.png);
47
- }
48
- dt.workstop, dt.workstop a
49
- {
50
- background-image: url(workstop.png);
51
- }
52
-
53
-
54
- /* Ticket Page */
55
- #worklogTicketForm
56
- {
57
- float: right;
58
- }
59
- fieldset.workloginfo ul
60
- {
61
- margin: 0;
62
- padding: 0;
63
- padding-left: 3em;
64
- font-size: 11px;
65
- list-style: url(work.png) disc;
66
- }
67
-
68
- html .jqmWindow {
69
- margin-left: -250px;
70
- width: 500px;
71
-
72
- background-color: #fff;
73
- border: 1px solid black;
74
- padding: 12px;
75
- }
76
-
77
- textarea#worklogComment {
78
- width: 100%;
79
- margin: 2px 0;
80
- }
@@ -1,336 +0,0 @@
1
- from time import time
2
- from datetime import tzinfo, timedelta, datetime
3
- from util import pretty_timedelta
4
- from trac.ticket.notification import TicketNotifyEmail
5
- from trac.ticket import Ticket
6
- from trac.ticket.web_ui import TicketModule
7
- from trac.util.datefmt import format_date, format_time, to_datetime
8
-
9
- class WorkLogManager:
10
- env = None
11
- config = None
12
- authname = None
13
- explanation = None
14
- now = None
15
-
16
- def __init__(self, env, config, authname='anonymous'):
17
- self.env = env
18
- self.config = config
19
- self.authname = authname
20
- self.explanation = ""
21
- self.now = int(time()) - 1
22
-
23
- def get_explanation(self):
24
- return self.explanation
25
-
26
- def can_work_on(self, ticket):
27
- # Need to check several things.
28
- # 1. Is some other user working on this ticket?
29
- # 2. a) Is the autostopstart setting true? or
30
- # b) Is the user working on a ticket already?
31
- # 3. a) Is the autoreassignaccept setting true? or
32
- # b) Is the ticket assigned to the user?
33
-
34
- # 0. Are you logged in?
35
- if self.authname == 'anonymous':
36
- self.explanation = 'You need to be logged in to work on tickets.'
37
- return False
38
-
39
- # 1. Other user working on it?
40
- who,since = self.who_is_working_on(ticket)
41
- if who:
42
- if who != self.authname:
43
- self.explanation = 'Another user (%s) has been working on ticket #%s since %s' % (who, ticket, since)
44
- else:
45
- self.explanation = 'You are already working on ticket #%s' % (ticket,)
46
- return False
47
-
48
- # 2. a) Is the autostopstart setting true? or
49
- # b) Is the user working on a ticket already?
50
- if not self.config.getbool('worklog', 'autostopstart'):
51
- active = self.get_active_task()
52
- if active:
53
- self.explanation = 'You cannot work on ticket #%s as you are currently working on ticket #%s. You have to chill out.' % (ticket, active['ticket'])
54
- return False
55
-
56
- # 3. a) Is the autoreassignaccept setting true? or
57
- # b) Is the ticket assigned to the user?
58
- if not self.config.getbool('worklog', 'autoreassignaccept'):
59
- tckt = Ticket(self.env, ticket)
60
- if self.authname != tckt['owner']:
61
- self.explanation = 'You cannot work on ticket #%s as you are not the owner. You should speak to %s.' % (ticket, tckt['owner'])
62
- return False
63
-
64
- # If we get here then we know we can start work :)
65
- return True
66
-
67
- def save_ticket(self, tckt, db, msg):
68
- # determine sequence number...
69
- cnum = 0
70
- tm = TicketModule(self.env)
71
- for change in tm.grouped_changelog_entries(tckt, db):
72
- if change['permanent']:
73
- cnum += 1
74
- nowdt = self.now
75
- nowdt = to_datetime(nowdt)
76
- tckt.save_changes(self.authname, msg, nowdt, db, cnum+1)
77
- ## Often the time overlaps and causes a db error,
78
- ## especially when the trac integration post-commit hook is used.
79
- ## NOTE TO SELF. I DON'T THINK THIS IS NECESSARY RIGHT NOW...
80
- #count = 0
81
- #while count < 10:
82
- # try:
83
- # tckt.save_changes(self.authname, msg, self.now, db, cnum+1)
84
- # count = 42
85
- # except Exception, e:
86
- # self.now += 1
87
- # count += 1
88
- db.commit()
89
-
90
- tn = TicketNotifyEmail(self.env)
91
- tn.notify(tckt, newticket=0, modtime=nowdt)
92
- # We fudge time as it has to be unique
93
- self.now += 1
94
-
95
-
96
- def start_work(self, ticket):
97
-
98
- if not self.can_work_on(ticket):
99
- return False
100
-
101
- # We could just horse all the fields of the ticket to the right values
102
- # bit it seems more correct to follow the in-build state-machine for
103
- # ticket modification.
104
-
105
- # If the ticket is closed, we need to reopen it.
106
- db = self.env.get_db_cnx()
107
- tckt = Ticket(self.env, ticket, db)
108
-
109
- if 'closed' == tckt['status']:
110
- tckt['status'] = 'reopened'
111
- tckt['resolution'] = ''
112
- self.save_ticket(tckt, db, 'Automatically reopening in order to start work.')
113
-
114
- # Reinitialise for next test
115
- db = self.env.get_db_cnx()
116
- tckt = Ticket(self.env, ticket, db)
117
-
118
-
119
- if self.authname != tckt['owner']:
120
- tckt['owner'] = self.authname
121
- if 'new' == tckt['status']:
122
- tckt['status'] = 'assigned'
123
- else:
124
- tckt['status'] = 'new'
125
- self.save_ticket(tckt, db, 'Automatically reassigning in order to start work.')
126
-
127
- # Reinitialise for next test
128
- db = self.env.get_db_cnx()
129
- tckt = Ticket(self.env, ticket, db)
130
-
131
-
132
- if 'assigned' != tckt['status']:
133
- tckt['status'] = 'assigned'
134
- self.save_ticket(tckt, db, 'Automatically accepting in order to start work.')
135
-
136
- # There is a chance the user may be working on another ticket at the moment
137
- # depending on config options
138
- if self.config.getbool('worklog', 'autostopstart'):
139
- # Don't care if this fails, as with these arguments the only failure
140
- # point is if there is no active task... which is the desired scenario :)
141
- self.stop_work()
142
- self.explanation = ''
143
-
144
- cursor = db.cursor()
145
- cursor.execute('INSERT INTO work_log (worker, ticket, lastchange, starttime, endtime) '
146
- 'VALUES (%s, %s, %s, %s, %s)',
147
- (self.authname, ticket, self.now, self.now, 0))
148
- db.commit()
149
- return True
150
-
151
-
152
- def stop_work(self, stoptime=None, comment=''):
153
- active = self.get_active_task()
154
- if not active:
155
- self.explanation = 'You cannot stop working as you appear to be a complete slacker already!'
156
- return False
157
-
158
- if stoptime:
159
- if stoptime <= active['starttime']:
160
- self.explanation = 'You cannot set your stop time to that value as it is before the start time!'
161
- return False
162
- elif stoptime >= self.now:
163
- self.explanation = 'You cannot set your stop time to that value as it is in the future!'
164
- return False
165
- else:
166
- stoptime = self.now - 1
167
-
168
- stoptime = float(stoptime)
169
-
170
- db = self.env.get_db_cnx();
171
- cursor = db.cursor()
172
- cursor.execute('UPDATE work_log '
173
- 'SET endtime=%s, lastchange=%s, comment=%s '
174
- 'WHERE worker=%s AND lastchange=%s AND endtime=0',
175
- (stoptime, stoptime, comment, self.authname, active['lastchange']))
176
- db.commit()
177
-
178
- message = ''
179
- # Leave a comment if the user has configured this or if they have entered
180
- # a work log comment.
181
- if self.config.getbool('worklog', 'comment') or comment:
182
- started = datetime.fromtimestamp(active['starttime'])
183
- finished = datetime.fromtimestamp(stoptime)
184
- message = '%s worked on this ticket for %s between %s %s and %s %s.' % \
185
- (self.authname, pretty_timedelta(started, finished), \
186
- format_date(active['starttime']), format_time(active['starttime']), \
187
- format_date(stoptime), format_time(stoptime))
188
- if comment:
189
- message += "\n[[BR]]\n" + comment
190
-
191
- if self.config.getbool('worklog', 'timingandestimation') and \
192
- self.config.get('ticket-custom', 'hours'):
193
- if not message:
194
- message = 'Hours recorded automatically by the worklog plugin.'
195
-
196
- round_delta = float(self.config.getint('worklog', 'roundup') or 1)
197
-
198
- # Get the delta in minutes
199
- delta = float(int(stoptime) - int(active['starttime'])) / float(60)
200
-
201
- # Round up if needed
202
- delta = int(round((delta / round_delta) + float(0.5))) * int(round_delta)
203
-
204
- db = self.env.get_db_cnx()
205
- tckt = Ticket(self.env, active['ticket'], db)
206
-
207
- # This hideous hack is here because I don't yet know how to do variable-DP rounding in python - sorry!
208
- # It's meant to round to 2 DP, so please replace it if you know how. Many thanks, MK.
209
- tckt['hours'] = str(float(int(100 * float(delta) / 60) / 100.0))
210
- self.save_ticket(tckt, db, message)
211
- message = ''
212
-
213
- if message:
214
- db = self.env.get_db_cnx()
215
- tckt = Ticket(self.env, active['ticket'], db)
216
- self.save_ticket(tckt, db, message)
217
-
218
- return True
219
-
220
-
221
- def who_is_working_on(self, ticket):
222
- db = self.env.get_db_cnx()
223
- cursor = db.cursor()
224
- cursor.execute('SELECT worker,starttime FROM work_log WHERE ticket=%s AND endtime=0', (ticket,))
225
- try:
226
- who,since = cursor.fetchone()
227
- return who,float(since)
228
- except:
229
- pass
230
- return None,None
231
-
232
- def who_last_worked_on(self, ticket):
233
- return "Not implemented"
234
-
235
- def get_latest_task(self):
236
- if self.authname == 'anonymous':
237
- return None
238
-
239
- db = self.env.get_db_cnx()
240
- cursor = db.cursor()
241
- cursor.execute('SELECT MAX(lastchange) FROM work_log WHERE worker=%s', (self.authname,))
242
- row = cursor.fetchone()
243
- if not row or not row[0]:
244
- return None
245
-
246
- lastchange = row[0]
247
-
248
- task = {}
249
- cursor.execute('SELECT wl.worker, wl.ticket, t.summary, wl.lastchange, wl.starttime, wl.endtime, wl.comment '
250
- 'FROM work_log wl '
251
- 'LEFT JOIN ticket t ON wl.ticket=t.id '
252
- 'WHERE wl.worker=%s AND wl.lastchange=%s', (self.authname, lastchange))
253
-
254
- for user,ticket,summary,lastchange,starttime,endtime,comment in cursor:
255
- if not comment:
256
- comment = ''
257
-
258
- task['user'] = user
259
- task['ticket'] = ticket
260
- task['summary'] = summary
261
- task['lastchange'] = float(lastchange)
262
- task['starttime'] = float(starttime)
263
- task['endtime'] = float(endtime)
264
- task['comment'] = comment
265
- return task
266
-
267
- def get_active_task(self):
268
- task = self.get_latest_task()
269
- if not task:
270
- return None
271
- if not task.has_key('endtime'):
272
- return None
273
-
274
- if task['endtime'] > 0:
275
- return None
276
-
277
- return task
278
-
279
- def get_work_log(self, mode='all'):
280
- db = self.env.get_db_cnx()
281
- cursor = db.cursor()
282
- if mode == 'user':
283
- cursor.execute('SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment '
284
- 'FROM work_log wl '
285
- 'INNER JOIN ticket t ON wl.ticket=t.id '
286
- 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' '
287
- 'WHERE wl.worker=%s '
288
- 'ORDER BY wl.lastchange DESC', (self.authname,))
289
- elif mode == 'summary':
290
- cursor.execute('SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment '
291
- 'FROM (SELECT worker,MAX(lastchange) AS lastchange FROM work_log GROUP BY worker) wlt '
292
- 'INNER JOIN work_log wl ON wlt.worker=wl.worker AND wlt.lastchange=wl.lastchange '
293
- 'INNER JOIN ticket t ON wl.ticket=t.id '
294
- 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' '
295
- 'ORDER BY wl.lastchange DESC, wl.worker')
296
- else:
297
- cursor.execute('SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment '
298
- 'FROM work_log wl '
299
- 'INNER JOIN ticket t ON wl.ticket=t.id '
300
- 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' '
301
- 'ORDER BY wl.lastchange DESC, wl.worker')
302
-
303
- rv = []
304
- for user,name,starttime,endtime,ticket,summary,status,comment in cursor:
305
- starttime = float(starttime)
306
- endtime = float(endtime)
307
-
308
- started = datetime.fromtimestamp(starttime)
309
-
310
- dispname = user
311
- if name:
312
- dispname = '%s (%s)' % (name, user)
313
-
314
- if not endtime == 0:
315
- finished = datetime.fromtimestamp(endtime)
316
- delta = 'Worked for %s (between %s %s and %s %s)' % \
317
- (pretty_timedelta(started, finished),
318
- format_date(starttime), format_time(starttime),
319
- format_date(endtime), format_time(endtime))
320
- else:
321
- delta = 'Started %s ago (%s %s)' % \
322
- (pretty_timedelta(started),
323
- format_date(starttime), format_time(starttime))
324
-
325
- rv.append({'user': user,
326
- 'name': name,
327
- 'dispname': dispname,
328
- 'starttime': int(starttime),
329
- 'endtime': int(endtime),
330
- 'delta': delta,
331
- 'ticket': ticket,
332
- 'summary': summary,
333
- 'status': status,
334
- 'comment': comment})
335
- return rv
336
-
@@ -1,598 +0,0 @@
1
- # IF YOU ADD A NEW SECTION OF REPORTS, You will need to make
2
- # sure that section is also added to the all_reports hashtable
3
- # near the bottom
4
-
5
- #Please try to keep this clean"
6
-
7
- billing_reports = [
8
- {
9
- "title":"Ticket Work Summary",
10
- "reportnumber":None,
11
- "version":12,
12
- "sql":"""
13
- SELECT __ticket__ as __group__, __style__, __ticket__,
14
- newvalue as Work_added, author, time, _ord
15
- FROM(
16
- SELECT '' as __style__, author, t.id as __ticket__,
17
- CAST(newvalue as REAL) as newvalue, ticket_change.time as time, 0 as _ord
18
- FROM ticket_change
19
- JOIN ticket t on t.id = ticket_change.ticket
20
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
21
- and billable.name = 'billable'
22
- WHERE field = 'hours' and
23
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
24
- AND billable.value in ($BILLABLE, $UNBILLABLE)
25
- AND ticket_change.time >= $STARTDATE
26
- AND ticket_change.time < $ENDDATE
27
-
28
- UNION
29
-
30
- SELECT 'background-color:#DFE;' as __style__,
31
- 'Total work done on the ticket in the selected time period ' as author,
32
- t.id as __ticket__, sum( CAST(newvalue as real) ) as newvalue,
33
- NULL as time, 1 as _ord
34
- FROM ticket_change
35
- JOIN ticket t on t.id = ticket_change.ticket
36
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
37
- and billable.name = 'billable'
38
- WHERE field = 'hours' and
39
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
40
- AND billable.value in ($BILLABLE, $UNBILLABLE)
41
- AND ticket_change.time >= $STARTDATE
42
- AND ticket_change.time < $ENDDATE
43
- GROUP By t.id
44
- ) as tbl
45
- ORDER BY __ticket__, _ord ASC, time ASC
46
-
47
- """
48
- },#END Ticket work summary
49
- {
50
- "title":"Milestone Work Summary",
51
- "reportnumber":None,
52
- "version":11,
53
- "sql":"""
54
-
55
- SELECT
56
- milestone as __group__, __style__, ticket, summary, newvalue as Work_added,
57
- time, _ord
58
- FROM(
59
- SELECT '' as __style__, t.id as ticket,
60
- SUM(CAST(newvalue as real)) as newvalue, t.summary as summary,
61
- MAX(ticket_change.time) as time, t.milestone as milestone, 0 as _ord
62
- FROM ticket_change
63
- JOIN ticket t on t.id = ticket_change.ticket
64
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
65
- and billable.name = 'billable'
66
- WHERE field = 'hours' and
67
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
68
- AND billable.value in ($BILLABLE, $UNBILLABLE)
69
- AND ticket_change.time >= $STARTDATE
70
- AND ticket_change.time < $ENDDATE
71
- GROUP BY t.milestone, t.id, t.summary
72
-
73
- UNION
74
-
75
- SELECT 'background-color:#DFE;' as __style__, NULL as ticket,
76
- sum(CAST(newvalue as real)) as newvalue, 'Total work done' as summary,
77
- NULL as time, t.milestone as milestone, 1 as _ord
78
- FROM ticket_change
79
- JOIN ticket t on t.id = ticket_change.ticket
80
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
81
- and billable.name = 'billable'
82
- WHERE field = 'hours' and
83
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
84
- AND billable.value in ($BILLABLE, $UNBILLABLE)
85
- AND ticket_change.time >= $STARTDATE
86
- AND ticket_change.time < $ENDDATE
87
- GROUP By t.milestone
88
- ) as tbl
89
- ORDER BY milestone, _ord ASC, ticket, time
90
-
91
-
92
-
93
- """
94
- },#END Milestone work summary
95
-
96
- {
97
- "title":"Developer Work Summary",
98
- "reportnumber":None,
99
- "version":11,
100
- "sql":"""
101
- SELECT author as __group__,__style__, ticket,
102
- newvalue as Work_added, time as time, _ord
103
- FROM(
104
- SELECT '' as __style__, author, cast(t.id as text) as ticket,
105
- CAST(newvalue as REAL) as newvalue, ticket_change.time as time, 0 as _ord
106
- FROM ticket_change
107
- JOIN ticket t on t.id = ticket_change.ticket
108
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
109
- and billable.name = 'billable'
110
- WHERE field = 'hours' and
111
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
112
- AND billable.value in ($BILLABLE, $UNBILLABLE)
113
- AND ticket_change.time >= $STARTDATE
114
- AND ticket_change.time < $ENDDATE
115
-
116
- UNION
117
-
118
- SELECT 'background-color:#DFE;' as __style__, author, NULL as ticket,
119
- sum(CAST(newvalue as real)) as newvalue, NULL as time, 1 as _ord
120
- FROM ticket_change
121
- JOIN ticket t on t.id = ticket_change.ticket
122
- LEFT JOIN ticket_custom as billable on billable.ticket = t.id
123
- and billable.name = 'billable'
124
- WHERE field = 'hours' and
125
- t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
126
- AND billable.value in ($BILLABLE, $UNBILLABLE)
127
- AND ticket_change.time >= $STARTDATE
128
- AND ticket_change.time < $ENDDATE
129
- GROUP By author
130
- ) as tbl
131
- ORDER BY author, _ord ASC, time
132
-
133
- """
134
- },#END Hours Per Developer
135
- ]
136
- ticket_hours_reports = [
137
- {
138
- "title": "Ticket Hours",
139
- "reportnumber": None,
140
- "version":8,
141
- "sql": """
142
- SELECT __color__, __style__, ticket, summary, component ,version, severity,
143
- milestone, status, owner, Estimated_work, Total_work, billable,_ord
144
- FROM (
145
- SELECT p.value AS __color__,
146
- '' as __style__,
147
- t.id AS ticket, summary AS summary, -- ## Break line here
148
- component,version, severity, milestone, status, owner,
149
- CAST(EstimatedHours.value as REAL) as Estimated_work,
150
- CAST(totalhours.value as REAL) as Total_work,
151
- CASE WHEN billable.value = 1 THEN 'Y' else 'N' END as billable,
152
- time AS created, changetime AS modified, -- ## Dates are formatted
153
- description AS _description_, -- ## Uses a full row
154
- changetime AS _changetime,
155
- reporter AS _reporter
156
- ,0 as _ord
157
-
158
- FROM ticket as t
159
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
160
-
161
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
162
- AND EstimatedHours.Ticket = t.Id
163
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
164
- AND totalhours.Ticket = t.Id
165
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
166
- AND billable.Ticket = t.Id
167
-
168
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
169
- AND billable.value in ($BILLABLE, $UNBILLABLE)
170
-
171
-
172
- UNION
173
-
174
- SELECT '1' AS __color__,
175
- 'background-color:#DFE;' as __style__,
176
- NULL as ticket, 'Total' AS summary,
177
- NULL as component,NULL as version, NULL as severity, NULL as milestone, NULL as status, NULL as owner,
178
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
179
- SUM(CAST(totalhours.value as real)) as Total_work,
180
- NULL as billable,
181
- NULL as created, NULL as modified, -- ## Dates are formatted
182
-
183
- NULL AS _description_,
184
- NULL AS _changetime,
185
- NULL AS _reporter
186
- ,1 as _ord
187
- FROM ticket as t
188
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
189
-
190
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
191
- AND EstimatedHours.Ticket = t.Id
192
-
193
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
194
- AND totalhours.Ticket = t.Id
195
-
196
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
197
- AND billable.Ticket = t.Id
198
-
199
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
200
- AND billable.value in ($BILLABLE, $UNBILLABLE)
201
- ) as tbl
202
- ORDER BY _ord ASC, ticket
203
- """
204
- },
205
- #END Ticket Hours
206
- {
207
- "title": "Ticket Hours with Description",
208
- "reportnumber": None,
209
- "version":9,
210
- "sql": """
211
- SELECT __color__, __style__, ticket, summary, component ,version, severity,
212
- milestone, status, owner, Estimated_work, Total_work, billable
213
- --,created, modified, -- ## Dates are formatted
214
- ,_description_
215
- -- _changetime,
216
- -- _reporter
217
- ,_ord
218
-
219
- FROM (
220
- SELECT p.value AS __color__,
221
- '' as __style__,
222
- t.id AS ticket, summary AS summary, -- ## Break line here
223
- component,version, severity, milestone, status, owner,
224
- CAST(EstimatedHours.value as REAL) as Estimated_work,
225
- CAST(totalhours.value as REAL) as Total_work,
226
- CASE WHEN billable.value = 1 THEN 'Y'
227
- else 'N'
228
- END as billable,
229
- time AS created, changetime AS modified, -- ## Dates are formatted
230
- description AS _description_, -- ## Uses a full row
231
- changetime AS _changetime,
232
- reporter AS _reporter
233
- ,0 as _ord
234
-
235
- FROM ticket as t
236
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
237
-
238
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
239
- AND EstimatedHours.Ticket = t.Id
240
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
241
- AND totalhours.Ticket = t.Id
242
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
243
- AND billable.Ticket = t.Id
244
-
245
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
246
- AND billable.value in ($BILLABLE, $UNBILLABLE)
247
-
248
-
249
- UNION
250
-
251
- SELECT '1' AS __color__,
252
- 'background-color:#DFE;' as __style__,
253
- NULL as ticket, 'Total' AS summary,
254
- NULL as component,NULL as version, NULL as severity, NULL as milestone, NULL as status, NULL as owner,
255
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
256
- SUM(CAST(totalhours.value as real)) as Total_work,
257
- NULL as billable,
258
- NULL as created, NULL as modified, -- ## Dates are formatted
259
-
260
- NULL AS _description_,
261
- NULL AS _changetime,
262
- NULL AS _reporter
263
- ,1 as _ord
264
- FROM ticket as t
265
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
266
-
267
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
268
- AND EstimatedHours.Ticket = t.Id
269
-
270
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
271
- AND totalhours.Ticket = t.Id
272
-
273
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
274
- AND billable.Ticket = t.Id
275
-
276
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
277
- AND billable.value in ($BILLABLE, $UNBILLABLE)
278
- ) as tbl
279
- ORDER BY _ord ASC, ticket
280
- """
281
- },
282
- #END Ticket Hours
283
-
284
- {
285
- "title":"Ticket Hours Grouped By Component",
286
- "reportnumber":None,
287
- "version":8,
288
- "sql": """
289
- SELECT __color__, __group__, __style__, ticket, summary, __component__ ,version,
290
- severity, milestone, status, owner, Estimated_work, total_work, billable,
291
- _ord
292
-
293
- FROM (
294
- SELECT p.value AS __color__,
295
- t.component AS __group__,
296
- '' as __style__,
297
- t.id AS ticket, summary AS summary, -- ## Break line here
298
- component as __component__,version, severity, milestone, status, owner,
299
- CAST(EstimatedHours.value as REAL) as Estimated_work,
300
- CAST(totalhours.value as REAL) as Total_work,
301
- CASE WHEN billable.value = 1 THEN 'Y'
302
- else 'N'
303
- END as billable,
304
- time AS created, changetime AS modified, -- ## Dates are formatted
305
- description AS _description_, -- ## Uses a full row
306
- changetime AS _changetime,
307
- reporter AS _reporter
308
- ,0 as _ord
309
-
310
- FROM ticket as t
311
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
312
-
313
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
314
- AND EstimatedHours.Ticket = t.Id
315
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
316
- AND totalhours.Ticket = t.Id
317
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
318
- AND billable.Ticket = t.Id
319
-
320
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
321
- AND billable.value in ($BILLABLE, $UNBILLABLE)
322
-
323
-
324
- UNION
325
-
326
- SELECT '1' AS __color__,
327
- t.component AS __group__,
328
- 'background-color:#DFE;' as __style__,
329
- NULL as ticket, 'Total work' AS summary,
330
- t.component as __component__, NULL as version, NULL as severity,
331
- NULL as milestone, NULL as status,
332
- NULL as owner,
333
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
334
- SUM(CAST(totalhours.value as real)) as Total_work,
335
- NULL as billable,
336
- NULL as created,
337
- NULL as modified, -- ## Dates are formatted
338
-
339
- NULL AS _description_,
340
- NULL AS _changetime,
341
- NULL AS _reporter
342
- ,1 as _ord
343
- FROM ticket as t
344
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
345
-
346
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
347
- AND EstimatedHours.Ticket = t.Id
348
-
349
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
350
- AND totalhours.Ticket = t.Id
351
-
352
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
353
- AND billable.Ticket = t.Id
354
-
355
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
356
- AND billable.value in ($BILLABLE, $UNBILLABLE)
357
- GROUP BY t.component
358
- ) as tbl
359
- ORDER BY __component__, _ord ASC,ticket
360
- """
361
- },
362
- # END Ticket Hours GROUPED BY COMPONENT
363
-
364
- {
365
- "title":"Ticket Hours Grouped By Component with Description",
366
- "reportnumber":None,
367
- "version":7,
368
- "sql": """
369
- SELECT __color__, __group__, __style__, ticket, summary, __component__ ,
370
- version, severity, milestone, status, owner, Estimated_work, Total_work,
371
- billable, _description_, _ord
372
-
373
- FROM (
374
- SELECT p.value AS __color__,
375
- t.component AS __group__,
376
- '' as __style__,
377
- t.id AS ticket, summary AS summary, -- ## Break line here
378
- component as __component__, version, severity, milestone, status, owner,
379
- CAST(EstimatedHours.value as REAL) as Estimated_work,
380
- CAST(totalhours.value as REAL) as Total_work,
381
- CASE WHEN billable.value = 1 THEN 'Y' else 'N' END as billable,
382
- time AS created, changetime AS modified, -- ## Dates are formatted
383
- description AS _description_, -- ## Uses a full row
384
- changetime AS _changetime,
385
- reporter AS _reporter
386
- ,0 as _ord
387
-
388
- FROM ticket as t
389
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
390
-
391
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
392
- AND EstimatedHours.Ticket = t.Id
393
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
394
- AND totalhours.Ticket = t.Id
395
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
396
- AND billable.Ticket = t.Id
397
-
398
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
399
- AND billable.value in ($BILLABLE, $UNBILLABLE)
400
-
401
-
402
- UNION
403
-
404
- SELECT '1' AS __color__,
405
- t.component AS __group__,
406
- 'background-color:#DFE;' as __style__,
407
- NULL as ticket, 'Total work' AS summary,
408
- t.component as __component__, NULL as version, NULL as severity,
409
- NULL as milestone, NULL as status, NULL as owner,
410
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
411
- SUM(CAST(totalhours.value as real)) as Total_work,
412
- NULL as billable,
413
- NULL as created, NULL as modified, -- ## Dates are formatted
414
-
415
- NULL AS _description_,
416
- NULL AS _changetime,
417
- NULL AS _reporter
418
- ,1 as _ord
419
- FROM ticket as t
420
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
421
-
422
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
423
- AND EstimatedHours.Ticket = t.Id
424
-
425
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
426
- AND totalhours.Ticket = t.Id
427
-
428
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
429
- AND billable.Ticket = t.Id
430
-
431
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
432
- AND billable.value in ($BILLABLE, $UNBILLABLE)
433
- GROUP BY t.component
434
- ) as tbl
435
- ORDER BY __component__, _ord ASC, ticket
436
- """
437
- },
438
- # END Ticket Hours Grouped BY Component with Description
439
- {
440
- "title":"Ticket Hours Grouped By Milestone",
441
- "reportnumber":None,
442
- "version":8,
443
- "sql": """
444
- SELECT __color__, __group__, __style__, ticket, summary, component ,version,
445
- severity, __milestone__, status, owner, Estimated_work, Total_work, billable,
446
- _ord
447
-
448
- FROM (
449
- SELECT p.value AS __color__,
450
- t.milestone AS __group__,
451
- '' as __style__,
452
- t.id AS ticket, summary AS summary, -- ## Break line here
453
- component,version, severity, milestone as __milestone__, status, owner,
454
- CAST(EstimatedHours.value as REAL) as Estimated_work,
455
- CAST(totalhours.value as REAL) as Total_work,
456
- CASE WHEN billable.value = 1 THEN 'Y'
457
- else 'N'
458
- END as billable,
459
- time AS created, changetime AS modified, -- ## Dates are formatted
460
- description AS _description_, -- ## Uses a full row
461
- changetime AS _changetime,
462
- reporter AS _reporter, 0 as _ord
463
-
464
- FROM ticket as t
465
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
466
-
467
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
468
- AND EstimatedHours.Ticket = t.Id
469
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
470
- AND totalhours.Ticket = t.Id
471
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
472
- AND billable.Ticket = t.Id
473
-
474
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
475
- AND billable.value in ($BILLABLE, $UNBILLABLE)
476
-
477
-
478
- UNION
479
-
480
- SELECT '1' AS __color__,
481
- t.milestone AS __group__,
482
- 'background-color:#DFE;' as __style__,
483
- NULL as ticket, 'Total work' AS summary,
484
- NULL as component,NULL as version, NULL as severity,
485
- t.milestone as __milestone__, NULL as status, NULL as owner,
486
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
487
- SUM(CAST(totalhours.value as real)) as Total_work,
488
- NULL as billable,
489
- NULL as created, NULL as modified, -- ## Dates are formatted
490
-
491
- NULL AS _description_,
492
- NULL AS _changetime,
493
- NULL AS _reporter
494
- ,1 as _ord
495
- FROM ticket as t
496
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
497
-
498
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
499
- AND EstimatedHours.Ticket = t.Id
500
-
501
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
502
- AND totalhours.Ticket = t.Id
503
-
504
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
505
- AND billable.Ticket = t.Id
506
-
507
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
508
- AND billable.value in ($BILLABLE, $UNBILLABLE)
509
- GROUP BY t.milestone
510
- ) as tbl
511
- ORDER BY __milestone__, _ord ASC, ticket
512
- """
513
- },
514
- #END Ticket Hours Grouped By MileStone
515
- {
516
- "title":"Ticket Hours Grouped By MileStone with Description",
517
- "reportnumber":None,
518
- "version":8,
519
- "sql": """
520
- SELECT __color__, __group__, __style__, ticket, summary, component ,version, severity,
521
- __milestone__, status, owner, Estimated_work, Total_work, billable,
522
- _description_, _ord
523
-
524
- FROM (
525
- SELECT p.value AS __color__,
526
- t.milestone AS __group__,
527
- '' as __style__,
528
- t.id AS ticket, summary AS summary, -- ## Break line here
529
- component,version, severity, milestone as __milestone__, status, owner,
530
- CAST(EstimatedHours.value as REAL) as Estimated_work,
531
- CAST(totalhours.value as REAL) as Total_work,
532
- CASE WHEN billable.value = 1 THEN 'Y'
533
- else 'N'
534
- END as billable,
535
- time AS created, changetime AS modified, -- ## Dates are formatted
536
- description AS _description_, -- ## Uses a full row
537
- changetime AS _changetime,
538
- reporter AS _reporter
539
- ,0 as _ord
540
-
541
- FROM ticket as t
542
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
543
-
544
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
545
- AND EstimatedHours.Ticket = t.Id
546
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
547
- AND totalhours.Ticket = t.Id
548
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
549
- AND billable.Ticket = t.Id
550
-
551
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
552
- AND billable.value in ($BILLABLE, $UNBILLABLE)
553
-
554
-
555
- UNION
556
-
557
- SELECT '1' AS __color__,
558
- t.milestone AS __group__,
559
- 'background-color:#DFE;' as __style__,
560
- NULL as ticket, 'Total work' AS summary,
561
- NULL as component,NULL as version, NULL as severity,
562
- t.milestone as __milestone__,
563
- NULL as status, NULL as owner,
564
- SUM(CAST(EstimatedHours.value as real)) as Estimated_work,
565
- SUM(CAST(totalhours.value as real)) as Total_work,
566
- NULL as billable,
567
- NULL as created, NULL as modified, -- ## Dates are formatted
568
- NULL AS _description_,
569
- NULL AS _changetime,
570
- NULL AS _reporter, 1 as _ord
571
- FROM ticket as t
572
- JOIN enum as p ON p.name=t.priority AND p.type='priority'
573
-
574
- LEFT JOIN ticket_custom as EstimatedHours ON EstimatedHours.name='estimatedhours'
575
- AND EstimatedHours.Ticket = t.Id
576
-
577
- LEFT JOIN ticket_custom as totalhours ON totalhours.name='totalhours'
578
- AND totalhours.Ticket = t.Id
579
-
580
- LEFT JOIN ticket_custom as billable ON billable.name='billable'
581
- AND billable.Ticket = t.Id
582
-
583
- WHERE t.status IN ($NEW, $ASSIGNED, $REOPENED, $CLOSED)
584
- AND billable.value in ($BILLABLE, $UNBILLABLE)
585
- GROUP BY t.milestone
586
- ) as tbl
587
- ORDER BY __milestone__, _ord ASC, ticket
588
- """
589
- }
590
- #END Ticket Hours Grouped By MileStone with Description
591
- ]
592
-
593
- all_reports = [
594
- {"title":"Billing Reports",
595
- "reports":billing_reports},
596
- {"title":"Ticket/Hour Reports",
597
- "reports": ticket_hours_reports}
598
- ]