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