summaryrefslogtreecommitdiff
path: root/FS/FS/part_export/batch_Common.pm
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2014-06-26 15:47:22 -0700
committerMark Wells <mark@freeside.biz>2014-06-26 16:04:51 -0700
commitfa978560e3b0473728ebf2fb32625765465c230a (patch)
tree07f90f1a1980f0f1fee00ad736a4b1adb5ca723e /FS/FS/part_export/batch_Common.pm
parent3e3441036353ea99dc85548bbdbe810edc81b181 (diff)
NENA2 E911 export and batch-oriented exports in general, #14049
Diffstat (limited to 'FS/FS/part_export/batch_Common.pm')
-rw-r--r--FS/FS/part_export/batch_Common.pm202
1 files changed, 202 insertions, 0 deletions
diff --git a/FS/FS/part_export/batch_Common.pm b/FS/FS/part_export/batch_Common.pm
new file mode 100644
index 0000000..f489497
--- /dev/null
+++ b/FS/FS/part_export/batch_Common.pm
@@ -0,0 +1,202 @@
+package FS::part_export::batch_Common;
+
+use strict;
+use base 'FS::part_export';
+use FS::Record qw(qsearch qsearchs);
+use FS::export_batch;
+use FS::export_batch_item;
+use Storable qw(nfreeze thaw);
+use MIME::Base64 qw(encode_base64 decode_base64);
+
+=head1 DESCRIPTION
+
+FS::part_export::batch_Common should be inherited by any export that stores
+pending service changes and processes them all at once. It provides the
+external interface, and has an internal interface that the subclass must
+implement.
+
+=head1 INTERFACE
+
+ACTION in all of these methods is one of 'insert', 'delete', 'replace',
+'suspend', 'unsuspend', 'pkg_change', or 'relocate'.
+
+ARGUMENTS is the arguments to the export_* method:
+
+- for insert, the new service
+
+- for suspend, unsuspend, or delete, the service to act on
+
+- for replace, the new service, followed by the old service
+
+- for pkg_change, the service, followed by the new and old packages
+ (as L<FS::cust_pkg> objects)
+
+- for relocate, the service, followed by the new location and old location
+ (as L<FS::cust_location> objects)
+
+=over 4
+
+=item immediate ACTION, ARGUMENTS
+
+This is called immediately from the export_* method, and does anything
+that needs to happen right then, except for inserting the
+L<FS::export_batch_item> record. Optional. If it exists, it can return
+a non-empty error string to cause the export to fail.
+
+=item data ACTION, ARGUMENTS
+
+This is called just before inserting the batch item, and returns a scalar
+to store in the item's C<data> field. If the export needs to remember
+anything about the service for the later batch-processing stage, it goes
+here. Remember that if the service is being deleted, the export will need
+to remember enough information to unprovision it when it's no longer in the
+database.
+
+If this returns a reference, it will be frozen down with Base64-Storable.
+
+=item process BATCH
+
+This is called from freeside-daily, once for each batch still in the 'open'
+or 'closed' state. It's expected to do whatever needs to be done with the
+batch, and report failure via die().
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=cut
+
+sub export_insert {
+ my $self = shift;
+ my $svc = shift;
+
+ $self->immediate('insert', $svc) || $self->create_item('insert', $svc);
+}
+
+sub export_delete {
+ my $self = shift;
+ my $svc = shift;
+
+ $self->immediate('delete', $svc) || $self->create_item('delete', $svc);
+}
+
+sub export_suspend {
+ my $self = shift;
+ my $svc = shift;
+
+ $self->immediate('suspend', $svc) || $self->create_item('suspend', $svc);
+}
+
+sub export_unsuspend {
+ my $self = shift;
+ my $svc = shift;
+
+ $self->immediate('unsuspend', $svc) || $self->create_item('unsuspend', $svc);
+}
+
+sub export_replace {
+ my $self = shift;
+ my $new = shift;
+ my $old = shift;
+
+ $self->immediate('replace', $new, $old)
+ || $self->create_item('replace', $new, $old)
+}
+
+sub export_relocate {
+ my $self = shift;
+ my $svc = shift;
+ my $new_loc = shift;
+ my $old_loc = shift;
+
+ $self->immediate('relocate', $svc, $new_loc, $old_loc)
+ || $self->create_item('relocate', $svc, $new_loc, $old_loc)
+}
+
+sub export_pkg_change {
+ my $self = shift;
+ my $svc = shift;
+ my $new_pkg = shift;
+ my $old_pkg = shift;
+
+ $self->immediate('pkg_change', $svc, $new_pkg)
+ || $self->create_item('pkg_change', $svc, $new_pkg)
+}
+
+=item create_item ACTION, ARGUMENTS
+
+Creates and inserts the L<FS::export_batch_item> record for the action.
+
+=cut
+
+sub create_item {
+ my $self = shift;
+ my $action = shift;
+ my $svc = shift;
+
+ # get memo field
+ my $data = $self->data($action, $svc, @_);
+ my $frozen = '';
+ if (ref $data) {
+ $data = base64_encode(nfreeze($data));
+ $frozen = 'Y';
+ }
+ my $batch_item = FS::export_batch_item->new({
+ 'svcnum' => $svc->svcnum,
+ 'action' => $action,
+ 'data' => $data,
+ 'frozen' => $frozen,
+ });
+ return $self->add_to_batch($batch_item);
+}
+
+sub immediate { # stub
+ '';
+}
+
+=item add_to_batch ITEM
+
+Actually inserts ITEM into the appropriate open batch. All fields in ITEM
+will be populated except for 'batchnum'. By default, all items for a
+single export will go into the same batch, but subclass exports may override
+this method.
+
+=cut
+
+sub add_to_batch {
+ my $self = shift;
+ my $batch_item = shift;
+ $batch_item->set( 'batchnum', $self->open_batch->batchnum );
+
+ $batch_item->insert;
+}
+
+=item open_batch
+
+Returns the current open batch for this export. If there isn't one yet,
+this will create one.
+
+=cut
+
+sub open_batch {
+ my $self = shift;
+ my $batch = qsearchs('export_batch', { status => 'open',
+ exportnum => $self->exportnum });
+ if (!$batch) {
+ $batch = FS::export_batch->new({
+ status => 'open',
+ exportnum => $self->exportnum
+ });
+ my $error = $batch->insert;
+ die $error if $error;
+ }
+ $batch;
+}
+
+=back
+
+=cut
+
+1;