SL::DB::DeliveryOrder: Dokumentation gefixt
[kivitendo-erp.git] / SL / DB / DeliveryOrder.pm
1 package SL::DB::DeliveryOrder;
2
3 use strict;
4
5 use Carp;
6
7 use SL::DB::MetaSetup::DeliveryOrder;
8 use SL::DB::Manager::DeliveryOrder;
9 use SL::DB::Helper::FlattenToForm;
10 use SL::DB::Helper::LinkedRecords;
11 use SL::DB::Helper::TransNumberGenerator;
12
13 use List::Util qw(first);
14
15 __PACKAGE__->meta->add_relationship(orderitems => { type         => 'one to many',
16                                                     class        => 'SL::DB::DeliveryOrderItem',
17                                                     column_map   => { id => 'delivery_order_id' },
18                                                     manager_args => { with_objects => [ 'part' ] }
19                                                   },
20                                     custom_shipto => {
21                                       type        => 'one to one',
22                                       class       => 'SL::DB::Shipto',
23                                       column_map  => { id => 'trans_id' },
24                                       query_args  => [ module => 'DO' ],
25                                     },
26                                    );
27
28 __PACKAGE__->meta->initialize;
29
30 __PACKAGE__->before_save('_before_save_set_donumber');
31
32 # hooks
33
34 sub _before_save_set_donumber {
35   my ($self) = @_;
36
37   $self->create_trans_number if !$self->donumber;
38
39   return 1;
40 }
41
42 # methods
43
44 sub items { goto &orderitems; }
45
46 sub items_sorted {
47   my ($self) = @_;
48
49   return [ sort {$a->id <=> $b->id } @{ $self->items } ];
50 }
51
52 sub sales_order {
53   my $self   = shift;
54   my %params = @_;
55
56
57   require SL::DB::Order;
58   my $orders = SL::DB::Manager::Order->get_all(
59     query => [
60       ordnumber => $self->ordnumber,
61       @{ $params{query} || [] },
62     ],
63   );
64
65   return first { $_->is_type('sales_order') } @{ $orders };
66 }
67
68 sub type {
69   return shift->customer_id ? 'sales_delivery_order' : 'purchase_delivery_order';
70 }
71
72 sub displayable_state {
73   my ($self) = @_;
74
75   return join '; ',
76     ($self->closed    ? $::locale->text('closed')    : $::locale->text('open')),
77     ($self->delivered ? $::locale->text('delivered') : $::locale->text('not delivered'));
78 }
79
80 sub date {
81   goto &transdate;
82 }
83
84 sub new_from {
85   my ($class, $source, %params) = @_;
86
87   croak("Unsupported source object type '" . ref($source) . "'") unless ref($source) eq 'SL::DB::Order';
88
89   my $terms = $source->can('payment_id') && $source->payment_id ? $source->payment_terms->terms_netto : 0;
90
91   my %args = ( map({ ( $_ => $source->$_ ) } qw(cp_id currency_id customer_id cusordnumber department_id employee_id globalproject_id intnotes language_id notes
92                                                 ordnumber reqdate salesman_id shippingpoint shipvia taxincluded taxzone_id transaction_description vendor_id
93                                              )),
94                closed    => 0,
95                is_sales  => !!$source->customer_id,
96                delivered => 0,
97                terms     => $terms,
98                transdate => DateTime->today_local,
99             );
100
101   # Custom shipto addresses (the ones specific to the sales/purchase
102   # record and not to the customer/vendor) are only linked from
103   # shipto -> delivery_orders. Meaning delivery_orders.shipto_id
104   # will not be filled in that case. Therefore we have to return the
105   # new shipto object as a separate object so that the caller can
106   # save it, too.
107   my $custom_shipto;
108   if (!$source->shipto_id && $source->id) {
109     my $old = $source->custom_shipto;
110     if ($old) {
111       $custom_shipto = SL::DB::Shipto->new(
112         map  { +($_ => $old->$_) }
113         grep { !m{^ (?: itime | mtime | shipto_id | trans_id ) $}x }
114         map  { $_->name }
115         @{ $old->meta->columns }
116       );
117       $custom_shipto->module('DO');
118     }
119
120   } else {
121     $args{shipto_id} = $source->shipto_id;
122   }
123
124   my $delivery_order = $class->new(%args, %params);
125
126   my @items = map {
127     my $source_item = $_;
128     SL::DB::DeliveryOrderItem->new(map({ ( $_ => $source_item->$_ ) }
129                                    qw(base_qty cusordnumber description discount lastcost longdescription marge_price_factor ordnumber parts_id price_factor price_factor_id
130                                       project_id qty reqdate sellprice serialnumber transdate unit
131                                    )));
132   } @{ $source->items_sorted };
133
134   $delivery_order->items(\@items);
135
136   return ($delivery_order, $custom_shipto);
137 }
138
139 1;
140 __END__
141
142 =pod
143
144 =encoding utf8
145
146 =head1 NAME
147
148 SL::DB::DeliveryOrder - Rose model for delivery orders (table
149 "delivery_orders")
150
151 =head1 FUNCTIONS
152
153 =over 4
154
155 =item C<date>
156
157 An alias for C<transdate> for compatibility with other sales/purchase models.
158
159 =item C<displayable_state>
160
161 Returns a human-readable description of the state regarding being
162 closed and delivered.
163
164 =item C<items>
165
166 An alias for C<deliver_orer_items> for compatibility with other
167 sales/purchase models.
168
169 =item C<items_sorted>
170
171 Returns the delivery order items sorted by their ID (same order they
172 appear in the frontend delivery order masks).
173
174 =item C<new_from $source>
175
176 Creates a new C<SL::DB::DeliveryOrder> instance and copies as much
177 information from C<$source> as possible. At the moment only instances
178 of C<SL::DB::Order> (sales quotations, sales orders, requests for
179 quotations and purchase orders) are supported as sources.
180
181 The conversion copies order items into delivery order items. Dates are copied
182 as appropriate, e.g. the C<transdate> field will be set to the current date.
183
184 Returns one or two objects depending on the context. In list context
185 the new delivery order instance and a shipto instance will be
186 returned. In scalar instance only the delivery order instance is
187 returned.
188
189 Custom shipto addresses (the ones specific to the sales/purchase
190 record and not to the customer/vendor) are only linked from C<shipto>
191 to C<delivery_orders>. Meaning C<delivery_orders.shipto_id> will not
192 be filled in that case. That's why a separate shipto object is created
193 and returned.
194
195 The objects returned are not saved.
196
197 =item C<sales_order>
198
199 TODO: Describe sales_order
200
201 =item C<type>
202
203 Returns a stringdescribing this record's type: either
204 C<sales_delivery_order> or C<purchase_delivery_order>.
205
206 =back
207
208 =head1 BUGS
209
210 Nothing here yet.
211
212 =head1 AUTHOR
213
214 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
215
216 =cut