my %controller_filter_spec;
sub make_filtered {
- my ($class, %specs) = @_;
+ my ($class, %specs) = @_;
- $specs{MODEL} //= $class->controller_name;
- $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
- $specs{FORM_PARAMS} //= 'filter';
- $specs{LAUNDER_TO} = '__INPLACE__' unless exists $specs{LAUNDER_TO};
- $specs{ONLY} //= [];
- $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
- $specs{ONLY_MAP} = @{ $specs{ONLY} } ? { map { ($_ => 1) } @{ $specs{ONLY} } } : { '__ALL__' => 1 };
+ $specs{MODEL} //= $class->controller_name;
+ $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
+ $specs{FORM_PARAMS} //= 'filter';
+ $specs{LAUNDER_TO} = '__INPLACE__' unless exists $specs{LAUNDER_TO};
+ $specs{ONLY} //= [];
+ $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
+ $specs{ONLY_MAP} = @{ $specs{ONLY} } ? { map { ($_ => 1) } @{ $specs{ONLY} } } : { '__ALL__' => 1 };
$controller_filter_spec{$class} = \%specs;
- my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
+ my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
$class->run_before('_save_current_filter_params', %hook_params);
SL::Controller::Helper::GetModels::register_get_models_handlers(
$calculated_params{query} = [
@{ $calculated_params{query} || [] },
- @{ $filter_args{query} || [] },
- @{ $params{query} || [] },
+ @{ $filter_args{ query} || [] },
+ @{ $params{ query} || [] },
];
$calculated_params{with_objects} = [
uniq
@{ $calculated_params{with_objects} || [] },
- @{ $filter_args{with_objects} || [] },
- @{ $params{with_objects} || [] },
+ @{ $filter_args{ with_objects} || [] },
+ @{ $params{ with_objects} || [] },
];
if ($laundered) {
sub _get_filter_args {
my ($self, $spec) = @_;
- $spec ||= $self->get_filter_spec;
+ $spec ||= $self->get_filter_spec;
- my %filter_args = ref($spec->{FILTER_ARGS}) eq 'CODE' ? %{ $spec->{FILTER_ARGS}->($self) }
- : $spec->{FILTER_ARGS} ? do { my $sub = $spec->{FILTER_ARGS}; %{ $self->$sub() } }
- : ();
+ my %filter_args = ref($spec->{FILTER_ARGS}) eq 'CODE' ? %{ $spec->{FILTER_ARGS}->($self) }
+ : $spec->{FILTER_ARGS} ? do { my $sub = $spec->{FILTER_ARGS}; %{ $self->$sub() } }
+ : ();
}
sub _save_current_filter_params {
my $priv = _priv($self);
if (_is_enabled($self) && $priv->{filter}) {
- my $filter_spec = $self->get_filter_spec;
+ my $filter_spec = $self->get_filter_spec;
my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($priv->{filter}, undef, $filter_spec->{FORM_PARAMS});
- %params = (%params, @$flattened);
+ %params = (%params, @$flattened);
}
# $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params);
return !_priv($self)->{disabled} && ($self->get_filter_spec->{ONLY_MAP}->{$self->action_name} || $self->get_filter_spec->{ONLY_MAP}->{'__ALL__'});
}
-
1;
__END__
my %controller_paginate_spec;
sub make_paginated {
- my ($class, %specs) = @_;
+ my ($class, %specs) = @_;
- $specs{MODEL} ||= $class->controller_name;
- $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
- $specs{PER_PAGE} ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
- $specs{FORM_PARAMS} ||= [ qw(page per_page) ];
- $specs{PAGINATE_ARGS} ||= '__FILTER__';
- $specs{ONLY} ||= [];
- $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
- $specs{ONLY_MAP} = @{ $specs{ONLY} } ? { map { ($_ => 1) } @{ $specs{ONLY} } } : { '__ALL__' => 1 };
+ $specs{MODEL} ||= $class->controller_name;
+ $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
+ $specs{PER_PAGE} ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
+ $specs{FORM_PARAMS} ||= [ qw(page per_page) ];
+ $specs{PAGINATE_ARGS} ||= '__FILTER__';
+ $specs{ONLY} ||= [];
+ $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
+ $specs{ONLY_MAP} = @{ $specs{ONLY} } ? { map { ($_ => 1) } @{ $specs{ONLY} } } : { '__ALL__' => 1 };
$controller_paginate_spec{$class} = \%specs;
- my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
+ my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
$class->run_before('_save_current_paginate_params', %hook_params);
SL::Controller::Helper::GetModels::register_get_models_handlers(
next if !defined $value || $value eq ''; # 0 is fine
if ('HASH' eq ref $value) {
my ($query, $more_objects) = flatten($value, _prefix($prefix, $key));
- push @result, @$query if $query;
+ push @result, @$query if $query;
_add_uniq($with_objects, $_) for _prefix($prefix, $key), @$more_objects;
} else {
push @result, _prefix($prefix, $key) => $value;
__PACKAGE__->run_before(sub { $::auth->assert('part_service_assembly_edit') });
__PACKAGE__->make_filtered(
- ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
- LAUNDER_TO => 'filter',
+ ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
+ LAUNDER_TO => 'filter',
);
__PACKAGE__->make_paginated(
- ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
+ ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
);
__PACKAGE__->make_sorted(
- ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
+ ONLY => [ qw(part_picker_search part_picker_result ajax_autocomplete) ],
- DEFAULT_BY => 'partnumber',
- DEFAULT_DIR => 1,
+ DEFAULT_BY => 'partnumber',
+ DEFAULT_DIR => 1,
- partnumber => t8('Partnumber'),
+ partnumber => t8('Partnumber'),
);
sub action_ajax_autocomplete {
}
sub init_parts {
- $_[0]->get_models;
+ $_[0]->get_models(with_objects => [ qw(unit_obj) ]);
}
1;
$item->marge_percent(0);
} else {
- my $lastcost = ! ($item->lastcost * 1) ? ($item->part->lastcost || 0) : $item->lastcost;
+ my $lastcost = ! ($item->lastcost * 1) ? ($item->part->lastcost || 0) : $item->lastcost;
+ my $linetotal_cost = _round($lastcost * $item->qty / $item->marge_price_factor, 2);
- $item->marge_total( $linetotal - $lastcost / $item->marge_price_factor);
+ $item->marge_total( $linetotal - $linetotal_cost);
$item->marge_percent($item->marge_total * 100 / $linetotal);
$self->marge_total( $self->marge_total + $item->marge_total);
- $data->{lastcost_total} += $lastcost;
+ $data->{lastcost_total} += $linetotal_cost;
}
my $taxkey = $item->part->get_taxkey(date => $self->transdate, is_sales => $data->{is_sales}, taxzone => $self->taxzone_id);
# this is to make selection like type => { part => 1, service => 1 } work
if ('HASH' eq ref $type) {
- $type = grep { $type->{$_} } keys %$type;
+ $type = [ grep { $type->{$_} } keys %$type ];
}
- my @types = listify($type);
+ my @types = grep { $_ } listify($type);
my @filter;
for my $type (@types) {
if ($type =~ m/^part/) {
- push @filter, (and => [ or => [ $prefix . assembly => 0, $prefix . assembly => undef ],
- "!${prefix}inventory_accno_id" => 0,
- "!${prefix}inventory_accno_id" => undef,
+ push @filter, (and => [ or => [ $prefix . assembly => 0, $prefix . assembly => undef ],
+ "!${prefix}inventory_accno_id" => 0,
+ "!${prefix}inventory_accno_id" => undef,
]);
} elsif ($type =~ m/^service/) {
push @filter, (and => [ or => [ $prefix . assembly => 0, $prefix . assembly => undef ],
- or => [ $prefix . inventory_accno_id => 0, $prefix . inventory_accno_id => undef ],
+ or => [ $prefix . inventory_accno_id => 0, $prefix . inventory_accno_id => undef ],
]);
} elsif ($type =~ m/^assembl/) {
push @filter, ($prefix . assembly => 1);
}
}
- return @filter > 2 ? (or => \@filter) :
- @filter ? @filter : ();
+ return @filter > 2 ? (or => \@filter) : @filter;
}
sub get_ordered_qty {
use base qw(SL::DB::Helper::Manager);
use SL::DB::Helper::Sorted;
+use SL::DB::Helper::Filtered;
sub object_class { 'SL::DB::Unit' }
__PACKAGE__->make_manager_methods;
+__PACKAGE__->add_filter_specs(
+ convertible_to => sub {
+ my ($key, $value, $prefix) = @_;
+ return __PACKAGE__->convertible_to_filter($key, $value, $prefix);
+ },
+);
sub _sort_spec {
return ( default => [ 'sortkey', 1 ],
});
}
+sub convertible_to_filter {
+ my ($class, $key, $unit_name, $prefix) = @_;
+
+ return () unless $unit_name;
+
+ $prefix //= '';
+
+ my $unit = $class->find_by(name => $unit_name);
+ if (!$unit) {
+ $::lxdebug->warn("Unit manager: No unit with name $unit_name");
+ return ();
+ }
+
+ return ("${prefix}name" => [ map { $_->name } @{ $unit->convertible_units } ]);
+}
+
1;
return @errors;
}
+sub calc_date {
+ my ($self, %params) = @_;
+
+ my $reference_date = $params{reference_date} || DateTime->today_local;
+ $reference_date = DateTime->from_kivitendo($reference_date) unless ref($reference_date) eq 'DateTime';
+
+ my $terms = ($params{terms} // 'net') eq 'discount' ? 'terms_skonto' : 'terms_netto';
+ my $date = $reference_date->add(days => $self->$terms);
+
+ my $dow = $date->day_of_week;
+ $date = $date->add(days => 8 - $dow) if $dow > 5;
+
+ return $date;
+}
+
1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::DB::PaymentTerm - Rose model for the payment_terms table
+
+=head1 SYNOPSIS
+
+ my $terms = SL::DB::PaymentTerm->new(id => $::form->{payment_id})->load;
+ my $due_date_net = $erms->calc_date(terms => 'net'); # uses terms_netto
+ my $due_date_discount = $erms->calc_date(terms => 'discount'); # uses terms_skonto
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<calc_date [%params]>
+
+Calculates and returns a due date as an instance of L<DateTime> by
+adding one of C<$self>'s terms fields. Note that the resulting date
+will be the following Monday if the result falls on a weekend.
+
+C<%params> can contain the following parameters:
+
+=over 4
+
+=item C<reference_date>
+
+The reference date from which the due date will be calculated. Can be
+either an instance of L<DateTime> or a scalar in which case the scalar
+is parsed via L<DateTime/from_kivitendo>.
+
+Defaults to the current date if unset.
+
+=item C<terms>
+
+Can be either C<net> or C<discount>. For C<net> the number of days to
+add to the reference date are C<$self-E<gt>terms_netto>. For
+C<discount> C<$self-E<gt>terms_skonto> is used.
+
+Defaults to C<net> if unset.
+
+=back
+
+=item C<validate>
+
+Validates before saving and returns an array of human-readable error
+messages in case of an error.
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
AND (table_name = ?)
SQL
- $self->db_query(qq|ALTER TABLE auth."$params{table}" DROP CONSTRAINT "${_}"|) for map { $_->[0] } @{ $constraints };
+ $self->db_query(qq|ALTER TABLE $params{schema}."$params{table}" DROP CONSTRAINT "${_}"|) for map { $_->[0] } @{ $constraints };
}
1;
use SL::AM;
use SL::Common;
use SL::CVar;
+use SL::DB::DeliveryOrder;
+use SL::DB::Status;
use SL::DBUtils;
use SL::RecordLinks;
use SL::IC;
my $form = $main::form;
my $spool = $::lx_office_conf{paths}->{spool};
- # connect to database
- my $dbh = $form->get_standard_dbh($myconfig);
-
- # delete spool files
- my $query = qq|SELECT s.spoolfile FROM status s WHERE s.trans_id = ?|;
- my $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{id}));
-
- my $spoolfile;
- my @spoolfiles = ();
- my @values;
-
- while (($spoolfile) = $sth->fetchrow_array) {
- push @spoolfiles, $spoolfile;
- }
- $sth->finish();
-
- # delete-values
- @values = (conv_i($form->{id}));
-
- # delete status entries
- $query = qq|DELETE FROM status
- WHERE trans_id = ?|;
- do_query($form, $dbh, $query, @values);
+ my $rc = SL::DB::Order->new->db->with_transaction(sub {
+ my @spoolfiles = grep { $_ } map { $_->spoolfile } @{ SL::DB::Manager::Status->get_all(where => [ trans_id => $form->{id} ]) };
- # delete individual entries
- $query = qq|DELETE FROM delivery_order_items_stock
- WHERE delivery_order_item_id IN (
- SELECT id FROM delivery_order_items
- WHERE delivery_order_id = ?
- )|;
- do_query($form, $dbh, $query, @values);
-
- # delete individual entries
- $query = qq|DELETE FROM delivery_order_items
- WHERE delivery_order_id = ?|;
- do_query($form, $dbh, $query, @values);
-
- # delete DO record
- $query = qq|DELETE FROM delivery_orders
- WHERE id = ?|;
- do_query($form, $dbh, $query, @values);
+ SL::DB::DeliveryOrder->new(id => $form->{id})->delete;
- $query = qq|DELETE FROM shipto
- WHERE trans_id = ? AND module = 'DO'|;
- do_query($form, $dbh, $query, @values);
-
- my $rc = $dbh->commit();
+ my $spool = $::lx_office_conf{paths}->{spool};
+ unlink map { "$spool/$_" } @spoolfiles if $spool;
- if ($rc) {
- foreach $spoolfile (@spoolfiles) {
- unlink "$spool/$spoolfile" if $spoolfile;
- }
- }
+ 1;
+ });
$main::lxdebug->leave_sub();
package Form;
+use Carp;
use Data::Dumper;
use CGI;
use SL::DB;
use SL::DBConnect;
use SL::DBUtils;
+use SL::DB::Customer;
use SL::DB::Default;
+use SL::DB::PaymentTerm;
+use SL::DB::Vendor;
use SL::DO;
use SL::IC;
use SL::IS;
my ($self, $myconfig, $reference_date) = @_;
- $reference_date = $reference_date ? conv_dateq($reference_date) . '::DATE' : 'current_date';
+ my $terms = $self->{payment_id} ? SL::DB::PaymentTerm->new(id => $self->{payment_id}) ->load
+ : $self->{customer_id} ? SL::DB::Customer ->new(id => $self->{customer_id})->load->payment
+ : $self->{vendor_id} ? SL::DB::Vendor ->new(id => $self->{vendor_id}) ->load->payment
+ : croak("Missing field in \$::form: payment_id, customer_id or vendor_id");
- my $dbh = $self->get_standard_dbh($myconfig);
- my ($payment_id, $duedate);
-
- if($self->{payment_id}) {
- $payment_id = $self->{payment_id};
- } elsif($self->{vendor_id}) {
- my $query = 'SELECT payment_id FROM vendor WHERE id = ?';
- ($payment_id) = selectrow_query($self, $dbh, $query, $self->{vendor_id});
- }
-
- if ($payment_id) {
- my $query = qq|SELECT ${reference_date} + terms_netto FROM payment_terms WHERE id = ?|;
- ($duedate) = selectrow_query($self, $dbh, $query, $payment_id);
- }
+ my $duedate = $terms->calc_date(reference_date => $reference_date)->to_kivitendo;
$main::lxdebug->leave_sub();
use SL::AM;
use SL::Common;
use SL::CVar;
+use SL::DB::Order;
use SL::DB::PeriodicInvoicesConfig;
+use SL::DB::Status;
use SL::DBUtils;
use SL::IC;
my ($self, $myconfig, $form) = @_;
- # connect to database
- my $dbh = $form->get_standard_dbh;
- $dbh->begin_work;
-
- # delete spool files
- my $query = qq|SELECT s.spoolfile FROM status s | .
- qq|WHERE s.trans_id = ?|;
- my @values = (conv_i($form->{id}));
- my $sth = $dbh->prepare($query);
- $sth->execute(@values) || $self->dberror($query);
-
- my $spoolfile;
- my @spoolfiles = ();
-
- while (($spoolfile) = $sth->fetchrow_array) {
- push @spoolfiles, $spoolfile;
- }
- $sth->finish;
-
- # delete-values
- @values = (conv_i($form->{id}));
-
- # periodic invoices and their configuration
- do_query($form, $dbh, qq|DELETE FROM periodic_invoices WHERE config_id IN (SELECT id FROM periodic_invoices_configs WHERE oe_id = ?)|, @values);
- do_query($form, $dbh, qq|DELETE FROM periodic_invoices_configs WHERE oe_id = ?|, @values);
-
- # delete status entries
- $query = qq|DELETE FROM status | .
- qq|WHERE trans_id = ?|;
- do_query($form, $dbh, $query, @values);
-
- # delete individual entries
- $query = qq|DELETE FROM orderitems | .
- qq|WHERE trans_id = ?|;
- do_query($form, $dbh, $query, @values);
+ my $rc = SL::DB::Order->new->db->with_transaction(sub {
+ my @spoolfiles = grep { $_ } map { $_->spoolfile } @{ SL::DB::Manager::Status->get_all(where => [ trans_id => $form->{id} ]) };
- $query = qq|DELETE FROM shipto | .
- qq|WHERE trans_id = ? AND module = 'OE'|;
- do_query($form, $dbh, $query, @values);
-
- # delete OE record
- $query = qq|DELETE FROM oe | .
- qq|WHERE id = ?|;
- do_query($form, $dbh, $query, @values);
+ SL::DB::Order->new(id => $form->{id})->delete;
- my $rc = $dbh->commit;
-
- if ($rc) {
my $spool = $::lx_office_conf{paths}->{spool};
- foreach $spoolfile (@spoolfiles) {
- unlink "$spool/$spoolfile" if $spoolfile;
- }
- }
+ unlink map { "$spool/$_" } @spoolfiles if $spool;
+
+ 1;
+ });
$main::lxdebug->leave_sub();
use strict;
+use SL::DB::Part;
+
use Exporter qw(import);
our @EXPORT = qw(part_picker);
sub part_picker {
my ($self, $name, $value, %params) = @_;
- my $name_e = $self->escape($name);
+
+ $value = SL::DB::Manager::Part->find_by(id => $value) if !ref $value;
+ my $id = delete($params{id}) || $self->name_to_id($name);
my $ret =
- $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => 'part_autocomplete', type => 'hidden') .
- $self->input_tag("", delete $params{type}, id => $self->name_to_id("$name_e\_type"), type => 'hidden') .
- $self->input_tag("", (ref $value && $value->can('description')) ? $value->description : '', id => $self->name_to_id("$name_e\_name"), %params) .
- $self->input_tag("", delete $params{column}, id => $self->name_to_id("$name_e\_column"), type => 'hidden');
+ $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => 'part_autocomplete', type => 'hidden', id => $id) .
+ join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(column type unit convertible_unit)) .
+ $self->input_tag("", (ref $value && $value->can('description')) ? $value->description : '', id => "${id}_name", %params);
$self->html_tag('span', $ret, class => 'part_picker');
}
=over 4
-=item C<part_picker NAME, VALUE, PARAMS>
+=item C<part_picker $name, $value, %params>
+
+All-in-one picker widget for parts. The name will be both id and name
+of the resulting hidden C<id> input field (but the ID can be
+overwritten with C<$params{id}>).
+
+An additional dummy input will be generated which is used to find
+parts. For a detailed description of it's behaviour, see section
+C<PART PICKER SPECIFICATION>.
+
+C<$value> can be a parts id or a C<Rose::DB:Object> instance.
All-in-one picker widget for parts. The name will be both id and name of the
resulting hidden C<id> input field. An additional dummy input will be generated
which is used to find parts. For a detailed description of it's behaviour, see
section L</PART PICKER SPECIFICATION>.
-C<VALUE> can be an id or C<Rose::DB:Object> instance.
+If C<%params> contains C<type> only parts of this type will be used
+for autocompletion. You may comma separate multiple types as in
+C<part,assembly>.
+
+If C<%params> contains C<unit> only parts with this unit will be used
+for autocompletion. You may comma separate multiple units as in
+C<h,min>.
-If C<PARAMS> contains C<type> only parts of this type will be used for
-autocompletion. You may comma separate multiple types as in C<part,assembly>.
+If C<%params> contains C<convertible_unit> only parts with a unit
+that's convertible to unit will be used for autocompletion.
Obsolete parts will by default not displayed for selection. However they are
accepted as default values and can persist during updates. As with other
var real_id = $real.attr('id');
var $dummy = $('#' + real_id + '_name');
var $type = $('#' + real_id + '_type');
+ var $unit = $('#' + real_id + '_unit');
+ var $convertible_unit = $('#' + real_id + '_convertible_unit');
var $column = $('#' + real_id + '_column');
var state = STATES.PICKED;
var last_real = $real.val();
};
function ajax_data(term) {
- return {
+ var data = {
'filter.all:substr::ilike': term,
- 'filter.type': $type.val().split(','),
'filter.obsolete': 0,
- column: $column.val()===undefined ? '' : $column.val(),
+ 'filter.unit_obj.convertible_to': $convertible_unit && $convertible_unit.val() ? $convertible_unit.val() : '',
+ column: $column && $column.val() ? $column.val() : '',
current: $real.val(),
- }
+ };
+
+ if ($type && $type.val())
+ data['filter.type'] = $type.val().split(',');
+
+ if ($unit && $unit.val())
+ data['filter.unit'] = $unit.val().split(',');
+
+ return data;
}
function set_item (item) {
real: function() { return $real },
dummy: function() { return $dummy },
type: function() { return $type },
+ unit: function() { return $unit },
+ convertible_unit: function() { return $convertible_unit },
column: function() { return $column },
update_results: update_results,
set_item: set_item,
return true;
}
-function close_jqm_window(params) {
- params = params || { };
- var url = params.url;
- var id = params.id ? params.id : 'jqm_popup_dialog';
-
- $('#' + id).jqmClose()();
-}
-
$(document).ready(function () {
// initialize all jQuery UI tab elements:
$(".tabwidget").each(function(idx, element) { $(element).tabs(); });
--- /dev/null
+# @tag: oe_do_delete_via_trigger
+# @description: Aus oe/delivery_orders via Trigger löschen können
+# @depends: release_3_0_0
+
+package SL::DBUpgrade2::oe_do_delete_via_trigger;
+
+use utf8;
+use strict;
+
+use parent qw(SL::DBUpgrade2::Base);
+
+sub run {
+ my ($self) = @_;
+
+ $self->drop_constraints(table => $_) for qw(periodic_invoices periodic_invoices_configs orderitems delivery_order_items delivery_order_items_stock);
+
+ my @queries = (
+ q|ALTER TABLE periodic_invoices ADD CONSTRAINT periodic_invoices_ar_id_fkey FOREIGN KEY (ar_id) REFERENCES ar (id) ON DELETE CASCADE|,
+ q|ALTER TABLE periodic_invoices ADD CONSTRAINT periodic_invoices_config_id_fkey FOREIGN KEY (config_id) REFERENCES periodic_invoices_configs (id) ON DELETE CASCADE|,
+
+ q|ALTER TABLE periodic_invoices_configs ADD CONSTRAINT periodic_invoices_configs_ar_chart_id_fkey FOREIGN KEY (ar_chart_id) REFERENCES chart (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE periodic_invoices_configs ADD CONSTRAINT periodic_invoices_configs_oe_id_fkey FOREIGN KEY (oe_id) REFERENCES oe (id) ON DELETE CASCADE|,
+ q|ALTER TABLE periodic_invoices_configs ADD CONSTRAINT periodic_invoices_configs_printer_id_fkey FOREIGN KEY (printer_id) REFERENCES printers (id) ON DELETE SET NULL|,
+
+ q|ALTER TABLE orderitems ADD CONSTRAINT orderitems_parts_id_fkey FOREIGN KEY (parts_id) REFERENCES parts (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE orderitems ADD CONSTRAINT orderitems_price_factor_id_fkey FOREIGN KEY (price_factor_id) REFERENCES price_factors (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE orderitems ADD CONSTRAINT orderitems_pricegroup_id_fkey FOREIGN KEY (pricegroup_id) REFERENCES pricegroup (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE orderitems ADD CONSTRAINT orderitems_project_id_fkey FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE SET NULL|,
+ q|ALTER TABLE orderitems ADD CONSTRAINT orderitems_trans_id_fkey FOREIGN KEY (trans_id) REFERENCES oe (id) ON DELETE CASCADE|,
+
+ q|ALTER TABLE delivery_order_items ADD CONSTRAINT delivery_order_items_delivery_order_id_fkey FOREIGN KEY (delivery_order_id) REFERENCES delivery_orders (id) ON DELETE CASCADE|,
+ q|ALTER TABLE delivery_order_items ADD CONSTRAINT delivery_order_items_parts_id_fkey FOREIGN KEY (parts_id) REFERENCES parts (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE delivery_order_items ADD CONSTRAINT delivery_order_items_price_factor_id_fkey FOREIGN KEY (price_factor_id) REFERENCES price_factors (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE delivery_order_items ADD CONSTRAINT delivery_order_items_pricegroup_id_fkey FOREIGN KEY (pricegroup_id) REFERENCES pricegroup (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE delivery_order_items ADD CONSTRAINT delivery_order_items_project_id_fkey FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE SET NULL|,
+
+ q|ALTER TABLE delivery_order_items_stock ADD CONSTRAINT delivery_order_items_stock_bin_id_fkey FOREIGN KEY (bin_id) REFERENCES bin (id) ON DELETE RESTRICT|,
+ q|ALTER TABLE delivery_order_items_stock ADD CONSTRAINT delivery_order_items_stock_delivery_order_item_id_fkey FOREIGN KEY (delivery_order_item_id) REFERENCES delivery_order_items (id) ON DELETE CASCADE|,
+ q|ALTER TABLE delivery_order_items_stock ADD CONSTRAINT delivery_order_items_stock_warehouse_id_fkey FOREIGN KEY (warehouse_id) REFERENCES warehouse (id) ON DELETE RESTRICT|,
+
+ q|CREATE OR REPLACE FUNCTION oe_before_delete_trigger() RETURNS trigger AS $$
+ BEGIN
+ DELETE FROM status WHERE trans_id = OLD.id;
+ DELETE FROM shipto WHERE (trans_id = OLD.id) AND (module = 'OE');
+
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql|,
+
+ q|DROP TRIGGER IF EXISTS delete_oe_dependencies ON oe|,
+
+ q|CREATE TRIGGER delete_oe_dependencies
+ BEFORE DELETE ON oe
+ FOR EACH ROW EXECUTE PROCEDURE oe_before_delete_trigger()|,
+
+ q|CREATE OR REPLACE FUNCTION delivery_orders_before_delete_trigger() RETURNS trigger AS $$
+ BEGIN
+ DELETE FROM status WHERE trans_id = OLD.id;
+ DELETE FROM delivery_order_items_stock WHERE delivery_order_item_id IN (SELECT id FROM delivery_order_items WHERE delivery_order_id = OLD.id);
+ DELETE FROM shipto WHERE (trans_id = OLD.id) AND (module = 'OE');
+
+ RETURN OLD;
+ END;
+ $$ LANGUAGE plpgsql|,
+
+ q|DROP TRIGGER IF EXISTS delete_delivery_orders_dependencies ON delivery_orders|,
+
+ q|CREATE TRIGGER delete_delivery_orders_dependencies
+ BEFORE DELETE ON delivery_orders
+ FOR EACH ROW EXECUTE PROCEDURE delivery_orders_before_delete_trigger()|);
+
+ $self->db_query($_) for @queries;
+
+ return 1;
+}
+
+1;