Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 6c44a351

Von Moritz Bunkus vor mehr als 5 Jahren hinzugefügt

  • ID 6c44a351d95cf1bcfa2a9f614382b818f581b1f6
  • Vorgänger ffda56c8
  • Nachfolger 2be804b9

API für Telefonnummernrückwärtssuche

Unterschiede anzeigen:

SL/Controller/PhoneNumber.pm
1
package SL::Controller::PhoneNumber;
2

  
3
use utf8;
4
use strict;
5
use parent qw(SL::Controller::Base);
6

  
7
use List::MoreUtils qw(any);
8
use List::Util qw(first);
9

  
10
use SL::JSON;
11
use SL::DBUtils;
12
use SL::Locale::String;
13
use SL::CTI;
14

  
15
use SL::DB::Contact;
16
use SL::DB::Customer;
17
use SL::DB::Vendor;
18

  
19
use Data::Dumper;
20

  
21
sub action_look_up {
22
  my ($self) = @_;
23

  
24
  my $number = $self->normalize_number($::form->{number} // '');
25

  
26
  return $self->render(\to_json({}), { type => 'json', process => 0 }) if ($number eq '');
27

  
28
  my $result = $self->find_contact_for_number($number)
29
    //         $self->find_customer_vendor_for_number($number)
30
    //         {};
31

  
32
  $self->render(\to_json($result), { type => 'json', process => 0 });
33
}
34

  
35
sub find_contact_for_number {
36
  my ($self, $number) = @_;
37

  
38
  my @number_fields = qw(cp_phone1 cp_phone2 cp_mobile1 cp_mobile2 cp_fax);
39

  
40
  my $contacts = SL::DB::Manager::Contact->get_all(
41
    inject_results => 1,
42
    where          => [ map({ (or => [ "!$_" => undef, "!$_"  => "" ],) } @number_fields) ],
43
  );
44

  
45
  my @hits;
46

  
47
  foreach my $contact (@{ $contacts }) {
48
    foreach my $field (@number_fields) {
49
      next if $self->normalize_number($contact->$field) ne $number;
50

  
51
      push @hits, $contact;
52
      last;
53
    }
54
  }
55

  
56
  return if !@hits;
57

  
58
  my @cv_ids = grep { $_ } map { $_->cp_cv_id } @hits;
59

  
60
  my %customers_vendors =
61
    map { ($_->id => $_) } (
62
      @{ SL::DB::Manager::Customer->get_all(where => [ id => \@cv_ids ], inject_results => 1) },
63
      @{ SL::DB::Manager::Vendor  ->get_all(where => [ id => \@cv_ids ], inject_results => 1) },
64
    );
65

  
66
  my $chosen = first {
67
       $_->cp_cv_id
68
    &&  $customers_vendors{$_->cp_cv_id}
69
    && !$customers_vendors{$_->cp_cv_id}->obsolete
70
    && ($_->cp_name !~ m{ungültig}i)
71
  } @hits;
72

  
73
  $chosen //= $hits[0];
74

  
75
  return {
76
    full_name => join(' ', grep { $_ ne '' } map { $_ // '' } ($chosen->cp_title, $chosen->cp_givenname, $chosen->cp_name)),
77
    map({ my $method = "cp_$_"; ($_ => $chosen->$method // '') } qw(title givenname name phone1 phone2 mobile1 mobile2 fax)),
78
  };
79
}
80

  
81
sub find_customer_vendor_for_number {
82
  my ($self, $number) = @_;
83

  
84
  my @number_fields = qw(phone fax);
85

  
86
  my @customers_vendors = map {
87
      my $class = "SL::DB::Manager::$_";
88
      @{ $class->get_all(
89
           inject_results => 1,
90
           where          => [ map({ (or => [ "!$_" => undef, "!$_"  => "" ],) } @number_fields) ],
91
         ) }
92
    } qw(Customer Vendor);
93

  
94
  my @hits;
95

  
96
  foreach my $customer_vendor (@customers_vendors) {
97
    foreach my $field (@number_fields) {
98
      next if $self->normalize_number($customer_vendor->$field) ne $number;
99

  
100
      push @hits, $customer_vendor;
101
      last;
102
    }
103
  }
104

  
105
  return if !@hits;
106

  
107
  my $chosen = first { !$_->obsolete } @hits;
108
  $chosen  //= $hits[0];
109

  
110
  return {
111
    full_name => $chosen->name  // '',
112
    phone1    => $chosen->phone // '',
113
    fax       => $chosen->fax   // '',
114
    map({ ($_ => '') } qw(title givenname name phone2 mobile1 mobile2)),
115
  };
116
}
117

  
118
sub normalize_number {
119
  my ($self, $number) = @_;
120

  
121
  return '' if ($number // '') eq '';
122

  
123
  my $config       = $::lx_office_conf{cti} || {};
124
  my $idp          = $config->{international_dialing_prefix} // '00';
125
  my $country_code = $config->{our_country_code}             // '49';
126

  
127
  $number          = SL::CTI->sanitize_number(number => $number);
128

  
129
  return $number if $number =~ m{^$idp};
130

  
131
  $number =~ s{^0+}{};
132

  
133
  return $idp . $country_code . $number;
134
}
135

  
136
1;
137

  
138
__END__
139

  
140
=pod
141

  
142
=encoding utf8
143

  
144
=head1 NAME
145

  
146
SL::Controller::Contact - Looking up information on contacts/customers/vendors based on a phone number
147

  
148
=head1 FUNCTIONS
149

  
150
=over 4
151

  
152
=item C<action_look_up>
153

  
154
This action can be used by external systems such as PBXes in order to
155
match a calling number to a name. Requires one form parameter to be
156
passed, C<number>.
157

  
158
The number will then be normalized. This requires that the
159
international dialing prefix and the server's own country code be set
160
up in C<kivitendo.conf>, section C<[cti]>. They default to C<00> and
161
C<49> (Germany) respectively.
162

  
163
Next the function will look up a contact whose normalized numbers
164
equals the requested number. The fields C<phone1>, C<phone2>,
165
C<mobile1>, C<mobile2> and C<fax> are considered. Active contacts are
166
given preference over inactive ones (inactive meaning that they don't
167
belong to a customer/vendor anymore or that the customer/vendor itself
168
is flagged as obsolete).
169

  
170
If no contact is found, customers & vendors are searched. Their fields
171
C<phone> and C<fax> are considered. The first customer/vendor who
172
isn't flagged as being obsolete is chosen; if there's none, the first
173
obsolete one is.
174

  
175
The function always sends one JSON-encoded object. If there's no hit
176
for the number, an empty object is returned. Otherwise the following
177
fields are present:
178

  
179
=over 4
180

  
181
=item C<full_name> — for contacts this is the concatenation of the
182
title, given name and family name; for customers/vendors it's the
183
company name
184

  
185
=item C<title> — title (empty for customers/vendors)
186

  
187
=item C<givenname> — first/given name (empty for customers/vendors)
188

  
189
=item C<name> — last/family name (empty for customers/vendors)
190

  
191
=item C<phone1> — first phone number (for all object types)
192

  
193
=item C<phone2> — second phone number (empty for customers/vendors)
194

  
195
=item C<mobile1> — first mobile number (empty for customers/vendors)
196

  
197
=item C<mobile2> — second mobile number (empty for customers/vendors)
198

  
199
=item C<fax> — fax number (for all object types)
200

  
201
=back
202

  
203
Here's an example how querying the API via C<curl> might look:
204

  
205
    curl --user user_name:password 'https://…/kivitendo/controller.pl?action=PhoneNumber/look_up&number=0049987655443321'
206

  
207
Note that the request must be authenticated via a valid Kivitendo
208
login. However, the user doesn't need any special permissions within
209
Kivitendo; any valid Kivitendo user will do.
210

  
211
=back
212

  
213
=head1 BUGS
214

  
215
Nothing here yet.
216

  
217
=head1 AUTHOR
218

  
219
Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
220

  
221
=cut
config/kivitendo.conf.default
370 370
external_prefix = 0
371 371
# The prefix for international calls (numbers starting with +).
372 372
international_dialing_prefix = 00
373
# Our own country code
374
our_country_code = 49

Auch abrufbar als: Unified diff