Revision da8f5ec2
Von Tamino Steinert vor fast 3 Jahren hinzugefügt
| SL/DB/Helper/ALL.pm | ||
|---|---|---|
|
use SL::DB::ProjectStatus;
|
||
|
use SL::DB::ProjectType;
|
||
|
use SL::DB::PurchaseInvoice;
|
||
|
use SL::DB::Reclamation;
|
||
|
use SL::DB::ReclamationItem;
|
||
|
use SL::DB::ReclamationReason;
|
||
|
use SL::DB::ReconciliationLink;
|
||
|
use SL::DB::RecordLink;
|
||
|
use SL::DB::RecordTemplate;
|
||
| SL/DB/Helper/Mappings.pm | ||
|---|---|---|
|
project_roles => 'project_role',
|
||
|
project_statuses => 'project_status',
|
||
|
project_types => 'project_type',
|
||
|
reclamations => 'Reclamation',
|
||
|
reclamation_items => 'ReclamationItem',
|
||
|
reclamation_reasons => 'ReclamationReason',
|
||
|
reconciliation_links => 'reconciliation_link',
|
||
|
record_links => 'record_link',
|
||
|
record_templates => 'record_template',
|
||
| SL/DB/Manager/Reclamation.pm | ||
|---|---|---|
|
package SL::DB::Manager::Reclamation;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Helper::Manager);
|
||
|
|
||
|
use SL::DB::Helper::Paginated;
|
||
|
use SL::DB::Helper::Sorted;
|
||
|
use SL::DB::Helper::Filtered;
|
||
|
|
||
|
sub object_class { 'SL::DB::Reclamation' }
|
||
|
|
||
|
__PACKAGE__->make_manager_methods;
|
||
|
|
||
|
__PACKAGE__->add_filter_specs(
|
||
|
type => sub {
|
||
|
my ($key, $value, $prefix) = @_;
|
||
|
return __PACKAGE__->type_filter($value, $prefix);
|
||
|
},
|
||
|
# todo when is this used?
|
||
|
#all => sub {
|
||
|
# my ($key, $value, $prefix) = @_;
|
||
|
# return or => [ map { $prefix . $_ => $value } qw(record_number customer.name vendor.name transaction_description) ]
|
||
|
#}
|
||
|
);
|
||
|
|
||
|
sub type_filter {
|
||
|
my $class = shift;
|
||
|
my $type = lc(shift || '');
|
||
|
my $prefix = shift || '';
|
||
|
|
||
|
return (and => [ "!customer_id" => undef ]) if $type eq 'sales_reclamation';
|
||
|
return (and => [ "!vendor_id" => undef ]) if $type eq 'purchase_reclamation';
|
||
|
|
||
|
die "Unknown type $type";
|
||
|
}
|
||
|
|
||
|
sub _sort_spec {
|
||
|
return (
|
||
|
default => [ 'transdate', 1 ],
|
||
|
nulls => {
|
||
|
transaction_description => 'FIRST',
|
||
|
default => 'LAST',
|
||
|
},
|
||
|
columns => {
|
||
|
SIMPLE => 'ALL',
|
||
|
customer => 'lower(customer.name)',
|
||
|
vendor => 'lower(vendor.name)',
|
||
|
employee => 'lower(employee.name)',
|
||
|
globalprojectnumber => 'lower(globalproject.projectnumber)',
|
||
|
|
||
|
# Bug in Rose::DB::Object: the next should be
|
||
|
# "globalproject.project_type.description". This workaround will
|
||
|
# only work if no other table with "project_type" is visible in
|
||
|
# the current query
|
||
|
globalproject_type => 'lower(project_type.description)',
|
||
|
|
||
|
map { ( $_ => "lower(reclamations.$_)" ) }
|
||
|
qw(record_number cv_record_number shippingpoint shipvia notes intnotes
|
||
|
transaction_description
|
||
|
),
|
||
|
});
|
||
|
}
|
||
|
|
||
|
1;
|
||
| SL/DB/Manager/ReclamationItem.pm | ||
|---|---|---|
|
# This file has been auto-generated only because it didn't exist.
|
||
|
# Feel free to modify it at will; it will not be overwritten automatically.
|
||
|
|
||
|
package SL::DB::Manager::ReclamationItem;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Helper::Manager);
|
||
|
|
||
|
sub object_class { 'SL::DB::ReclamationItem' }
|
||
|
|
||
|
__PACKAGE__->make_manager_methods;
|
||
|
|
||
|
1;
|
||
| SL/DB/Manager/ReclamationReason.pm | ||
|---|---|---|
|
package SL::DB::Manager::ReclamationReason;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Helper::Manager);
|
||
|
use SL::DB::Helper::Paginated;
|
||
|
use SL::DB::Helper::Filtered;
|
||
|
|
||
|
use SL::DB::Helper::Sorted;
|
||
|
|
||
|
sub object_class { 'SL::DB::ReclamationReason' }
|
||
|
|
||
|
__PACKAGE__->make_manager_methods;
|
||
|
__PACKAGE__->add_filter_specs(
|
||
|
all => sub {
|
||
|
my ($key, $value, $prefix) = @_;
|
||
|
return or => [ map { $prefix . $_ => $value } qw(reclamation_reason) ]
|
||
|
},
|
||
|
);
|
||
|
|
||
|
sub _sort_spec {
|
||
|
return ( default => [ 'position', 1 ],
|
||
|
columns => { SIMPLE => 'ALL' });
|
||
|
}
|
||
|
1;
|
||
| SL/DB/MetaSetup/Reclamation.pm | ||
|---|---|---|
|
# This file has been auto-generated. Do not modify it; it will be overwritten
|
||
|
# by rose_auto_create_model.pl automatically.
|
||
|
package SL::DB::Reclamation;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Object);
|
||
|
|
||
|
__PACKAGE__->meta->table('reclamations');
|
||
|
|
||
|
__PACKAGE__->meta->columns(
|
||
|
amount => { type => 'numeric', precision => 15, scale => 5 },
|
||
|
closed => { type => 'boolean', default => 'false', not_null => 1 },
|
||
|
contact_id => { type => 'integer' },
|
||
|
currency_id => { type => 'integer', not_null => 1 },
|
||
|
customer_id => { type => 'integer' },
|
||
|
cv_record_number => { type => 'text' },
|
||
|
delivered => { type => 'boolean', default => 'false', not_null => 1 },
|
||
|
delivery_term_id => { type => 'integer' },
|
||
|
department_id => { type => 'integer' },
|
||
|
employee_id => { type => 'integer', not_null => 1 },
|
||
|
exchangerate => { type => 'numeric', precision => 15, scale => 5 },
|
||
|
globalproject_id => { type => 'integer' },
|
||
|
id => { type => 'integer', not_null => 1, sequence => 'id' },
|
||
|
intnotes => { type => 'text' },
|
||
|
itime => { type => 'timestamp', default => 'now()' },
|
||
|
language_id => { type => 'integer' },
|
||
|
mtime => { type => 'timestamp' },
|
||
|
netamount => { type => 'numeric', precision => 15, scale => 5 },
|
||
|
notes => { type => 'text' },
|
||
|
payment_id => { type => 'integer' },
|
||
|
record_number => { type => 'text', not_null => 1 },
|
||
|
reqdate => { type => 'date' },
|
||
|
salesman_id => { type => 'integer' },
|
||
|
shippingpoint => { type => 'text' },
|
||
|
shipto_id => { type => 'integer' },
|
||
|
shipvia => { type => 'text' },
|
||
|
tax_point => { type => 'date' },
|
||
|
taxincluded => { type => 'boolean', not_null => 1 },
|
||
|
taxzone_id => { type => 'integer', not_null => 1 },
|
||
|
transaction_description => { type => 'text' },
|
||
|
transdate => { type => 'date', default => 'now()' },
|
||
|
vendor_id => { type => 'integer' },
|
||
|
);
|
||
|
|
||
|
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
|
||
|
|
||
|
__PACKAGE__->meta->allow_inline_column_values(1);
|
||
|
|
||
|
__PACKAGE__->meta->foreign_keys(
|
||
|
contact => {
|
||
|
class => 'SL::DB::Contact',
|
||
|
key_columns => { contact_id => 'cp_id' },
|
||
|
},
|
||
|
|
||
|
currency => {
|
||
|
class => 'SL::DB::Currency',
|
||
|
key_columns => { currency_id => 'id' },
|
||
|
},
|
||
|
|
||
|
customer => {
|
||
|
class => 'SL::DB::Customer',
|
||
|
key_columns => { customer_id => 'id' },
|
||
|
},
|
||
|
|
||
|
delivery_term => {
|
||
|
class => 'SL::DB::DeliveryTerm',
|
||
|
key_columns => { delivery_term_id => 'id' },
|
||
|
},
|
||
|
|
||
|
department => {
|
||
|
class => 'SL::DB::Department',
|
||
|
key_columns => { department_id => 'id' },
|
||
|
},
|
||
|
|
||
|
employee => {
|
||
|
class => 'SL::DB::Employee',
|
||
|
key_columns => { employee_id => 'id' },
|
||
|
},
|
||
|
|
||
|
globalproject => {
|
||
|
class => 'SL::DB::Project',
|
||
|
key_columns => { globalproject_id => 'id' },
|
||
|
},
|
||
|
|
||
|
language => {
|
||
|
class => 'SL::DB::Language',
|
||
|
key_columns => { language_id => 'id' },
|
||
|
},
|
||
|
|
||
|
payment => {
|
||
|
class => 'SL::DB::PaymentTerm',
|
||
|
key_columns => { payment_id => 'id' },
|
||
|
},
|
||
|
|
||
|
salesman => {
|
||
|
class => 'SL::DB::Employee',
|
||
|
key_columns => { salesman_id => 'id' },
|
||
|
},
|
||
|
|
||
|
shipto => {
|
||
|
class => 'SL::DB::Shipto',
|
||
|
key_columns => { shipto_id => 'shipto_id' },
|
||
|
},
|
||
|
|
||
|
taxzone => {
|
||
|
class => 'SL::DB::TaxZone',
|
||
|
key_columns => { taxzone_id => 'id' },
|
||
|
},
|
||
|
|
||
|
vendor => {
|
||
|
class => 'SL::DB::Vendor',
|
||
|
key_columns => { vendor_id => 'id' },
|
||
|
},
|
||
|
);
|
||
|
|
||
|
1;
|
||
|
;
|
||
| SL/DB/MetaSetup/ReclamationItem.pm | ||
|---|---|---|
|
# This file has been auto-generated. Do not modify it; it will be overwritten
|
||
|
# by rose_auto_create_model.pl automatically.
|
||
|
package SL::DB::ReclamationItem;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Object);
|
||
|
|
||
|
__PACKAGE__->meta->table('reclamation_items');
|
||
|
|
||
|
__PACKAGE__->meta->columns(
|
||
|
active_discount_source => { type => 'text', default => '', not_null => 1 },
|
||
|
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
|
base_qty => { type => 'float', precision => 4, scale => 4 },
|
||
|
description => { type => 'text' },
|
||
|
discount => { type => 'float', precision => 4, scale => 4 },
|
||
|
id => { type => 'serial', not_null => 1 },
|
||
|
itime => { type => 'timestamp', default => 'now()' },
|
||
|
lastcost => { type => 'numeric', precision => 15, scale => 5 },
|
||
|
longdescription => { type => 'text' },
|
||
|
mtime => { type => 'timestamp' },
|
||
|
parts_id => { type => 'integer', not_null => 1 },
|
||
|
position => { type => 'integer', not_null => 1 },
|
||
|
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
|
||
|
price_factor_id => { type => 'integer' },
|
||
|
pricegroup_id => { type => 'integer' },
|
||
|
project_id => { type => 'integer' },
|
||
|
qty => { type => 'float', precision => 4, scale => 4 },
|
||
|
reason_description_ext => { type => 'text' },
|
||
|
reason_description_int => { type => 'text' },
|
||
|
reason_id => { type => 'integer', not_null => 1 },
|
||
|
reclamation_id => { type => 'integer', not_null => 1 },
|
||
|
reqdate => { type => 'date' },
|
||
|
sellprice => { type => 'numeric', precision => 15, scale => 5 },
|
||
|
serialnumber => { type => 'text' },
|
||
|
unit => { type => 'varchar', length => 20 },
|
||
|
);
|
||
|
|
||
|
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
|
||
|
|
||
|
__PACKAGE__->meta->allow_inline_column_values(1);
|
||
|
|
||
|
__PACKAGE__->meta->foreign_keys(
|
||
|
part => {
|
||
|
class => 'SL::DB::Part',
|
||
|
key_columns => { parts_id => 'id' },
|
||
|
},
|
||
|
|
||
|
price_factor_obj => {
|
||
|
class => 'SL::DB::PriceFactor',
|
||
|
key_columns => { price_factor_id => 'id' },
|
||
|
},
|
||
|
|
||
|
pricegroup => {
|
||
|
class => 'SL::DB::Pricegroup',
|
||
|
key_columns => { pricegroup_id => 'id' },
|
||
|
},
|
||
|
|
||
|
project => {
|
||
|
class => 'SL::DB::Project',
|
||
|
key_columns => { project_id => 'id' },
|
||
|
},
|
||
|
|
||
|
reason => {
|
||
|
class => 'SL::DB::ReclamationReason',
|
||
|
key_columns => { reason_id => 'id' },
|
||
|
},
|
||
|
|
||
|
reclamation => {
|
||
|
class => 'SL::DB::Reclamation',
|
||
|
key_columns => { reclamation_id => 'id' },
|
||
|
},
|
||
|
|
||
|
unit_obj => {
|
||
|
class => 'SL::DB::Unit',
|
||
|
key_columns => { unit => 'name' },
|
||
|
},
|
||
|
);
|
||
|
|
||
|
1;
|
||
|
;
|
||
| SL/DB/MetaSetup/ReclamationReason.pm | ||
|---|---|---|
|
# This file has been auto-generated. Do not modify it; it will be overwritten
|
||
|
# by rose_auto_create_model.pl automatically.
|
||
|
package SL::DB::ReclamationReason;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use parent qw(SL::DB::Object);
|
||
|
|
||
|
__PACKAGE__->meta->table('reclamation_reasons');
|
||
|
|
||
|
__PACKAGE__->meta->columns(
|
||
|
description => { type => 'text', not_null => 1 },
|
||
|
id => { type => 'serial', not_null => 1 },
|
||
|
itime => { type => 'timestamp', default => 'now()' },
|
||
|
mtime => { type => 'timestamp' },
|
||
|
name => { type => 'text', not_null => 1 },
|
||
|
position => { type => 'integer', not_null => 1 },
|
||
|
valid_for_purchase => { type => 'boolean', default => 'false', not_null => 1 },
|
||
|
valid_for_sales => { type => 'boolean', default => 'false', not_null => 1 },
|
||
|
);
|
||
|
|
||
|
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
|
||
|
|
||
|
__PACKAGE__->meta->allow_inline_column_values(1);
|
||
|
|
||
|
1;
|
||
|
;
|
||
| SL/DB/Reclamation.pm | ||
|---|---|---|
|
package SL::DB::Reclamation;
|
||
|
|
||
|
use utf8;
|
||
|
use strict;
|
||
|
|
||
|
use Carp;
|
||
|
use DateTime;
|
||
|
use List::Util qw(max sum0);
|
||
|
use List::MoreUtils qw(any);
|
||
|
|
||
|
use SL::DB::MetaSetup::Reclamation;
|
||
|
use SL::DB::Manager::Reclamation;
|
||
|
use SL::DB::Helper::Attr;
|
||
|
use SL::DB::Helper::AttrHTML;
|
||
|
use SL::DB::Helper::AttrSorted;
|
||
|
use SL::DB::Helper::FlattenToForm;
|
||
|
use SL::DB::Helper::LinkedRecords;
|
||
|
use SL::DB::Helper::PriceTaxCalculator;
|
||
|
use SL::DB::Helper::PriceUpdater;
|
||
|
use SL::DB::Helper::TransNumberGenerator;
|
||
|
use SL::Locale::String qw(t8);
|
||
|
use SL::RecordLinks;
|
||
|
use Rose::DB::Object::Helpers qw(as_tree);
|
||
|
|
||
|
__PACKAGE__->meta->add_relationship(
|
||
|
|
||
|
reclamation_items => {
|
||
|
type => 'one to many',
|
||
|
class => 'SL::DB::ReclamationItem',
|
||
|
column_map => { id => 'reclamation_id' },
|
||
|
manager_args => {
|
||
|
with_objects => [ 'part', 'reason' ]
|
||
|
}
|
||
|
},
|
||
|
custom_shipto => {
|
||
|
type => 'one to one',
|
||
|
class => 'SL::DB::Shipto',
|
||
|
column_map => { id => 'trans_id' },
|
||
|
query_args => [ module => 'Reclamation' ],
|
||
|
},
|
||
|
exchangerate_obj => {
|
||
|
type => 'one to one',
|
||
|
class => 'SL::DB::Exchangerate',
|
||
|
column_map => { currency_id => 'currency_id', transdate => 'transdate' },
|
||
|
},
|
||
|
);
|
||
|
|
||
|
SL::DB::Helper::Attr::make(__PACKAGE__, daily_exchangerate => 'numeric');
|
||
|
|
||
|
__PACKAGE__->meta->initialize;
|
||
|
|
||
|
__PACKAGE__->attr_html('notes');
|
||
|
__PACKAGE__->attr_sorted('items');
|
||
|
|
||
|
__PACKAGE__->before_save('_before_save_set_record_number');
|
||
|
__PACKAGE__->before_save('_before_save_remove_empty_custom_shipto');
|
||
|
__PACKAGE__->before_save('_before_save_set_custom_shipto_module');
|
||
|
|
||
|
# hooks
|
||
|
|
||
|
sub _before_save_set_record_number {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
$self->create_trans_number if !$self->record_number;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
sub _before_save_remove_empty_custom_shipto {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
$self->custom_shipto(undef) if $self->custom_shipto && $self->custom_shipto->is_empty;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
sub _before_save_set_custom_shipto_module {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
$self->custom_shipto->module('Reclamation') if $self->custom_shipto;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
# methods
|
||
|
|
||
|
sub items { goto &reclamation_items; }
|
||
|
sub add_items { goto &add_reclamation_items; }
|
||
|
sub record_items { goto &reclamation_items; }
|
||
|
|
||
|
sub type {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
return 'sales_reclamation' if $self->customer_id;
|
||
|
return 'purchase_reclamation' if $self->vendor_id;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
sub is_type {
|
||
|
my ($self, $type) = @_;
|
||
|
return $self->type eq $type;
|
||
|
}
|
||
|
|
||
|
sub effective_tax_point {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
return $self->tax_point || $self->reqdate || $self->transdate;
|
||
|
}
|
||
|
|
||
|
sub displayable_type {
|
||
|
my $type = shift->type;
|
||
|
|
||
|
return $::locale->text('Sales Reclamation') if $type eq 'sales_reclamation';
|
||
|
return $::locale->text('Purchase Reclamation') if $type eq 'purchase_reclamation';
|
||
|
|
||
|
die 'invalid type';
|
||
|
}
|
||
|
|
||
|
sub displayable_name {
|
||
|
join ' ', grep $_, map $_[0]->$_, qw(displayable_type record_number);
|
||
|
};
|
||
|
|
||
|
sub is_sales {
|
||
|
croak 'not an accessor' if @_ > 1;
|
||
|
return !!shift->customer_id;
|
||
|
}
|
||
|
|
||
|
sub daily_exchangerate {
|
||
|
my ($self, $val) = @_;
|
||
|
|
||
|
return 1 if $self->currency_id == $::instance_conf->get_currency_id;
|
||
|
|
||
|
my $rate = (any { $self->is_type($_) } qw(sales_reclamation)) ? 'buy'
|
||
|
: (any { $self->is_type($_) } qw(purchase_reclamation)) ? 'sell'
|
||
|
: undef;
|
||
|
return if !$rate;
|
||
|
|
||
|
if (defined $val) {
|
||
|
croak t8('exchange rate has to be positive') if $val <= 0;
|
||
|
if (!$self->exchangerate_obj) {
|
||
|
$self->exchangerate_obj(SL::DB::Exchangerate->new(
|
||
|
currency_id => $self->currency_id,
|
||
|
transdate => $self->transdate,
|
||
|
$rate => $val,
|
||
|
));
|
||
|
} elsif (!defined $self->exchangerate_obj->$rate) {
|
||
|
$self->exchangerate_obj->$rate($val);
|
||
|
} else {
|
||
|
croak t8('exchange rate already exists, no update allowed');
|
||
|
}
|
||
|
}
|
||
|
return $self->exchangerate_obj->$rate if $self->exchangerate_obj;
|
||
|
}
|
||
|
|
||
|
sub taxes {
|
||
|
my ($self) = @_;
|
||
|
# add taxes to recalmation
|
||
|
my %pat = $self->calculate_prices_and_taxes();
|
||
|
my @taxes;
|
||
|
foreach my $tax_id (keys %{ $pat{taxes_by_tax_id} }) {
|
||
|
my $netamount = sum0 map { $pat{amounts}->{$_}->{amount} } grep { $pat{amounts}->{$_}->{tax_id} == $tax_id } keys %{ $pat{amounts} };
|
||
|
push(@taxes, { amount => $pat{taxes_by_tax_id}->{$tax_id},
|
||
|
netamount => $netamount,
|
||
|
tax => SL::DB::Tax->new(id => $tax_id)->load });
|
||
|
}
|
||
|
return \@taxes;
|
||
|
}
|
||
|
|
||
|
sub displayable_state {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
return $self->closed ? $::locale->text('closed') : $::locale->text('open');
|
||
|
}
|
||
|
|
||
|
sub valid_reclamation_reasons {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
my $valid_for_type = ($self->type =~ m{sales} ? 'valid_for_sales' : 'valid_for_purchase');
|
||
|
return SL::DB::Manager::ReclamationReason->get_all_sorted(
|
||
|
where => [ $valid_for_type => 1 ]);
|
||
|
}
|
||
|
|
||
|
#TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden
|
||
|
sub new_from {
|
||
|
my ($class, $source, %params) = @_;
|
||
|
my %allowed_sources = map { $_ => 1 } qw(
|
||
|
SL::DB::Reclamation
|
||
|
);
|
||
|
unless( $allowed_sources{ref $source} ) {
|
||
|
croak("Unsupported source object type '" . ref($source) . "'");
|
||
|
}
|
||
|
croak("A destination type must be given as parameter") unless $params{destination_type};
|
||
|
|
||
|
my $destination_type = delete $params{destination_type};
|
||
|
|
||
|
my @from_tos = (
|
||
|
#Reclamation
|
||
|
{ from => 'sales_reclamation', to => 'sales_reclamation', abbr => 'srsr', },
|
||
|
{ from => 'purchase_reclamation', to => 'purchase_reclamation', abbr => 'prpr', },
|
||
|
{ from => 'sales_reclamation', to => 'purchase_reclamation', abbr => 'srpr', },
|
||
|
{ from => 'purchase_reclamation', to => 'sales_reclamation', abbr => 'prsr', },
|
||
|
);
|
||
|
my $from_to = (grep { $_->{from} eq $source->type && $_->{to} eq $destination_type} @from_tos)[0];
|
||
|
if (!$from_to) {
|
||
|
croak("Cannot convert from '" . $source->type . "' to '" . $destination_type . "'");
|
||
|
}
|
||
|
|
||
|
my $is_abbr_any = sub {
|
||
|
any { $from_to->{abbr} eq $_ } @_;
|
||
|
};
|
||
|
|
||
|
my %record_args = (
|
||
|
record_number => undef,
|
||
|
employee => SL::DB::Manager::Employee->current,
|
||
|
closed => 0,
|
||
|
delivered => 0,
|
||
|
transdate => DateTime->today_local,
|
||
|
reqdate => DateTime->today_local->next_workday(),
|
||
|
);
|
||
|
if ( $is_abbr_any->(qw(srsr prpr srpr prsr)) ) { #Reclamation
|
||
|
map { $record_args{$_} = $source->$_ } # {{{ for vim folds
|
||
|
qw(
|
||
|
amount
|
||
|
contact_id
|
||
|
currency_id
|
||
|
customer_id
|
||
|
cv_record_number
|
||
|
delivery_term_id
|
||
|
department_id
|
||
|
exchangerate
|
||
|
globalproject_id
|
||
|
intnotes
|
||
|
language_id
|
||
|
netamount
|
||
|
notes
|
||
|
payment_id
|
||
|
salesman_id
|
||
|
shippingpoint
|
||
|
shipvia
|
||
|
tax_point
|
||
|
taxincluded
|
||
|
taxzone_id
|
||
|
transaction_description
|
||
|
vendor_id
|
||
|
); # }}} for vim folds
|
||
|
}
|
||
|
|
||
|
if ( ($from_to->{from} =~ m{sales}) && ($from_to->{to} =~ m{purchase}) ) {
|
||
|
$record_args{customer_id} = undef;
|
||
|
$record_args{salesman_id} = undef;
|
||
|
$record_args{payment_id} = undef;
|
||
|
$record_args{delivery_term_id} = undef;
|
||
|
}
|
||
|
if ( ($from_to->{from} =~ m{purchase}) && ($from_to->{to} =~ m{sales}) ) {
|
||
|
$record_args{vendor_id} = undef;
|
||
|
$record_args{salesman_id} = undef;
|
||
|
$record_args{payment_id} = undef;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ($source->can('shipto_id')) {
|
||
|
# Custom shipto addresses (the ones specific to the sales/purchase record and
|
||
|
# not to the customer/vendor) are only linked from shipto → record.
|
||
|
# Meaning record.shipto_id will not be filled in that case.
|
||
|
if (!$source->shipto_id && $source->id) {
|
||
|
$record_args{custom_shipto} = $source->custom_shipto->clone($class) if $source->can('custom_shipto') && $source->custom_shipto;
|
||
|
} elsif ($source->shipto_id) {
|
||
|
$record_args{shipto_id} = $source->shipto_id;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
my $reclamation = $class->new(%record_args);
|
||
|
$reclamation->assign_attributes(%{ $params{attributes} }) if $params{attributes};
|
||
|
|
||
|
unless ($params{no_linked_records}) {
|
||
|
$reclamation->{"converted_from_record_type_ref"} = ref($source);
|
||
|
$reclamation->{"converted_from_record_id"} = $source->id;
|
||
|
};
|
||
|
|
||
|
my $items = delete($params{items}) || $source->items;
|
||
|
|
||
|
my @items = map { SL::DB::ReclamationItem->new_from($_, $from_to->{to}, no_linked_records => $params{no_linked_records}); } @{ $items };
|
||
|
|
||
|
@items = grep { $params{item_filter}->($_) } @items if $params{item_filter};
|
||
|
@items = grep { $_->qty * 1 } @items if $params{skip_items_zero_qty};
|
||
|
@items = grep { $_->qty >=0 } @items if $params{skip_items_negative_qty};
|
||
|
|
||
|
$reclamation->items(\@items);
|
||
|
return $reclamation;
|
||
|
}
|
||
|
|
||
|
sub customervendor {
|
||
|
my ($reclamation) = @_;
|
||
|
return $reclamation->is_sales ? $reclamation->customer : $reclamation->vendor;
|
||
|
}
|
||
|
|
||
|
sub date {
|
||
|
goto &transdate;
|
||
|
}
|
||
|
|
||
|
sub digest {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
sprintf "%s %s %s (%s)",
|
||
|
$self->record_number,
|
||
|
$self->customervendor->name,
|
||
|
$self->amount_as_number,
|
||
|
$self->date->to_kivitendo;
|
||
|
}
|
||
|
|
||
|
1;
|
||
|
|
||
|
__END__
|
||
|
|
||
|
=pod
|
||
|
|
||
|
=encoding utf8
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
SL::DB::Reclamation - reclamation Datenbank Objekt.
|
||
|
|
||
|
=head1 FUNCTIONS
|
||
|
|
||
|
=head2 C<type>
|
||
|
|
||
|
Returns one of the following string types:
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item sales_reclamation
|
||
|
|
||
|
=item purchase_reclamation
|
||
|
|
||
|
=item sales_quotation
|
||
|
|
||
|
=item request_quotation
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head2 C<is_type TYPE>
|
||
|
|
||
|
Returns true if the reclamation is of the given type.
|
||
|
|
||
|
=head2 C<daily_exchangerate $val>
|
||
|
|
||
|
Gets or sets the exchangerate object's value. This is the value from the
|
||
|
table C<exchangerate> depending on the reclamation's currency, the transdate and
|
||
|
if it is a sales or purchase reclamation.
|
||
|
|
||
|
The reclamation object (respectively the table C<oe>) has an own column
|
||
|
C<exchangerate> which can be get or set with the accessor C<exchangerate>.
|
||
|
|
||
|
The idea is to drop the legacy table C<exchangerate> in the future and to
|
||
|
give all relevant tables it's own C<exchangerate> column.
|
||
|
|
||
|
So, this method is here if you need to access the "legacy" exchangerate via
|
||
|
an reclamation object.
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item C<$val>
|
||
|
|
||
|
(optional) If given, the exchangerate in the "legacy" table is set to this
|
||
|
value, depending on currency, transdate and sales or purchase.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head2 C<convert_to_delivery_order %params>
|
||
|
|
||
|
Creates a new delivery reclamation with C<$self> as the basis by calling
|
||
|
L<SL::DB::DeliveryReclamation::new_from>. That delivery reclamation is saved, and
|
||
|
C<$self> is linked to the new invoice via
|
||
|
L<SL::DB::RecordLink>. C<$self>'s C<delivered> attribute is set to
|
||
|
C<true>, and C<$self> is saved.
|
||
|
|
||
|
The arguments in C<%params> are passed to
|
||
|
L<SL::DB::DeliveryReclamation::new_from>.
|
||
|
|
||
|
Returns C<undef> on failure. Otherwise the new delivery reclamation will be
|
||
|
returned.
|
||
|
|
||
|
=head2 C<convert_to_invoice %params>
|
||
|
|
||
|
Creates a new invoice with C<$self> as the basis by calling
|
||
|
L<SL::DB::Invoice::new_from>. That invoice is posted, and C<$self> is
|
||
|
linked to the new invoice via L<SL::DB::RecordLink>. C<$self>'s
|
||
|
C<closed> attribute is set to C<true>, and C<$self> is saved.
|
||
|
|
||
|
The arguments in C<%params> are passed to L<SL::DB::Invoice::post>.
|
||
|
|
||
|
Returns the new invoice instance on success and C<undef> on
|
||
|
failure. The whole process is run inside a transaction. On failure
|
||
|
nothing is created or changed in the database.
|
||
|
|
||
|
At the moment only sales quotations and sales reclamations can be converted.
|
||
|
|
||
|
=head2 C<new_from $source, %params>
|
||
|
|
||
|
Creates a new C<SL::DB::Reclamation> instance and copies as much
|
||
|
information from C<$source> as possible. At the moment only records with the
|
||
|
same destination type as the source type and sales reclamations from
|
||
|
sales quotations and purchase reclamations from requests for quotations can be
|
||
|
created.
|
||
|
|
||
|
The C<transdate> field will be set to the current date.
|
||
|
|
||
|
The conversion copies the reclamation items as well.
|
||
|
|
||
|
Returns the new reclamation instance. The object returned is not
|
||
|
saved.
|
||
|
|
||
|
C<%params> can include the following options
|
||
|
(C<destination_type> is mandatory):
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item C<destination_type>
|
||
|
|
||
|
(mandatory)
|
||
|
The type of the newly created object. Can be C<sales_quotation>,
|
||
|
C<sales_reclamation>, C<purchase_quotation> or C<purchase_reclamation> for now.
|
||
|
|
||
|
=item C<items>
|
||
|
|
||
|
An optional array reference of RDBO instances for the items to use. If
|
||
|
missing then the method C<items_sorted> will be called on
|
||
|
C<$source>. This option can be used to override the sorting, to
|
||
|
exclude certain positions or to add additional ones.
|
||
|
|
||
|
=item C<skip_items_negative_qty>
|
||
|
|
||
|
If trueish then items with a negative quantity are skipped. Items with
|
||
|
a quantity of 0 are not affected by this option.
|
||
|
|
||
|
=item C<skip_items_zero_qty>
|
||
|
|
||
|
If trueish then items with a quantity of 0 are skipped.
|
||
|
|
||
|
=item C<item_filter>
|
||
|
|
||
|
An optional code reference that is called for each item with the item
|
||
|
as its sole parameter. Items for which the code reference returns a
|
||
|
falsish value will be skipped.
|
||
|
|
||
|
=item C<attributes>
|
||
|
|
||
|
An optional hash reference. If it exists then it is passed to C<new>
|
||
|
allowing the caller to set certain attributes for the new delivery
|
||
|
reclamation.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head1 BUGS
|
||
|
|
||
|
Nothing here yet.
|
||
|
|
||
|
=head1 AUTHOR
|
||
|
|
||
|
Sven Schöling <s.schoeling@linet-services.de>
|
||
|
|
||
|
=cut
|
||
| SL/DB/ReclamationItem.pm | ||
|---|---|---|
|
package SL::DB::ReclamationItem;
|
||
|
|
||
|
use utf8;
|
||
|
use strict;
|
||
|
|
||
|
use List::MoreUtils qw(any);
|
||
|
|
||
|
use SL::DB::MetaSetup::ReclamationItem;
|
||
|
use SL::DB::Manager::ReclamationItem;
|
||
|
use SL::DB::ReclamationReason;
|
||
|
use SL::DB::Helper::ActsAsList;
|
||
|
use SL::DB::Helper::LinkedRecords;
|
||
|
use SL::DB::Helper::RecordItem;
|
||
|
use SL::DB::Helper::CustomVariables (
|
||
|
sub_module => 'reclamation_items',
|
||
|
cvars_alias => 1,
|
||
|
overloads => {
|
||
|
parts_id => {
|
||
|
class => 'SL::DB::Part',
|
||
|
module => 'IC',
|
||
|
}
|
||
|
},
|
||
|
);
|
||
|
use SL::Helper::ShippedQty;
|
||
|
|
||
|
__PACKAGE__->meta->initialize;
|
||
|
|
||
|
__PACKAGE__->configure_acts_as_list(group_by => [qw(reclamation_id)]);
|
||
|
|
||
|
sub shipped_qty {
|
||
|
my ($self, %params) = @_;
|
||
|
|
||
|
my $force = delete $params{force};
|
||
|
|
||
|
SL::Helper::ShippedQty->new(%params)->calculate($self)->write_to_objects if $force || !defined $self->{shipped_qty};
|
||
|
|
||
|
$self->{shipped_qty};
|
||
|
}
|
||
|
|
||
|
sub is_linked_to_record {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
if(scalar(@{$self->linked_records}) || $self->{converted_from_record_item_type_ref}) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden
|
||
|
sub new_from {
|
||
|
my ($class, $source, $parent_type, %params) = @_;
|
||
|
unless (any {ref($source) eq $_}
|
||
|
qw(
|
||
|
SL::DB::ReclamationItem
|
||
|
)
|
||
|
) {
|
||
|
croak("Unsupported source object type '" . ref($source) . "'");
|
||
|
}
|
||
|
my @custom_variables = map { _clone_cvar_for_reclamation_item($_) } @{ $source->custom_variables };
|
||
|
|
||
|
|
||
|
my %item_args;
|
||
|
if (ref($source) eq 'SL::DB::ReclamationItem') {
|
||
|
map { $item_args{$_} = $source->$_ } qw(
|
||
|
active_discount_source active_price_source base_qty description discount
|
||
|
lastcost longdescription parts_id position price_factor price_factor_id
|
||
|
pricegroup_id project_id qty reason_description_ext reason_description_int
|
||
|
reason_id reqdate sellprice serialnumber
|
||
|
unit
|
||
|
);
|
||
|
$item_args{custom_variables} = \@custom_variables;
|
||
|
}
|
||
|
|
||
|
my $item = $class->new(%item_args);
|
||
|
|
||
|
if ( $source->record->is_sales() && ($parent_type =~ m{sales}) ) {
|
||
|
$item->sellprice($source->lastcost);
|
||
|
$item->discount(0);
|
||
|
}
|
||
|
if ( !$source->record->is_sales() && ($parent_type =~ m{purchase}) ) {
|
||
|
$item->lastcost($source->sellprice);
|
||
|
}
|
||
|
|
||
|
$item->assign_attributes(%{ $params{attributes} }) if $params{attributes};
|
||
|
|
||
|
unless ($params{no_linked_records}) {
|
||
|
$item->{"converted_from_record_item_type_ref"} = ref($source);
|
||
|
$item->{"converted_from_record_item_id"} = $source->id;
|
||
|
}
|
||
|
|
||
|
return $item;
|
||
|
}
|
||
|
|
||
|
sub _clone_cvar_for_reclamation_item {
|
||
|
my ($cvar) = @_;
|
||
|
|
||
|
my $cloned = $_->clone_and_reset;
|
||
|
$cloned->sub_module('reclamation_items');
|
||
|
|
||
|
return $cloned;
|
||
|
}
|
||
|
|
||
|
sub customervendor {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
return $self->reclamation->customervendor;
|
||
|
}
|
||
|
|
||
|
sub delivered_qty { goto &shipped_qty }
|
||
|
sub record { goto &reclamation }
|
||
|
sub record_id { goto &reclamation_id }
|
||
|
sub trans_id { goto &reclamation_id }
|
||
|
sub date { goto &reqdate }
|
||
|
|
||
|
1;
|
||
|
|
||
|
__END__
|
||
|
|
||
|
=pod
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
SL::DB::ReclamationItems: Rose model for reclamationitems
|
||
|
|
||
|
=head1 FUNCTIONS
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item C<shipped_qty PARAMS>
|
||
|
|
||
|
Calculates the shipped qty for this reclamationitem (measured in the current unit)
|
||
|
and returns it.
|
||
|
|
||
|
Note that the shipped qty is expected not to change within the request and is
|
||
|
cached in C<shipped_qty> once calculated. If C<< force => 1 >> is passed, the
|
||
|
existibng cache is ignored.
|
||
|
|
||
|
Given parameters will be passed to L<SL::Helper::ShippedQty>, so you can force
|
||
|
the shipped/delivered distinction like this:
|
||
|
|
||
|
$_->shipped_qty(require_stock_out => 0);
|
||
|
|
||
|
Note however that calculating shipped_qty on individual Reclamationitems is generally
|
||
|
a bad idea. See L<SL::Helper::ShippedQty> for way to compute these all at once.
|
||
|
|
||
|
=item C<delivered_qty>
|
||
|
|
||
|
Alias for L</shipped_qty>.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head1 AUTHORS
|
||
|
|
||
|
G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt>
|
||
|
|
||
|
=cut
|
||
| SL/DB/ReclamationReason.pm | ||
|---|---|---|
|
package SL::DB::ReclamationReason;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
use SL::DB::MetaSetup::ReclamationReason;
|
||
|
use SL::DB::Manager::ReclamationReason;
|
||
|
use SL::DB::Helper::ActsAsList
|
||
|
|
||
|
__PACKAGE__->meta->initialize;
|
||
|
|
||
|
sub validate {
|
||
|
my ($self) = @_;
|
||
|
|
||
|
my @errors;
|
||
|
if (!$self->name) {
|
||
|
push @errors, $::locale->text('The name is missing.');
|
||
|
}
|
||
|
if (!$self->description) {
|
||
|
push @errors, $::locale->text('The description is missing.');
|
||
|
}
|
||
|
return @errors;
|
||
|
}
|
||
|
|
||
|
1;
|
||
| scripts/rose_auto_create_model.pl | ||
|---|---|---|
|
ap => { payment_id => 'payment_terms', },
|
||
|
|
||
|
orderitems => { parts_id => 'part', trans_id => 'order', },
|
||
|
reclamation_items => { parts_id => 'part' },
|
||
|
delivery_order_items => { parts_id => 'part' },
|
||
|
invoice => { parts_id => 'part' },
|
||
|
follow_ups => { created_for_user => 'created_for_employee', created_by => 'created_by_employee', },
|
||
| sql/Pg-upgrade2/clean_up_record_links_before_delete_trigger.sql | ||
|---|---|---|
|
-- @tag: clean_up_record_links_before_delete_trigger
|
||
|
-- @description: delete trigger for record_links clean up
|
||
|
-- @depends: release_3_5_7
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION clean_up_record_links_before_delete() RETURNS trigger AS $$
|
||
|
BEGIN
|
||
|
DELETE FROM record_links
|
||
|
WHERE (from_table = TG_TABLE_NAME AND from_id = OLD.id)
|
||
|
OR (to_table = TG_TABLE_NAME AND to_id = OLD.id);
|
||
|
RETURN OLD;
|
||
|
END;
|
||
|
$$ LANGUAGE plpgsql;
|
||
| sql/Pg-upgrade2/delete_cvars_on_trans_deletion_add_reclamation_items.sql | ||
|---|---|---|
|
-- @tag: delete_cvars_on_trans_deletion_add_reclamation_items
|
||
|
-- @description: Add reclamation_items to trigger
|
||
|
-- @depends: delete_cvars_on_trans_deletion_add_shipto reclamations
|
||
|
|
||
|
CREATE OR REPLACE FUNCTION delete_custom_variables_trigger()
|
||
|
RETURNS TRIGGER AS $$
|
||
|
BEGIN
|
||
|
IF (TG_TABLE_NAME IN ('orderitems', 'delivery_order_items', 'invoice', 'reclamation_items')) THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('IC', TG_TABLE_NAME, old.id);
|
||
|
END IF;
|
||
|
|
||
|
IF (TG_TABLE_NAME = 'parts') THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('IC', '', old.id);
|
||
|
END IF;
|
||
|
|
||
|
IF (TG_TABLE_NAME IN ('customer', 'vendor')) THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('CT', '', old.id);
|
||
|
END IF;
|
||
|
|
||
|
IF (TG_TABLE_NAME = 'contacts') THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('Contacts', '', old.cp_id);
|
||
|
END IF;
|
||
|
|
||
|
IF (TG_TABLE_NAME = 'project') THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('Projects', '', old.id);
|
||
|
END IF;
|
||
|
|
||
|
IF (TG_TABLE_NAME = 'shipto') THEN
|
||
|
PERFORM delete_custom_variables_with_sub_module('ShipTo', '', old.shipto_id);
|
||
|
END IF;
|
||
|
|
||
|
RETURN old;
|
||
|
END;
|
||
|
$$ LANGUAGE plpgsql;
|
||
|
|
||
|
CREATE TRIGGER reclamation_items_delete_custom_variables_after_deletion
|
||
|
AFTER DELETE ON reclamation_items
|
||
|
FOR EACH ROW EXECUTE PROCEDURE delete_custom_variables_trigger();
|
||
| sql/Pg-upgrade2/reclamations.sql | ||
|---|---|---|
|
-- @tag: reclamations
|
||
|
-- @description: Add reclamations, reclamation_items and reclamation_reasons
|
||
|
-- @depends: release_3_5_7
|
||
|
-- @ignore: 0
|
||
|
|
||
|
CREATE TABLE reclamation_reasons (
|
||
|
id SERIAL PRIMARY KEY,
|
||
|
name TEXT NOT NULL,
|
||
|
description TEXT NOT NULL,
|
||
|
position INTEGER NOT NULL,
|
||
|
itime TIMESTAMP without time zone DEFAULT now(),
|
||
|
mtime TIMESTAMP without time zone,
|
||
|
valid_for_sales BOOLEAN NOT NULL DEFAULT false,
|
||
|
valid_for_purchase BOOLEAN NOT NULL DEFAULT false
|
||
|
);
|
||
|
CREATE TRIGGER mtime_reclamation_reasons
|
||
|
BEFORE UPDATE ON reclamation_reasons
|
||
|
FOR EACH ROW EXECUTE PROCEDURE set_mtime();
|
||
|
|
||
|
CREATE TABLE reclamations (
|
||
|
--basic
|
||
|
id INTEGER NOT NULL DEFAULT nextval('id'),
|
||
|
record_number TEXT NOT NULL,
|
||
|
transdate DATE DEFAULT now(),
|
||
|
itime TIMESTAMP without time zone DEFAULT now(),
|
||
|
mtime TIMESTAMP without time zone,
|
||
|
delivered BOOLEAN NOT NULL DEFAULT false,
|
||
|
closed BOOLEAN NOT NULL DEFAULT false,
|
||
|
--header
|
||
|
employee_id INTEGER NOT NULL REFERENCES employee(id),
|
||
|
globalproject_id INTEGER REFERENCES project(id),
|
||
|
delivery_term_id INTEGER REFERENCES delivery_terms(id),
|
||
|
shipto_id INTEGER REFERENCES shipto(shipto_id),
|
||
|
department_id INTEGER REFERENCES department(id),
|
||
|
contact_id INTEGER REFERENCES contacts(cp_id),
|
||
|
shipvia TEXT,
|
||
|
transaction_description TEXT,
|
||
|
shippingpoint TEXT,
|
||
|
cv_record_number TEXT,
|
||
|
reqdate DATE,
|
||
|
--money/summery
|
||
|
amount NUMERIC(15,5),
|
||
|
netamount NUMERIC(15,5),
|
||
|
payment_id INTEGER REFERENCES payment_terms(id),
|
||
|
currency_id INTEGER NOT NULL REFERENCES currencies(id),
|
||
|
taxincluded BOOLEAN NOT NULL,
|
||
|
tax_point DATE,
|
||
|
exchangerate NUMERIC(15,5),
|
||
|
taxzone_id INTEGER NOT NULL REFERENCES tax_zones(id),
|
||
|
--other
|
||
|
notes TEXT,
|
||
|
intnotes TEXT,
|
||
|
language_id INTEGER REFERENCES language(id),
|
||
|
|
||
|
salesman_id INTEGER REFERENCES employee(id),
|
||
|
customer_id INTEGER REFERENCES customer(id),
|
||
|
|
||
|
vendor_id INTEGER REFERENCES vendor(id),
|
||
|
|
||
|
CONSTRAINT reclamations_customervendor_check CHECK (
|
||
|
(customer_id IS NOT NULL AND vendor_id IS NULL)
|
||
|
OR (vendor_id IS NOT NULL AND customer_id IS NULL)
|
||
|
),
|
||
|
|
||
|
PRIMARY KEY (id)
|
||
|
);
|
||
|
CREATE TRIGGER mtime_reclamations BEFORE UPDATE ON reclamations FOR EACH ROW EXECUTE PROCEDURE set_mtime();
|
||
|
|
||
|
ALTER TABLE defaults ADD COLUMN p_reclamation_record_number TEXT NOT NULL DEFAULT 0;
|
||
|
ALTER TABLE defaults ADD COLUMN s_reclamation_record_number TEXT NOT NULL DEFAULT 0;
|
||
|
|
||
|
CREATE TABLE reclamation_items (
|
||
|
--base
|
||
|
id SERIAL PRIMARY KEY,
|
||
|
reclamation_id INTEGER NOT NULL REFERENCES reclamations(id) ON DELETE CASCADE,
|
||
|
reason_id INTEGER NOT NULL REFERENCES reclamation_reasons(id),
|
||
|
reason_description_ext TEXT,
|
||
|
reason_description_int TEXT,
|
||
|
position INTEGER NOT NULL CHECK(position > 0),
|
||
|
itime TIMESTAMP without time zone DEFAULT now(),
|
||
|
mtime TIMESTAMP without time zone,
|
||
|
--header
|
||
|
project_id INTEGER REFERENCES project(id) ON DELETE SET NULL,
|
||
|
--part description
|
||
|
parts_id INTEGER NOT NULL REFERENCES parts(id),
|
||
|
description TEXT,
|
||
|
longdescription TEXT,
|
||
|
serialnumber TEXT,
|
||
|
base_qty REAL,
|
||
|
qty REAL,
|
||
|
unit character varying(20) REFERENCES units(name),
|
||
|
--money
|
||
|
sellprice NUMERIC(15,5),
|
||
|
lastcost NUMERIC(15,5),
|
||
|
discount REAL,
|
||
|
pricegroup_id INTEGER REFERENCES pricegroup(id),
|
||
|
price_factor_id INTEGER REFERENCES price_factors(id),
|
||
|
price_factor NUMERIC(15,5) DEFAULT 1,
|
||
|
active_price_source TEXT NOT NULL DEFAULT ''::text,
|
||
|
active_discount_source TEXT NOT NULL DEFAULT ''::text,
|
||
|
--other
|
||
|
reqdate DATE
|
||
|
);
|
||
|
CREATE TRIGGER mtime_reclamation_items BEFORE UPDATE ON reclamation_items FOR EACH ROW EXECUTE PROCEDURE set_mtime();
|
||
| sql/Pg-upgrade2/record_links_delete_triggers__reclamations__reclamation_items.sql | ||
|---|---|---|
|
-- @tag: record_links_delete_triggers__reclamations__reclamation_items
|
||
|
-- @description: delete corresponding record_links if reclamation or reclamation_item is deleted
|
||
|
-- @depends: clean_up_record_links_before_delete_trigger reclamations
|
||
|
|
||
|
CREATE TRIGGER before_delete_reclamation_items_clean_up_record_linkes_trigger
|
||
|
BEFORE DELETE ON reclamation_items FOR EACH ROW EXECUTE
|
||
|
PROCEDURE clean_up_record_links_before_delete();
|
||
|
|
||
|
CREATE TRIGGER before_delete_reclamations_clean_up_record_linkes_trigger
|
||
|
BEFORE DELETE ON reclamations FOR EACH ROW EXECUTE
|
||
|
PROCEDURE clean_up_record_links_before_delete();
|
||
Auch abrufbar als: Unified diff
Reclamation: sql-script for data tables and rose objects added