Closed ammist closed 7 years ago
heya @ammist ya that sounds great. This is a feature we had quasi planned on, but you'll probably find there are a few EE core changes that will need to happen for fully make this happen. But we'll see.
Hopefully, the key should just be having your code hook into creating the line items at the correct time, and then putting the line items in the right place in the tree, and then everything else should be basically handled for you.
First off, how do you want these "ticket extras" to appear in the invoice/receipt? Do you want them to look like price modifiers, being sub-items under the ticket price? (meaning they'll appear like they lower/raise the ticket price) Or do you want them to appear as separate line items? (ie, appear under "additional charges" in the receipt, separate from the ticket prices?) Putting them as sub-items under the ticket price is good if ALL the tickets purchased of that type have the same modifier, and you'd like to have the receipt show who has which "ticket extra". But it gets tricky if there are multiple purchases of a ticket, but each with different "ticket extras", because you'll basically need to split up the original ticket line item, and create different ticket line items each with different "ticket extras"... Putting them as separate line items will probably be the easiest but it's not obvious which ticket extras are associated with which ticket purchase... So, your preferences?
The more I read through the code, the more places it seems this could hook into, depending on how we want the registration, and the "extras" to work.
The specific use case I want to solve for is a convention, where each attendee can sign up for workshops that have additional materials fees. In addition, each convention attendee gets to purchase memorabilia (a T-shirt, a figurine, a pen, or all three in one deluxe convention schwag package).
The invoice should show:
1 General Admission Convention ticket 0-4 Workshops (These are purchased as tickets assigned to Date/Times. There are two workshops in each time slot) 0-3 Memorabilia Selections
So, I think the memorabilia should show up as separate line items, since they aren't related to tickets - really the event itself.
In the database, it looks like Line Items are linked to Transactions, which are linked to Registrations. It looks like the line items show up on the invoice, which will make it easier for the event staff to provide the correct memorabilia in everyone's bag.
So, I need to output the selection form for the extras, pass the selection values to something that will generate line items out of it, put the line items in the event cart, and...
Hi Anca,
It turns out Brent put together a code snippet that shows how to add line items to the cart, where the item is based on the selection of an answer from the registration form. You can follow the code example here:
Hope that helps!
Hi Anca,
That code snippet that Josh posted (thnx Josh!) should hopefully give you an idea of what you need, or at least get you pretty close to it. Plz note that that snippet is for adding a charge to the entire transaction, whereas I think you want to add additional line items for various registrants. The one thing I can think that may be missing for you, is a way to associate the selected memorabilia with a particular registration.
You could likely do everything you want by hooking into the 'FHEEEED_Single_PageCheckoutinitialize_checkoutcheckout' filter, and parsing the request at that point and not even bother with hooking into 'AHEEEE_System__core_loaded_and_ready'.
The EE_Checkout object that is passed to the callback for the 'FHEEEED_Single_PageCheckoutinitialize_checkout__checkout' filter will give you access to the registrations via the transaction. You could then loop through the registrations, check the answers to their reg form questions, and then do stuff based on their answers something like this:
function add_memorabilia_to_purchase( EE_Checkout $checkout ) {
$registrations = $checkout->transaction->registrations();
foreach ( $registrations as $registration ) {
if ( $registration instanceof EE_Registration ) {
$reg_form_question_answers = $registration->answers();
// look at answers, find ones regarding memorabilia
// add line items
// maybe add extra meta to registration as well regarding purchase ?
$registration->add_extra_meta(
'memorabilia',
'medium t-shirt'
// or maybe a list of LIN_IDs for the added line items,
// to make it easier to cross reference
);
}
}
}
please do not hesitate to ask specific questions, or post code for us to give feedback on.
Wow, this is great! I'm taking a look now and will get back to you with more questions / info.
What I see here will definitely make this work for the project I'm doing now - where we are restricting registrations to one person each (yay, simplicity!), and getting this to work with help me figure out the rest of the process to make this usable by others.
Well, it's been a while (and lots of back and forth figuring out the details, but I've got this working! I used the method recommended in in @joshfeck's gist, and it works great to add line items.
Take a look in our dev environment: http://bricks.techliminal.com/events/convention/
One problem is that when someone uses a promo code, the total for the swag line item is set to 0. I'm trying to figure out where this happens.
I'm running my filter on both "initialize" and "finalize" checkout like so:
add_filter( 'FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', 'bbtb_filter_checkout', 100, 1); add_filter( 'FHEE__EED_Single_Page_Checkout___final_verifications__checkout', 'bbtb_filter_checkout', 100, 1);
Really hard to say without seeing more of your code...
The cart totals get recalculated when adding a promotion, so I would maybe walk through everything that happens in \EE_Line_Item::recalculate_total_including_taxes() (core/db_classes/EE_Line_Item.class.php) to see if you can spot where the zeroing occurs.
From there, it may be a case of fixing how your data is entered, or it may be a bug in our code, or a bad assumption regarding the nature of the data in the line items table.
On that note, are you recording the required line item(s) for your swag in the wp_esp_line_item table ?
Hmm... I'm going to take a look at the EE_Line_Item class, but I wonder if this is a clue:
` function bbtb_filter_checkout( EE_Checkout $checkout){
// verify checkout
if ( ! $checkout instanceof EE_Checkout ) {
return $checkout;
}
// verify cart
$cart = $checkout->cart;
if ( ! $cart instanceof EE_Cart ) {
return $checkout;
}
// verify grand total line item
$grand_total = $cart->get_grand_total();
if ( ! $grand_total instanceof EE_Line_Item ) {
return $checkout;
}
// Some stuff happens here where we check the answers and do some calculations
// Allow only one purchase of swag and bricks per registration.
$existing_swag = $grand_total->get_child_line_item( $swag_item[ 'code' ] );
if ($existing_swag instanceof EE_Line_item){
$grand_total->delete_child_line_item($swag_item[ 'code' ] );
}
$pre_tax_subtotal->add_child_line_item(
EE_Line_Item::new_instance( array(
'LIN_name' => $swag_item[ 'name' ] . ':' . $description,
'LIN_desc' => '',
'LIN_unit_price' => (float) $total,
'LIN_quantity' => 1,
'LIN_is_taxable' => $swag_item[ 'taxable' ],
'LIN_order' => 0,
'LIN_total' => (float) $total,
'LIN_type' => EEM_Line_Item::type_line_item,
'LIN_code' => $swag_item[ 'code' ],
) )
);
$grand_total->recalculate_total_including_taxes();
return $checkout;
`
I am not specifically saving any of the line items in the database beyond whatever add_child_line_item does.
If I don't add a promo code, the totals are added and payment is processed. If I add the promo code, the total cost for the swag is set to 0, and, when going to Paypal, the items and quantities aren't passed along.
All right, I"m off to read the code for recalculate_total_including_taxes.
hey @ammist, this is just a guess, but maybe you need to set the TXN_ID
on the newly created line item. ie,
$pre_tax_subtotal->add_child_line_item(
EE_Line_Item::new_instance( array(
'LIN_name' => $swag_item[ 'name' ] . ':' . $description,
'LIN_desc' => '',
'LIN_unit_price' => (float) $total,
'LIN_quantity' => 1,
'LIN_is_taxable' => $swag_item[ 'taxable' ],
'LIN_order' => 0,
'LIN_total' => (float) $total,
'LIN_type' => EEM_Line_Item::type_line_item,
'LIN_code' => $swag_item[ 'code' ],
'TXN_ID' => $pre_tax_subtotal->get( 'TXN_ID' ) // <----------- add this maybe?
) )
);
Hmm. I haven't quite figured out source of the problem, but adding the txn_id helped. Looks like the information that's saved in the database is correct (e.g. The Line Item tables have the right totals for the events, the discounts, and the swag) but what is displayed on the screen and what is sent over to PayPal is wrong. On the back-end, the transaction shows the correct items and totals as well.
So probably I have to look more closely at EE_Line_Item and how it instantiates itself from the database for the front-end while displaying the checkout.
Looking more closely I found the following in EED_Promotions.module.php (from the Promotions Addon).
$cart->get_grand_total()->recalculate_total_including_taxes();
$cart->get_grand_total()->save();
$registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' );
$registration_processor->update_registration_final_prices(
$cart->get_grand_total()->transaction()
);
$cart->save_cart( false );
$return_data = $this->_get_payment_info( $cart );
$return_data['success'] = $promotion->accept_message();
EED_Single_Page_Checkout::update_checkout();
Now I'm looking at how the EE_Registration_processor
applies its filters, as well as how the checkout is updated.
I think that because the values are saved correctly in the database (and even display correctly on the subsequent receipt page) the problem is just how the data is parsed and passed out of the checkout screen to the payment processor (PayPal).
ok so the line items are saved correctly to the DB now, and subsequent pages show them correctly too, but the payments page isn't updated with this new info, and its passing the outdated info onto paypal. So it sounds like you're adding the line items too late, or maybe need to recalculate the line item totals again.
Hey, are the line items being saved correctly to the DB IMMEDIATELY? ie, if you check the line items in the DB or in the wp dashboard BEFORE going ot paypal, are they correct? If yes, then the payments page and info sent to paypal just needs to be refreshed somehow; if no, then the line items are somehow getting fixed upon return from paypal...
Hi @mnelson4.
Wow, I had a huge long reply, but didn't actually save it. Argh! I did figure it out (and fixed it using a brute-force solution, which I would love to discuss over a more immediate medium like Skype).
The issue seems to be related to the fact that the EE_Promotion module does an additional "process" over the cart, running all of the filters, including EE_Specific_Registrations_Line_Item_Filter
. This filter makes some assumptions about the hierarchy of the cart, that aren't true of promotions or the way that I added the swag items.
Specifically, this line in the Specific Registrations Line Item Filter: Line 98. It sets the $percent_of_running_total
value to 0, for all line items that aren't of type "Ticket", if the "running total" of "totals of children" is 0. This means that if there is a specific amount discount in the cart, which happens to zero out the event totals, all other line items that are peers of the event are zeroed out.
I think that 0 should be a 1 (Because if a line item has a Price, that total should be counted 100% towards the sum of the children, since all other children are zeroed out)
Here's the cart hierarchy with a promotion and a swag item. I used 0's to denote indents since Markdown doesn't like to indent more than a couple of levels.
0 Grand Total: sub-total: 50 00 Pre-Tax Subtotal: sub-total: 50 000 Convention: sub-total: Event: 0 0000 General Admission: line-item: Ticket: 65 00000 General Admission: sub-item: Price: 65 0000 Discount: line-item: Promotion: -65 000 Swag: line-item: Price: 50
Anyway, I addressed this issue w/ my particular setup by changing that 0 to a 1, and commenting out line 101, which changes the running total of children based on the percentage calculation. This works for our event, since we are only registering one person at a time (due to swag consideration), but might have an effect on other types of events that EE deals with.
I think there's a more fundamental issue with how specific dollar value promotions are applied, but I haven't tested out all too many other scenarios. As I said earlier, I would be happy to talk through this in more detail over Skype.
So this change I made also affects how the registrations are displayed in the back-end - because I changed the child total, the swag is being displayed fully with each individual event ticket, rather than showing as a partial value (which actually makes more sense to the admins of this site).
Hi anca would you like to create a unit test that shows the problem you're encountering and what you'd expect the results to be? You can look at tests/test cases/core/helpers/EEH_Line_Item_Test.php for some examples.
Hmm. That's an interesting idea. I haven't gotten unit tests working in my environment but that would certainly be helpful to what I'm doing.
How would you suggest integrating the EE_Promotion module into the test case? Are there test cases for that module that I could use as examples?
Ya having unit tests setup is helpful, but if you're not setup for it that's ok. (FYI I don't think the promotions addon has any unit tests; besides the logic that does all these calculations is in core, promotions just adds a line item, then core does all the calculations with it). I can set those up quite easily; and see how your proposed fix handles a variety of line item free structures
Hi there. It's going to be a few days before I get to this - I've got another project on the front burner.
going to close this since it's been over 6 months now with no response, and I'm going to assume that no news is good news
I'm working on developing an addon, so this is just a question.
My addon allows people to sell things like Tshirts and other schwag as part of a purchase. I've figured out how to create the "Ticket Extras" and now i'm tackling the other end of the process, which would be paying for them.
I'm trying to figure out the best way to do this, and I've come up with a couple:
Anyway, if you can offer me some suggestions / guidance I would appreciate it.
Thanks,
Anca.