55dfc0640f9575f5761ec18fa0be83ed2942278c
[kivitendo-erp.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::Shop;
10 use SL::DB::MetaSetup::ShopOrder;
11 use SL::DB::Manager::ShopOrder;
12 use SL::DB::Helper::LinkedRecords;
13 use SL::Locale::String qw(t8);
14 use Carp;
15
16 __PACKAGE__->meta->add_relationships(
17   shop_order_items => {
18     class      => 'SL::DB::ShopOrderItem',
19     column_map => { id => 'shop_order_id' },
20     type       => 'one to many',
21   },
22 );
23
24 __PACKAGE__->meta->initialize;
25
26 sub convert_to_sales_order {
27   my ($self, %params) = @_;
28
29   my $customer = delete $params{customer};
30   my $employee = delete $params{employee};
31   croak "param customer is missing" unless ref($customer) eq 'SL::DB::Customer';
32   croak "param employee is missing" unless ref($employee) eq 'SL::DB::Employee';
33
34   require SL::DB::Order;
35   require SL::DB::OrderItem;
36   require SL::DB::Part;
37   require SL::DB::Shipto;
38   my @error_report;
39
40   my @items = map{
41
42     my $part = SL::DB::Manager::Part->find_by(partnumber => $_->partnumber);
43
44     unless($part){
45       push @error_report, t8('Part with partnumber: #1 not found', $_->partnumber);
46     }else{
47       my $current_order_item = SL::DB::OrderItem->new(
48         parts_id            => $part->id,
49         description         => $part->description,
50         qty                 => $_->quantity,
51         sellprice           => $_->price,
52         unit                => $part->unit,
53         position            => $_->position,
54         active_price_source => $_->active_price_source,
55       );
56     }
57   }@{ $self->shop_order_items };
58
59   if(!scalar(@error_report)){
60
61     my $shipto_id;
62     if ($self->billing_firstname ne $self->delivery_firstname || $self->billing_lastname ne $self->delivery_lastname || $self->billing_city ne $self->delivery_city || $self->billing_street ne $self->delivery_street) {
63       if(my $address = SL::DB::Manager::Shipto->find_by( shiptoname   => $self->delivery_firstname . " " . $self->delivery_lastname,
64                                                          shiptostreet => $self->delivery_street,
65                                                          shiptocity   => $self->delivery_city,
66                                                         )) {
67         $shipto_id = $address->{shipto_id};
68       } else {
69         my $deliveryaddress = SL::DB::Shipto->new;
70         $deliveryaddress->assign_attributes(
71           shiptoname         => $self->delivery_firstname . " " . $self->delivery_lastname,
72           shiptodepartment_1 => $self->delivery_company,
73           shiptodepartment_2 => $self->delivery_department,
74           shiptostreet       => $self->delivery_street,
75           shiptozipcode      => $self->delivery_zipcode,
76           shiptocity         => $self->delivery_city,
77           shiptocountry      => $self->delivery_country,
78           trans_id           => $customer->id,
79           module             => "CT",
80         );
81         $deliveryaddress->save;
82         $shipto_id = $deliveryaddress->{shipto_id};
83       }
84     }
85
86     my $shop = SL::DB::Manager::Shop->find_by(id => $self->shop_id);
87     my $order = SL::DB::Order->new(
88       amount                  => $self->amount,
89       cusordnumber            => $self->shop_ordernumber,
90       customer_id             => $customer->id,
91       shipto_id               => $shipto_id,
92       orderitems              => [ @items ],
93       employee_id             => $employee->id,
94       intnotes                => $customer->notes,
95       salesman_id             => $employee->id,
96       taxincluded             => $self->tax_included,
97       payment_id              => $customer->payment_id,
98       taxzone_id              => $customer->taxzone_id,
99       currency_id             => $customer->currency_id,
100       transaction_description => $shop->transaction_description,
101       transdate               => DateTime->today_local
102     );
103      return $order;
104    }else{
105      my %error_order = (error   => 1,
106                         errors  => [ @error_report ],
107                        );
108      return \%error_order;
109    }
110 };
111
112 sub check_for_existing_customers {
113   my ($self, %params) = @_;
114
115   my $name     = $self->billing_lastname ne '' ? $self->billing_firstname . " " . $self->billing_lastname : '';
116   my $lastname = $self->billing_lastname ne '' ? "%" . $self->billing_lastname . "%"                      : '';
117   my $company  = $self->billing_company  ne '' ? "%" . $self->billing_company  . "%"                      : '';
118   my $street   = $self->billing_street   ne '' ?  $self->billing_street                                   : '';
119
120   # Fuzzysearch for street to find e.g. "Dorfstrasse - Dorfstr. - Dorfstraße"
121   my $fs_query = <<SQL;
122 SELECT *
123 FROM customer
124 WHERE (
125    (
126     ( name ILIKE ? OR name ILIKE ? )
127       AND
128     zipcode ILIKE ?
129    )
130  OR
131    ( street % ?  AND zipcode ILIKE ?)
132  OR
133    email ILIKE ?
134 ) AND obsolete = 'F'
135 SQL
136
137   my @values = ($lastname, $company, $self->billing_zipcode, $street, $self->billing_zipcode, $self->billing_email);
138
139   my $customers = SL::DB::Manager::Customer->get_objects_from_sql(
140     sql  => $fs_query,
141     args => \@values,
142   );
143
144   return $customers;
145 }
146
147 sub get_customer{
148   my ($self, %params) = @_;
149   my $shop = SL::DB::Manager::Shop->find_by(id => $self->shop_id);
150   my $customer_proposals = $self->check_for_existing_customers;
151   my $name = $self->billing_firstname . " " . $self->billing_lastname;
152   my $customer = 0;
153   if(!scalar(@{$customer_proposals})){
154     my %address = ( 'name'                  => $name,
155                     'department_1'          => $self->billing_company,
156                     'department_2'          => $self->billing_department,
157                     'street'                => $self->billing_street,
158                     'zipcode'               => $self->billing_zipcode,
159                     'city'                  => $self->billing_city,
160                     'email'                 => $self->billing_email,
161                     'country'               => $self->billing_country,
162                     'greeting'              => $self->billing_greeting,
163                     'fax'                   => $self->billing_fax,
164                     'phone'                 => $self->billing_phone,
165                     'ustid'                 => $self->billing_vat,
166                     'taxincluded_checked'   => $shop->pricetype eq "brutto" ? 1 : 0,
167                     'taxincluded'           => $shop->pricetype eq "brutto" ? 1 : 0,
168                     'pricegroup_id'         => (split '\/',$shop->price_source)[0] eq "pricegroup" ?  (split '\/',$shop->price_source)[1] : undef,
169                     'taxzone_id'            => $shop->taxzone_id,
170                     'currency'              => $::instance_conf->get_currency_id,
171                     #'payment_id'            => 7345,# TODO hardcoded
172                   );
173     $customer = SL::DB::Customer->new(%address);
174
175     $customer->save;
176     my $snumbers = "customernumber_" . $customer->customernumber;
177     SL::DB::History->new(
178                       trans_id    => $customer->id,
179                       snumbers    => $snumbers,
180                       employee_id => SL::DB::Manager::Employee->current->id,
181                       addition    => 'SAVED',
182                       what_done   => 'Shopimport',
183                     )->save();
184
185   }elsif(scalar(@{$customer_proposals}) == 1){
186     # 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"
187     $customer = SL::DB::Manager::Customer->find_by( id       => $customer_proposals->[0]->id,
188                                                     name     => $name,
189                                                     email    => $self->billing_email,
190                                                     street   => $self->billing_street,
191                                                     zipcode  => $self->billing_zipcode,
192                                                     city     => $self->billing_city,
193                                                     obsolete => 'F',
194                                                   );
195   }
196
197   return $customer;
198 }
199
200 sub compare_to {
201   my ($self, $other) = @_;
202
203   return  1 if  $self->transfer_date && !$other->transfer_date;
204   return -1 if !$self->transfer_date &&  $other->transfer_date;
205
206   my $result = 0;
207   $result    = $self->transfer_date <=> $other->transfer_date if $self->transfer_date;
208   return $result || ($self->id <=> $other->id);
209 }
210
211 1;
212
213 __END__
214
215 =pod
216
217 =encoding utf-8
218
219 =head1 NAME
220
221 SL::DB::ShopOrder - Model for the 'shop_orders' table
222
223 =head1 SYNOPSIS
224
225 This is a standard Rose::DB::Object based model and can be used as one.
226
227 =head1 METHODS
228
229 =over 4
230
231 =item C<convert_to_sales_order>
232
233 =item C<check_for_existing_customers>
234
235 Inexact search for possible matches with existing customers in the database.
236
237 Returns all found customers as an arrayref of SL::DB::Customer objects.
238
239 =item C<get_customer>
240
241 returns only one customer from the check_for_existing_customers if the return from it is 0 or 1 customer.
242
243 When it is 0 get customer creates a new customer object of the shop order billing data and returns it
244
245 =item C<compare_to>
246
247 =back
248
249 =head1 TODO
250
251 some variables like payments could be better implemented. Transaction description is hardcoded
252
253 =head1 AUTHORS
254
255 Werner Hahn E<lt>wh@futureworldsearch.netE<gt>
256
257 G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt>
258
259 =cut