+sub used {
+  my ($self) = @_;
+
+  return unless $self->shipto_id;
+
+  require SL::DB::Order;
+  require SL::DB::Invoice;
+  require SL::DB::DeliveryOrder;
+
+  return SL::DB::Manager::Order->get_all_count(query => [ shipto_id => $self->shipto_id ])
+      || SL::DB::Manager::Invoice->get_all_count(query => [ shipto_id => $self->shipto_id ])
+      || SL::DB::Manager::DeliveryOrder->get_all_count(query => [ shipto_id => $self->shipto_id ]);
+}
+
+sub is_empty {
+  my ($self) = @_;
+
+  # todo: consider cvars
+  my @fields_to_consider = grep { !m{^ (?: itime | mtime | shipto_id | trans_id | shiptocp_gender | module ) $}x } map {$_->name} $self->meta->columns;
+
+  return all { trim($self->$_) eq '' } @fields_to_consider;
+}
+
+sub detach {
+  $_[0]->trans_id(undef);
+  $_[0];
+}
+
+sub clone {
+  my ($self, $target) = @_;
+
+  my $type   = ref($target) || $target;
+  my $module = $type =~ m{::Order$}               ? 'OE'
+             : $type =~ m{::DeliveryOrder$}       ? 'DO'
+             : $type =~ m{::Invoice$}             ? 'AR'
+             : $type =~ m{::(?:Customer|Vendor)$} ? 'CT'
+             :                                      croak "Unsupported target class '$type'";
+
+  my $new_shipto = SL::DB::Shipto->new(
+    (map  { +($_ => $self->$_) }
+     grep { !m{^ (?: itime | mtime | shipto_id | trans_id ) $}x }
+     map  { $_->name }
+     @{ $self->meta->columns }),
+    module           => $module,
+    custom_variables => [ map { $_->clone_and_reset } @{ $self->custom_variables } ],
+  );
+
+  return $new_shipto;
+}
+