RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / part_export / sql_Common.pm
1 package FS::part_export::sql_Common;
2 use base qw( FS::part_export );
3
4 use strict;
5 use Tie::IxHash;
6 use FS::DBI;
7
8 tie my %options, 'Tie::IxHash',
9   'datasrc'            => { label => 'DBI data source' },
10   'username'           => { label => 'Database username' },
11   'password'           => { label => 'Database password' },
12   'table'              => { label => 'Database table' },
13   'schema'             => { label =>
14                               'Database schema mapping to Freeside methods.',
15                             type  => 'textarea',
16                           },
17   'static'             => { label =>
18                               'Database schema mapping to static values.',
19                             type  => 'textarea',
20                           },
21   'primary_key'        => { label => 'Database primary key' },
22 ;
23
24 sub sql_options {
25   \%options;
26 }
27 sub _schema_map { shift->_map('schema'); }
28 sub _static_map { shift->_map('static'); }
29
30 sub _map {
31   my $self = shift;
32   map { /^\s*(\S+)\s*(\S+)\s*$/ } split("\n", $self->option(shift) );
33 }
34
35 sub _map_arg_callback {
36   ();
37 }
38
39 sub rebless { shift; }
40
41 sub _export_insert {
42   my($self, $svc_x) = (shift, shift);
43
44   my %schema = $self->_schema_map;
45   my %static = $self->_static_map;
46
47   my %record = (
48
49     ( map { $_ => $static{$_} } keys %static ),
50   
51     ( map { my $value = $schema{$_};
52             my @arg = $self->_map_arg_callback($value);
53             $_ => $svc_x->$value(@arg);
54           } keys %schema
55     ),
56
57   );
58
59   my $err_or_queue =
60     $self->sql_Common_queue(
61       $svc_x->svcnum,
62       'insert',
63       $self->option('table'),
64       %record
65     );
66   return $err_or_queue unless ref($err_or_queue);
67
68   '';
69
70 }
71
72 sub _export_replace {
73   my($self, $new, $old) = (shift, shift, shift);
74
75   my %schema = $self->_schema_map;
76   my %static = $self->_static_map;
77
78   my @primary_key = ();
79   if ( $self->option('primary_key') =~ /,/ ) {
80     foreach my $key ( split(/\s*,\s*/, $self->option('primary_key') ) ) {
81       my $keymap = $schema{$key};
82       push @primary_key, $old->$keymap();
83     }
84   } else {
85     my $keymap = $schema{$self->option('primary_key')};
86     push @primary_key, $old->$keymap();
87   }
88
89   my %record = (
90
91     ( map { $_ => $static{$_} } keys %static ),
92   
93     ( map { my $value = $schema{$_};
94             my @arg = $self->_map_arg_callback($value);
95             $_ => $new->$value(@arg);
96           } keys %schema
97     ),
98
99   );
100
101   my $err_or_queue = $self->sql_Common_queue(
102     $new->svcnum,
103     'replace',
104     $self->option('table'),
105     $self->option('primary_key'), @primary_key, 
106     %record,
107   );
108   return $err_or_queue unless ref($err_or_queue);
109   '';
110 }
111
112 sub _export_delete {
113   my ( $self, $svc_x ) = (shift, shift);
114
115   my %schema = $self->_schema_map;
116
117   my %primary_key = ();
118   if ( $self->option('primary_key') =~ /,/ ) {
119     foreach my $key ( split(/\s*,\s*/, $self->option('primary_key') ) ) {
120       my $keymap = $schema{$key};
121       $primary_key{ $key } = $svc_x->$keymap();
122     }
123   } else {
124     my $keymap = $schema{$self->option('primary_key')};
125     $primary_key{ $self->option('primary_key') } = $svc_x->$keymap(),
126   }
127
128   my $err_or_queue = $self->sql_Common_queue(
129     $svc_x->svcnum,
130     'delete',
131     $self->option('table'),
132     %primary_key,
133     #$self->option('primary_key') => $svc_x->$keymap(),
134   );
135   return $err_or_queue unless ref($err_or_queue);
136   '';
137 }
138
139 sub sql_Common_queue {
140   my( $self, $svcnum, $method ) = (shift, shift, shift);
141   my $queue = new FS::queue {
142     'svcnum' => $svcnum,
143     'job'    => "FS::part_export::sql_Common::sql_Common_$method",
144   };
145   $queue->insert(
146     $self->option('datasrc'),
147     $self->option('username'),
148     $self->option('password'),
149     @_,
150   ) or $queue;
151 }
152
153 sub sql_Common_insert { #subroutine, not method
154   my $dbh = sql_Common_connect(shift, shift, shift);
155   my( $table, %record ) = @_;
156
157   my $sth = $dbh->prepare(
158     "INSERT INTO $table ( ". join(", ", keys %record).
159     " ) VALUES ( ". join(", ", map '?', keys %record ). " )"
160   ) or die $dbh->errstr;
161
162   $sth->execute( values(%record) )
163     or die "can't insert into $table table: ". $sth->errstr;
164
165   $dbh->disconnect;
166 }
167
168 sub sql_Common_delete { #subroutine, not method
169   my $dbh = sql_Common_connect(shift, shift, shift);
170   my( $table, %record ) = @_;
171
172   my $sth = $dbh->prepare(
173     "DELETE FROM $table WHERE ". join(' AND ', map "$_ = ? ", keys %record )
174   ) or die $dbh->errstr;
175
176   $sth->execute( map $record{$_}, keys %record )
177     or die "can't delete from $table table: ". $sth->errstr;
178
179   $dbh->disconnect;
180 }
181
182 sub sql_Common_replace { #subroutine, not method
183   my $dbh = sql_Common_connect(shift, shift, shift);
184
185   my( $table, $pkey ) = ( shift, shift );
186
187   my %primary_key = ();
188   if ( $pkey =~ /,/ ) {
189     foreach my $key ( split(/\s*,\s*/, $pkey ) ) {
190       $primary_key{$key} = shift;
191     }
192   } else {
193     $primary_key{$pkey} = shift;
194   }
195
196   my %record = @_;
197
198   my $sth = $dbh->prepare(
199     "UPDATE $table".
200     ' SET '.   join(', ',    map "$_ = ?", keys %record      ).
201     ' WHERE '. join(' AND ', map "$_ = ?", keys %primary_key )
202   ) or die $dbh->errstr;
203
204   $sth->execute( values(%record), values(%primary_key) );
205
206   $dbh->disconnect;
207 }
208
209 sub sql_Common_connect {
210   #my($datasrc, $username, $password) = @_;
211   #DBI->connect($datasrc, $username, $password) or die $DBI::errstr;
212   FS::DBI->connect(@_) or die $FS::DBI::errstr;
213 }
214
215 1;
216