mollie / laravel-cashier-mollie

Official Mollie integration for Laravel Cashier
https://www.cashiermollie.com/
MIT License
137 stars 45 forks source link

One-Time charge: order items orderable_id / model #122

Closed divdax closed 4 months ago

divdax commented 2 years ago

It would be great we could set the orderable morph relationship for one time charges like so:

$product = App\Models\SomethingOrderable::find(1);
$result = $user->newCharge();

$item = new ChargeItemBuilder($user);
$item->quantity($data->qty);
$item->unitPrice(money($data->price*100,'EUR'));
$item->description($data->name);
$item->taxPercentage(19);
$tiem->orderableModel($product); // <---------- new method

$result->addItem($item->make());

$result = $result->create();

Currently orderable_id & oderable_type in table order_items is always empty.

sandervanhooft commented 2 years ago

How about this?

$item = new \Laravel\Cashier\Charge\ChargeItemBuilder($user, $orderable);
divdax commented 2 years ago

@sandervanhooft yeah... much better! :)

sandervanhooft commented 2 years ago

Would be even cooler to do something like this and fill everything automatically:

class ChargeItemBuilder
{
    // ...

    public static function forChargeable(Chargeable $chargeable, Model $billable)
    {

        $result = new static($billable);
        $result->orderable = $chargeable->orderable();
        $result->unitPrice($chargeable->unitPrice());
        $result->description($chargeable->description());
        $result->taxPercentage($billable->taxPercentage());

        return $result;
    }
}
interface Chargeable
{
    public function orderable(): Model;
    public function unitPrice(): Money;
    public function description(): string;
}

This would require some additional modifications around handlePaymentFailed/Paid on the orderable model (also see InteractsWithOrderItems. 🤔

Need to investigate if this is possible without breaking change.

sandervanhooft commented 2 years ago

For clarity, this would allow you to do stuff like

$itemA = ChargeItemBuilder::forChargeable($chargeableA, $billable)->make();
$itemB = ChargeItemBuilder::forChargeable($chargeableB, $billable)
    ->taxPercentage(5.5) // overrides allowed
    ->description('Some other description')  // overrides allowed
    ->quantity(3)
    ->make();

$result = $user->newCharge()
    ->addItem($itemA)
    ->addItem($itemB)
    ->setRedirectUrl('https://www.example.com')
    ->create();
divdax commented 2 years ago

This is awesome! 😍

sandervanhooft commented 2 years ago

Thanks @divdax .

This is going to involve several steps, need to be careful to not break any existing installations. First impressions:

  1. Split InteractsWithOrderItems into the following interfaces and apply as such:

    • HandlesPaymentStatusUpdates
    • ProcessesOrderItem
    • PreprocessesOrderItems (already exists)
  2. Add checks to Order.handlePaymentPaid etc to check if the handlePaymentFailed method exists on the item before calling it.

  3. Add Chargeable interface.

  4. Add ChargeItemBuilder::forChargeable()

divdax commented 2 years ago

Do you think it's possible?

sandervanhooft commented 2 years ago

We have put the first steps towards this on our backlog 🤞

divdax commented 1 year ago

First of all happy new year! 🎉 Sorry for asking, but do you have any news here?

tobischulz commented 1 year ago

Hey, this would help a lot! Is there currently any way to get all one-time charges for a user?

valerius21 commented 4 months ago

Any updates on this?

Naoray commented 4 months ago

Hi @valerius21,

this will likely included within the next major release of this package. There is currently no ETA for the next major release, but I expect it to happen within this year.