Revision 6c053f87
Von Tamino Steinert vor etwa 2 Jahren hinzugefügt
SL/DB/Helper/ALL.pm | ||
---|---|---|
108 | 108 |
use SL::DB::ProjectStatus; |
109 | 109 |
use SL::DB::ProjectType; |
110 | 110 |
use SL::DB::PurchaseInvoice; |
111 |
use SL::DB::Reclamation; |
|
112 |
use SL::DB::ReclamationItem; |
|
113 |
use SL::DB::ReclamationReason; |
|
111 | 114 |
use SL::DB::ReconciliationLink; |
112 | 115 |
use SL::DB::RecordLink; |
113 | 116 |
use SL::DB::RecordTemplate; |
SL/DB/Helper/Mappings.pm | ||
---|---|---|
187 | 187 |
project_roles => 'project_role', |
188 | 188 |
project_statuses => 'project_status', |
189 | 189 |
project_types => 'project_type', |
190 |
reclamations => 'Reclamation', |
|
191 |
reclamation_items => 'ReclamationItem', |
|
192 |
reclamation_reasons => 'ReclamationReason', |
|
190 | 193 |
reconciliation_links => 'reconciliation_link', |
191 | 194 |
record_links => 'record_link', |
192 | 195 |
record_templates => 'record_template', |
SL/DB/Manager/Reclamation.pm | ||
---|---|---|
1 |
package SL::DB::Manager::Reclamation; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::DB::Helper::Manager); |
|
6 |
|
|
7 |
use SL::DB::Helper::Paginated; |
|
8 |
use SL::DB::Helper::Sorted; |
|
9 |
use SL::DB::Helper::Filtered; |
|
10 |
|
|
11 |
sub object_class { 'SL::DB::Reclamation' } |
|
12 |
|
|
13 |
__PACKAGE__->make_manager_methods; |
|
14 |
|
|
15 |
__PACKAGE__->add_filter_specs( |
|
16 |
type => sub { |
|
17 |
my ($key, $value, $prefix) = @_; |
|
18 |
return __PACKAGE__->type_filter($value, $prefix); |
|
19 |
}, |
|
20 |
# todo when is this used? |
|
21 |
#all => sub { |
|
22 |
# my ($key, $value, $prefix) = @_; |
|
23 |
# return or => [ map { $prefix . $_ => $value } qw(record_number customer.name vendor.name transaction_description) ] |
|
24 |
#} |
|
25 |
); |
|
26 |
|
|
27 |
sub type_filter { |
|
28 |
my $class = shift; |
|
29 |
my $type = lc(shift || ''); |
|
30 |
my $prefix = shift || ''; |
|
31 |
|
|
32 |
return (and => [ "!customer_id" => undef ]) if $type eq 'sales_reclamation'; |
|
33 |
return (and => [ "!vendor_id" => undef ]) if $type eq 'purchase_reclamation'; |
|
34 |
|
|
35 |
die "Unknown type $type"; |
|
36 |
} |
|
37 |
|
|
38 |
sub _sort_spec { |
|
39 |
return ( |
|
40 |
default => [ 'transdate', 1 ], |
|
41 |
nulls => { |
|
42 |
transaction_description => 'FIRST', |
|
43 |
default => 'LAST', |
|
44 |
}, |
|
45 |
columns => { |
|
46 |
SIMPLE => 'ALL', |
|
47 |
customer => 'lower(customer.name)', |
|
48 |
vendor => 'lower(vendor.name)', |
|
49 |
employee => 'lower(employee.name)', |
|
50 |
globalprojectnumber => 'lower(globalproject.projectnumber)', |
|
51 |
|
|
52 |
# Bug in Rose::DB::Object: the next should be |
|
53 |
# "globalproject.project_type.description". This workaround will |
|
54 |
# only work if no other table with "project_type" is visible in |
|
55 |
# the current query |
|
56 |
globalproject_type => 'lower(project_type.description)', |
|
57 |
|
|
58 |
map { ( $_ => "lower(reclamations.$_)" ) } |
|
59 |
qw(record_number cv_record_number shippingpoint shipvia notes intnotes |
|
60 |
transaction_description |
|
61 |
), |
|
62 |
}); |
|
63 |
} |
|
64 |
|
|
65 |
1; |
SL/DB/Manager/ReclamationItem.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 |
package SL::DB::Manager::ReclamationItem; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use parent qw(SL::DB::Helper::Manager); |
|
9 |
|
|
10 |
sub object_class { 'SL::DB::ReclamationItem' } |
|
11 |
|
|
12 |
__PACKAGE__->make_manager_methods; |
|
13 |
|
|
14 |
1; |
SL/DB/Manager/ReclamationReason.pm | ||
---|---|---|
1 |
package SL::DB::Manager::ReclamationReason; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::DB::Helper::Manager); |
|
6 |
use SL::DB::Helper::Paginated; |
|
7 |
use SL::DB::Helper::Filtered; |
|
8 |
|
|
9 |
use SL::DB::Helper::Sorted; |
|
10 |
|
|
11 |
sub object_class { 'SL::DB::ReclamationReason' } |
|
12 |
|
|
13 |
__PACKAGE__->make_manager_methods; |
|
14 |
__PACKAGE__->add_filter_specs( |
|
15 |
all => sub { |
|
16 |
my ($key, $value, $prefix) = @_; |
|
17 |
return or => [ map { $prefix . $_ => $value } qw(reclamation_reason) ] |
|
18 |
}, |
|
19 |
); |
|
20 |
|
|
21 |
sub _sort_spec { |
|
22 |
return ( default => [ 'position', 1 ], |
|
23 |
columns => { SIMPLE => 'ALL' }); |
|
24 |
} |
|
25 |
1; |
SL/DB/MetaSetup/Reclamation.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::Reclamation; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('reclamations'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
amount => { type => 'numeric', precision => 15, scale => 5 }, |
|
13 |
closed => { type => 'boolean', default => 'false', not_null => 1 }, |
|
14 |
contact_id => { type => 'integer' }, |
|
15 |
currency_id => { type => 'integer', not_null => 1 }, |
|
16 |
customer_id => { type => 'integer' }, |
|
17 |
cv_record_number => { type => 'text' }, |
|
18 |
delivered => { type => 'boolean', default => 'false', not_null => 1 }, |
|
19 |
delivery_term_id => { type => 'integer' }, |
|
20 |
department_id => { type => 'integer' }, |
|
21 |
employee_id => { type => 'integer', not_null => 1 }, |
|
22 |
exchangerate => { type => 'numeric', precision => 15, scale => 5 }, |
|
23 |
globalproject_id => { type => 'integer' }, |
|
24 |
id => { type => 'integer', not_null => 1, sequence => 'id' }, |
|
25 |
intnotes => { type => 'text' }, |
|
26 |
itime => { type => 'timestamp', default => 'now()' }, |
|
27 |
language_id => { type => 'integer' }, |
|
28 |
mtime => { type => 'timestamp' }, |
|
29 |
netamount => { type => 'numeric', precision => 15, scale => 5 }, |
|
30 |
notes => { type => 'text' }, |
|
31 |
payment_id => { type => 'integer' }, |
|
32 |
record_number => { type => 'text', not_null => 1 }, |
|
33 |
reqdate => { type => 'date' }, |
|
34 |
salesman_id => { type => 'integer' }, |
|
35 |
shippingpoint => { type => 'text' }, |
|
36 |
shipto_id => { type => 'integer' }, |
|
37 |
shipvia => { type => 'text' }, |
|
38 |
tax_point => { type => 'date' }, |
|
39 |
taxincluded => { type => 'boolean', not_null => 1 }, |
|
40 |
taxzone_id => { type => 'integer', not_null => 1 }, |
|
41 |
transaction_description => { type => 'text' }, |
|
42 |
transdate => { type => 'date', default => 'now()' }, |
|
43 |
vendor_id => { type => 'integer' }, |
|
44 |
); |
|
45 |
|
|
46 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
47 |
|
|
48 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
49 |
|
|
50 |
__PACKAGE__->meta->foreign_keys( |
|
51 |
contact => { |
|
52 |
class => 'SL::DB::Contact', |
|
53 |
key_columns => { contact_id => 'cp_id' }, |
|
54 |
}, |
|
55 |
|
|
56 |
currency => { |
|
57 |
class => 'SL::DB::Currency', |
|
58 |
key_columns => { currency_id => 'id' }, |
|
59 |
}, |
|
60 |
|
|
61 |
customer => { |
|
62 |
class => 'SL::DB::Customer', |
|
63 |
key_columns => { customer_id => 'id' }, |
|
64 |
}, |
|
65 |
|
|
66 |
delivery_term => { |
|
67 |
class => 'SL::DB::DeliveryTerm', |
|
68 |
key_columns => { delivery_term_id => 'id' }, |
|
69 |
}, |
|
70 |
|
|
71 |
department => { |
|
72 |
class => 'SL::DB::Department', |
|
73 |
key_columns => { department_id => 'id' }, |
|
74 |
}, |
|
75 |
|
|
76 |
employee => { |
|
77 |
class => 'SL::DB::Employee', |
|
78 |
key_columns => { employee_id => 'id' }, |
|
79 |
}, |
|
80 |
|
|
81 |
globalproject => { |
|
82 |
class => 'SL::DB::Project', |
|
83 |
key_columns => { globalproject_id => 'id' }, |
|
84 |
}, |
|
85 |
|
|
86 |
language => { |
|
87 |
class => 'SL::DB::Language', |
|
88 |
key_columns => { language_id => 'id' }, |
|
89 |
}, |
|
90 |
|
|
91 |
payment => { |
|
92 |
class => 'SL::DB::PaymentTerm', |
|
93 |
key_columns => { payment_id => 'id' }, |
|
94 |
}, |
|
95 |
|
|
96 |
salesman => { |
|
97 |
class => 'SL::DB::Employee', |
|
98 |
key_columns => { salesman_id => 'id' }, |
|
99 |
}, |
|
100 |
|
|
101 |
shipto => { |
|
102 |
class => 'SL::DB::Shipto', |
|
103 |
key_columns => { shipto_id => 'shipto_id' }, |
|
104 |
}, |
|
105 |
|
|
106 |
taxzone => { |
|
107 |
class => 'SL::DB::TaxZone', |
|
108 |
key_columns => { taxzone_id => 'id' }, |
|
109 |
}, |
|
110 |
|
|
111 |
vendor => { |
|
112 |
class => 'SL::DB::Vendor', |
|
113 |
key_columns => { vendor_id => 'id' }, |
|
114 |
}, |
|
115 |
); |
|
116 |
|
|
117 |
1; |
|
118 |
; |
SL/DB/MetaSetup/ReclamationItem.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::ReclamationItem; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('reclamation_items'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
active_discount_source => { type => 'text', default => '', not_null => 1 }, |
|
13 |
active_price_source => { type => 'text', default => '', not_null => 1 }, |
|
14 |
base_qty => { type => 'float', precision => 4, scale => 4 }, |
|
15 |
description => { type => 'text' }, |
|
16 |
discount => { type => 'float', precision => 4, scale => 4 }, |
|
17 |
id => { type => 'serial', not_null => 1 }, |
|
18 |
itime => { type => 'timestamp', default => 'now()' }, |
|
19 |
lastcost => { type => 'numeric', precision => 15, scale => 5 }, |
|
20 |
longdescription => { type => 'text' }, |
|
21 |
mtime => { type => 'timestamp' }, |
|
22 |
parts_id => { type => 'integer', not_null => 1 }, |
|
23 |
position => { type => 'integer', not_null => 1 }, |
|
24 |
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 }, |
|
25 |
price_factor_id => { type => 'integer' }, |
|
26 |
pricegroup_id => { type => 'integer' }, |
|
27 |
project_id => { type => 'integer' }, |
|
28 |
qty => { type => 'float', precision => 4, scale => 4 }, |
|
29 |
reason_description_ext => { type => 'text' }, |
|
30 |
reason_description_int => { type => 'text' }, |
|
31 |
reason_id => { type => 'integer', not_null => 1 }, |
|
32 |
reclamation_id => { type => 'integer', not_null => 1 }, |
|
33 |
reqdate => { type => 'date' }, |
|
34 |
sellprice => { type => 'numeric', precision => 15, scale => 5 }, |
|
35 |
serialnumber => { type => 'text' }, |
|
36 |
unit => { type => 'varchar', length => 20 }, |
|
37 |
); |
|
38 |
|
|
39 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
40 |
|
|
41 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
42 |
|
|
43 |
__PACKAGE__->meta->foreign_keys( |
|
44 |
part => { |
|
45 |
class => 'SL::DB::Part', |
|
46 |
key_columns => { parts_id => 'id' }, |
|
47 |
}, |
|
48 |
|
|
49 |
price_factor_obj => { |
|
50 |
class => 'SL::DB::PriceFactor', |
|
51 |
key_columns => { price_factor_id => 'id' }, |
|
52 |
}, |
|
53 |
|
|
54 |
pricegroup => { |
|
55 |
class => 'SL::DB::Pricegroup', |
|
56 |
key_columns => { pricegroup_id => 'id' }, |
|
57 |
}, |
|
58 |
|
|
59 |
project => { |
|
60 |
class => 'SL::DB::Project', |
|
61 |
key_columns => { project_id => 'id' }, |
|
62 |
}, |
|
63 |
|
|
64 |
reason => { |
|
65 |
class => 'SL::DB::ReclamationReason', |
|
66 |
key_columns => { reason_id => 'id' }, |
|
67 |
}, |
|
68 |
|
|
69 |
reclamation => { |
|
70 |
class => 'SL::DB::Reclamation', |
|
71 |
key_columns => { reclamation_id => 'id' }, |
|
72 |
}, |
|
73 |
|
|
74 |
unit_obj => { |
|
75 |
class => 'SL::DB::Unit', |
|
76 |
key_columns => { unit => 'name' }, |
|
77 |
}, |
|
78 |
); |
|
79 |
|
|
80 |
1; |
|
81 |
; |
SL/DB/MetaSetup/ReclamationReason.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::ReclamationReason; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('reclamation_reasons'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
description => { type => 'text', not_null => 1 }, |
|
13 |
id => { type => 'serial', not_null => 1 }, |
|
14 |
itime => { type => 'timestamp', default => 'now()' }, |
|
15 |
mtime => { type => 'timestamp' }, |
|
16 |
name => { type => 'text', not_null => 1 }, |
|
17 |
position => { type => 'integer', not_null => 1 }, |
|
18 |
valid_for_purchase => { type => 'boolean', default => 'false', not_null => 1 }, |
|
19 |
valid_for_sales => { type => 'boolean', default => 'false', not_null => 1 }, |
|
20 |
); |
|
21 |
|
|
22 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
23 |
|
|
24 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
25 |
|
|
26 |
1; |
|
27 |
; |
SL/DB/Reclamation.pm | ||
---|---|---|
1 |
package SL::DB::Reclamation; |
|
2 |
|
|
3 |
use utf8; |
|
4 |
use strict; |
|
5 |
|
|
6 |
use Carp; |
|
7 |
use DateTime; |
|
8 |
use List::Util qw(max sum0); |
|
9 |
use List::MoreUtils qw(any); |
|
10 |
|
|
11 |
use SL::DB::MetaSetup::Reclamation; |
|
12 |
use SL::DB::Manager::Reclamation; |
|
13 |
use SL::DB::Helper::Attr; |
|
14 |
use SL::DB::Helper::AttrHTML; |
|
15 |
use SL::DB::Helper::AttrSorted; |
|
16 |
use SL::DB::Helper::FlattenToForm; |
|
17 |
use SL::DB::Helper::LinkedRecords; |
|
18 |
use SL::DB::Helper::PriceTaxCalculator; |
|
19 |
use SL::DB::Helper::PriceUpdater; |
|
20 |
use SL::DB::Helper::TransNumberGenerator; |
|
21 |
use SL::Locale::String qw(t8); |
|
22 |
use SL::RecordLinks; |
|
23 |
use Rose::DB::Object::Helpers qw(as_tree); |
|
24 |
|
|
25 |
__PACKAGE__->meta->add_relationship( |
|
26 |
|
|
27 |
reclamation_items => { |
|
28 |
type => 'one to many', |
|
29 |
class => 'SL::DB::ReclamationItem', |
|
30 |
column_map => { id => 'reclamation_id' }, |
|
31 |
manager_args => { |
|
32 |
with_objects => [ 'part', 'reason' ] |
|
33 |
} |
|
34 |
}, |
|
35 |
custom_shipto => { |
|
36 |
type => 'one to one', |
|
37 |
class => 'SL::DB::Shipto', |
|
38 |
column_map => { id => 'trans_id' }, |
|
39 |
query_args => [ module => 'Reclamation' ], |
|
40 |
}, |
|
41 |
exchangerate_obj => { |
|
42 |
type => 'one to one', |
|
43 |
class => 'SL::DB::Exchangerate', |
|
44 |
column_map => { currency_id => 'currency_id', transdate => 'transdate' }, |
|
45 |
}, |
|
46 |
); |
|
47 |
|
|
48 |
SL::DB::Helper::Attr::make(__PACKAGE__, daily_exchangerate => 'numeric'); |
|
49 |
|
|
50 |
__PACKAGE__->meta->initialize; |
|
51 |
|
|
52 |
__PACKAGE__->attr_html('notes'); |
|
53 |
__PACKAGE__->attr_sorted('items'); |
|
54 |
|
|
55 |
__PACKAGE__->before_save('_before_save_set_record_number'); |
|
56 |
__PACKAGE__->before_save('_before_save_remove_empty_custom_shipto'); |
|
57 |
__PACKAGE__->before_save('_before_save_set_custom_shipto_module'); |
|
58 |
|
|
59 |
# hooks |
|
60 |
|
|
61 |
sub _before_save_set_record_number { |
|
62 |
my ($self) = @_; |
|
63 |
|
|
64 |
$self->create_trans_number if !$self->record_number; |
|
65 |
|
|
66 |
return 1; |
|
67 |
} |
|
68 |
|
|
69 |
sub _before_save_remove_empty_custom_shipto { |
|
70 |
my ($self) = @_; |
|
71 |
|
|
72 |
$self->custom_shipto(undef) if $self->custom_shipto && $self->custom_shipto->is_empty; |
|
73 |
|
|
74 |
return 1; |
|
75 |
} |
|
76 |
|
|
77 |
sub _before_save_set_custom_shipto_module { |
|
78 |
my ($self) = @_; |
|
79 |
|
|
80 |
$self->custom_shipto->module('Reclamation') if $self->custom_shipto; |
|
81 |
|
|
82 |
return 1; |
|
83 |
} |
|
84 |
|
|
85 |
# methods |
|
86 |
|
|
87 |
sub items { goto &reclamation_items; } |
|
88 |
sub add_items { goto &add_reclamation_items; } |
|
89 |
sub record_items { goto &reclamation_items; } |
|
90 |
|
|
91 |
sub type { |
|
92 |
my ($self) = @_; |
|
93 |
|
|
94 |
return 'sales_reclamation' if $self->customer_id; |
|
95 |
return 'purchase_reclamation' if $self->vendor_id; |
|
96 |
|
|
97 |
return; |
|
98 |
} |
|
99 |
|
|
100 |
sub is_type { |
|
101 |
my ($self, $type) = @_; |
|
102 |
return $self->type eq $type; |
|
103 |
} |
|
104 |
|
|
105 |
sub effective_tax_point { |
|
106 |
my ($self) = @_; |
|
107 |
|
|
108 |
return $self->tax_point || $self->reqdate || $self->transdate; |
|
109 |
} |
|
110 |
|
|
111 |
sub displayable_type { |
|
112 |
my $type = shift->type; |
|
113 |
|
|
114 |
return $::locale->text('Sales Reclamation') if $type eq 'sales_reclamation'; |
|
115 |
return $::locale->text('Purchase Reclamation') if $type eq 'purchase_reclamation'; |
|
116 |
|
|
117 |
die 'invalid type'; |
|
118 |
} |
|
119 |
|
|
120 |
sub displayable_name { |
|
121 |
join ' ', grep $_, map $_[0]->$_, qw(displayable_type record_number); |
|
122 |
}; |
|
123 |
|
|
124 |
sub is_sales { |
|
125 |
croak 'not an accessor' if @_ > 1; |
|
126 |
return !!shift->customer_id; |
|
127 |
} |
|
128 |
|
|
129 |
sub daily_exchangerate { |
|
130 |
my ($self, $val) = @_; |
|
131 |
|
|
132 |
return 1 if $self->currency_id == $::instance_conf->get_currency_id; |
|
133 |
|
|
134 |
my $rate = (any { $self->is_type($_) } qw(sales_reclamation)) ? 'buy' |
|
135 |
: (any { $self->is_type($_) } qw(purchase_reclamation)) ? 'sell' |
|
136 |
: undef; |
|
137 |
return if !$rate; |
|
138 |
|
|
139 |
if (defined $val) { |
|
140 |
croak t8('exchange rate has to be positive') if $val <= 0; |
|
141 |
if (!$self->exchangerate_obj) { |
|
142 |
$self->exchangerate_obj(SL::DB::Exchangerate->new( |
|
143 |
currency_id => $self->currency_id, |
|
144 |
transdate => $self->transdate, |
|
145 |
$rate => $val, |
|
146 |
)); |
|
147 |
} elsif (!defined $self->exchangerate_obj->$rate) { |
|
148 |
$self->exchangerate_obj->$rate($val); |
|
149 |
} else { |
|
150 |
croak t8('exchange rate already exists, no update allowed'); |
|
151 |
} |
|
152 |
} |
|
153 |
return $self->exchangerate_obj->$rate if $self->exchangerate_obj; |
|
154 |
} |
|
155 |
|
|
156 |
sub taxes { |
|
157 |
my ($self) = @_; |
|
158 |
# add taxes to recalmation |
|
159 |
my %pat = $self->calculate_prices_and_taxes(); |
|
160 |
my @taxes; |
|
161 |
foreach my $tax_id (keys %{ $pat{taxes_by_tax_id} }) { |
|
162 |
my $netamount = sum0 map { $pat{amounts}->{$_}->{amount} } grep { $pat{amounts}->{$_}->{tax_id} == $tax_id } keys %{ $pat{amounts} }; |
|
163 |
push(@taxes, { amount => $pat{taxes_by_tax_id}->{$tax_id}, |
|
164 |
netamount => $netamount, |
|
165 |
tax => SL::DB::Tax->new(id => $tax_id)->load }); |
|
166 |
} |
|
167 |
return \@taxes; |
|
168 |
} |
|
169 |
|
|
170 |
sub displayable_state { |
|
171 |
my ($self) = @_; |
|
172 |
|
|
173 |
return $self->closed ? $::locale->text('closed') : $::locale->text('open'); |
|
174 |
} |
|
175 |
|
|
176 |
sub valid_reclamation_reasons { |
|
177 |
my ($self) = @_; |
|
178 |
|
|
179 |
my $valid_for_type = ($self->type =~ m{sales} ? 'valid_for_sales' : 'valid_for_purchase'); |
|
180 |
return SL::DB::Manager::ReclamationReason->get_all_sorted( |
|
181 |
where => [ $valid_for_type => 1 ]); |
|
182 |
} |
|
183 |
|
|
184 |
#TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden |
|
185 |
sub new_from { |
|
186 |
my ($class, $source, %params) = @_; |
|
187 |
my %allowed_sources = map { $_ => 1 } qw( |
|
188 |
SL::DB::Reclamation |
|
189 |
); |
|
190 |
unless( $allowed_sources{ref $source} ) { |
|
191 |
croak("Unsupported source object type '" . ref($source) . "'"); |
|
192 |
} |
|
193 |
croak("A destination type must be given as parameter") unless $params{destination_type}; |
|
194 |
|
|
195 |
my $destination_type = delete $params{destination_type}; |
|
196 |
|
|
197 |
my @from_tos = ( |
|
198 |
#Reclamation |
|
199 |
{ from => 'sales_reclamation', to => 'sales_reclamation', abbr => 'srsr', }, |
|
200 |
{ from => 'purchase_reclamation', to => 'purchase_reclamation', abbr => 'prpr', }, |
|
201 |
{ from => 'sales_reclamation', to => 'purchase_reclamation', abbr => 'srpr', }, |
|
202 |
{ from => 'purchase_reclamation', to => 'sales_reclamation', abbr => 'prsr', }, |
|
203 |
); |
|
204 |
my $from_to = (grep { $_->{from} eq $source->type && $_->{to} eq $destination_type} @from_tos)[0]; |
|
205 |
if (!$from_to) { |
|
206 |
croak("Cannot convert from '" . $source->type . "' to '" . $destination_type . "'"); |
|
207 |
} |
|
208 |
|
|
209 |
my $is_abbr_any = sub { |
|
210 |
any { $from_to->{abbr} eq $_ } @_; |
|
211 |
}; |
|
212 |
|
|
213 |
my %record_args = ( |
|
214 |
record_number => undef, |
|
215 |
employee => SL::DB::Manager::Employee->current, |
|
216 |
closed => 0, |
|
217 |
delivered => 0, |
|
218 |
transdate => DateTime->today_local, |
|
219 |
reqdate => DateTime->today_local->next_workday(), |
|
220 |
); |
|
221 |
if ( $is_abbr_any->(qw(srsr prpr srpr prsr)) ) { #Reclamation |
|
222 |
map { $record_args{$_} = $source->$_ } # {{{ for vim folds |
|
223 |
qw( |
|
224 |
amount |
|
225 |
contact_id |
|
226 |
currency_id |
|
227 |
customer_id |
|
228 |
cv_record_number |
|
229 |
delivery_term_id |
|
230 |
department_id |
|
231 |
exchangerate |
|
232 |
globalproject_id |
|
233 |
intnotes |
|
234 |
language_id |
|
235 |
netamount |
|
236 |
notes |
|
237 |
payment_id |
|
238 |
salesman_id |
|
239 |
shippingpoint |
|
240 |
shipvia |
|
241 |
tax_point |
|
242 |
taxincluded |
|
243 |
taxzone_id |
|
244 |
transaction_description |
|
245 |
vendor_id |
|
246 |
); # }}} for vim folds |
|
247 |
} |
|
248 |
|
|
249 |
if ( ($from_to->{from} =~ m{sales}) && ($from_to->{to} =~ m{purchase}) ) { |
|
250 |
$record_args{customer_id} = undef; |
|
251 |
$record_args{salesman_id} = undef; |
|
252 |
$record_args{payment_id} = undef; |
|
253 |
$record_args{delivery_term_id} = undef; |
|
254 |
} |
|
255 |
if ( ($from_to->{from} =~ m{purchase}) && ($from_to->{to} =~ m{sales}) ) { |
|
256 |
$record_args{vendor_id} = undef; |
|
257 |
$record_args{salesman_id} = undef; |
|
258 |
$record_args{payment_id} = undef; |
|
259 |
} |
|
260 |
|
|
261 |
|
|
262 |
if ($source->can('shipto_id')) { |
|
263 |
# Custom shipto addresses (the ones specific to the sales/purchase record and |
|
264 |
# not to the customer/vendor) are only linked from shipto → record. |
|
265 |
# Meaning record.shipto_id will not be filled in that case. |
|
266 |
if (!$source->shipto_id && $source->id) { |
|
267 |
$record_args{custom_shipto} = $source->custom_shipto->clone($class) if $source->can('custom_shipto') && $source->custom_shipto; |
|
268 |
} elsif ($source->shipto_id) { |
|
269 |
$record_args{shipto_id} = $source->shipto_id; |
|
270 |
} |
|
271 |
} |
|
272 |
|
|
273 |
my $reclamation = $class->new(%record_args); |
|
274 |
$reclamation->assign_attributes(%{ $params{attributes} }) if $params{attributes}; |
|
275 |
|
|
276 |
unless ($params{no_linked_records}) { |
|
277 |
$reclamation->{"converted_from_record_type_ref"} = ref($source); |
|
278 |
$reclamation->{"converted_from_record_id"} = $source->id; |
|
279 |
}; |
|
280 |
|
|
281 |
my $items = delete($params{items}) || $source->items; |
|
282 |
|
|
283 |
my @items = map { SL::DB::ReclamationItem->new_from($_, $from_to->{to}, no_linked_records => $params{no_linked_records}); } @{ $items }; |
|
284 |
|
|
285 |
@items = grep { $params{item_filter}->($_) } @items if $params{item_filter}; |
|
286 |
@items = grep { $_->qty * 1 } @items if $params{skip_items_zero_qty}; |
|
287 |
@items = grep { $_->qty >=0 } @items if $params{skip_items_negative_qty}; |
|
288 |
|
|
289 |
$reclamation->items(\@items); |
|
290 |
return $reclamation; |
|
291 |
} |
|
292 |
|
|
293 |
sub customervendor { |
|
294 |
my ($reclamation) = @_; |
|
295 |
return $reclamation->is_sales ? $reclamation->customer : $reclamation->vendor; |
|
296 |
} |
|
297 |
|
|
298 |
sub date { |
|
299 |
goto &transdate; |
|
300 |
} |
|
301 |
|
|
302 |
sub digest { |
|
303 |
my ($self) = @_; |
|
304 |
|
|
305 |
sprintf "%s %s %s (%s)", |
|
306 |
$self->record_number, |
|
307 |
$self->customervendor->name, |
|
308 |
$self->amount_as_number, |
|
309 |
$self->date->to_kivitendo; |
|
310 |
} |
|
311 |
|
|
312 |
1; |
|
313 |
|
|
314 |
__END__ |
|
315 |
|
|
316 |
=pod |
|
317 |
|
|
318 |
=encoding utf8 |
|
319 |
|
|
320 |
=head1 NAME |
|
321 |
|
|
322 |
SL::DB::Reclamation - reclamation Datenbank Objekt. |
|
323 |
|
|
324 |
=head1 FUNCTIONS |
|
325 |
|
|
326 |
=head2 C<type> |
|
327 |
|
|
328 |
Returns one of the following string types: |
|
329 |
|
|
330 |
=over 4 |
|
331 |
|
|
332 |
=item sales_reclamation |
|
333 |
|
|
334 |
=item purchase_reclamation |
|
335 |
|
|
336 |
=item sales_quotation |
|
337 |
|
|
338 |
=item request_quotation |
|
339 |
|
|
340 |
=back |
|
341 |
|
|
342 |
=head2 C<is_type TYPE> |
|
343 |
|
|
344 |
Returns true if the reclamation is of the given type. |
|
345 |
|
|
346 |
=head2 C<daily_exchangerate $val> |
|
347 |
|
|
348 |
Gets or sets the exchangerate object's value. This is the value from the |
|
349 |
table C<exchangerate> depending on the reclamation's currency, the transdate and |
|
350 |
if it is a sales or purchase reclamation. |
|
351 |
|
|
352 |
The reclamation object (respectively the table C<oe>) has an own column |
|
353 |
C<exchangerate> which can be get or set with the accessor C<exchangerate>. |
|
354 |
|
|
355 |
The idea is to drop the legacy table C<exchangerate> in the future and to |
|
356 |
give all relevant tables it's own C<exchangerate> column. |
|
357 |
|
|
358 |
So, this method is here if you need to access the "legacy" exchangerate via |
|
359 |
an reclamation object. |
|
360 |
|
|
361 |
=over 4 |
|
362 |
|
|
363 |
=item C<$val> |
|
364 |
|
|
365 |
(optional) If given, the exchangerate in the "legacy" table is set to this |
|
366 |
value, depending on currency, transdate and sales or purchase. |
|
367 |
|
|
368 |
=back |
|
369 |
|
|
370 |
=head2 C<convert_to_delivery_order %params> |
|
371 |
|
|
372 |
Creates a new delivery reclamation with C<$self> as the basis by calling |
|
373 |
L<SL::DB::DeliveryReclamation::new_from>. That delivery reclamation is saved, and |
|
374 |
C<$self> is linked to the new invoice via |
|
375 |
L<SL::DB::RecordLink>. C<$self>'s C<delivered> attribute is set to |
|
376 |
C<true>, and C<$self> is saved. |
|
377 |
|
|
378 |
The arguments in C<%params> are passed to |
|
379 |
L<SL::DB::DeliveryReclamation::new_from>. |
|
380 |
|
|
381 |
Returns C<undef> on failure. Otherwise the new delivery reclamation will be |
|
382 |
returned. |
|
383 |
|
|
384 |
=head2 C<convert_to_invoice %params> |
|
385 |
|
|
386 |
Creates a new invoice with C<$self> as the basis by calling |
|
387 |
L<SL::DB::Invoice::new_from>. That invoice is posted, and C<$self> is |
|
388 |
linked to the new invoice via L<SL::DB::RecordLink>. C<$self>'s |
|
389 |
C<closed> attribute is set to C<true>, and C<$self> is saved. |
|
390 |
|
|
391 |
The arguments in C<%params> are passed to L<SL::DB::Invoice::post>. |
|
392 |
|
|
393 |
Returns the new invoice instance on success and C<undef> on |
|
394 |
failure. The whole process is run inside a transaction. On failure |
|
395 |
nothing is created or changed in the database. |
|
396 |
|
|
397 |
At the moment only sales quotations and sales reclamations can be converted. |
|
398 |
|
|
399 |
=head2 C<new_from $source, %params> |
|
400 |
|
|
401 |
Creates a new C<SL::DB::Reclamation> instance and copies as much |
|
402 |
information from C<$source> as possible. At the moment only records with the |
|
403 |
same destination type as the source type and sales reclamations from |
|
404 |
sales quotations and purchase reclamations from requests for quotations can be |
|
405 |
created. |
|
406 |
|
|
407 |
The C<transdate> field will be set to the current date. |
|
408 |
|
|
409 |
The conversion copies the reclamation items as well. |
|
410 |
|
|
411 |
Returns the new reclamation instance. The object returned is not |
|
412 |
saved. |
|
413 |
|
|
414 |
C<%params> can include the following options |
|
415 |
(C<destination_type> is mandatory): |
|
416 |
|
|
417 |
=over 4 |
|
418 |
|
|
419 |
=item C<destination_type> |
|
420 |
|
|
421 |
(mandatory) |
|
422 |
The type of the newly created object. Can be C<sales_quotation>, |
|
423 |
C<sales_reclamation>, C<purchase_quotation> or C<purchase_reclamation> for now. |
|
424 |
|
|
425 |
=item C<items> |
|
426 |
|
|
427 |
An optional array reference of RDBO instances for the items to use. If |
|
428 |
missing then the method C<items_sorted> will be called on |
|
429 |
C<$source>. This option can be used to override the sorting, to |
|
430 |
exclude certain positions or to add additional ones. |
|
431 |
|
|
432 |
=item C<skip_items_negative_qty> |
|
433 |
|
|
434 |
If trueish then items with a negative quantity are skipped. Items with |
|
435 |
a quantity of 0 are not affected by this option. |
|
436 |
|
|
437 |
=item C<skip_items_zero_qty> |
|
438 |
|
|
439 |
If trueish then items with a quantity of 0 are skipped. |
|
440 |
|
|
441 |
=item C<item_filter> |
|
442 |
|
|
443 |
An optional code reference that is called for each item with the item |
|
444 |
as its sole parameter. Items for which the code reference returns a |
|
445 |
falsish value will be skipped. |
|
446 |
|
|
447 |
=item C<attributes> |
|
448 |
|
|
449 |
An optional hash reference. If it exists then it is passed to C<new> |
|
450 |
allowing the caller to set certain attributes for the new delivery |
|
451 |
reclamation. |
|
452 |
|
|
453 |
=back |
|
454 |
|
|
455 |
=head1 BUGS |
|
456 |
|
|
457 |
Nothing here yet. |
|
458 |
|
|
459 |
=head1 AUTHOR |
|
460 |
|
|
461 |
Sven Schöling <s.schoeling@linet-services.de> |
|
462 |
|
|
463 |
=cut |
SL/DB/ReclamationItem.pm | ||
---|---|---|
1 |
package SL::DB::ReclamationItem; |
|
2 |
|
|
3 |
use utf8; |
|
4 |
use strict; |
|
5 |
|
|
6 |
use List::MoreUtils qw(any); |
|
7 |
|
|
8 |
use SL::DB::MetaSetup::ReclamationItem; |
|
9 |
use SL::DB::Manager::ReclamationItem; |
|
10 |
use SL::DB::ReclamationReason; |
|
11 |
use SL::DB::Helper::ActsAsList; |
|
12 |
use SL::DB::Helper::LinkedRecords; |
|
13 |
use SL::DB::Helper::RecordItem; |
|
14 |
use SL::DB::Helper::CustomVariables ( |
|
15 |
sub_module => 'reclamation_items', |
|
16 |
cvars_alias => 1, |
|
17 |
overloads => { |
|
18 |
parts_id => { |
|
19 |
class => 'SL::DB::Part', |
|
20 |
module => 'IC', |
|
21 |
} |
|
22 |
}, |
|
23 |
); |
|
24 |
use SL::Helper::ShippedQty; |
|
25 |
|
|
26 |
__PACKAGE__->meta->initialize; |
|
27 |
|
|
28 |
__PACKAGE__->configure_acts_as_list(group_by => [qw(reclamation_id)]); |
|
29 |
|
|
30 |
sub shipped_qty { |
|
31 |
my ($self, %params) = @_; |
|
32 |
|
|
33 |
my $force = delete $params{force}; |
|
34 |
|
|
35 |
SL::Helper::ShippedQty->new(%params)->calculate($self)->write_to_objects if $force || !defined $self->{shipped_qty}; |
|
36 |
|
|
37 |
$self->{shipped_qty}; |
|
38 |
} |
|
39 |
|
|
40 |
sub is_linked_to_record { |
|
41 |
my ($self) = @_; |
|
42 |
|
|
43 |
if(scalar(@{$self->linked_records}) || $self->{converted_from_record_item_type_ref}) { |
|
44 |
return 1; |
|
45 |
} |
|
46 |
|
|
47 |
return 0; |
|
48 |
} |
|
49 |
|
|
50 |
#TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden |
|
51 |
sub new_from { |
|
52 |
my ($class, $source, $parent_type, %params) = @_; |
|
53 |
unless (any {ref($source) eq $_} |
|
54 |
qw( |
|
55 |
SL::DB::ReclamationItem |
|
56 |
) |
|
57 |
) { |
|
58 |
croak("Unsupported source object type '" . ref($source) . "'"); |
|
59 |
} |
|
60 |
my @custom_variables = map { _clone_cvar_for_reclamation_item($_) } @{ $source->custom_variables }; |
|
61 |
|
|
62 |
|
|
63 |
my %item_args; |
|
64 |
if (ref($source) eq 'SL::DB::ReclamationItem') { |
|
65 |
map { $item_args{$_} = $source->$_ } qw( |
|
66 |
active_discount_source active_price_source base_qty description discount |
|
67 |
lastcost longdescription parts_id position price_factor price_factor_id |
|
68 |
pricegroup_id project_id qty reason_description_ext reason_description_int |
|
69 |
reason_id reqdate sellprice serialnumber |
|
70 |
unit |
|
71 |
); |
|
72 |
$item_args{custom_variables} = \@custom_variables; |
|
73 |
} |
|
74 |
|
|
75 |
my $item = $class->new(%item_args); |
|
76 |
|
|
77 |
if ( $source->record->is_sales() && ($parent_type =~ m{sales}) ) { |
|
78 |
$item->sellprice($source->lastcost); |
|
79 |
$item->discount(0); |
|
80 |
} |
|
81 |
if ( !$source->record->is_sales() && ($parent_type =~ m{purchase}) ) { |
|
82 |
$item->lastcost($source->sellprice); |
|
83 |
} |
|
84 |
|
|
85 |
$item->assign_attributes(%{ $params{attributes} }) if $params{attributes}; |
|
86 |
|
|
87 |
unless ($params{no_linked_records}) { |
|
88 |
$item->{"converted_from_record_item_type_ref"} = ref($source); |
|
89 |
$item->{"converted_from_record_item_id"} = $source->id; |
|
90 |
} |
|
91 |
|
|
92 |
return $item; |
|
93 |
} |
|
94 |
|
|
95 |
sub _clone_cvar_for_reclamation_item { |
|
96 |
my ($cvar) = @_; |
|
97 |
|
|
98 |
my $cloned = $_->clone_and_reset; |
|
99 |
$cloned->sub_module('reclamation_items'); |
|
100 |
|
|
101 |
return $cloned; |
|
102 |
} |
|
103 |
|
|
104 |
sub customervendor { |
|
105 |
my ($self) = @_; |
|
106 |
|
|
107 |
return $self->reclamation->customervendor; |
|
108 |
} |
|
109 |
|
|
110 |
sub delivered_qty { goto &shipped_qty } |
|
111 |
sub record { goto &reclamation } |
|
112 |
sub record_id { goto &reclamation_id } |
|
113 |
sub trans_id { goto &reclamation_id } |
|
114 |
sub date { goto &reqdate } |
|
115 |
|
|
116 |
1; |
|
117 |
|
|
118 |
__END__ |
|
119 |
|
|
120 |
=pod |
|
121 |
|
|
122 |
=head1 NAME |
|
123 |
|
|
124 |
SL::DB::ReclamationItems: Rose model for reclamationitems |
|
125 |
|
|
126 |
=head1 FUNCTIONS |
|
127 |
|
|
128 |
=over 4 |
|
129 |
|
|
130 |
=item C<shipped_qty PARAMS> |
|
131 |
|
|
132 |
Calculates the shipped qty for this reclamationitem (measured in the current unit) |
|
133 |
and returns it. |
|
134 |
|
|
135 |
Note that the shipped qty is expected not to change within the request and is |
|
136 |
cached in C<shipped_qty> once calculated. If C<< force => 1 >> is passed, the |
|
137 |
existibng cache is ignored. |
|
138 |
|
|
139 |
Given parameters will be passed to L<SL::Helper::ShippedQty>, so you can force |
|
140 |
the shipped/delivered distinction like this: |
|
141 |
|
|
142 |
$_->shipped_qty(require_stock_out => 0); |
|
143 |
|
|
144 |
Note however that calculating shipped_qty on individual Reclamationitems is generally |
|
145 |
a bad idea. See L<SL::Helper::ShippedQty> for way to compute these all at once. |
|
146 |
|
|
147 |
=item C<delivered_qty> |
|
148 |
|
|
149 |
Alias for L</shipped_qty>. |
|
150 |
|
|
151 |
=back |
|
152 |
|
|
153 |
=head1 AUTHORS |
|
154 |
|
|
155 |
G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt> |
|
156 |
|
|
157 |
=cut |
SL/DB/ReclamationReason.pm | ||
---|---|---|
1 |
package SL::DB::ReclamationReason; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use SL::DB::MetaSetup::ReclamationReason; |
|
6 |
use SL::DB::Manager::ReclamationReason; |
|
7 |
use SL::DB::Helper::ActsAsList |
|
8 |
|
|
9 |
__PACKAGE__->meta->initialize; |
|
10 |
|
|
11 |
sub validate { |
|
12 |
my ($self) = @_; |
|
13 |
|
|
14 |
my @errors; |
|
15 |
if (!$self->name) { |
|
16 |
push @errors, $::locale->text('The name is missing.'); |
|
17 |
} |
|
18 |
if (!$self->description) { |
|
19 |
push @errors, $::locale->text('The description is missing.'); |
|
20 |
} |
|
21 |
return @errors; |
|
22 |
} |
|
23 |
|
|
24 |
1; |
scripts/rose_auto_create_model.pl | ||
---|---|---|
72 | 72 |
ap => { payment_id => 'payment_terms', }, |
73 | 73 |
|
74 | 74 |
orderitems => { parts_id => 'part', trans_id => 'order', }, |
75 |
reclamation_items => { parts_id => 'part' }, |
|
75 | 76 |
delivery_order_items => { parts_id => 'part' }, |
76 | 77 |
invoice => { parts_id => 'part' }, |
77 | 78 |
follow_ups => { created_by => 'created_by_employee', }, |
sql/Pg-upgrade2/clean_up_record_links_before_delete_trigger.sql | ||
---|---|---|
1 |
-- @tag: clean_up_record_links_before_delete_trigger |
|
2 |
-- @description: delete trigger for record_links clean up |
|
3 |
-- @depends: release_3_5_7 |
|
4 |
|
|
5 |
CREATE OR REPLACE FUNCTION clean_up_record_links_before_delete() RETURNS trigger AS $$ |
|
6 |
BEGIN |
|
7 |
DELETE FROM record_links |
|
8 |
WHERE (from_table = TG_TABLE_NAME AND from_id = OLD.id) |
|
9 |
OR (to_table = TG_TABLE_NAME AND to_id = OLD.id); |
|
10 |
RETURN OLD; |
|
11 |
END; |
|
12 |
$$ LANGUAGE plpgsql; |
sql/Pg-upgrade2/delete_cvars_on_trans_deletion_add_reclamation_items.sql | ||
---|---|---|
1 |
-- @tag: delete_cvars_on_trans_deletion_add_reclamation_items |
|
2 |
-- @description: Add reclamation_items to trigger |
|
3 |
-- @depends: delete_cvars_on_trans_deletion_add_shipto reclamations |
|
4 |
|
|
5 |
CREATE OR REPLACE FUNCTION delete_custom_variables_trigger() |
|
6 |
RETURNS TRIGGER AS $$ |
|
7 |
BEGIN |
|
8 |
IF (TG_TABLE_NAME IN ('orderitems', 'delivery_order_items', 'invoice', 'reclamation_items')) THEN |
|
9 |
PERFORM delete_custom_variables_with_sub_module('IC', TG_TABLE_NAME, old.id); |
|
10 |
END IF; |
|
11 |
|
|
12 |
IF (TG_TABLE_NAME = 'parts') THEN |
|
13 |
PERFORM delete_custom_variables_with_sub_module('IC', '', old.id); |
|
14 |
END IF; |
|
15 |
|
|
16 |
IF (TG_TABLE_NAME IN ('customer', 'vendor')) THEN |
|
17 |
PERFORM delete_custom_variables_with_sub_module('CT', '', old.id); |
|
18 |
END IF; |
|
19 |
|
|
20 |
IF (TG_TABLE_NAME = 'contacts') THEN |
|
21 |
PERFORM delete_custom_variables_with_sub_module('Contacts', '', old.cp_id); |
|
22 |
END IF; |
|
23 |
|
|
24 |
IF (TG_TABLE_NAME = 'project') THEN |
|
25 |
PERFORM delete_custom_variables_with_sub_module('Projects', '', old.id); |
|
26 |
END IF; |
|
27 |
|
|
28 |
IF (TG_TABLE_NAME = 'shipto') THEN |
|
29 |
PERFORM delete_custom_variables_with_sub_module('ShipTo', '', old.shipto_id); |
|
30 |
END IF; |
|
31 |
|
|
32 |
RETURN old; |
|
33 |
END; |
|
34 |
$$ LANGUAGE plpgsql; |
|
35 |
|
|
36 |
CREATE TRIGGER reclamation_items_delete_custom_variables_after_deletion |
|
37 |
AFTER DELETE ON reclamation_items |
|
38 |
FOR EACH ROW EXECUTE PROCEDURE delete_custom_variables_trigger(); |
sql/Pg-upgrade2/reclamations.sql | ||
---|---|---|
1 |
-- @tag: reclamations |
|
2 |
-- @description: Add reclamations, reclamation_items and reclamation_reasons |
|
3 |
-- @depends: release_3_5_7 |
|
4 |
-- @ignore: 0 |
|
5 |
|
|
6 |
CREATE TABLE reclamation_reasons ( |
|
7 |
id SERIAL PRIMARY KEY, |
|
8 |
name TEXT NOT NULL, |
|
9 |
description TEXT NOT NULL, |
|
10 |
position INTEGER NOT NULL, |
|
11 |
itime TIMESTAMP without time zone DEFAULT now(), |
|
12 |
mtime TIMESTAMP without time zone, |
|
13 |
valid_for_sales BOOLEAN NOT NULL DEFAULT false, |
|
14 |
valid_for_purchase BOOLEAN NOT NULL DEFAULT false |
|
15 |
); |
|
16 |
CREATE TRIGGER mtime_reclamation_reasons |
|
17 |
BEFORE UPDATE ON reclamation_reasons |
|
18 |
FOR EACH ROW EXECUTE PROCEDURE set_mtime(); |
|
19 |
|
|
20 |
CREATE TABLE reclamations ( |
|
21 |
--basic |
|
22 |
id INTEGER NOT NULL DEFAULT nextval('id'), |
|
23 |
record_number TEXT NOT NULL, |
|
24 |
transdate DATE DEFAULT now(), |
|
25 |
itime TIMESTAMP without time zone DEFAULT now(), |
|
26 |
mtime TIMESTAMP without time zone, |
|
27 |
delivered BOOLEAN NOT NULL DEFAULT false, |
|
28 |
closed BOOLEAN NOT NULL DEFAULT false, |
|
29 |
--header |
|
30 |
employee_id INTEGER NOT NULL REFERENCES employee(id), |
|
31 |
globalproject_id INTEGER REFERENCES project(id), |
|
32 |
delivery_term_id INTEGER REFERENCES delivery_terms(id), |
|
33 |
shipto_id INTEGER REFERENCES shipto(shipto_id), |
|
34 |
department_id INTEGER REFERENCES department(id), |
|
35 |
contact_id INTEGER REFERENCES contacts(cp_id), |
|
36 |
shipvia TEXT, |
|
37 |
transaction_description TEXT, |
|
38 |
shippingpoint TEXT, |
|
39 |
cv_record_number TEXT, |
|
40 |
reqdate DATE, |
|
41 |
--money/summery |
|
42 |
amount NUMERIC(15,5), |
|
43 |
netamount NUMERIC(15,5), |
|
44 |
payment_id INTEGER REFERENCES payment_terms(id), |
|
45 |
currency_id INTEGER NOT NULL REFERENCES currencies(id), |
|
46 |
taxincluded BOOLEAN NOT NULL, |
|
47 |
tax_point DATE, |
|
48 |
exchangerate NUMERIC(15,5), |
|
49 |
taxzone_id INTEGER NOT NULL REFERENCES tax_zones(id), |
|
50 |
--other |
|
51 |
notes TEXT, |
|
52 |
intnotes TEXT, |
|
53 |
language_id INTEGER REFERENCES language(id), |
|
54 |
|
|
55 |
salesman_id INTEGER REFERENCES employee(id), |
|
56 |
customer_id INTEGER REFERENCES customer(id), |
|
57 |
|
|
58 |
vendor_id INTEGER REFERENCES vendor(id), |
|
59 |
|
|
60 |
CONSTRAINT reclamations_customervendor_check CHECK ( |
|
61 |
(customer_id IS NOT NULL AND vendor_id IS NULL) |
|
62 |
OR (vendor_id IS NOT NULL AND customer_id IS NULL) |
|
63 |
), |
|
64 |
|
|
65 |
PRIMARY KEY (id) |
|
66 |
); |
|
67 |
CREATE TRIGGER mtime_reclamations BEFORE UPDATE ON reclamations FOR EACH ROW EXECUTE PROCEDURE set_mtime(); |
|
68 |
|
|
69 |
ALTER TABLE defaults ADD COLUMN p_reclamation_record_number TEXT NOT NULL DEFAULT 0; |
|
70 |
ALTER TABLE defaults ADD COLUMN s_reclamation_record_number TEXT NOT NULL DEFAULT 0; |
|
71 |
|
|
72 |
CREATE TABLE reclamation_items ( |
|
73 |
--base |
|
74 |
id SERIAL PRIMARY KEY, |
|
75 |
reclamation_id INTEGER NOT NULL REFERENCES reclamations(id) ON DELETE CASCADE, |
|
76 |
reason_id INTEGER NOT NULL REFERENCES reclamation_reasons(id), |
|
77 |
reason_description_ext TEXT, |
|
78 |
reason_description_int TEXT, |
|
79 |
position INTEGER NOT NULL CHECK(position > 0), |
|
80 |
itime TIMESTAMP without time zone DEFAULT now(), |
|
81 |
mtime TIMESTAMP without time zone, |
|
82 |
--header |
|
83 |
project_id INTEGER REFERENCES project(id) ON DELETE SET NULL, |
|
84 |
--part description |
|
85 |
parts_id INTEGER NOT NULL REFERENCES parts(id), |
|
86 |
description TEXT, |
|
87 |
longdescription TEXT, |
|
88 |
serialnumber TEXT, |
|
89 |
base_qty REAL, |
|
90 |
qty REAL, |
|
91 |
unit character varying(20) REFERENCES units(name), |
|
92 |
--money |
|
93 |
sellprice NUMERIC(15,5), |
|
94 |
lastcost NUMERIC(15,5), |
|
95 |
discount REAL, |
|
96 |
pricegroup_id INTEGER REFERENCES pricegroup(id), |
|
97 |
price_factor_id INTEGER REFERENCES price_factors(id), |
|
98 |
price_factor NUMERIC(15,5) DEFAULT 1, |
|
99 |
active_price_source TEXT NOT NULL DEFAULT ''::text, |
|
100 |
active_discount_source TEXT NOT NULL DEFAULT ''::text, |
|
101 |
--other |
|
102 |
reqdate DATE |
|
103 |
); |
|
104 |
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 | ||
---|---|---|
1 |
-- @tag: record_links_delete_triggers__reclamations__reclamation_items |
|
2 |
-- @description: delete corresponding record_links if reclamation or reclamation_item is deleted |
|
3 |
-- @depends: clean_up_record_links_before_delete_trigger reclamations |
|
4 |
|
|
5 |
CREATE TRIGGER before_delete_reclamation_items_clean_up_record_linkes_trigger |
|
6 |
BEFORE DELETE ON reclamation_items FOR EACH ROW EXECUTE |
|
7 |
PROCEDURE clean_up_record_links_before_delete(); |
|
8 |
|
|
9 |
CREATE TRIGGER before_delete_reclamations_clean_up_record_linkes_trigger |
|
10 |
BEFORE DELETE ON reclamations FOR EACH ROW EXECUTE |
|
11 |
PROCEDURE clean_up_record_links_before_delete(); |
Auch abrufbar als: Unified diff
Reclamation: sql-script for data tables and rose objects added