Getting Stripe Upcoming Invoice Line Items with Laravel Cashier - laravel

I'm attempting to use Laravel Cashier to retrieve line items of the client's upcoming invoice. I'm having difficulty obtaining the invoice in the first place. Though I've found the undocumented public function "upcomingInvoice," I can't get any of its protected properties out.
Even with it, I'm having trouble understanding how to use the poorly documented "asStripe..." functions, presumably asStripeInovice(), to return the line items.
I've tried a whole host of things and it would muddle things up to write them all out, so I figure it might be better just to ask how to go about it.
Thanks!

Try this one liner code in laravel 7 or 8 with cashier.
$user->upcomingInvoice()
And you're good getting all upcoming invoices details.

As up update, I was able to get this to work just using the Stripe client, like so:
$stripe = new StripeClient(env('STRIPE_SECRET'));
$upcomingLineItems = $stripe->invoices
->upcomingLines(['customer' => $customer['stripe_id']]);
I'll still leave this open in case there's a way to do it with Cashier's methods, but it now doesn't seem necessary.

Similarly, I wanted to be able to display the "amount due today" to a user prior to switching subscription plans (which takes into account proration as well as any credit applied to the customer's account). I was able to do this in Laravel using the following:
$stripe_client = new StripeClient(config('stripe.secret'));
$items = [
[
'id' => $user->subscription()->items()->first()->stripe_id,
'price' => $selected_plan, # Switch to new price
],
];
$invoice = $stripe_client->invoices->upcoming([
'customer' => $user->stripe_id,
'subscription' => $user->subscription()->stripe_id,
'subscription_items' => $items,
'subscription_proration_date' => Carbon::now()->timestamp
]);
$amount_due = $invoice->amount_due; // and there it is

Related

Programmatically modify related products in magento

I'm trying to programmatically manipulate the product relations in a Magento store.
From what I've read, setRelatedLinkData should be the way to go.
As I simple test, I'm just trying to replace a products related products with nothing (i.e. an empty array), however it's not working - the product in question is still showing the related product in the backend.
The test code I'm working with is:
$product = Mage::getModel('catalog/product')->load($product->getId());
$linkData = array();
print_r($linkData);
$product->setRelatedLinkData($linkData);
echo "Save\n";
$r = $product->save();
As mentioned above however the product still has a related product when I reload it in the backend.
NOTE: I don't only want to remove related products, eventually I want to be able to add new ones as well, so a DELTE FROM... SQL query isn't what I am looking for. However if I can't get it to work to remove products, then it's certainly not going to work to add them, so one step at a time :-)
The quickest way I can think of is to use the Link Resource:
app/code/core/Mage/Catalog/Model/Resource/Product/Link.php saveProductLinks
// sample code
$product = Mage::getModel('catalog/product')->load(147);
$linkData = array();
Mage::getResourceModel('catalog/product_link')->saveProductLinks(
$product, $linkData, Mage_Catalog_Model_Product_Link::LINK_TYPE_RELATED
);
and if you want to assign products use the same code but provide this as $linkData:
$linkData = array(
'145' => array('position' => 1),
'146' => array('position' => 2)
);

different currencies in ci_merchant?

I want to do a webshop, where users pay via paypal. Everything works perfectly, if I use the default currencies. However I want to pay with Hungarian Forint, which is not working.
In the merchant library I have found this:
public static $NUMERIC_CURRENCY_CODES = array(
'AUD' => '036',
'CAD' => '124',
'EUR' => '978',
'GBP' => '826',
'NZD' => '554',
'USD' => '840',
);
So I added a new line: 'HUF' => '348', but regardless when I want to pass the HUF parameter to the CI-Merchant, its not working. Matter of fact, I can change anything in this array, the results will be the same
This is how I pass the parameters:
$params = array(
'amount' => $osszeg,
'currency' => 'HUF',
'return_url' => 'something',
'cancel_url' => 'something');
(paypal supports Hungarian forint, so the problem is not there)
Is there any way to make this work? Thank you very much for your answers in advance.
Firstly, don't use CI Merchant, it has been unsupported for nearly a year now. Omnipay is its replacement.
If you must use CI Merchant, then the currency parameter is correct. You don't need to add the numeric currency code, since paypal uses standard 3 letter currency codes. It's passed through to paypal here:
https://github.com/expressodev/ci-merchant/blob/master/libraries/merchant/merchant_paypal_base.php#L94
Now since you only say it's 'not working', I don't know what the actual problem is so can't really help diagnose. If there is an error message, what is it? I suspect that the currency is not enabled on your paypal account.

Seeding and pivot tables?

I'm trying to popular a pivot table with ids in a seed.
$id = DB::table('products')->insertGetId(array(
array(
'title' => 'Product A',
'published' => 1
)
));
DB::table('product_user')->insert(array(
array(
'product_id' => $id,
'user_id' => '9999999999'
)
));
Is the above the best way to do it? By getting an id via insertGetId and then putting it in the pivot table Is there a better way?
Also the above way gives an error:
[ErrorException]
preg_replace(): Parameter mismatch, pattern is a string while replacement i
s an array
I suspect $id is an array, how can i get InsertGetId to return an int?
Well, you can print_r it and seek for the id attribute, and then call $id->attribute on the second insert.
But...
"Me myself", I like to use Eloquent. The mainly reason is: 'Cause it too god damm FUN. Really, Eloquent it's one of the most beautful things I've ever seen in the programming world. I use to thought that .NET was a master piece of software (I was young and naive, though) but once a came across Laravel/Eloquent, I became so AMAZED!
That being said, in my humble opinion, use Eloquent is the best way of doing it!
I'm assuming that you have a table called products and another called users, and you have a product_user table to make the connection. Using Eloquent, you can simply do this:
$user = User::find($user_id);
$product = Product::find($product_id);
$product->user->attach($user);
...I reacomend this approach for several reasons, but the first one is: is way more readable.
Well, I hope I ain't been too prolixous on my answer, and that it hope you and others.

Magento abandoned cart for guest/unconfirmed users

In Magento abandoned cart only works for verified registered users. Is there a way to capture it for guest and unconfirmed users programmaticaly?
Also is there a way to email alert for the same?
Please tell me atleast where should I start on this. I found on a forum that with below SQL you can get all the abandoned carts, but I found some of them missing from there as well.
SELECT entity_id, customer_firstname, customer_email, items_count, grand_total, created_at
FROM sales_flat_quote
WHERE entity_id NOT IN (SELECT quote_item_id AS quote_id FROM sales_flat_order_item)
AND items_count >0
AND customer_email IS NOT NULL
ORDER BY `sales_flat_quote`.`created_at` DESC
I use a third party system for doing something like this. They cost but can be a valuable tool, especially if you have impulsive buy items. As the user is not logged in on the site, Magento can only store their basket as a quote using their session, so you are not able to get any details about the customer or the abandoned cart other than the contents of it.
If you are only interested in the items added to peoples abandoned baskets you can create custom SQL looking at the two tables you have identified in your example. Magento creates a quote for every cart which gets converted into an order when the customer purchases so the sales_quotes are table are where you need to start.
Regarding third party services, they normally involve having listeners on text boxes on the site such as email text box, name etc which post data using ajax when the field is modified. Good for capturing data during guest checkout if you have it enabled and the customer fails to finalize purchase. They do the same for add to cart buttons and start to build up a custom profile of the customer and the items in their cart as they use the site.
When somebody orders you then call another ajax request which tells the third party the customer has purchased, and those that it does not get this final request from is what it classifies as an abandoned cart. Most of these systems will email the customer after a set amount of time and days which you can define and you can normally send many emails at different time periods. You can normally also view all the abandoned carts and customer data that has been collected.
Magento's built in abandoned cart is ok for basic use but I wouldn't rely upon it. AFAIK it has no way of triggering emails for abandoned carts. E-Mail retargeting as described above can be very effective at re-capturing abandoned sales.
Have a look at somebody like exacttarget or search for magento email abandoned cart modules as I believe there are a few around that will plug and play with magento.
I was having same issue and able to solve it into magento 1.9.2 by following method:
Step-1:
Copy Collection.php file from
app/code/core/Mage/Reports/Model/Resource/Quote/
to
app/code/local/Mage/Reports/Model/Resource/Quote/
Step-2:
replace following code from line no: 194
$customerName = $adapter->getConcatSql(array('cust_fname.value', 'cust_mname.value', 'cust_lname.value',), ' ');
$this->getSelect()
->joinInner(
array('cust_email' => $attrEmailTableName),
'cust_email.entity_id = main_table.customer_id',
array('email' => 'cust_email.email')
)
->joinInner(
array('cust_fname' => $attrFirstnameTableName),
implode(' AND ', array(
'cust_fname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_fname.attribute_id = ?', (int) $attrFirstnameId),
)),
array('firstname' => 'cust_fname.value')
)
->joinInner(
array('cust_mname' => $attrMiddlenameTableName),
implode(' AND ', array(
'cust_mname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_mname.attribute_id = ?', (int) $attrMiddlenameId),
)),
array('middlename' => 'cust_mname.value')
)
->joinInner(
array('cust_lname' => $attrLastnameTableName),
implode(' AND ', array(
'cust_lname.entity_id = main_table.customer_id',
$adapter->quoteInto('cust_lname.attribute_id = ?', (int) $attrLastnameId)
)),
array(
'lastname' => 'cust_lname.value',
'customer_name' => $customerName
)
);
$this->_joinedFields['customer_name'] = $customerName;
$this->_joinedFields['email'] = 'cust_email.email';
with
$customerName = $adapter->getConcatSql(array('main_table.customer_firstname', 'main_table.customer_middlename', 'main_table.customer_lastname',), ' ');
$this->getSelect()
->columns(
array(
'email' => new Zend_Db_Expr('main_table.customer_email'),
'firstname' => new Zend_Db_Expr('main_table.customer_firstname'),
'middlename' => new Zend_Db_Expr('main_table.customer_middlename'),
'lastname' => new Zend_Db_Expr('main_table.customer_lastname'),
'customer_name' => $customerName
)
)
->where('main_table.customer_email IS NOT NULL');
$this->_joinedFields['customer_name'] = $customerName;
$this->_joinedFields['email'] = 'main_table.customer_email';
You can load cart for a guest if you know quote id. Try the following code:
$quote = Mage::getModel('sales/quote')->loadByIdWithoutStore($quoteId);
if ($quote) {
Mage::getSingleton('checkout/session')->setQuoteId($quoteId);
Mage::getSingleton('checkout/cart')->setQuote($quote);
}

Custom Magento Report for Taxable/Non-Taxable sales

Let me preface by saying I'm new to Magento as well as Data Collections in general (only recently begun working with OOP/frameworks).
I've followed the excellent tutorial here and I'm familiar with Alan Storm's overviews on the subject. My aim is to create a custom Magento report which, given a start/end date, will return the following totals:
Taxable Net (SUM subtotal for orders with tax)
Non-Taxable Net (SUM subtotal for orders without tax)
*Total Gross Sales (Grand total)
*Total Net Sales (Grand subtotal)
*Total Shipping
*Total Tax
*For these figures, I realize they are available in existing separate reports or can be manually calculated from them, however the purpose of this report is to give our store owner a single page to visit and file to export to send to his accountant for tax purposes.
I have the basic report structure already in place in Adminhtml including the date range, and I'm confident I can include additional filters if needed for order status/etc. Now I just need to pull the correct Data collection and figure out how to retrieve the relevant data.
My trouble is I can't make heads or tails of how the orders data is stored, what Joins are necessary (if any), how to manipulate the data once I have it, or how they interface with the Grid I've set up. The existing tutorials on the subject that I've found are all specifically dealing with product reports, as opposed to the aggregate sales data I need.
Many thanks in advance if anyone can point me in the right direction to a resource that can help me understand how to work with Magento sales data, or offer any other insight.
I have been working on something extremely similar and I used that tutorial as my base.
Expanding Orders Join Inner
Most of the order information you need is located in sales_flat_order with relates to $this->getTable('sales/order')
This actually already exists in her code but the array is empty so you need to populate it with the fields you want, here for example is mine:
->joinInner(
array('order' => $this->getTable('sales/order')),
implode(' AND ', $orderJoinCondition),
array(
'order_id' => 'order.entity_id',
'store_id' => 'order.store_id',
'currency_code' => 'order.order_currency_code',
'state' => 'order.state',
'status' => 'order.status',
'shipping_amount' => 'order.shipping_amount',
'shipping_tax_amount' => 'order.shipping_tax_amount',
'shipping_incl_tax' => 'base_shipping_incl_tax',
'subtotal' => 'order.subtotal',
'subtotal_incl_tax' => 'order.subtotal_incl_tax',
'total_item_count' => 'order.total_item_count',
'created_at' => 'order.created_at',
'updated_at' => 'order.updated_at'
))
To find the fields just desc sales_flat_order in mysql.
Adding additional Join Left
Ok so if you want information from other tables you need to add an ->joinLeft() for example I needed the shipment tracking number:
Create the Join condition:
$shipmentJoinCondition = array(
$orderTableAliasName . '.entity_id = shipment.order_id'
);
Perform the join left:
->joinLeft(
array('shipment' => $this->getTable('sales/shipment_track')),
implode(' AND ', $shipmentJoinCondition),
array(
'track_number' => 'shipment.track_number'
)
)
Sorry I couldn't go into more depth just dropping the snippet for you here.
Performing Calculations
To modify the data returned to the grid you have to change addItem(Varien_Object $item) in your model, basically whatever is returned from here get put in the grid, and well I am not 100% sure how it works and it seems a bit magical to me.
Ok first things first $item is an object, whatever you do to this object will stay with the object (sorry terrible explanation): Example, I wanted to return each order on a separate line and for each have (1/3, 2/3, 3/3), any changes I made would happen globally to the order object so they would all show (3/3). So keep this in mind, if funky stuff starts happening use PHP Clone.
$item_array = clone $item;
So now onto your logic, you can add any key you want to the array and it will be accessible in Grid.php
For example(bad since subtotal_incl_tax exists) :
$item_array['my_taxable_net_calc'] = $item['sub_total'] + $item['tax'];
Then at the end do:
$this->_items[] = $item_array;
return $this->_items;
You can also add more rows based on the existing by just adding more data to $this->_items[];
$this->_items[] = $item_array;
$this->_items[] = $item_array;
return $this->_items;
Would return same item on two lines.
Sorry I have started to lose the plot, if something doesn't make sense just ask, hope this helped.
Oh and to add to Block/Adminhtml/namespace/Grid.php
$this->addColumn('my_taxable_net_calc', array(
'header' => Mage::helper('report')->__('Taxable Net'),
'sortable' => false,
'filter' => false,
'index' => 'my_taxable_net_calc'
));

Resources