Neue OrderItem Methoden
[kivitendo-erp.git] / SL / DB / OrderItem.pm
1 package SL::DB::OrderItem;
2
3 use strict;
4
5 use List::Util qw(sum);
6
7 use SL::DB::MetaSetup::OrderItem;
8 use SL::DB::Manager::OrderItem;
9 use SL::DB::DeliveryOrderItemsStock;
10 use SL::DB::Helper::ActsAsList;
11 use SL::DB::Helper::LinkedRecords;
12 use SL::DB::Helper::RecordItem;
13 use SL::DB::Helper::CustomVariables (
14   sub_module  => 'orderitems',
15   cvars_alias => 1,
16   overloads   => {
17     parts_id => {
18       class => 'SL::DB::Part',
19       module => 'IC',
20     }
21   },
22 );
23
24 __PACKAGE__->meta->initialize;
25
26 __PACKAGE__->configure_acts_as_list(group_by => [qw(trans_id)]);
27
28 sub is_price_update_available {
29   my $self = shift;
30   return $self->origprice > $self->part->sellprice;
31 }
32
33 sub shipped_qty {
34   my ($self) = @_;
35
36   my $d_orders = $self->order->linked_records(direction => 'to', to => 'SL::DB::DeliveryOrder');
37   my @doi      = grep { $_->parts_id == $self->parts_id } map { $_->orderitems } @$d_orders;
38
39   require SL::AM;
40   return sum(map { AM->convert_unit($_->unit => $self->unit) * $_->qty } @doi);
41 }
42
43 sub linked_delivery_order_items {
44   my ($self) = @_;
45
46   return $self->linked_records(direction => 'to', to => 'SL::DB::DeliveryOrderItem');
47 }
48
49 sub delivered_qty {
50   # checks for delivery_order_stock_id entries, which have been converted to inventory entries
51   # uses several rose relationships
52   # doesn't differentiate between sales and orders
53
54   my ($self) = @_;
55   my $delivered_qty = 0;
56   foreach my $doi ( @{$self->linked_delivery_order_items} ) {
57     next unless scalar @{$doi->delivery_order_stock_entries};
58     $delivered_qty += sum map { $_->inventory ? $_->qty : 0 } @{$doi->delivery_order_stock_entries};
59   };
60   return $delivered_qty;
61 };
62
63 sub delivered_qty_sql {
64   # checks for delivery_order_stock_id entries, which have been converted to inventory entries
65   my ($self) = @_;
66
67 my $query = <<SQL;
68 SELECT (sum(i.qty) * CASE WHEN oe.customer_id IS NULL THEN 1 ELSE -1 END) AS delivered
69  FROM orderitems oi
70  INNER JOIN record_links rl                 ON (    oi.id             = rl.FROM_id
71                                                 and rl.FROM_table     = 'orderitems'
72                                                 and rl.to_table::text = 'delivery_order_items'::text
73                                                )
74  INNER JOIN delivery_order_items doi        ON (doi.id =rl.to_id)
75  INNER JOIN delivery_order_items_stock dois ON (dois.delivery_order_item_id = doi.id)
76  INNER JOIN inventory i                     ON (dois.id = i.delivery_order_items_stock_id)
77  INNER JOIN oe                              ON (oe.id = oi.trans_id)
78  WHERE oi.id = ?
79  GROUP BY oi.id, oe.id
80 SQL
81   my ($delivered_qty) = selectfirst_array_query($::form, $self->db->dbh, $query, $self->id);
82
83   return $delivered_qty;
84 };
85
86 sub delivered_qty_sql_multi {
87   # checks for delivery_order_stock_id entries, which have been converted to inventory entries
88   my ($self) = @_;
89
90 my $query = <<SQL;
91 SELECT sum(dois.qty) from delivery_order_items_stock dois
92   LEFT OUTER JOIN inventory i ON (dois.id = i.delivery_order_items_stock_id)
93 WHERE
94   dois.delivery_order_item_id in (
95 SELECT
96   to_id
97 FROM
98   record_links
99 WHERE
100   (
101     from_id = in AND
102     from_table = 'orderitems' AND
103     to_table = 'delivery_order_items'
104   )
105 )
106 SQL
107   my ($delivered_qty) = selectfirst_array_query($::form, $self->db->dbh, $query, $self->id);
108
109   return $delivered_qty;
110 };
111
112 sub record { goto &order }
113
114 1;
115
116 __END__
117
118 =pod
119
120 =head1 NAME
121
122 SL::DB::OrderItems: Rose model for orderitems
123
124 =head1 FUNCTIONS
125
126 =over 4
127
128 =item C<shipped_qty>
129
130 =item C<shipped_qty>
131
132 returns the number of orderitems which are already linked to Delivery Orders.
133 The linked key is parts_id and not orderitems (id) -> delivery_order_items (id).
134 Therefore this function is not safe for identical parts_id.
135 Sample call:
136 C<$::form-E<gt>format_amount(\%::myconfig, $_[0]-E<gt>shipped_qty);>
137
138 =item C<delivered_qty>
139
140 Returns the amount of this orderitem that has been delivered, meaning it
141 appears in a delivery order AND has been transferred. The delivery order items
142 are found by direct record_links from orderitems to delivery order items.
143 Delivery order items that were added manually and not via the record workflow
144 will therefore not be calculated correctly.
145
146 Orders that were created before the individual items were linked (this feature
147 was added in kivitendo 3.2.0) will therefore return incorrect results.
148
149 =item C<delivered_qty_sql>
150
151 Does the same as delivered_qty, but via sql.
152
153
154
155 =item C<delivered_qty_sql>
156
157 Returns the amount of the orderitem that has actually been shipped, not just where delivery_order_items exist (how delivered_qty works).
158
159 Doesn't deal with different units yet.
160
161 =back
162
163 =head1 TODO
164
165 Older versions of OrderItem.pm had more functions which where used for calculating the
166 qty for the different states of the Delivery Order.
167 For example to get the qty in already marked as delivered Delivery Orders:
168
169 C<delivered_qty>
170
171 return $self-E<gt>_delivered_qty;
172
173   sub _delivered_qty {
174   (..)
175     my @d_orders_delivered = grep { $_-E<gt>delivered } @$d_orders;
176     my @doi_delivered      = grep { $_-E<gt>parts_id == $self-E<gt>parts_id } map { $_-E<gt>orderitems } @d_orders_delivered;
177   }
178
179 In general the function C<shipped_qty> and all (project) related functions should be marked deprecate,
180  because of the better linked item to item data in the record_links table.
181
182 =head1 AUTHORS
183
184 G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt>
185
186 =cut
187
188