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.
4 package SL::DB::ShopOrder;
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);
15 __PACKAGE__->meta->add_relationships(
17 class => 'SL::DB::ShopOrderItem',
18 column_map => { id => 'shop_order_id' },
19 type => 'one to many',
23 __PACKAGE__->meta->initialize;
25 sub convert_to_sales_order {
26 my ($self, %params) = @_;
28 my $customer = delete $params{customer};
29 my $employee = delete $params{employee};
30 my $transdate = delete $params{transdate} // DateTime->today_local;
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';
35 # check if caller wants optional partial transfer and create partial soi array
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
43 my @soi = $partial_transfer
44 ? grep { $pos_ids{$_->id} } @{ $self->shop_order_items }
45 : @{ $self->shop_order_items };
47 require SL::DB::Order;
48 use SL::DB::Order::TypeData qw(:types);
49 require SL::DB::OrderItem;
51 require SL::DB::Shipto;
57 my $part = SL::DB::Manager::Part->find_by(partnumber => $_->partnumber);
60 push @error_report, t8('Part with partnumber: #1 not found', $_->partnumber);
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
67 sellprice => $_->price,
69 position => $_->position,
70 active_price_source => $_->active_price_source,
71 discount => $_->discount,
75 if(!scalar(@error_report)){
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,
83 $shipto_id = $address->{shipto_id};
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,
97 $deliveryaddress->save;
98 $shipto_id = $deliveryaddress->{shipto_id};
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(),
122 my %error_order = (error => 1,
123 errors => [ @error_report ],
125 return \%error_order;
129 sub check_for_existing_customers {
130 my ($self, %params) = @_;
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 : '';
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;
148 ( name ILIKE ? OR name ILIKE ? )
153 ( street % ? AND zipcode ILIKE ?)
155 ( email ILIKE ? OR invoice_mail ILIKE ? )
159 my @values = ($lastname, $company, $self->billing_zipcode, $street, $self->billing_zipcode, $self->billing_email, $self->billing_email);
161 $customers = SL::DB::Manager::Customer->get_objects_from_sql(
166 # If trgm extension is not installed
167 $customers = SL::DB::Manager::Customer->get_all(
171 or => [ 'name' => { ilike => $lastname },
172 'name' => { ilike => $company },
174 'zipcode' => { ilike => $zipcode },
177 and => [ 'street' => { ilike => $street_not_fuzzy },
178 'zipcode' => { ilike => $zipcode },
182 'email' => { ilike => $email },
183 'invoice_mail' => { ilike => $email },
186 and => [ obsolete => 'F' ]
194 sub check_for_open_invoices {
196 my $open_invoices = SL::DB::Manager::Invoice->get_all_count(
197 query => [customer_id => $self->{kivi_customer_id},
198 paid => {lt_sql => 'amount'},
201 return $open_invoices;
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;
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,
233 $customer = SL::DB::Customer->new(%address);
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,
242 what_done => 'Shopimport',
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,
249 email => $self->billing_email,
250 street => $self->billing_street,
251 zipcode => $self->billing_zipcode,
252 city => $self->billing_city,
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;
264 my ($self, $other) = @_;
266 return 1 if $self->transfer_date && !$other->transfer_date;
267 return -1 if !$self->transfer_date && $other->transfer_date;
270 $result = $self->transfer_date <=> $other->transfer_date if $self->transfer_date;
271 return $result || ($self->id <=> $other->id);
274 sub has_differing_delivery_address {
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 // '')
282 sub delivery_fullname {
283 ($_[0]->delivery_firstname // '') . " " . ($_[0]->delivery_lastname // '')
296 SL::DB::ShopOrder - Model for the 'shop_orders' table
300 This is a standard Rose::DB::Object based model and can be used as one.
306 =item C<convert_to_sales_order>
308 =item C<check_for_existing_customers>
310 Inexact search for possible matches with existing customers in the database.
312 Returns all found customers as an arrayref of SL::DB::Customer objects.
314 =item C<get_customer>
316 returns only one customer from the check_for_existing_customers if the return from it is 0 or 1 customer.
318 When it is 0 get customer creates a new customer object of the shop order billing data and returns it
326 some variables like payments could be better implemented. Transaction description is hardcoded
330 Werner Hahn E<lt>wh@futureworldsearch.netE<gt>
332 G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt>