00be5c1425d556be96028f902ecb4a0403cb831b
[kivitendo-erp.git] / peppershop / erplib.php
1 <?php
2 /*
3
4 shop muß gesetzt sein, obsolet nicht
5
6 Multishop: Hierfür müssen benutzerdefinierte Variablen angelegt werden.
7 Typ:checkbox,  Name=shop[0-9A-Z]+, Bearbeitbar=nein 
8
9
10 */
11
12 class erp {
13
14     var $db = false;
15     var $error = false;
16     var $pricegroup = 0;
17     var $TAX = false;
18     var $mkPart = true;
19     var $divStd = false;
20     var $divVerm = false;
21     var $doordnr = false;
22     var $docustnr = false;
23     var $lager = 1;
24     var $warehouse_id = 0;
25     var $transtype = 0;
26     var $preordnr = '';
27     var $precustnr = '';
28     var $OEinsPart = false;
29     var $INVnetto = true; //Rechnungen mit Nettopreisen
30     var $SHOPincl = true; //Shoppreise sind Brutto
31
32     function erp($db,$error,$divStd,$divVerm,$doordnr,$docustnr,$preordnr,$precustnr,$INVnetto,$SHOPincl,$OEinsPart,$lager,$pricegroup,$ERPusrID) {
33         $this->db = $db;
34         $this->pricegroup = $pricegroup;
35         $this->employee_id = $ERPusrID;
36         $this->error = $error;
37         $this->divStd  = $divStd;
38         $this->divVerm = $divVerm;
39         $this->doordnr = $doordnr;
40         $this->preordnr = $preordnr;
41         $this->docustnr = $docustnr;
42         $this->precustnr = $precustnr;
43         $this->INVnetto = ($INVnetto == 1)?true:false;
44         $this->SHOPincl = ($SHOPincl == 1)?true:false;
45         $this->OEinsPart = ($OEinsPart == 1)?true:false;
46         $this->lager = ($lager)?$lager:1;
47         $this->getTax();
48         if ( $lager > 1 ) {
49             $sql  = "SELECT warehouse_id from bin where id = ".$this->lager;
50             $rs = $this->db->getOne($sql);
51             if ( $rs['warehouse_id'] > 0 ) {
52                 $this->warehouse_id = $rs['warehouse_id'];
53                 $sql = "SELECT id from transfer_type WHERE direction = 'in' and description = 'stock'";
54                 $rs = $this->db->getOne($sql);
55                 $this->transtype = $rs['id'];
56             } else {
57                 $this->lager = 1;
58             }
59         }
60     }
61
62     function getTax() {
63         $sql  = "SELECT  BG.id AS bugru,T.rate,TK.startdate,C.taxkey_id, ";
64         $sql .= "(SELECT id FROM chart WHERE accno = T.taxnumber) AS tax_id, ";
65         $sql .= "BG.income_accno_id_0,BG.expense_accno_id_0 ";
66         $sql .= "FROM buchungsgruppen BG LEFT JOIN chart C ON BG.income_accno_id_0=C.id ";
67         $sql .= "LEFT JOIN taxkeys TK ON TK.chart_id=C.id ";
68         $sql .= "LEFT JOIN tax T ON T.id=TK.tax_id WHERE TK.startdate <= now()";
69         $rs = $this->db->getAll($sql);
70         if ($rs) foreach ($rs as $row) {
71             $nr = $row['bugru'];
72             if (!$this->TAX[$nr]) {
73                 $data = array();
74                 $data['startdate'] =     $row['startdate'];
75                 $data['rate'] =     $row['rate'];
76                 $data['taxkey'] =     $row['taxkey_id'];
77                 $data['taxid'] =     $row['tax_id'];
78                 $data['income'] =     $row['income_accno_id_0'];
79                 $data['expense'] =     $row['expense_accno_id_0'];
80                 $this->TAX[$nr] = $data;
81             } else if ($this->TAX[$nr]['startdate'] < $row['startdate']) {
82                 $this->TAX[$nr]["startdate"] =     $row['startdate'];
83                 $this->TAX[$nr]["rate"] =     $row['rate'];
84                 $this->TAX[$nr]["taxkey"] =     $row['taxkey_id'];
85                 $this->TAX[$nr]["taxid"] =     $row['tax_id'];
86                 $this->TAX[$nr]["income"] =     $row['income_accno_id_0'];
87                 $this->TAX[$nr]["expense"] =     $row['expense_accno_id_0'];
88             }
89         }
90     }
91
92     function getParts($stdprice=0,$shop=0) {
93         $where = "WHERE 1=1 ";
94         if ($stdprice>0) {
95              $sql  = "SELECT P.partnumber,P.description,P.notes,P.weight,G.price as sellprice,P.sellprice as stdprice,";
96              $sql .= "PG.partsgroup,P.image,P.buchungsgruppen_id as bugru,P.unit";
97              if ($this->lager>1) {
98                    $sql .= ",(select sum(qty) from inventory where bin_id = ".$this->lager." and parts_id = P.id) as onhand ";
99              } else {
100                    $sql .= ",P.onhand ";
101              }
102              $sql .= "FROM parts P ";
103              $sql .= "LEFT JOIN partsgroup PG on PG.id=P.partsgroup_id ";
104              $sql .= "LEFT JOIN prices G on G.parts_id=P.id ";
105              $where .= "AND (G.pricegroup_id=$stdprice ";
106              $where .= "or G.pricegroup_id is null) ";
107         } else {
108              $sql  = "SELECT P.partnumber,P.description,P.notes,P.weight,P.sellprice,";
109              $sql .= "PG.partsgroup,P.image,P.buchungsgruppen_id as bugru,P.unit ";
110              if ($this->lager>1) {
111                    $sql .= ",(select sum(qty) from inventory where bin_id = ".$this->lager." and parts_id = P.id) as onhand ";
112              } else {
113                    $sql .= ",P.onhand ";
114              }
115              $sql .= "FROM parts P left join partsgroup PG on PG.id=P.partsgroup_id ";
116         }
117         if ($shop>0) {  
118             $sql .= "LEFT JOIN custom_variables CV on CV.trans_id=P.id ";
119             $where .= "AND (CV.config_id = $shop AND bool_value = 't')";
120         }
121         $where .= "AND shop = 't' ";
122         $where .= "AND obsolete = 'f' ORDER BY P.partnumber";
123         $rs = $this->db->getAll($sql.$where);
124         if ($rs) for($i = 0; $i < count($rs); $i++) {
125            $rs[$i]['tax'] = $this->TAX[$rs[$i]['bugru']]['rate'];
126         }
127         return $rs;
128     }
129
130     function getPartsLang($lang,$alle) {
131         $sql  = "SELECT P.partnumber,L.translation,P.description,L.longdescription,P.notes,PG.partsgroup ";
132         $sql .= "FROM parts P left join translation L on L.parts_id=P.id left join partsgroup PG on PG.id=P.partsgroup_id ";
133         $sql .= "WHERE P.shop='t' and (L.language_id = $lang";
134         if ($alle) {
135             $sql .= " or L.language_id is Null)";
136         } else { 
137             $sql.=")"; 
138         };
139         $rs = $this->getAll($sql);
140         $data=array();
141         if ($rs) foreach ($rs as $row) {
142             if (!$data[$row["partnumber"]]) $data[$row["partnumber"]]=$row;
143         }
144         return $data;
145     }
146     function getNewNr($typ) {
147         /*
148           so = Auftragsnummer
149           customer = Kundennummer 
150         */
151         $typ .= "number";
152         $sql = "SELECT $typ FROM defaults";
153         $rs = $this->db->getOne($sql);
154         $i=strlen($rs["$typ"])-1;
155         //Nummern können Buchstaben, Zeichen und Zahlen enthalten
156         //nur die Zahlen von rechts werden aber inkrementiert.
157         while($i>=0) {
158             if ($rs["$typ"][$i] >= "0" and $rs["$typ"][$i]<="9") {
159                 $n=$rs["$typ"][$i].$n;
160                 $i--;
161             } else {
162                 $pre = substr($rs["$typ"],0,$i+1);
163                 $i=-1;
164             }
165         };
166         $nr = (int)$n + 1;
167         $sonr = $pre.$nr;
168         $sql = "UPDATE defaults SET $typ = '$sonr'";
169         $rc = $this->db->query($sql);
170         if (!$rc) {
171             $this->error->write('erplib','Neue Nummer ($typ) nicht gesichert: '.$sonr);
172         }
173         return $sonr;
174     }
175     function newOrder($data) {
176         /*Einen neuen Auftrag anlegen. Folgendes Array muß übergeben werden:
177         $data = array(ordnumber,customer_id,employee_id,taxzone_id,amount,netamount,transdate,notes,intnotes,shipvia)
178         Rückgabe oe.id */
179         $this->db->begin();
180         $incltax = ($this->INVnetto)?'f':'t';
181         $sql  = "INSERT INTO oe (ordnumber,customer_id,employee_id,taxzone_id,taxincluded,curr,amount,netamount,transdate,notes,intnotes,shipvia,cusordnumber) ";
182         $sql .= "values (:ordnumber,:customer_id,:employee_id,:taxzone_id,'$incltax',:curr,:amount,:netamount,:transdate,:notes,:intnotes,:shipvia,:cusordnumber)";
183         $rc = $this->db->insert($sql,$data);
184         $sql = "SELECT * FROM oe where ordnumber = '".$data["ordnumber"]."'";
185         $rs = $this->db->getOne($sql);
186         if (!$rs['id']) {
187             $this->error->write('erplib','Auftrag erzeugen: '.$data["ordnumber"]);
188             $this->db->rollback();
189             return false;
190         } else {
191             $this->error->out(" Auftrag: ".$data["ordnumber"]." ");
192             return $rs['id'];
193         }
194     }
195     function insParts($trans_id,$data,$longtxt) {
196         /*Artikel in die orderitem einfügen. Folgende Daten müssen übergeben werden:
197         $trans_id = (int) oe.id
198         $data = array(trans_id,partnumber,description,longdescription,qty,sellprice,unit)*/
199         foreach ($data as $row) {
200              $row['trans_id'] = $trans_id;
201              //$sql = "SELECT id FROM parts WHERE partnumber = '".$row['partnumber']."'";
202              //$tmp = $this->db->getOne($sql);
203              $tmp = $this->chkPartnumber($row,$this->OEinsPart,true);
204              if ($tmp) {
205                  $row['parts_id'] = $tmp['id'];
206              } else {
207                  if ($this->TAX[$this->divStd['BUGRU']]['rate'] == $row['mwst']/100) {
208                       $row['parts_id'] = $this->divStd['ID'];
209                  } else if ($this->TAX[$this->divVerm['BUGRU']]['rate'] == $row['mwst']/100) {
210                       $row['parts_id'] = $this->divVerm['ID'];
211                  } else {
212                       $row['parts_id'] = $this->divStd['ID'];
213                  }
214              }
215              if ($this->INVnetto) {
216                  if ($this->SHOPincl) 
217                      $row['sellprice'] = round($row['sellprice'] / (100 + $row['taxrate']) * 100,2);
218              } else {
219                  if (!$this->SHOPincl) 
220                      $row['sellprice'] = round($row['sellprice'] * (100 + $row['taxrate']) * 100,2);
221              }
222              $row['unit'] = $this->chkUnit($row['unit']);
223              if ($longtxt == 1) {
224                  //$row['longdescription'] = addslashes($row['longdescription']);
225                  $row['longdescription'] = $row['longdescription'];
226              } else {
227                  //$row['longdescription'] = addslashes($tmp['longdescription']);
228                  $row['longdescription'] = $tmp['longdescription'];
229              }
230              //$row['description'] = addslashes($row['description']);
231              $sql  = "INSERT INTO orderitems (trans_id,parts_id,description,longdescription,qty,sellprice,unit,pricegroup_id,discount) ";
232              $sql .= "VALUES (:trans_id,:parts_id,:description,:longdescription,:qty,:sellprice,:unit,0,0)";
233              $row["trans_id"]=$trans_id;
234              $rc = $this->db->insert($sql,$row);
235              if (!$rc) {
236                  $this->db->rollback();
237                  return false;
238              };
239         };
240         $this->db->commit();
241         return true;
242     }
243     function insCustomer($data) {
244         $this->error->out('Insert:'.$data["name"].' ');
245         if ($this->docustnr == 1) {
246             $data['customernumber'] = $this->getNewNr('customer');
247         } else {
248             $data['customernumber'] = $data['shopid'];
249         }
250         $data['customernumber'] = $this->precustnr.$data['customernumber'];
251             if ($data['customernumber']>0) {
252                 if (!$data['greeting']) $data['greeting'] = '';
253                 $sql  = "INSERT INTO customer (greeting,name,street,city,zipcode,country,contact,phone,email,customernumber)";
254                 $sql .= " VALUES (:greeting,:name,:street,:city,:zipcode,:country,:contact,:phone,:email,:customernumber)";
255                 $rc =  $this->db->insert($sql,$data);
256                 $sql = "SELECT id FROM customer WHERE customernumber = '".$data['customernumber']."'";
257                 $rs = $this->db->getOne($sql);
258                 $rc = $rs['id'];
259                 $this->error->out("Kd-Nr: ".$data['customernumber'].":".$rs['id']);
260             } else {
261                 $this->error->write('erplib','Kunde anlegen: '.$data["name"]);
262                 $this->db->rollback();
263                 return false;
264             }
265             return $rc;
266     }
267     function chkCustomer($data) {
268         if ($data['customer_id']>0) {
269             $sql = "SELECT * FROM customer WHERE id = ".$data['customer_id'];
270             $rs = $this->db->getOne($sql);
271             if ($rs['id'] == $data['customer_id']) {
272                  $this->error->out('Update:'.$data['customer_id'].' ');
273                  $sql  = "UPDATE customer SET greeting = :greeting,name = :name,street = :street,city = :city,country = :country,";
274                  $sql .= "zipcode = :zipcode,contact = :contact,phone = :phone,email = :email WHERE id = :customer_id";
275                  $rc =  $this->db->update($sql,$data);
276                  if ($rc) $rc = $data['customer_id'];
277             } else {
278                 $rc = $this->insCustomer($data);
279             }
280         } else {
281             $rc = $this->insCustomer($data);
282         }
283         return $rc;
284     }
285     function mkAuftrag($data,$shop,$longtxt) {
286         $this->db->Begin();
287         $data["notes"] .= "\nBezahlung:".$data['bezahlung']."\n";
288         if ($data['bezahlung'] == "Kreditkarte")   $data["notes"] .= $data['kreditkarte']."\n"; 
289         if ($shop) { 
290            $data["intnotes"] = "Shop: $shop";
291         } else {
292            $data["intnotes"] = "";
293         };
294         $data["customer_id"] = $this->chkCustomer($data["customer"]);
295         $parts = $data['parts'];
296         unset($data['parts']);
297         unset($data['customer']);
298         if ($this->doordnr == 1) {
299             $data["ordnumber"] = $this->getNewNr('so');
300         } else {
301             $data["ordnumber"] = $data['cusordnumber'];
302         }
303         $data["ordnumber"] = $this->preordnr.$data["ordnumber"];
304         $tid = $this->newOrder($data);
305         if ($tid) {
306             $rc = $this->insParts($tid,$parts,$longtxt);  
307             if (!$rc) {
308                  $this->error->write('erplib','Artikel zu Auftrag');
309                  return -1;
310             }
311         } else {
312             $this->error->write('erplib','Auftrag anlegen');
313             return -1;
314         }
315         $this->error->out($data["customer"]["firma"]." ");
316         $rc = $this->db->Commit();
317         return $data["customer_id"];
318     }
319     function chkPartsgroup($pg,$new=True) {
320        /*gibt es die Warengruppe?
321        Rückgabe nichts oder die partsgroup.id
322        ggf neu anlegen*/
323        $sql = "SELECT * FROM partsgroup WHERE partsgroup = '".$pg."'";
324        $rs = $this->db->getOne($sql);
325        if ($rs) {
326            return $rs['id'];
327        } else if ($this->mkPart and $new) {
328            return $this->mkNewPartsgroup($pg);
329        } else {
330            return '';
331        };
332     }
333     function mkNewPartsgroup($name) {
334        $sql = "INSERT INTO partsgroup (partsgroup) VALUES ('".$name."')";
335        $rc = $this->db->query($sql);
336        if ($rc) {
337            return $this->chkPartsgroup($name,False);
338        } else {
339            return '';
340        }
341     }
342     function chkUnit($unit) {
343        /*Prüfen ob es die Unit gibt.
344          wenn nicht, die Standardunit zurückgeben*/
345        if ($unit == '') {
346            return $this->stdUnit();
347        } else {
348            $sql = "SELECT * FROM units WHERE name ilike '".$unit."'";
349            $rs = $this->db->getOne($sql);
350            if ($rs) {
351               return $rs["name"];
352            } else {
353                return $this->stdUnit();
354            }
355        }
356     }
357     function stdUnit() {
358        $sql = "SELECT * FROM units WHERE type = 'dimension' ORDER BY sortkey LIMIT 1";
359        $rs = $this->db->getOne($sql);
360        return $rs["name"];
361     }
362     function chkPartnumber($data,$new=True,$long=false) {
363        $sql = "SELECT * FROM parts WHERE partnumber = '".$data["partnumber"]."'";
364        $rs = $this->db->getOne($sql);
365        if ($rs) {
366            if ($long) {
367                return $rs;
368            } else {
369                return $rs['id'];
370            }
371        } else if ($new and $this->mkPart) {
372            $data['id'] = $this->mkNewPart($data);
373            if ($long) {
374                return $data;
375            } else {
376                return $data['id'];
377            }
378        } else {
379            return '';
380        };
381     }
382     function mkNewPart($data) {
383        /*eine neue Ware anlegen, sollte nicht direkt aufgerufen werden.
384        Auf vorhandene partnumber wird nicht geprüft.
385        Folgendes Array muß übergeben werden:
386        $data = array(partnumber,description,longdescription,weight,sellprice,taxrate,partsgroup,unit)
387        Rückgabe parts.id
388        */
389        $link = '<a href="../ic.pl?action=edit&id=%d" target="_blank">';
390        if ($data['partnumber'] == '') {
391            $this->error->write('erplib','Artikelnummer fehlt');
392            return false;
393        }
394        if ($data['description'] == '') {
395            $this->error->write('erplib','Artikelbezeichnung fehlt');
396            return false;
397        }
398        $data['notes'] = addslashes($data['longdescription']);
399        if ($data['weight']*1 != $data['weight']) $data['weight']=0;
400        if ($data['sellprice']*1 != $data['sellprice']) $data['sellprice']=0;
401        if (!in_array($data["buchungsgruppen_id"],$this->TAX)) {
402            foreach ($this->TAX as $key=>$tax) {
403                 if ($tax["rate"] == $data["taxrate"]/100) {
404                     $data["buchungsgruppen_id"] = $key;
405                     break;
406                 }
407            }
408            if (!$data["buchungsgruppen_id"]) {
409                $this->error->write('erplib','Buchungsgruppe konnte nicht zugeordnet werden');
410                return false;
411            }
412        };
413        if ($data["partsgroup"]) {
414            $data["partsgroup_id"] = $this->chkPartsgroup($data["partsgroup"]);
415        } else {
416            $data["partsgroup_id"] = '';
417        };
418        $data['unit'] = $this->chkUnit($data['unit']);
419        if ($data['unit'] == '') {
420            $this->error->write('erplib','Artikeleinheit fehlt oder falsch');
421            return false;
422        }
423        $data['shop'] = 't';
424        $sql  = "INSERT INTO parts (partnumber,description,sellprice,weight,notes,shop,unit,partsgroup_id,";
425        $sql .= "image,buchungsgruppen_id,inventory_accno_id,income_accno_id,expense_accno_id) ";
426        $sql .= "VALUES (:partnumber,:description,:sellprice,:weight,:notes,:shop,:unit,:partsgroup_id,";
427        $sql .= ":image,:buchungsgruppen_id,1,1,1)";
428        $rc = $this->db->insert($sql,$data);
429        $data['parts_id'] = $this->chkPartnumber($data,false);
430        if ( $this->pricegroup > 0 ) {
431             $sql  = "INSERT INTO prices (parts_id,pricegroup_id,price) VALUES (:parts_id,:pricegroup,:shoppreis)";
432             $data['pricegroup'] = $this->pricegroup;
433             $rc = $this->db->insert($sql,$data);
434        };
435        if ( $data['onhand'] > 0 and $this->lager > 1) $this->insLager($data);
436        $x =  $this->chkPartnumber($data,False);
437        $this->error->write('erplib',$data['description'].' '.$data['partnumber']);
438        $this->error->out(sprintf($link,$data['parts_id']).$data['description'].' '.$data['partnumber'].'</a>',true);
439        return $x;
440     }
441     function insLager($data) {
442         $rc = $this->db->Begin();
443         $sql = "SELECT nextval(('id'::text)::regclass) as id from id";
444         $rs = $this->db->getOne($sql);
445         $sql  = "INSERT INTO inventory (warehouse_id,parts_id,shippingdate,employee_id,bin_id,qty,trans_id,trans_type_id,comment) ";
446         $sql .= "VALUES (:wid,:parts_id,now(),:employee_id,:bid,:onhand,:next,:tt,'Shopübernahme')";
447         $data['next'] = $rs['id'];
448         $data['tt'] = $this->transtype;
449         $data['bid'] = $this->lager;
450         $data['wid'] = $this->warehouse_id;
451         $data['employee_id'] = $this->employee_id;
452         $rc = $this->db->insert($sql,$data);
453         if ( $rc ) {
454            $this->db->Commit();
455         } else {
456            $this->db->Rollback();
457         }
458     }
459 }
460 ?>