how to access items within the basket

1 week 13 hours ago #315539 by activha

Can you be more specific? What exactly are you struggling with?


For the payment display part. I'd like a nicer solution to display and also update payments and payments states when there is a pending, reversed, refund or completed state.

The code attached seems to work to display pending and completed payments but when there is a refund or a partial refund it fails displaying the remaining amount correctly and also fails to display the negative refund.

If you have any idea to enhance it I would greatly appreciate. Am testing Invoice Manager on our devel website and this could be a nice addition to deal with CBsubs invoicing and centralize everything.
6 days 16 hours ago - 5 days 17 hours ago #315549 by krileon
The code you're using just loops through a baskets payment rows when the baskets status changes. If you're just trying to display information from the database you should be able to just query the _cbsubs_payment_items database table for payment row information. Can probably even do this entirely with CB Query Field. Example as follows.

Query:
SELECT * FROM `#__cbsubs_payments` WHERE `by_user_id` = '[user_id]' ORDER BY `time_paid` DESC
Output: Multiple Rows
Header:
<table>
	<thead>
		<tr>
			<th>Invoice</th>
			<th>Item</th>
			<th>Amount</th>
			<th>Date</th>
		</tr>
	</thead>
	<tbody>
Row:
		<tr>
			<td><a href="INVOICE_URL" target="_blank">[column_invoice]</a></td>
			<td>[column_item_name]</td>
			<td>[column_mc_gross]</td>
			<td>[column_time_paid]</td>
		</tr>
Footer:
	</tbody>
</table>

The above will display their full payment history as a table. You can add more columns to it, adjust the column values in the query if you like, etc.. The invoice column value links to their frontend invoice (basket) as well.


Kyle (Krileon)
Community Builder Team Member
Before posting on forums: Read FAQ thoroughly + Read our Documentation + Search the forums
CB links: Documentation - Templates - CBSubs - Hosting - Forge - Incubator - GroupJive
--
If you are a Professional, Developer, or CB Paid Subscriptions subscriber and have a support issue please always post in your respective support forums for best results!
--
If I've missed your support post with a delay of 3 days or greater and are a Professional, Developer, or CBSubs subscriber please send me a private message with your thread and will reply when possible!
--
Please note I am available Monday - Friday from 8:00 AM EST to 4:00 PM EST. I am away on weekends (Saturday and Sunday) and if I've missed your post on or before a weekend after business hours please wait for the next following business day (Monday) and will get to your issue as soon as possible, thank you.
--
My role here is to provide guidance and assistance. I cannot provide custom code for each custom requirement. Please do not inquire me about custom development.
5 days 23 hours ago - 5 days 22 hours ago #315564 by activha
Yes we already used this query to display payments in the front end.
But as I wrote at multiple times, payments are not invoices and we need an integration with a correct invoice component outside for lots of business and legal reasons.

JoomlaThat Invoices Manager seems fine and this is why we tried to wrote this plugin. You should review writing a formal CBsubs integration for them as they have already lots of joomla components listed.

I changed the payment part and the plugin and the test to include both basket and payment.

Mind to review it from your point of view ?
<?php

use CB\Database\Table\UserTable;

if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }

global $_PLUGINS;
$_PLUGINS->registerFunction( 'onCPayAfterPaymentStatusUpdateEvent', 'onCPayAfterPaymentStatusUpdateEvent', 'getahainvoicemanagerTab' );

class getahainvoicemanagerTab extends cbTabHandler {
 	public function onCPayAfterPaymentStatusUpdateEvent( $user, $paymentBasket, /** @noinspection PhpUnusedParameterInspection */ $subscriptions, $unifiedStatus, /** @noinspection PhpUnusedParameterInspection */ $previousUnifiedStatus, /** @noinspection PhpUnusedParameterInspection */ $eventType, /** @noinspection PhpUnusedParameterInspection */ $notification ) {
		global $_CB_framework;

		// if ( ( ! ( ( $unifiedStatus == 'Completed' ) || ( $unifiedStatus == 'Processed' ) ) ) || ( ! is_object( $user ) ) ) {
// 			return;
// 		}

		$params							=	cbpaidApp::settingsParams();
		$invFile						=	$_CB_framework->getCfg( 'absolute_path' ) . '/components/com_invoices/helpers/helpers.php';
		if ( ! file_exists( $invFile ) ) {
			return;
		}
		$paramsiv = JComponentHelper::getParams( 'com_invoices' );
		$component = "com_comprofiler" ;
		include_once($invFile);

		$db = JFactory::getDBO();

		$is_new = false;
		$must_update = false ;
		$invoice_id = 0 ;
		//we check if this particular order-payment combination exists for CBsubs
		$query = " SELECT * FROM #__cbsubs_payments WHERE payment_basket_id = '".$paymentBasket->id."' ORDER BY time_paid DESC LIMIT 1";
		$db->setQuery($query);
		$last_payment = $db->loadObject();

		//we check if this particular order had already been tracked
		$query = " SELECT id FROM #__invoices_invoices WHERE external_type = '".$component."' AND external_id = '". $paymentBasket->id."'-'". $last_payment->id ."'";
		$db->setQuery($query);
		$exists = $db->loadResult();

		if(!$exists){
			$is_new = true ;
		}
		else{
			$must_update = true ;
			$invoice_id = $exists;
		}

		if($is_new || $must_update){

			$query = ' SELECT i.real_invoice_num FROM #__invoices_invoices as i WHERE i.type = 1 '.' ORDER BY i.id DESC ';
			$db->setQuery( $query );
			$real_invoice_num = $db->loadResult() + 1;
			$invoice_num = InvoicesHelper::getInvoiceNum($real_invoice_num) ;

			$taxes = array();

			$invoice_date = date('Y-m-d H:i:s');

			$app = JFactory::getApplication();
			if($app->isSite()) $language = "fr-FR"; 
			else $language = $paramsiv->get('default_language', 'en-GB');

			$link_contact = 2;
			$contact_id = 0;

			$query = " SELECT id FROM #__invoices_contacts WHERE email = '". $paymentBasket->payer_email ."'";
			$db->setQuery($query);
			$contact_id = (int)$db->loadResult();

			if($contact_id) $link_contact = 1;

			if(!$is_new){ // we are updating. These fields should NOT be updated.
				$real_invoice_num = null;
				$invoice_num = null;
				$invoice_date = null;
				$language = null;
				$link_contact = 1;
				$contact_id = null;
			}
			$invoice_status = null;
			
			//to do voir les traductions sur IM
//			if($paymentBasket->payment_status = "Pending") $invoice_status = "En attente";
// 			if($paymentBasket->payment_status = "Completed") $invoice_status = "Payé";
// 			if($paymentBasket->payment_status = "Refunded") $invoice_status = "Remboursé";
// 			if($paymentBasket->payment_status = "Partially-Refunded") $invoice_status = "Partiellement Remboursé";
// 			if($paymentBasket->payment_status = "Denied") $invoice_status = "Paiement Refusé";


			$invoice_data = array(
							"id" => $invoice_id ,
							"to_name" => $paymentBasket->first_name . " " .$paymentBasket->last_name,
							"to_company" => $paymentBasket->payer_business_name,
							"to_address" => $paymentBasket->address_street,
							"to_email" => $paymentBasket->payer_email,
							"to_zipcode" => $paymentBasket->address_zip,
							"to_city" => $paymentBasket->address_city,
							"to_state" => $paymentBasket->address_state,
							"to_country" => $paymentBasket->address_country,
							"to_phone" => $paymentBasket->contact_phone,
							"to_vatid" => $paymentBasket->vat_number,
							"vincular_cliente_checkbox" => $link_contact,
							"user_id" => $contact_id,
							"from_name" => $paramsiv->get('from_name'),
							"from_address" => $paramsiv->get('from_address'),
							"from_num" => $paramsiv->get('from_num'),
							"from_url" => $paramsiv->get('from_url'),
							"from_email" => $paramsiv->get('from_email'),
							"from_phone" => $paramsiv->get('from_phone'),
							"invoice_num" => $invoice_num,
							"real_invoice_num" => $real_invoice_num,
							"invoice_date" => $invoice_date,
							"template_id" => $paramsiv->get('invoice_template'),
							"currency_id" => $paramsiv->get('currency_id'),
							"language" => $language,
// 							"publish" => $paramsiv->get('activation'),
							"publish" => 1,
// 							"is_recurrent" => $paymentBasket->recurring,
							"start_publish" => null,
							"end_publish" => null,
							//to do invoice date plus 15j
							"invoice_duedate" => date('Y-m-d H:i:s', strtotime(' + 15 days')),
							"joomla_user_id" => $paymentBasket->user_id,
							"taxes" => $taxes,
							"status" => $invoice_status,
							"external_type" => $component,
							"external_id" => $paymentBasket->id."-'". $last_payment->id,
							"external_ref" => $paymentBasket->invoice,
							//"discount" => $order_discount_price,
							"sendemail" => $paramsiv->get('sendemail', 0)
							) ;


		$items = array();

		$value = ($paymentBasket->mc_gross-$paymentBasket->tax);
		$diff = ($paymentBasket->mc_gross-$value);
		
		if($paymentBasket->tax > 0) $thetax = round(( $diff / $value ) * 100, $paramsiv->get('roundtax', 2)) ;
		else $thetax = 0 ;
		

		$products = $paymentBasket->loadPaymentItems();
		
		foreach($products as $product){ 
				$name = $product->alias;
				$sku = $product->plan_id;
				$subscription =	$product->loadSubscription();
				$plan =	$subscription ? $subscription->getPlan() : cbpaidPlansMgr::getInstance()->loadPlan( $product->plan_id );
				if ( !$plan ) {
					$plan_name =  "Prestations";
				}
				$plan_name = addslashes( $plan->name );
			
		$items[] = array(
							"id" => $paymentBasket->id,
							"sku" => $sku,
							"name" => $plan_name,
							"desc" => $paymentBasket->item_number,
							"value" => $value,
							"amount" => $paymentBasket->quantity,
							"tax" => $thetax  ,
							"tax_id" => $paramsiv->get('tax_id', 0),
							"external_type" => $component,
							"product_id" => $products->artnum,
							);
		}
		
		//Shipping
		if($paymentBasket->mc_shipping > 0){

			$shipping_name = "";
			$shipping_name = $paymentBasket->shipping;

			$shipping_price = $paymentBasket->mc_shipping;

			$shipping_item_exists = 0;

			if($must_update){
				$query = " SELECT id FROM #__invoices_items WHERE invoice_id = '".$invoice_id."' AND external_type = '".$component."_shipping' ";
				$db->setQuery($query);
				$shipping_item_exists = $db->loadResult();
			}

			$shipping_item_id = $shipping_item_exists ;

			$items[] = array(
								"id" => $shipping_item_id,
								"sku" => "",
								"name" => JText::_("Shipping"),
								"desc" => $shipping_name,
								"value" => $shipping_price,
								"amount" => 1,
								"tax" => ( $theorder->tax / $shipping_price ) * 100,
								"tax_id" => $paramsiv->get('tax_id', 0),
								"external_type" => $component."_shipping",
								"product_id" => 0,
								);
		}

		//Payment
		if($paymentBasket->mc_gross > 0){

			$payment_name = "";
			$payment_name = $paymentBasket->payment_type;

			$payment_item_exists = 0 ;

			if($must_update){
				$query = " SELECT id FROM #__invoices_items WHERE invoice_id = '".$invoice_id."' AND external_type = '".$component."_payment'";
				$db->setQuery($query);
				$payment_item_exists = $db->loadResult();
			}

			$payment_item_id = $payment_item_exists ;

			$items[] = array(
								"id" => $payment_item_id,
								"sku" => $sku,
								"name" => $plan_name,
								"desc" => $paymentBasket->item_number,
								"value" => $value,
								"amount" => $paymentBasket->quantity,
								"tax" => $thetax ,
								"tax_id" => $paramsiv->get('tax_id', 0),
								"external_type" => $component."_payment",
								"product_id" => $products->artnum

								);
		}
		
		$payments = array();

		if($paymentBasket->payment_status == "Completed") $payment_status = 1 ;
		else $payment_status = 0 ;

		$payment_exists = 0 ;

		//if(!$paymentBasket->payment_gross) $paymentBasket = $paymentBasket->old;

		if($must_update){
			$query = " SELECT id FROM #__invoices_payments WHERE invoice_id = '".$invoice_id."' AND payment_type = 'payment_".$paymentBasket->payment_method . "' ";
			$db->setQuery($query);
			$payment_exists = $db->loadResult();
		}

		$payment_id = $payment_exists;

// 			if($last_payment->payment_status == "Completed") $payment_status = 1 ;
			$payments[0] = array(
							"id" => $payment_id,
							"payment_details" => $last_payment->txn_id,
							"payment_datetime" => $last_payment->time_paid,
							"payment_amount" => $last_payment->mc_gross,
							"payment_type" => "payment_".$last_payment->payment_method,
							"payment_description" => $last_payment->payment_type . " - Réglement n°: ".$last_payment->id . " - id : " . $last_payment->txn_id,
							"payment_id" => $last_payment->id,
							"payment_status" => $payment_status
							);				

		InvoicesHelper::create_invoice($invoice_data, $items, $payments);
		}
	}	
}
5 days 17 hours ago #315569 by krileon
Why was the below usage no longer sufficient? Code to renumber payment rows, display them, and output a CBSubs driven invoice was all provided.

www.joomlapolis.com/forum/255-developer-members-support/240879-invoicing-for-recurring-payments


Kyle (Krileon)
Community Builder Team Member
Before posting on forums: Read FAQ thoroughly + Read our Documentation + Search the forums
CB links: Documentation - Templates - CBSubs - Hosting - Forge - Incubator - GroupJive
--
If you are a Professional, Developer, or CB Paid Subscriptions subscriber and have a support issue please always post in your respective support forums for best results!
--
If I've missed your support post with a delay of 3 days or greater and are a Professional, Developer, or CBSubs subscriber please send me a private message with your thread and will reply when possible!
--
Please note I am available Monday - Friday from 8:00 AM EST to 4:00 PM EST. I am away on weekends (Saturday and Sunday) and if I've missed your post on or before a weekend after business hours please wait for the next following business day (Monday) and will get to your issue as soon as possible, thank you.
--
My role here is to provide guidance and assistance. I cannot provide custom code for each custom requirement. Please do not inquire me about custom development.
5 days 17 hours ago - 5 days 17 hours ago #315570 by activha
We need to integrate CBsubs invoices in a global component because we also have Hikashop invoices.
The legal law in France obliges us to have a single numbering for all invoices so Invoice Manager seems the good solution provided that we can integrate CBsubs

I edited the plugin to test the combination $paymentBasket->id . $last_payment->id for external_id and it seems to work pretty well to issue new invoices for each new payment.

The only drawback is that I don't succeed in dealing with refund or denied payments which issue a new id in CBsubs_payment but without referring to the previous try.

Would you have an idea for that ?
5 days 17 hours ago #315572 by krileon
Refunds should have the previous payment referenced in parent_txn_id if the refund IPN is able to provide that information.


Kyle (Krileon)
Community Builder Team Member
Before posting on forums: Read FAQ thoroughly + Read our Documentation + Search the forums
CB links: Documentation - Templates - CBSubs - Hosting - Forge - Incubator - GroupJive
--
If you are a Professional, Developer, or CB Paid Subscriptions subscriber and have a support issue please always post in your respective support forums for best results!
--
If I've missed your support post with a delay of 3 days or greater and are a Professional, Developer, or CBSubs subscriber please send me a private message with your thread and will reply when possible!
--
Please note I am available Monday - Friday from 8:00 AM EST to 4:00 PM EST. I am away on weekends (Saturday and Sunday) and if I've missed your post on or before a weekend after business hours please wait for the next following business day (Monday) and will get to your issue as soon as possible, thank you.
--
My role here is to provide guidance and assistance. I cannot provide custom code for each custom requirement. Please do not inquire me about custom development.
Moderators: beatnantkrileon
Time to create page: 0.427 seconds
Facebook Twitter Google LinkedIn