fix capitalization of RT tables and columns - mysql fix
[freeside.git] / FS / FS / TicketSystem / RT_Internal.pm
1 package FS::TicketSystem::RT_Internal;
2
3 use strict;
4 use vars qw( @ISA $DEBUG $me );
5 use Data::Dumper;
6 use MIME::Entity;
7 use FS::UID qw(dbh);
8 use FS::CGI qw(popurl);
9 use FS::TicketSystem::RT_Libs;
10 use RT::CurrentUser;
11
12 @ISA = qw( FS::TicketSystem::RT_Libs );
13
14 $DEBUG = 0;
15 $me = '[FS::TicketSystem::RT_Internal]';
16
17 sub sql_num_customer_tickets {
18   "( select count(*) from Tickets
19                      join Links on ( Tickets.id = Links.LocalBase )
20      where ( Status = 'new' or Status = 'open' or Status = 'stalled' )
21        and Target = 'freeside://freeside/cust_main/' || custnum
22    )";
23 }
24
25 sub baseurl {
26   #my $self = shift;
27   if ( $RT::URI::freeside::URL ) {
28     $RT::URI::freeside::URL. '/rt/';
29   } else {
30     'http://you_need_to_set_RT_URI_freeside_URL_in_SiteConfig.pm/';
31   }
32 }
33
34 #mapping/genericize??
35 #ShowConfigTab ModifySelf
36 sub access_right {
37   my( $self, $session, $right ) = @_;
38
39   #return '' unless $conf->config('ticket_system');
40   return '' unless FS::Conf->new->config('ticket_system');
41
42   $session = $self->session($session);
43
44   $session->{'CurrentUser'}->HasRight( Right  => $right,
45                                        Object => $RT::System );
46 }
47
48 sub session {
49   my( $self, $session ) = @_;
50
51   if ( $session && $session->{'Current_User'} ) {
52     warn "$me session: using existing session and CurrentUser: \n".
53          Dumper($session->{'CurrentUser'})
54       if $DEBUG;
55  } else {
56     warn "$me session: loading session and CurrentUser\n" if $DEBUG > 1;
57     $session = $self->_web_external_auth($session);
58   }
59
60   $session;
61 }
62
63 sub init {
64   my $self = shift;
65
66   warn "$me init: loading RT libraries\n" if $DEBUG;
67   eval '
68     use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" );
69     use RT;
70     #it looks like the rest are taken care of these days in RT::InitClasses
71     #use RT::Ticket;
72     #use RT::Transactions;
73     #use RT::Users;
74     #use RT::CurrentUser;
75     #use RT::Templates;
76     #use RT::Queues;
77     #use RT::ScripActions;
78     #use RT::ScripConditions;
79     #use RT::Scrips;
80     #use RT::Groups;
81     #use RT::GroupMembers;
82     #use RT::CustomFields;
83     #use RT::CustomFieldValues;
84     #use RT::ObjectCustomFieldValues;
85
86     #for web external auth...
87     use RT::Interface::Web;
88   ';
89   die $@ if $@;
90
91   warn "$me init: loading RT config\n" if $DEBUG;
92   {
93     local $SIG{__DIE__};
94     eval 'RT::LoadConfig();';
95   }
96   die $@ if $@;
97
98   warn "$me init: initializing RT\n" if $DEBUG;
99   {
100     local $SIG{__DIE__};
101     eval 'RT::Init("NoSignalHandlers"=>1);';
102   }
103   die $@ if $@;
104
105   warn "$me init: complete" if $DEBUG;
106 }
107
108 =item create_ticket SESSION_HASHREF, OPTION => VALUE ...
109
110 Class method.  Creates a ticket.  If there is an error, returns the scalar
111 error, otherwise returns the newly created RT::Ticket object.
112
113 Accepts the following options:
114
115 =over 4
116
117 =item queue
118
119 Queue name or Id
120
121 =item subject
122
123 Ticket subject
124
125 =item requestor
126
127 Requestor email address or arrayref of addresses
128
129 =item cc
130
131 Cc: email address or arrayref of addresses
132
133 =item message
134
135 Ticket message
136
137 =item mime_type
138
139 MIME type to use for message.  Defaults to text/plain.  Specifying text/html
140 can be useful to use HTML markup in message.
141
142 =item custnum
143
144 Customer number (see L<FS::cust_main>) to associate with ticket.
145
146 =item svcnum
147
148 Service number (see L<FS::cust_svc>) to associate with ticket.  Will also
149 associate the customer who has this service (unless the service is unlinked).
150
151 =back
152
153 =cut
154
155 sub create_ticket {
156   my($self, $session, %param) = @_;
157
158   $session = $self->session($session);
159
160   my $Queue = RT::Queue->new($session->{'CurrentUser'});
161   $Queue->Load( $param{'queue'} );
162
163   my $req = ref($param{'requestor'})
164               ? $param{'requestor'}
165               : ( $param{'requestor'} ? [ $param{'requestor'} ] : [] );
166
167   my $cc = ref($param{'cc'})
168              ? $param{'cc'}
169              : ( $param{'cc'} ? [ $param{'cc'} ] : [] );
170
171   my $mimeobj = MIME::Entity->build(
172     'Data' => $param{'message'},
173     'Type' => ( $param{'mime_type'} || 'text/plain' ),
174   );
175
176   my %ticket = (
177     'Queue'     => $Queue->Id,
178     'Subject'   => $param{'subject'},
179     'Requestor' => $req,
180     'Cc'        => $cc,
181     'MIMEObj'   => $mimeobj,
182   );
183   warn Dumper(\%ticket) if $DEBUG > 1;
184
185   my $Ticket = RT::Ticket->new($session->{'CurrentUser'});
186   my( $id, $Transaction, $ErrStr );
187   {
188     local $SIG{__DIE__};
189     ( $id, $Transaction, $ErrStr ) = $Ticket->Create( %ticket );
190   }
191   return $ErrStr if $id == 0;
192
193   warn "ticket got id $id\n" if $DEBUG;
194
195   #XXX check errors adding custnum/svcnum links (put it in a transaction)...
196   # but we do already know they're good
197
198   if ( $param{'custnum'} ) {
199     my( $val, $msg ) = $Ticket->_AddLink(
200      'Type'   => 'MemberOf',
201      'Target' => 'freeside://freeside/cust_main/'. $param{'custnum'},
202     );
203   }
204
205   if ( $param{'svcnum'} ) {
206     my( $val, $msg ) = $Ticket->_AddLink(
207      'Type'   => 'MemberOf',
208      'Target' => 'freeside://freeside/cust_svc/'. $param{'svcnum'},
209     );
210   }
211
212   $Ticket;
213 }
214
215 #shameless false laziness w/rt/html/autohandler to get logged into RT from afar
216 sub _web_external_auth {
217   my( $self, $session ) = @_;
218
219   my $user = $FS::CurrentUser::CurrentUser->username;
220
221   $session ||= {};
222   $session->{'CurrentUser'} = RT::CurrentUser->new();
223
224   warn "$me _web_external_auth loading RT user for $user\n"
225     if $DEBUG > 1;
226
227   $session->{'CurrentUser'}->Load($user);
228
229   if ( ! $session->{'CurrentUser'}->Id() ) {
230
231       # Create users on-the-fly
232
233       warn "can't load RT user for $user; auto-creating\n"
234         if $DEBUG;
235
236       my $UserObj = RT::User->new( RT::CurrentUser->new('RT_System') );
237
238       my ( $val, $msg ) = $UserObj->Create(
239           %{ ref($RT::AutoCreate) ? $RT::AutoCreate : {} },
240           Name  => $user,
241           Gecos => $user,
242       );
243
244       if ($val) {
245
246           # now get user specific information, to better create our user.
247           my $new_user_info
248               = RT::Interface::Web::WebExternalAutoInfo($user);
249
250           # set the attributes that have been defined.
251           # FIXME: this is a horrible kludge. I'm sure there's something cleaner
252           foreach my $attribute (
253               'Name',                  'Comments',
254               'Signature',             'EmailAddress',
255               'PagerEmailAddress',     'FreeformContactInfo',
256               'Organization',          'Disabled',
257               'Privileged',            'RealName',
258               'NickName',              'Lang',
259               'EmailEncoding',         'WebEncoding',
260               'ExternalContactInfoId', 'ContactInfoSystem',
261               'ExternalAuthId',        'Gecos',
262               'HomePhone',             'WorkPhone',
263               'MobilePhone',           'PagerPhone',
264               'Address1',              'Address2',
265               'City',                  'State',
266               'Zip',                   'Country'
267               )
268           {
269               #uhh, wrong root
270               #$m->comp( '/Elements/Callback', %ARGS,
271               #    _CallbackName => 'NewUser' );
272
273               my $method = "Set$attribute";
274               $UserObj->$method( $new_user_info->{$attribute} )
275                   if ( defined $new_user_info->{$attribute} );
276           }
277           $session->{'CurrentUser'}->Load($user);
278       }
279       else {
280
281          # we failed to successfully create the user. abort abort abort.
282           delete $session->{'CurrentUser'};
283
284           die "can't auto-create RT user"; #an error message would be nice :/
285           #$m->abort() unless $RT::WebFallbackToInternalAuth;
286           #$m->comp( '/Elements/Login', %ARGS,
287           #    Error => loc( 'Cannot create user: [_1]', $msg ) );
288       }
289   }
290
291   unless ( $session->{'CurrentUser'}->Id() ) {
292       delete $session->{'CurrentUser'};
293
294       die "can't auto-create RT user";
295       #$user = $orig_user;
296       # 
297       #if ($RT::WebExternalOnly) {
298       #    $m->comp( '/Elements/Login', %ARGS,
299       #        Error => loc('You are not an authorized user') );
300       #    $m->abort();
301       #}
302   }
303
304   $session;
305
306 }
307
308 1;
309