]> wagnertech.de Git - mfinanz.git/blob - SL/DB/ShopOrder.pm
restart apache2 in postinst
[mfinanz.git] / SL / DB / ShopOrder.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::ShopOrder;
5
6 use strict;
7
8 use SL::DBUtils;
9 use SL::DB::MetaSetup::ShopOrder;
10 use SL::DB::Manager::ShopOrder;
11 use SL::DB::Helper::LinkedRecords;
12 use SL::Locale::String qw(t8);
13 use Carp;
14
15 __PACKAGE__->meta->add_relationships(
16   shop_order_items => {
17     class      => 'SL::DB::ShopOrderItem',
18     column_map => { id => 'shop_order_id' },
19     type       => 'one to many',
20   },
21 );
22
23 __PACKAGE__->meta->initialize;
24
25 sub convert_to_sales_order {
26   my ($self, %params) = @_;
27
28   my $customer  = delete $params{customer};
29   my $employee  = delete $params{employee};
30   my $transdate = delete $params{transdate} // DateTime->today_local;
31
32   croak "param customer is missing" unless ref($customer) eq 'SL::DB::Customer';
33   croak "param employee is missing" unless ref($employee) eq 'SL::DB::Employee';
34
35   # check if caller wants optional partial transfer and create partial soi array
36   my $partial_transfer;
37   my %pos_ids;
38   if ($params{pos_ids}) {
39     $partial_transfer = 1;
40     %pos_ids          =  %{ delete $params{pos_ids} };
41     # TODO check if pos_ids is a valid hash
42   }
43   my @soi = $partial_transfer
44           ? grep { $pos_ids{$_->id} } @{ $self->shop_order_items }
45           : @{ $self->shop_order_items };
46
47   require SL::DB::Order;
48   use SL::DB::Order::TypeData qw(:types);
49   require SL::DB::OrderItem;
50   require SL::DB::Part;
51   require SL::DB::Shipto;
52   require SL::DB::Shop;
53   my @error_report;
54
55   my @items = map{
56
57     my $part = SL::DB::Manager::Part->find_by(partnumber => $_->partnumber);
58
59     unless($part){
60       push @error_report, t8('Part with partnumber: #1 not found', $_->partnumber);
61     }else{
62       my $current_order_item = SL::DB::OrderItem->new(
63         parts_id            => $part->id,
64         description         => $_->description, # description from the shop
65         longdescription     => $part->notes,    # longdescription from parts. TODO locales
66         qty                 => $_->quantity,
67         sellprice           => $_->price,
68         unit                => $part->unit,
69         position            => $_->position,
70         active_price_source => $_->active_price_source,
71         discount            => $_->discount,
72       );
73     }
74   } @soi;
75   if(!scalar(@error_report)){
76
77     my $shipto_id;
78     if ($self->has_differing_delivery_address) {
79       if(my $address = SL::DB::Manager::Shipto->find_by( shiptoname   => $self->delivery_fullname,
80                                                          shiptostreet => $self->delivery_street,
81                                                          shiptocity   => $self->delivery_city,
82                                                         )) {
83         $shipto_id = $address->{shipto_id};
84       } else {
85         my $deliveryaddress = SL::DB::Shipto->new;
86         $deliveryaddress->assign_attributes(
87           shiptoname         => $self->delivery_fullname,
88           shiptodepartment_1 => $self->delivery_company,
89           shiptodepartment_2 => $self->delivery_department,
90           shiptostreet       => $self->delivery_street,
91           shiptozipcode      => $self->delivery_zipcode,
92           shiptocity         => $self->delivery_city,
93           shiptocountry      => $self->delivery_country,
94           trans_id           => $customer->id,
95           module             => "CT",
96         );
97         $deliveryaddress->save;
98         $shipto_id = $deliveryaddress->{shipto_id};
99       }
100     }
101
102     my $shop = SL::DB::Manager::Shop->find_by(id => $self->shop_id);
103     my $order = SL::DB::Order->new(
104       amount                  => $self->amount,
105       cusordnumber            => $self->shop_ordernumber,
106       customer_id             => $customer->id,
107       shipto_id               => $shipto_id,
108       orderitems              => [ @items ],
109       employee_id             => $employee->id,
110       intnotes                => $customer->notes,
111       salesman_id             => $employee->id,
112       taxincluded             => $self->tax_included,
113       payment_id              => $self->payment_id,
114       taxzone_id              => $customer->taxzone_id,
115       currency_id             => $customer->currency_id,
116       transaction_description => $shop->transaction_description,
117       transdate               => $transdate,
118       record_type             => SALES_ORDER_TYPE(),
119     );
120      return $order;
121    }else{
122      my %error_order = (error   => 1,
123                         errors  => [ @error_report ],
124                        );
125      return \%error_order;
126    }
127 };
128
129 sub check_for_existing_customers {
130   my ($self, %params) = @_;
131   my $customers;
132
133   my $name             = $self->billing_lastname ne '' ? $self->billing_firstname . " " . $self->billing_lastname : '';
134   my $lastname         = $self->billing_lastname ne '' ? "%" . $self->billing_lastname . "%"                      : '';
135   my $company          = $self->billing_company  ne '' ? "%" . $self->billing_company  . "%"                      : '';
136   my $street           = $self->billing_street   ne '' ?  $self->billing_street                                   : '';
137   my $street_not_fuzzy = $self->billing_street   ne '' ?  "%" . $self->billing_street . "%"                       : '';
138   my $zipcode          = $self->billing_street   ne '' ?  $self->billing_zipcode                                  : '';
139   my $email            = $self->billing_street   ne '' ?  $self->billing_email                                    : '';
140
141   if(check_trgm($::form->get_standard_dbh())) {
142     # Fuzzysearch for street to find e.g. "Dorfstrasse - Dorfstr. - Dorfstraße"
143     my $fs_query = <<SQL;
144 SELECT *
145 FROM customer
146 WHERE (
147    (
148     ( name ILIKE ? OR name ILIKE ? )
149       AND
150     zipcode ILIKE ?
151    )
152  OR
153    ( street % ?  AND zipcode ILIKE ?)
154  OR
155    ( email ILIKE ? OR invoice_mail ILIKE ? )
156 ) AND obsolete = 'F'
157 SQL
158
159     my @values = ($lastname, $company, $self->billing_zipcode, $street, $self->billing_zipcode, $self->billing_email, $self->billing_email);
160
161     $customers = SL::DB::Manager::Customer->get_objects_from_sql(
162       sql  => $fs_query,
163       args => \@values,
164     );
165   }else{
166     # If trgm extension is not installed
167     $customers = SL::DB::Manager::Customer->get_all(
168       where => [
169                  or => [
170                    and => [
171                             or => [ 'name' => { ilike => $lastname },
172                                     'name' => { ilike => $company  },
173                             ],
174                             'zipcode' => { ilike => $zipcode },
175                    ],
176                    and => [
177                             and => [ 'street'  => { ilike => $street_not_fuzzy },
178                                      'zipcode' => { ilike => $zipcode },
179                             ],
180                    ],
181                    or  => [
182                             'email'        => { ilike => $email },
183                             'invoice_mail' => { ilike => $email },
184                    ],
185                  ],
186                  and => [ obsolete => 'F' ]
187       ],
188     );
189   }
190
191   return $customers;
192 }
193
194 sub check_for_open_invoices {
195   my ($self) = @_;
196     my $open_invoices = SL::DB::Manager::Invoice->get_all_count(
197       query => [customer_id => $self->{kivi_customer_id},
198               paid => {lt_sql => 'amount'},
199       ],
200     );
201   return $open_invoices;
202 }
203
204 sub get_customer{
205   my ($self, %params) = @_;
206   my $shop = SL::DB::Manager::Shop->find_by(id => $self->shop_id);
207   my $customer_proposals = $self->check_for_existing_customers;
208   my $name = $self->billing_firstname . " " . $self->billing_lastname;
209   my $customer = 0;
210   my $default_payment    = SL::DB::Manager::PaymentTerm->get_first();
211   my $payment_id = $default_payment ? $default_payment->id : undef;
212   if(!scalar(@{$customer_proposals})){
213     my %address = ( 'name'                  => $name,
214                     'department_1'          => $self->billing_company,
215                     'department_2'          => $self->billing_department,
216                     'street'                => $self->billing_street,
217                     'zipcode'               => $self->billing_zipcode,
218                     'city'                  => $self->billing_city,
219                     'email'                 => $self->billing_email,
220                     'invoice_mail'          => $self->billing_email,
221                     'country'               => $self->billing_country,
222                     'greeting'              => $self->billing_greeting,
223                     'fax'                   => $self->billing_fax,
224                     'phone'                 => $self->billing_phone,
225                     'ustid'                 => $self->billing_vat,
226                     'taxincluded_checked'   => $shop->pricetype eq "brutto" ? 1 : 0,
227                     'taxincluded'           => $shop->pricetype eq "brutto" ? 1 : 0,
228                     'pricegroup_id'         => (split '\/',$shop->price_source)[0] eq "pricegroup" ?  (split '\/',$shop->price_source)[1] : undef,
229                     'taxzone_id'            => $shop->taxzone_id,
230                     'currency'              => $::instance_conf->get_currency_id,
231                     'payment_id'            => $payment_id,
232                   );
233     $customer = SL::DB::Customer->new(%address);
234
235     $customer->save;
236     my $snumbers = "customernumber_" . $customer->customernumber;
237     SL::DB::History->new(
238                       trans_id    => $customer->id,
239                       snumbers    => $snumbers,
240                       employee_id => SL::DB::Manager::Employee->current->id,
241                       addition    => 'SAVED',
242                       what_done   => 'Shopimport',
243                     )->save();
244
245   }elsif(scalar(@{$customer_proposals}) == 1){
246     # check if the proposal is the right customer, could be different names under the same address. Depends on how first- and familyname is handled. Here is for customername = companyname or customername = "firstname familyname"
247     $customer = SL::DB::Manager::Customer->find_by( id       => $customer_proposals->[0]->id,
248                                                     name     => $name,
249                                                     email    => $self->billing_email,
250                                                     street   => $self->billing_street,
251                                                     zipcode  => $self->billing_zipcode,
252                                                     city     => $self->billing_city,
253                                                     obsolete => 'F',
254                                                   );
255   }
256   if( ref $customer eq 'SL::DB::Customer') {
257     $customer->update_attributes(invoice_mail => $self->billing_email) if $customer->invoice_mail ne $self->billing_email;
258   }
259
260   return $customer;
261 }
262
263 sub compare_to {
264   my ($self, $other) = @_;
265
266   return  1 if  $self->transfer_date && !$other->transfer_date;
267   return -1 if !$self->transfer_date &&  $other->transfer_date;
268
269   my $result = 0;
270   $result    = $self->transfer_date <=> $other->transfer_date if $self->transfer_date;
271   return $result || ($self->id <=> $other->id);
272 }
273
274 sub has_differing_delivery_address {
275   my ($self) = @_;
276   ($self->billing_firstname // '') ne ($self->delivery_firstname // '') ||
277   ($self->billing_lastname  // '') ne ($self->delivery_lastname  // '') ||
278   ($self->billing_city      // '') ne ($self->delivery_city      // '') ||
279   ($self->billing_street    // '') ne ($self->delivery_street    // '')
280 }
281
282 sub delivery_fullname {
283   ($_[0]->delivery_firstname // '') . " " . ($_[0]->delivery_lastname // '')
284 }
285
286 1;
287
288 __END__
289
290 =pod
291
292 =encoding utf-8
293
294 =head1 NAME
295
296 SL::DB::ShopOrder - Model for the 'shop_orders' table
297
298 =head1 SYNOPSIS
299
300 This is a standard Rose::DB::Object based model and can be used as one.
301
302 =head1 METHODS
303
304 =over 4
305
306 =item C<convert_to_sales_order>
307
308 =item C<check_for_existing_customers>
309
310 Inexact search for possible matches with existing customers in the database.
311
312 Returns all found customers as an arrayref of SL::DB::Customer objects.
313
314 =item C<get_customer>
315
316 returns only one customer from the check_for_existing_customers if the return from it is 0 or 1 customer.
317
318 When it is 0 get customer creates a new customer object of the shop order billing data and returns it
319
320 =item C<compare_to>
321
322 =back
323
324 =head1 TODO
325
326 some variables like payments could be better implemented. Transaction description is hardcoded
327
328 =head1 AUTHORS
329
330 Werner Hahn E<lt>wh@futureworldsearch.netE<gt>
331
332 G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt>
333
334 =cut