6 use FS::Record qw(qsearchs qsearch dbh);
14 $FS::UID::AutoCommit = 0;
17 my $file = shift or usage();
18 open my $in, '<', $file or die "$file: $!\n";
19 my $csv = Text::CSV->new({ binary => 1, auto_diag => 2 });
21 $csv->column_names($csv->getline($in));
26 # default is to charge per second; edit this if needed
28 while (my $row = $csv->getline_hr($in)) {
31 # ProfileKey is just a number
32 my $rate = qsearchs('rate', { 'ratename' => $row->{'ProfileKey'} });
34 $rate = FS::rate->new({ 'ratename' => $row->{'ProfileKey'} });
35 $error = $rate->insert;
39 # DestinationId looks like "Country - City" or "Country - Mobile -
40 # Carrier" (or sometimes just "Country - Mobile").
41 my $region = qsearchs('rate_region', {
42 'regionname' => $row->{'DestinationId'}
45 $region = FS::rate_region->new({
46 'regionname' => $row->{'DestinationId'}
48 $error = $region->insert;
52 # Prefix strings found in there look like
53 # "e164:123-45-6nnnnnnn-"
54 # The first group of digits is the country code, any others are the
55 # prefix. Sometimes the nnnn's are NNNN's. The dashes are not guaranteed
56 # to be anywhere specific.
57 # Catchall prefixes start with "-A", which has a meaning like "match
58 # anything, but at a lower priority than a digit match".
59 # NANPA numbers use "1-", and for a catchall area code use "1-AAA-".
60 my $cc_long = $row->{CountryCodeLong};
61 $cc_long =~ /^e164:(\d+)-([\d-]*)A*-?n+-$/i;
63 if (!$countrycode) { # totally legit reasons for this, e.g. 1-AAA-411
64 warn "can't parse number prefix:\n$cc_long\n";
71 'regionnum' => $region->regionnum,
72 'countrycode' => $countrycode,
75 my $rate_prefix = qsearchs('rate_prefix', \%prefix);
77 $rate_prefix = FS::rate_prefix->new(\%prefix);
78 $error = $rate_prefix->insert;
82 # enough to identify the detail
84 'ratenum' => $rate->ratenum,
85 'dest_regionnum' => $region->regionnum,
89 my $dest_detail = qsearchs('rate_detail', \%detail);
90 # ProfileRate is 5 decimal places, same as rate_detail.min_charge
92 $dest_detail = FS::rate_detail->new({
95 'min_charge' => $row->{ProfileRate},
96 'sec_granularity' => $granularity,
98 $error = $dest_detail->insert;
100 local $FS::Record::nowarn_identical = 1;
101 $dest_detail->set('min_charge' => $row->{ProfileRate});
102 $error = $dest_detail->replace;
104 die $error if $error;
111 die "Usage: rate-intl.import <user> <file>.csv\n\n";