/**
  * @param EE_Line_Item $line_item
  * @param array        $options
  * @return mixed
  */
 public function display_line_item(EE_Line_Item $line_item, $options = array())
 {
     EE_Registry::instance()->load_helper('HTML');
     $html = '';
     // set some default options and merge with incoming
     $default_options = array('show_desc' => TRUE, 'odd' => FALSE);
     $options = array_merge($default_options, (array) $options);
     switch ($line_item->type()) {
         case EEM_Line_Item::type_total:
             // loop thru children
             foreach ($line_item->children() as $child_line_item) {
                 // recursively feed children back into this method
                 //					$html .= $this->display_line_item( $child_line_item, $options );
             }
             //				$html .= $this->_separator_row( $options );
             //				$html .= $this->_total_row( $line_item, __('Total', 'event_espresso'), $options );
             break;
         case EEM_Line_Item::type_sub_total:
             // loop thru children
             foreach ($line_item->children() as $child_line_item) {
                 // recursively feed children back into this method
                 //					$html .= $this->display_line_item( $child_line_item, $options );
             }
             //				$html .= $this->_total_row( $line_item, __('Sub-Total', 'event_espresso'), $options );
             break;
         case EEM_Line_Item::type_tax_sub_total:
             // loop thru children
             foreach ($line_item->children() as $child_line_item) {
                 // recursively feed children back into this method
                 //					$html .= $this->display_line_item( $child_line_item, $options );
             }
             //				$html .= $this->_total_row( $line_item, __('Tax Total', 'event_espresso'), $options );
             break;
         case EEM_Line_Item::type_line_item:
             // item row
             //				$html .= $this->_item_row( $line_item, $options );
             // got any kids?
             foreach ($line_item->children() as $child_line_item) {
                 //					$this->display_line_item( $child_line_item, $options );
             }
             break;
         case EEM_Line_Item::type_sub_line_item:
             //				$html .= $this->_sub_item_row( $line_item, $options );
             break;
         case EEM_Line_Item::type_tax:
             //				$html .= $this->_tax_row( $line_item, $options );
             break;
     }
     return $html;
 }
示例#2
0
 /**
  *	@process items for adding to cart
  *	@access public
  *	@param EE_Ticket $ticket
  *	@param int $qty
  *	@return TRUE on success, FALSE on fail
  */
 public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
 {
     $datetimes = $ticket->datetimes();
     $event_names = array();
     foreach ($datetimes as $datetime) {
         $event = $datetime->event();
         $event_names[$event->ID()] = $event->name();
     }
     $description_addition = " (For " . implode(", ", $event_names) . ")";
     $full_description = $ticket->description() . $description_addition;
     // add $ticket to cart
     $line_item = EE_Line_Item::new_instance(array('LIN_name' => $ticket->name(), 'LIN_desc' => $full_description, 'LIN_unit_price' => $ticket->price(), 'LIN_quantity' => $qty, 'LIN_is_taxable' => $ticket->taxable(), 'LIN_order' => count($this->_grand_total->children()), 'LIN_total' => $ticket->price() * $qty, 'LIN_type' => EEM_Line_Item::type_line_item, 'OBJ_ID' => $ticket->ID(), 'OBJ_type' => 'Ticket'));
     //now add the sub-line items
     $running_total_for_ticket = 0;
     foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
         $sign = $price->is_discount() ? -1 : 1;
         $price_total = $price->is_percent() ? $running_total_for_ticket * $price->amount() / 100 : $price->amount() * $qty;
         $sub_line_item = EE_Line_Item::new_instance(array('LIN_name' => $price->name(), 'LIN_desc' => $price->desc(), 'LIN_quantity' => $price->is_percent() ? null : $qty, 'LIN_is_taxable' => false, 'LIN_order' => $price->order(), 'LIN_total' => $sign * $price_total, 'LIN_type' => EEM_Line_Item::type_sub_line_item, 'OBJ_ID' => $price->ID(), 'OBJ_type' => 'Price'));
         if ($price->is_percent()) {
             $sub_line_item->set_percent($sign * $price->amount());
         } else {
             $sub_line_item->set_unit_price($sign * $price->amount());
         }
         $running_total_for_ticket += $price_total;
         $line_item->add_child_line_item($sub_line_item);
     }
     $this->_add_item($line_item);
     return $this->save_cart() ? TRUE : FALSE;
 }
/**
 * Recursive function for traversing all the sub-items of each line item
 * and displaying them in the table
 * @param EE_Line_Item $line_item
 * @param boolean $odd for indicating whether to style this line item as an 'odd' or 'even'
 */
function ee_invoice_display_line_item(EE_Line_Item $line_item, $show_line_item_description, $odd = false)
{
    switch ($line_item->type()) {
        case EEM_Line_Item::type_total:
            foreach ($line_item->children() as $child_line_item) {
                ee_invoice_display_line_item($child_line_item, $show_line_item_description);
            }
            ?>
							<tr><td colspan="<?php 
            echo $show_line_item_description ? 5 : 4;
            ?>
"><hr></td></tr>
							<tr class="total_tr odd">
								<td colspan="<?php 
            echo $show_line_item_description ? 2 : 1;
            ?>
">&nbsp;</td>
								<td colspan="2" class="total" id="total_currency"><?php 
            _e('Total', 'event_espresso');
            ?>
</td>
								<td class="total"><?php 
            echo $line_item->total_no_code();
            ?>
</td>
							</tr>
						<?php 
            break;
        case EEM_Line_Item::type_sub_total:
            foreach ($line_item->children() as $child_line_item) {
                //$odd = !$odd;
                ee_invoice_display_line_item($child_line_item, $show_line_item_description, $odd);
            }
            ?>
							<tr class="total_tr odd">
								<td colspan="<?php 
            echo $show_line_item_description ? 2 : 1;
            ?>
">&nbsp;</td>
								<td colspan="2" class="total" id="total_currency"><?php 
            _e('Sub-Total', 'event_espresso');
            ?>
</td>
								<td class="total"><?php 
            echo $line_item->total_no_code();
            ?>
</td>
							</tr>
						<?php 
            break;
        case EEM_Line_Item::type_tax_sub_total:
            foreach ($line_item->children() as $child_line_item) {
                $odd = !$odd;
                ee_invoice_display_line_item($child_line_item, $show_line_item_description, $odd);
            }
            ?>
							<tr class="total_tr odd">
								<td colspan="<?php 
            echo $show_line_item_description ? 2 : 1;
            ?>
">&nbsp;</td>
								<td colspan="2" class="total" id="total_currency"><?php 
            _e('Tax Total', 'event_espresso');
            ?>
</td>
								<td class="total"><?php 
            echo $line_item->total_no_code();
            ?>
</td>
							</tr>
						<?php 
            break;
        case EEM_Line_Item::type_line_item:
            $subitems = $line_item->children();
            $has_subitems = count($subitems) > 1;
            if ($has_subitems) {
                ?>
							<tr class="item <?php 
                echo $odd ? 'odd' : '';
                ?>
">
								<td class="item_l"><?php 
                echo $line_item->name();
                ?>
</td>
								<?php 
                if ($show_line_item_description) {
                    ?>
<td class="item_l"><?php 
                    echo $line_item->desc();
                    ?>
</td><?php 
                }
                ?>
								<td class="item_l"><?php 
                echo $line_item->quantity();
                ?>
</td>

								<td class="item_c"><?php 
                echo $line_item->unit_price_no_code();
                ?>
</td>

								<td class="item_r"> <?php 
                echo $line_item->total_no_code();
                echo $line_item->is_taxable() ? '*' : '';
                ?>
 </td>
								<?php 
                //<td class="item_l"><?php  $datetimes_strings = array(); foreach($datetimes as $datetime){ $datetimes_strings[]= $datetime->start_date_and_time();} echo implode(", ",$datetimes_strings);
                ?>
							</tr>
							<?php 
                if ($has_subitems) {
                    foreach ($line_item->children() as $child_line_item) {
                        ee_invoice_display_line_item($child_line_item, $show_line_item_description, $odd);
                    }
                }
            } else {
                //no subitems - just show this line item
                ?>
								<tr class="item <?php 
                echo $odd ? 'odd' : '';
                ?>
">
									<td class="item_l"><?php 
                echo $line_item->name();
                ?>
</td>
									<?php 
                if ($show_line_item_description) {
                    ?>
<td class="item_l"><?php 
                    echo $line_item->desc();
                    ?>
</td><?php 
                }
                ?>
									<td class="item_l"><?php 
                echo $line_item->quantity();
                ?>
</td>
									<td class="item_c"><?php 
                echo $line_item->unit_price_no_code();
                ?>
</td>
									<td class="item_r"> <?php 
                echo $line_item->total_no_code();
                echo $line_item->is_taxable() ? '*' : '';
                ?>
 </td>
									<?php 
                //<td class="item_l"><?php  $datetimes_strings = array(); foreach($datetimes as $datetime){ $datetimes_strings[]= $datetime->start_date_and_time();} echo implode(", ",$datetimes_strings);
                ?>
								</tr>
							<?php 
            }
            break;
        case EEM_Line_Item::type_sub_line_item:
            ?>
						<tr class="item subitem-row">
							<td class="item_l subitem"><?php 
            echo $line_item->name();
            ?>
</td>
							<?php 
            if ($show_line_item_description) {
                ?>
<td class="item_l"><?php 
                echo $line_item->desc();
                ?>
</td><?php 
            }
            ?>
							<?php 
            if ($line_item->is_percent()) {
                ?>
									<td></td>
									<td class="item_c"><?php 
                echo $line_item->percent();
                ?>
%</td>
							<?php 
            } else {
                //flat discount/surcharge
                ?>
									<td></td>
									<td class="item_c"><?php 
                echo $line_item->unit_price_no_code();
                ?>
</td>
							<?php 
            }
            ?>
							<td class="item_r"><?php 
            echo $line_item->total_no_code();
            ?>
</td>
						</tr>
						<?php 
            break;
        case EEM_Line_Item::type_tax:
            ?>
						<tr class="item sub-item tax-total">
							<td class="item_l"><?php 
            echo $line_item->name();
            ?>
</td>
							<?php 
            if ($show_line_item_description) {
                ?>
<td class="item_l"><?php 
                echo $line_item->desc();
                ?>
</td><?php 
            }
            ?>
							<td colspan="2" class="item_c"><?php 
            echo $line_item->percent();
            ?>
%</td>

							<td class="item_r"><?php 
            echo $line_item->total_no_code();
            ?>
</td>
						</tr><?php 
            break;
    }
}
 /**
  * Checks if this line item, or any of its children, actually has a description.
  * If none do, then the template can decide to not show any description column
  * @param EE_Line_Item $line_item
  * @return boolean
  */
 function check_if_any_line_items_have_a_description(EE_Line_Item $line_item)
 {
     if ($line_item->desc()) {
         return true;
     } else {
         foreach ($line_item->children() as $child_line_item) {
             if ($this->check_if_any_line_items_have_a_description($child_line_item)) {
                 return true;
             }
         }
         //well, if I and my children don't have descriptions, I guess not
         return false;
     }
 }
 /**
  * Calculates the registration's final price, taking into account that they
  * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
  * and receive a portion of any transaction-wide discounts.
  * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
  * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
  * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
  * and brent's final price should be $5.50.
  *
  * In order to do this, we basically need to traverse the line item tree calculating
  * the running totals (just as if we were recalculating the total), but when we identify
  * regular line items, we need to keep track of their share of the grand total.
  * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
  * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
  * when there are non-taxable items; otherwise they would be the same)
  *
  * @param EE_Line_Item $line_item
  * @param array $billable_ticket_quantities 		array of EE_Ticket IDs and their corresponding quantity that
  *                                          									can be included in price calculations at this moment
  * @return array 		keys are line items for tickets IDs and values are their share of the running total,
  *                                          plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg
  *                                          array(
  *                                          12 => 4.3
  *                                          23 => 8.0
  *                                          'total' => 16.6,
  *                                          'taxable' => array(
  *                                          12 => 10,
  *                                          23 => 4
  *                                          ).
  *                                          So to find which registrations have which final price, we need to find which line item
  *                                          is theirs, which can be done with
  *                                          `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );`
  */
 public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
 {
     //init running grand total if not already
     if (!isset($running_totals['total'])) {
         $running_totals['total'] = 0;
     }
     if (!isset($running_totals['taxable'])) {
         $running_totals['taxable'] = array('total' => 0);
     }
     foreach ($line_item->children() as $child_line_item) {
         switch ($child_line_item->type()) {
             case EEM_Line_Item::type_sub_total:
                 $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities);
                 //combine arrays but preserve numeric keys
                 $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
                 $running_totals['total'] += $running_totals_from_subtotal['total'];
                 $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
                 break;
             case EEM_Line_Item::type_tax_sub_total:
                 //find how much the taxes percentage is
                 if ($child_line_item->percent() != 0) {
                     $tax_percent_decimal = $child_line_item->percent() / 100;
                 } else {
                     $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
                 }
                 //and apply to all the taxable totals, and add to the pretax totals
                 foreach ($running_totals as $line_item_id => $this_running_total) {
                     //"total" and "taxable" array key is an exception
                     if ($line_item_id === 'taxable') {
                         continue;
                     }
                     $taxable_total = $running_totals['taxable'][$line_item_id];
                     $running_totals[$line_item_id] += $taxable_total * $tax_percent_decimal;
                 }
                 break;
             case EEM_Line_Item::type_line_item:
                 // ticket line items or ????
                 if ($child_line_item->OBJ_type() === 'Ticket') {
                     // kk it's a ticket
                     if (isset($running_totals[$child_line_item->ID()])) {
                         //huh? that shouldn't happen.
                         $running_totals['total'] += $child_line_item->total();
                     } else {
                         //its not in our running totals yet. great.
                         if ($child_line_item->is_taxable()) {
                             $taxable_amount = $child_line_item->unit_price();
                         } else {
                             $taxable_amount = 0;
                         }
                         // are we only calculating totals for some tickets?
                         if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
                             $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
                             $running_totals[$child_line_item->ID()] = $quantity ? $child_line_item->unit_price() : 0;
                             $running_totals['taxable'][$child_line_item->ID()] = $quantity ? $taxable_amount : 0;
                         } else {
                             $quantity = $child_line_item->quantity();
                             $running_totals[$child_line_item->ID()] = $child_line_item->unit_price();
                             $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
                         }
                         $running_totals['taxable']['total'] += $taxable_amount * $quantity;
                         $running_totals['total'] += $child_line_item->unit_price() * $quantity;
                     }
                 } else {
                     // it's some other type of item added to the cart
                     // it should affect the running totals
                     // basically we want to convert it into a PERCENT modifier. Because
                     // more clearly affect all registration's final price equally
                     $line_items_percent_of_running_total = $running_totals['total'] > 0 ? $child_line_item->total() / $running_totals['total'] + 1 : 1;
                     foreach ($running_totals as $line_item_id => $this_running_total) {
                         //the "taxable" array key is an exception
                         if ($line_item_id === 'taxable') {
                             continue;
                         }
                         // update the running totals
                         // yes this actually even works for the running grand total!
                         $running_totals[$line_item_id] = $line_items_percent_of_running_total * $this_running_total;
                         if ($child_line_item->is_taxable()) {
                             $running_totals['taxable'][$line_item_id] = $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
                         }
                     }
                 }
                 break;
         }
     }
     return $running_totals;
 }
 /**
  * Checks line item and children list $txn as their transaction.
  * Used by E_UnitTestCase_Test::test_new_typical_transaction()
  * @param EE_Transaction $txn
  * @param EE_Line_Item $line_item
  */
 private function _ensure_txn_on_line_item_and_children($txn, $line_item)
 {
     $this->assertEquals($txn->ID(), $line_item->TXN_ID());
     foreach ($line_item->children() as $child_line_item) {
         $this->_ensure_txn_on_line_item_and_children($txn, $child_line_item);
     }
 }
 /**
  * Prints out a representation of the line item tree
  * @param EE_Line_Item $line_item
  * @param int $indentation
  * @return void
  */
 public static function visualize(EE_Line_Item $line_item, $indentation = 0)
 {
     echo "\r\n";
     for ($i = 0; $i < $indentation; $i++) {
         echo "-";
     }
     echo $line_item->name() . ": " . $line_item->type() . " \$" . $line_item->total();
     if ($line_item->is_taxable()) {
         echo " taxable";
     }
     if ($line_item->children()) {
         foreach ($line_item->children() as $child) {
             self::visualize($child, $indentation + 1);
         }
     }
 }