1<?php
2
3
4/* Definition of the cart class
5this class can hold all the information for:
6
7i)   a sales order
8ii)  an invoice
9iii) a credit note
10
11*/
12
13
14Class Cart {
15
16	var $LineItems; /*array of objects of class LineDetails using the product id as the pointer */
17	var $total; /*total cost of the items ordered */
18	var $totalVolume;
19	var $totalWeight;
20	var $LineCounter;
21	var $ItemsOrdered; /*no of different line items ordered */
22	var $DeliveryDate;
23	var $DefaultSalesType;
24	var $SalesTypeName;
25	var $DefaultCurrency;
26	var $CurrDecimalPlaces;
27	var $PaymentTerms;
28	var $DeliverTo;
29	var $DelAdd1;
30	var $DelAdd2;
31	var $DelAdd3;
32	var $DelAdd4;
33	var $DelAdd5;
34	var $DelAdd6;
35	var $SalesPerson;
36	var $PhoneNo;
37	var $Email;
38	var $CustRef;
39	var $Comments;
40	var $Location;
41	var $LocationName;
42	var $DebtorNo;
43	var $CustomerName;
44	var $Orig_OrderDate;
45	var $Branch;
46	var $TransID;
47	var $ShipVia;
48	var $FreightCost;
49	var $FreightTaxes;
50	Var $OrderNo;
51	Var $Consignment;
52	Var $Quotation;
53	Var $DeliverBlind;
54	Var $CreditAvailable; //in customer currency
55	Var $TaxGroup;
56	Var $DispatchTaxProvince;
57	Var $DefaultPOLine;
58	Var $DeliveryDays;
59	var $TaxTotals;
60	var $TaxGLCodes;
61	var $BuyerName;
62	var $SpecialInstructions;
63
64	function __construct(){
65	/*Constructor function initialises a new shopping cart */
66		$this->LineItems = array();
67		$this->total=0;
68		$this->ItemsOrdered=0;
69		$this->LineCounter=0;
70		$this->DefaultSalesType='';
71		$this->FreightCost =0;
72		$this->FreightTaxes = array();
73		$this->CurrDecimalPlaces=2; //default
74	}
75
76	function cart() {
77		self::__construct();
78	}
79
80	function add_to_cart($StockID,
81							$Qty,
82							$Descr,
83							$LongDescr,
84							$Price,
85							$Disc=0,
86							$UOM,
87							$Volume,
88							$Weight,
89							$QOHatLoc=0,
90							$MBflag='B',
91							$ActDispatchDate=NULL,
92							$QtyInvoiced=0,
93							$DiscCat='',
94							$Controlled=0,
95							$Serialised=0,
96							$DecimalPlaces=0,
97							$Narrative='',
98							$UpdateDB='No',
99							$LineNumber=-1,
100							$TaxCategory=0,
101							$vtigerProductID='',
102							$ItemDue = '',
103							$POLine='',
104							$StandardCost=0,
105							$EOQ=1,
106							$NextSerialNo=0,
107							$ExRate=1,
108							$identifier=0){
109
110		if (isset($StockID) AND $StockID!="" AND $Qty>0 AND isset($Qty)){
111
112			if ($Price<0){ /*madness check - use a credit note to give money away!*/
113				$Price=0;
114			}
115
116			if ($LineNumber==-1){
117				$LineNumber = $this->LineCounter;
118			}
119
120			$this->LineItems[$LineNumber] = new LineDetails($LineNumber,
121															$StockID,
122															$Descr,
123															$LongDescr,
124															$Qty,
125															$Price,
126															$Disc,
127															$UOM,
128															$Volume,
129															$Weight,
130															$QOHatLoc,
131															$MBflag,
132															$ActDispatchDate,
133															$QtyInvoiced,
134															$DiscCat,
135															$Controlled,
136															$Serialised,
137															$DecimalPlaces,
138															$Narrative,
139															$TaxCategory,
140															$ItemDue,
141															$POLine,
142															$StandardCost,
143															$EOQ,
144															$NextSerialNo,
145															$ExRate);
146			$this->ItemsOrdered++;
147
148			if ($UpdateDB=='Yes'){
149				/*ExistingOrder !=0 set means that an order is selected or created for entry
150				of items - ExistingOrder is set to 0 in scripts that should not allow
151				adding items to the order - New orders have line items added at the time of
152				committing the order to the DB in DeliveryDetails.php
153				 GET['ModifyOrderNumber'] is only set when the items are first
154				being retrieved from the DB - dont want to add them again - would return
155				errors anyway */
156
157				$sql = "INSERT INTO salesorderdetails (orderlineno,
158														orderno,
159														stkcode,
160														quantity,
161														unitprice,
162														discountpercent,
163														itemdue,
164														poline)
165													VALUES(" . $LineNumber . ",
166														" . $_SESSION['ExistingOrder' . $identifier] . ",
167														'" . trim(mb_strtoupper($StockID)) ."',
168														" . $Qty . ",
169														" . $Price . ",
170														" . $Disc . ",'
171														" . FormatDateForSQL($ItemDue) . "',
172														" . $POLine . ")";
173				$result = DB_query($sql,
174							_('The order line for') . ' ' . mb_strtoupper($StockID) . ' ' ._('could not be inserted'));
175			}
176
177			$this->LineCounter = $LineNumber + 1;
178			Return 1;
179		}
180		Return 0;
181	}
182
183	function update_cart_item( $UpdateLineNumber,
184								$Qty,
185								$Price,
186								$Disc,
187								$Narrative,
188								$UpdateDB='No',
189								$ItemDue,
190								$POLine,
191								$GPPercent,
192								$identifier){
193
194		if ($Qty>0){
195			$this->LineItems[$UpdateLineNumber]->Quantity = $Qty;
196		}
197		$this->LineItems[$UpdateLineNumber]->Price = $Price;
198		$this->LineItems[$UpdateLineNumber]->DiscountPercent = $Disc;
199		$this->LineItems[$UpdateLineNumber]->Narrative = $Narrative;
200		$this->LineItems[$UpdateLineNumber]->ItemDue = $ItemDue;
201		$this->LineItems[$UpdateLineNumber]->POLine = $POLine;
202		$this->LineItems[$UpdateLineNumber]->GPPercent = $GPPercent;
203		if ($UpdateDB=='Yes'){
204			$result = DB_query("UPDATE salesorderdetails SET quantity=" . $Qty . ",
205															unitprice=" . $Price . ",
206															discountpercent=" . $Disc . ",
207															narrative ='" . $Narrative . "',
208															itemdue = '" . FormatDateForSQL($ItemDue) . "',
209															poline = '" . $POLine . "'
210								WHERE orderno=" . $_SESSION['ExistingOrder'.$identifier] . "
211								AND orderlineno=" . $UpdateLineNumber,
212								 _('The order line number') . ' ' . $UpdateLineNumber .  ' ' . _('could not be updated'));
213		}
214	}
215
216	function remove_from_cart($LineNumber, $UpdateDB='No', $identifier=0){
217
218		if (!isset($LineNumber) OR $LineNumber=='' OR $LineNumber < 0){ /* over check it */
219			prnMsg(_('No Line Number passed to remove_from_cart, so nothing has been removed.'), 'error');
220			return;
221		}
222		if ($UpdateDB=='Yes'){
223			if ($this->Some_Already_Delivered($LineNumber)==0){
224				/* nothing has been delivered, delete it. */
225				$result = DB_query("DELETE FROM salesorderdetails
226									WHERE orderno='" . $_SESSION['ExistingOrder' . $identifier] . "'
227									AND orderlineno='" . $LineNumber . "'",
228									_('The order line could not be deleted because')
229									);
230				prnMsg( _('Deleted Line Number'). ' ' . $LineNumber . ' ' . _('from existing Order Number').' ' . $_SESSION['ExistingOrder' . $identifier], 'success');
231			} else {
232				/* something has been delivered. Clear the remaining Qty and Mark Completed */
233				$result = DB_query("UPDATE salesorderdetails SET quantity=qtyinvoiced,
234																completed=1
235									WHERE orderno='" . $_SESSION['ExistingOrder' . $identifier] ."'
236									AND orderlineno='" . $LineNumber . "'" ,
237								   _('The order line could not be updated as completed because')
238								   );
239				prnMsg(_('Removed Remaining Quantity and set Line Number '). ' ' . $LineNumber . ' ' . _('as Completed for existing Order Number').' ' . $_SESSION['ExistingOrder'], 'success');
240			}
241		}
242		/* Since we need to check the LineItem above and might affect the DB, don't unset until after DB is updates occur */
243		$this->CreditAvailable +=  ($this->LineItems[$LineNumber]->Quantity*$this->LineItems[$LineNumber]->Price*(1-$this->LineItems[$LineNumber]->DiscountPercent));
244		unset($this->LineItems[$LineNumber]);
245		$this->ItemsOrdered--;
246
247	}//remove_from_cart()
248
249	function Get_StockID_List(){
250		/* Makes a comma seperated list of the stock items ordered
251		for use in SQL expressions */
252
253		$StockID_List='';
254		foreach ($this->LineItems as $StockItem) {
255			$StockID_List .= ",'" . $StockItem->StockID . "'";
256		}
257
258		return mb_substr($StockID_List, 1);
259
260	}
261
262	function Any_Already_Delivered(){
263		/* Checks if there have been deliveries of line items */
264
265		foreach ($this->LineItems as $StockItem) {
266			if ($StockItem->QtyInv !=0){
267				return 1;
268			}
269		}
270
271		return 0;
272
273	}
274
275	function Some_Already_Delivered($LineNumber){
276		/* Checks if there have been deliveries of a specific line item */
277
278		if ($this->LineItems[$LineNumber]->QtyInv !=0){
279			return $this->LineItems[$LineNumber]->QtyInv;
280		}
281		return 0;
282	}
283
284	function AllDummyLineItems(){
285		foreach ($this->LineItems as $StockItem) {
286			if($StockItem->MBflag !='D'){
287				return false;
288			}
289		}
290		return true;
291	}
292
293	function GetExistingTaxes($LineNumber, $stkmoveno){
294		/*Gets the Taxes and rates applicable to this line from the TaxGroup of the branch and TaxCategory of the item
295		and the taxprovince of the dispatch location */
296
297		$sql = "SELECT stockmovestaxes.taxauthid,
298					taxauthorities.description,
299					taxauthorities.taxglcode,
300					stockmovestaxes.taxcalculationorder,
301					stockmovestaxes.taxontax,
302					stockmovestaxes.taxrate
303				FROM stockmovestaxes INNER JOIN taxauthorities
304					ON stockmovestaxes.taxauthid = taxauthorities.taxid
305				WHERE stkmoveno = '" . $stkmoveno . "'
306				ORDER BY taxcalculationorder";
307
308		$ErrMsg = _('The taxes and rates for this item could not be retrieved because');
309		$GetTaxRatesResult = DB_query($sql,$ErrMsg);
310		$i=1;
311		while ($myrow = DB_fetch_array($GetTaxRatesResult)){
312
313			$this->LineItems[$LineNumber]->Taxes[$i] =   new Tax($myrow['taxcalculationorder'],
314																$myrow['taxauthid'],
315																$myrow['description'],
316																$myrow['taxrate'],
317																$myrow['taxontax'],
318																$myrow['taxglcode']);
319			$i++;
320		}
321	} //end method GetExistingTaxes
322
323	function GetTaxes($LineNumber){
324		/*Gets the Taxes and rates applicable to this line from the TaxGroup of the branch and TaxCategory of the item
325		and the taxprovince of the dispatch location */
326
327		$SQL = "SELECT taxgrouptaxes.calculationorder,
328					taxauthorities.description,
329					taxgrouptaxes.taxauthid,
330					taxauthorities.taxglcode,
331					taxgrouptaxes.taxontax,
332					taxauthrates.taxrate
333			FROM taxauthrates INNER JOIN taxgrouptaxes ON
334				taxauthrates.taxauthority=taxgrouptaxes.taxauthid
335				INNER JOIN taxauthorities ON
336				taxauthrates.taxauthority=taxauthorities.taxid
337			WHERE taxgrouptaxes.taxgroupid=" . $this->TaxGroup . "
338			AND taxauthrates.dispatchtaxprovince=" . $this->DispatchTaxProvince . "
339			AND taxauthrates.taxcatid = " . $this->LineItems[$LineNumber]->TaxCategory . "
340			ORDER BY taxgrouptaxes.calculationorder";
341
342		$ErrMsg = _('The taxes and rates for this item could not be retrieved because');
343		$GetTaxRatesResult = DB_query($SQL,$ErrMsg);
344		unset($this->LineItems[$LineNumber]->Taxes);
345		if (DB_num_rows($GetTaxRatesResult)==0){
346			prnMsg(_('It appears that taxes are not defined correctly for this customer tax group') ,'error');
347		} else {
348			$i=1;
349			while ($myrow = DB_fetch_array($GetTaxRatesResult)){
350				$this->LineItems[$LineNumber]->Taxes[$i] = new Tax($myrow['calculationorder'],
351																	$myrow['taxauthid'],
352																	$myrow['description'],
353																	$myrow['taxrate'],
354																	$myrow['taxontax'],
355																	$myrow['taxglcode']);
356				$i++;
357			} //end loop around different taxes
358		} //end if there are some taxes defined
359	} //end method GetTaxes
360
361	function GetFreightTaxes () {
362		/*Gets the Taxes and rates applicable to the freight based on the tax group of the branch combined with the tax category for this particular freight
363		and SESSION['FreightTaxCategory'] the taxprovince of the dispatch location */
364
365		$sql = "SELECT taxcatid FROM taxcategories WHERE taxcatname='Freight'";// This tax category is hardcoded inside the database.
366		$TaxCatQuery = DB_query($sql);
367
368		if ($TaxCatRow = DB_fetch_array($TaxCatQuery)) {
369		  $TaxCatID = $TaxCatRow['taxcatid'];
370		} else {
371  		  prnMsg( _('Cannot find tax category Freight which must always be defined'),'error');
372		  exit();
373		}
374
375		$SQL = "SELECT taxgrouptaxes.calculationorder,
376					taxauthorities.description,
377					taxgrouptaxes.taxauthid,
378					taxauthorities.taxglcode,
379					taxgrouptaxes.taxontax,
380					taxauthrates.taxrate
381				FROM taxauthrates INNER JOIN taxgrouptaxes ON
382					taxauthrates.taxauthority=taxgrouptaxes.taxauthid
383					INNER JOIN taxauthorities ON
384					taxauthrates.taxauthority=taxauthorities.taxid
385				WHERE taxgrouptaxes.taxgroupid='" . $this->TaxGroup . "'
386				AND taxauthrates.dispatchtaxprovince='" . $this->DispatchTaxProvince . "'
387				AND taxauthrates.taxcatid = '" . $TaxCatID . "'
388				ORDER BY taxgrouptaxes.calculationorder";
389
390		$ErrMsg = _('The taxes and rates for this item could not be retrieved because');
391		$GetTaxRatesResult = DB_query($SQL,$ErrMsg);
392		$i=1;
393		while ($myrow = DB_fetch_array($GetTaxRatesResult)){
394
395			$this->FreightTaxes[$i] = new Tax($myrow['calculationorder'],
396												$myrow['taxauthid'],
397												$myrow['description'],
398												$myrow['taxrate'],
399												$myrow['taxontax'],
400												$myrow['taxglcode']);
401			$i++;
402		}
403	} //end method GetFreightTaxes()
404
405} /* end of cart class defintion */
406
407Class LineDetails {
408	Var $LineNumber;
409	Var $StockID;
410	Var $ItemDescription;
411	Var $LongDescription;
412	Var $Quantity;
413	Var $Price;
414	Var $DiscountPercent;
415	Var $Units;
416	Var $Volume;
417	Var $Weight;
418	Var $ActDispDate;
419	Var $QtyInv;
420	Var $QtyDispatched;
421	Var $StandardCost;
422	Var $QOHatLoc;
423	Var $MBflag;	/*Make Buy Dummy, Assembly or Kitset */
424	Var $DiscCat; /* Discount Category of the item if any */
425	Var $Controlled;
426	Var $Serialised;
427	Var $DecimalPlaces;
428	Var $SerialItems;
429	Var $Narrative;
430	Var $TaxCategory;
431	Var $Taxes;
432	Var $WorkOrderNo;
433	Var $ItemDue;
434	Var $POLine;
435	Var $EOQ;
436	Var $NextSerialNo;
437	Var $GPPercent;
438
439	function __construct ($LineNumber,
440							$StockItem,
441							$Descr,
442							$LongDescr,
443							$Qty,
444							$Prc,
445							$DiscPercent,
446							$UOM,
447							$Volume,
448							$Weight,
449							$QOHatLoc,
450							$MBflag,
451							$ActDispatchDate,
452							$QtyInvoiced,
453							$DiscCat,
454							$Controlled,
455							$Serialised,
456							$DecimalPlaces,
457							$Narrative,
458							$TaxCategory,
459							$ItemDue,
460							$POLine,
461							$StandardCost,
462							$EOQ,
463							$NextSerialNo,
464							$ExRate ){
465
466/* Constructor function to add a new LineDetail object with passed params */
467		$this->LineNumber = $LineNumber;
468		$this->StockID =$StockItem;
469		$this->ItemDescription = $Descr;
470		$this->LongDescription = $LongDescr;
471		$this->Quantity = $Qty;
472		$this->Price = $Prc;
473		$this->DiscountPercent = $DiscPercent;
474		$this->Units = $UOM;
475		$this->Volume = $Volume;
476		$this->Weight = $Weight;
477		$this->ActDispDate = $ActDispatchDate;
478		$this->QtyInv = $QtyInvoiced;
479		if ($Controlled==1){
480			$this->QtyDispatched = 0;
481		} else {
482			if ($_SESSION['InvoiceQuantityDefault']==1){
483				$this->QtyDispatched = $Qty - $QtyInvoiced;
484			} else {
485				$this->QtyDispathced = 0;
486			}
487		}
488		$this->QOHatLoc = $QOHatLoc;
489		$this->MBflag = $MBflag;
490		$this->DiscCat = $DiscCat;
491		$this->Controlled = $Controlled;
492		$this->Serialised = $Serialised;
493		$this->DecimalPlaces = $DecimalPlaces;
494		$this->SerialItems = array();
495		$this->Narrative = $Narrative;
496		$this->Taxes = array();
497		$this->TaxCategory = $TaxCategory;
498		$this->WorkOrderNo = 0;
499		$this->ItemDue = $ItemDue;
500		$this->POLine = $POLine;
501		$this->StandardCost = $StandardCost;
502		$this->EOQ = $EOQ;
503		$this->NextSerialNo = $NextSerialNo;
504
505		if ($Prc > 0){
506			$this->GPPercent = ((($Prc * (1 - $DiscPercent)) - ($StandardCost * $ExRate))*100)/$Prc;
507		} else {
508			$this->GPPercent = 0;
509		}
510	} //end constructor function for LineDetails
511
512	function LineDetails($LineNumber,
513							$StockItem,
514							$Descr,
515							$LongDescr,
516							$Qty,
517							$Prc,
518							$DiscPercent,
519							$UOM,
520							$Volume,
521							$Weight,
522							$QOHatLoc,
523							$MBflag,
524							$ActDispatchDate,
525							$QtyInvoiced,
526							$DiscCat,
527							$Controlled,
528							$Serialised,
529							$DecimalPlaces,
530							$Narrative,
531							$TaxCategory,
532							$ItemDue,
533							$POLine,
534							$StandardCost,
535							$EOQ,
536							$NextSerialNo,
537							$ExRate ) {
538		self::__construct($LineNumber,
539							$StockItem,
540							$Descr,
541							$LongDescr,
542							$Qty,
543							$Prc,
544							$DiscPercent,
545							$UOM,
546							$Volume,
547							$Weight,
548							$QOHatLoc,
549							$MBflag,
550							$ActDispatchDate,
551							$QtyInvoiced,
552							$DiscCat,
553							$Controlled,
554							$Serialised,
555							$DecimalPlaces,
556							$Narrative,
557							$TaxCategory,
558							$ItemDue,
559							$POLine,
560							$StandardCost,
561							$EOQ,
562							$NextSerialNo,
563							$ExRate );
564	}
565
566}
567
568Class Tax {
569	Var $TaxCalculationOrder;  /*the index for the array */
570	Var $TaxAuthID;
571	Var $TaxAuthDescription;
572	Var $TaxRate;
573	Var $TaxOnTax;
574	var $TaxGLCode;
575
576	function __construct ($TaxCalculationOrder,
577			$TaxAuthID,
578			$TaxAuthDescription,
579			$TaxRate,
580			$TaxOnTax,
581			$TaxGLCode){
582
583		$this->TaxCalculationOrder = $TaxCalculationOrder;
584		$this->TaxAuthID = $TaxAuthID;
585		$this->TaxAuthDescription = $TaxAuthDescription;
586		$this->TaxRate =  $TaxRate;
587		$this->TaxOnTax = $TaxOnTax;
588		$this->TaxGLCode = $TaxGLCode;
589	}
590	function Tax ($TaxCalculationOrder,
591			$TaxAuthID,
592			$TaxAuthDescription,
593			$TaxRate,
594			$TaxOnTax,
595			$TaxGLCode) {
596
597		self::__construct($TaxCalculationOrder,
598			$TaxAuthID,
599			$TaxAuthDescription,
600			$TaxRate,
601			$TaxOnTax,
602			$TaxGLCode);
603	}
604}
605
606?>
607