Laravel Cashier (Stripe) get subscription cost or coupon used? - laravel-5

I'm using Laravel Cashier with Stripe.
In my account panel I want to show users how much their monthly subscription is costing them.
Users can have a normal plan without a coupon or the same plan with a coupon that makes it half price.
Is there anyway Cashier can tell me how much the monthly subscription is costing them or if they signed up using a coupon? Or is this something I have to store in my own database at the time they subscribe?

I created a coupon trait that I use on my User Model. Hope that helps.
<?php
namespace App\Traits;
use Carbon\Carbon;
trait Coupon
{
public function getSubscriptions()
{
return $this->asStripeCustomer()->subscriptions->data;
}
public function getSubscription()
{
foreach ($this->getSubscriptions() as $subscription) {
if ($subscription->status === 'active') {
return $subscription;
}
}
}
public function discount()
{
return $this->getSubscription()->discount;
}
public function discountCustomerId()
{
return $this->discount()->customer;
}
public function discountSubscriptionId()
{
return $this->discount()->subscription;
}
public function discountStartDate()
{
return Carbon::createFromTimestamp($this->discount()->start);
}
public function discountEndDate()
{
return Carbon::createFromTimestamp($this->discount()->end);
}
public function discountDaysLeft()
{
return $this->discountEndDate()
->diffInDays($this->discountStartDate());
}
public function coupon()
{
return $this->discount()->coupon;
}
public function couponIsValid()
{
return $this->coupon()->valid;
}
}

Related

Get attributes from relationship parent model

I'm loading some data for the user like this.
Method 1
$user->load(['subscription.payementTypes']);
Method 2
$user->load(['charity.payementTypes']);
Is there anyway I can figure out in the PaymentType model that it is called via subscription or charity?
I want to call an Accessor in PaymentType based on Subscription or Charity
// For Subscriptions
public function getPaymentDescriptionAttribute()
{
// if Subscription
// if Charity
}
The relationships are as follows.
//Class User
public function subscription()
{
return $this->hasOne(Subscription::class);
}
public function charity()
{
return $this->hasOne(Charity::class);
}
//Class Subscription
public function paymentTypes()
{
return $this->belongsToMany(PaymentType::class);
}
I feel like in class Subscription, you should name it paymentTypes. I'd say it's a hasMany though?
public function paymentTypes()
{
return $this->hasMany(PaymentType::class);
}
and in the PaymentType you can do
public function subscription
{
return $this->belongsTo(Subscription::class);
}
if it is not working you can do somthing like this
in User.php
//Class User
public function subscriptionWithPaymentType()
{
return $this->hasOne(Subscription::class)->with('paymentTypes');
}
then you can do this
$user->load(['subscriptionWithPaymentType']);

How to get multiple relationships Data in My Laravel Vue Project

I have a 3 model "User","Review","ReviewReplay"
in user Model
public function reviews()
{
return $this->hasMany('App\Models\Review');
}
public function reviewReplys()
{
return $this->hasMany('App\Models\ReviewReply');
}
In Review Model
public function user()
{
return $this->belongsTo('App\Models\User');
}
public function reviewReplys()
{
return $this->hasMany('App\Models\ReviewReply');
}
in Review Replay Model
public function user()
{
return $this->belongsTo('App\Models\User');
}
public function review()
{
return $this->belongsTo('App\Models\Reviews');
}
in My Controller
public function getReview($id)
{
$review= Review::where('product_id',$id)->with('user','reviewReplys')->paginate(10);
return response()->json($review);
}
Now here I run Review foreach loop and here I need review.reviewReplay.user information. How I Get The Review Replay User information inside Review Foreach loop.
You can do it as below.
$review= Review::where('product_id',$id)->with(['reviewReplys.user'])->paginate(10);
with(['reviewReplys.user']) --> it will make connection between Review model to reviewReplys model +
reviewReplys model to User model

laravel hasManyDeepFromRelations with group by

Models and relations
class Publisher extends Model
{
use HasRelationships;
public function collections(): BelongsToMany
{
return $this->belongsToMany(Collection::class)
->orderBy('title')
->using(CollectionPublisher::class);
}
public function series(): HasManyDeep
{
return $this->hasManyDeepFromRelations($this->collections(), (new Collection())->series());
}
}
class Collection extends Model
{
use HasRelationships, Translatable;
public function editions(): HasMany
{
return $this->hasMany(Edition::class);
}
public function series(): HasManyDeep
{
return $this->hasManyDeepFromRelations($this->editions(), (new Edition)->series());
}
}
class Edition extends Model
{
use HasRelationships, LoadsRelationshipsWithoutScopes, Translatable;
public function series(): BelongsTo
{
return $this->belongsTo(Series::class);
}
public function collection(): BelongsTo
{
return $this->belongsTo(Collection::class);
}
}
And of course there is a Series model.
The problem is that the series relation on the Publisher is returning each Series as many times as there is an Edition for that Publisher in the Series
How do I trim it down so each series is only returned once?
A simple groupBy('series.id') does not work due to the full group by limitations, and I'm not sure how to get around this using the has many deep package.
I finally came up with a solution
On the Publisher model:
public function series(): Builder
{
return $this->hasManyDeepFromRelations($this->collections(), (new Collection())->series())
->getQuery()
->select('series.*')
->groupBy('series.id');
}
The getQuery() part (undocumented in Laravel) limits the scope and allows the groupBy() to work
Thanks to Jonas Staudenmeir for the help

Laravel - Delete if no relationship exists

Below is the one of the model. I would like to delete a Telco entry only if no other model is referencing it? What is the best method?
namespace App;
use Illuminate\Database\Eloquent\Model;
class Telco extends Model
{
public function operators()
{
return $this->hasMany('App\Operator');
}
public function packages()
{
return $this->hasMany('App\Package');
}
public function topups()
{
return $this->hasMany('App\Topup');
}
public function users()
{
return $this->morphMany('App\User', 'owner');
}
public function subscribers()
{
return $this->hasManyThrough('App\Subscriber', 'App\Operator');
}
}
You can use deleting model event and check if there any related records before deletion and prevent deletion if any exists.
In your Telco model
protected static function boot()
{
parent::boot();
static::deleting(function($telco) {
$relationMethods = ['operators', 'packages', 'topups', 'users'];
foreach ($relationMethods as $relationMethod) {
if ($telco->$relationMethod()->count() > 0) {
return false;
}
}
});
}
$relationships = array('operators', 'packages', 'topups', 'users', 'subscribers');
$telco = Telco::find($id);
$should_delete = true;
foreach($relationships as $r) {
if ($telco->$r->isNotEmpty()) {
$should_delete = false;
break;
}
}
if ($should_delete == true) {
$telco->delete();
}
Well, I know this is ugly, but I think it should work. If you prefer to un-ugly this, just call every relationship attributes and check whether it returns an empty collection (meaning there is no relationship)
If all relationships are empty, then delete!
After seeing the answers here, I don't feel copy pasting the static function boot to every models that need it. So I make a trait called SecureDelete. I put #chanafdo's foreach, inside a public function in SecureDelete.
This way, I can reuse it to models that need it.
SecureDelete.php
trait SecureDelete
{
/**
* Delete only when there is no reference to other models.
*
* #param array $relations
* #return response
*/
public function secureDelete(String ...$relations)
{
$hasRelation = false;
foreach ($relations as $relation) {
if ($this->$relation()->withTrashed()->count()) {
$hasRelation = true;
break;
}
}
if ($hasRelation) {
$this->delete();
} else {
$this->forceDelete();
}
}
}
Add use SecureDelete to the model that needs it.
use Illuminate\Database\Eloquent\Model;
use App\Traits\SecureDelete;
class Telco extends Model
{
use SecureDelete;
public function operators()
{
return $this->hasMany('App\Operator');
}
// other eloquent relationships (packages, topups, etc)
}
TelcoController.php
public function destroy(Telco $telco)
{
return $telco->secureDelete('operators', 'packages', 'topups');
}
In addition, instead of Trait, you can also make a custom model e.g BaseModel.php that extends Illuminate\Database\Eloquent\Model, put the function secureDelete there, and change your models to extends BaseModel.

Laravel 4 Relationship: messaging system

I followed the suggestions from user ehp in order to build a lightweight messaging-system:
https://stackoverflow.com/a/18717864/1084315
Users: id | username
Messages: id | from | content
user_messages: user_id | message_id
class User extends Eloquent {
public function messages()
{
return $this->belongsToMany('Message');
}
public function sent_messages()
{
return $this->hasMany('Messages', 'from');
}
}
class Message extends Eloquent {
public function from()
{
return $this->belongsTo('User', 'from');
}
public function to()
{
return $this->belongsToMany('User');
}
}
I create a message like this:
User::find(2)->messages()->create(array('text'=>'this is a message from admin to someone', 'from'=>'1');
Now I need to find / get every Message from a specific user to a specific user.
But in this example only the 'from' IDs are stored in the 'messages' table directly.
I can not even access the pivot of any Message by using
User::find(1)->sent_messages()->get();
What are best practices for collecting messages between one and another user?
Any help highly appreciated
First of all, I think there's a small typo:
public function sent_messages() {
return $this->hasMany('Messages', 'from');
}
This should probably be:
public function sent_messages() {
return $this->hasMany('Message', 'from');
}
Now, if you're looking to get all the messages sent from one user to another, what about this? Untested, but placing a constraint on the to relationship should do the trick.
$messages_from_A_to_B = Message::where('from', $UserA->id)->whereHas('to', function($q) use ($UserB) {
$q->where('user_id', $UserB->id);
})->get();
On a side note, I'm assuming that you specifically require that a user can send a message to more than one user? Else the following table structure seems like it would be easier:
users: id
messages: from | to
And then you just need:
class User extends Eloquent {
public function messages() {
return $this->hasMany('Message', 'to');
}
public function sent_messages() {
return $this->hasMany('Message', 'from');
}
}
class Message extends Eloquent {
public function from() {
return $this->belongsTo('User', 'from');
}
public function to() {
return $this->belongsTo('User', 'to');
}
}
$messages_from_A_to_B = Message::where('from', $UserA->id)->where('to', $UserB->id)->get();

Resources