Dokumentation
[kivitendo-erp.git] / SL / DB / Order.pm
1 package SL::DB::Order;
2
3 use utf8;
4 use strict;
5
6 use Carp;
7 use DateTime;
8 use List::Util qw(max);
9
10 use SL::DB::MetaSetup::Order;
11 use SL::DB::Manager::Order;
12 use SL::DB::Invoice;
13 use SL::DB::Helper::LinkedRecords;
14 use SL::DB::Helper::PriceTaxCalculator;
15 use SL::DB::Helper::TransNumberGenerator;
16 use SL::RecordLinks;
17
18 __PACKAGE__->meta->add_relationship(
19   orderitems => {
20     type         => 'one to many',
21     class        => 'SL::DB::OrderItem',
22     column_map   => { id => 'trans_id' },
23     manager_args => {
24       with_objects => [ 'part' ]
25     }
26   },
27   periodic_invoices_config => {
28     type                   => 'one to one',
29     class                  => 'SL::DB::PeriodicInvoicesConfig',
30     column_map             => { id => 'oe_id' },
31   },
32   periodic_invoices        => {
33     type                   => 'one to many',
34     class                  => 'SL::DB::PeriodicInvoice',
35     column_map             => { id => 'oe_id' },
36   },
37   payment_term => {
38     type       => 'one to one',
39     class      => 'SL::DB::PaymentTerm',
40     column_map => { payment_id => 'id' },
41   },
42 );
43
44 __PACKAGE__->meta->initialize;
45
46 # methods
47
48 sub items { goto &orderitems; }
49
50 sub type {
51   my $self = shift;
52
53   return 'sales_order'       if $self->customer_id && ! $self->quotation;
54   return 'purchase_order'    if $self->vendor_id   && ! $self->quotation;
55   return 'sales_quotation'   if $self->customer_id &&   $self->quotation;
56   return 'request_quotation' if $self->vendor_id   &&   $self->quotation;
57
58   return;
59 }
60
61 sub is_type {
62   return shift->type eq shift;
63 }
64
65 sub invoices {
66   my $self   = shift;
67   my %params = @_;
68
69   if ($self->quotation) {
70     return [];
71   } else {
72     return SL::DB::Manager::Invoice->get_all(
73       query => [
74         ordnumber => $self->ordnumber,
75         @{ $params{query} || [] },
76       ]
77     );
78   }
79 }
80
81 sub abschlag_invoices {
82   return shift()->invoices(query => [ abschlag => 1 ]);
83 }
84
85 sub end_invoice {
86   return shift()->invoices(query => [ abschlag => 0 ]);
87 }
88
89 sub convert_to_invoice {
90   my ($self, %params) = @_;
91
92   croak("Conversion to invoices is only supported for sales records") unless $self->customer_id;
93
94   if (!$params{ar_id}) {
95     my $chart = SL::DB::Manager::Chart->get_all(query   => [ SL::DB::Manager::Chart->link_filter('AR') ],
96                                                 sort_by => 'id ASC',
97                                                 limit   => 1)->[0];
98     croak("No AR chart found and no parameter `ar_id' given") unless $chart;
99     $params{ar_id} = $chart->id;
100   }
101
102   my $invoice;
103   if (!$self->db->do_transaction(sub {
104     $invoice = SL::DB::Invoice->new_from($self)->post(%params) || die;
105     $self->link_to_record($invoice);
106     $self->update_attributes(closed => 1);
107     # die;
108   })) {
109     return undef;
110   }
111
112   return $invoice;
113 }
114
115 1;
116
117 __END__
118
119 =head1 NAME
120
121 SL::DB::Order - Order Datenbank Objekt.
122
123 =head1 FUNCTIONS
124
125 =head2 type
126
127 Returns one of the following string types:
128
129 =over 4
130
131 =item saes_order
132
133 =item purchase_order
134
135 =item sales_quotation
136
137 =item request_quotation
138
139 =back
140
141 =head2 is_type TYPE
142
143 Rreturns true if the order is of the given type.
144
145 =item C<convert_to_invoice %params>
146
147 Creates a new invoice with C<$self> as the basis by calling
148 L<SL::DB::Invoice::new_from>. That invoice is posted, and C<$self> is
149 linked to the new invoice via L<SL::DB::RecordLink>. C<$self>'s
150 C<closed> attribute is set to C<true>, and C<$self> is saved.
151
152 The arguments in C<%params> are passed to
153 L<SL::DB::Invoice::post>. One parameter of note is
154 C<$paras{ar_id}>. If set it must be the ID of the accounts receivables
155 chart to post to. If it is not set then the first chart configured for
156 accounts receivables is used.
157
158 Returns the new invoice instance on success and C<undef> on
159 failure. The whole process is run inside a transaction. On failure
160 nothing is created or changed in the database.
161
162 At the moment only sales quotations and sales orders can be converted.
163
164 =item C<create_sales_process>
165
166 Creates and saves a new sales process. Can only be called for sales
167 orders.
168
169 The newly created process will be linked bidirectionally to both
170 C<$self> and to all sales quotations that are linked to C<$self>.
171
172 Returns the newly created process instance.
173
174 =back
175
176 =head1 BUGS
177
178 Nothing here yet.
179
180 =head1 AUTHOR
181
182 Sven Schöling <s.schoeling@linet-services.de>
183
184 =cut