1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-08 20:22:42 +01:00

Fixes for wrong product types being used cost => price

This commit is contained in:
David Bomba 2024-02-22 14:00:39 +11:00
parent 42b111db58
commit 55d512b0a5
8 changed files with 104 additions and 31 deletions

View File

@ -23,7 +23,9 @@ class OptionalRecurringProducts extends Component
public function quantity($id, $value): void public function quantity($id, $value): void
{ {
$this->dispatch('purchase.context', property: "bundle.optional_recurring_products.{$id}.quantity", value: $value); $this->dispatch('purchase.context', property: "bundle.optional_recurring_products.{$id}.quantity", value: $value);
} }
public function render(): \Illuminate\View\View public function render(): \Illuminate\View\View

View File

@ -73,8 +73,6 @@ class Methods extends Component
? \App\Utils\Number::formatValue($invoice->partial, $invoice->client->currency()) ? \App\Utils\Number::formatValue($invoice->partial, $invoice->client->currency())
: \App\Utils\Number::formatValue($invoice->balance, $invoice->client->currency()); : \App\Utils\Number::formatValue($invoice->balance, $invoice->client->currency());
nlog($invoice->toArray());
$this->dispatch('purchase.context', property: 'form.company_gateway_id', value: $company_gateway_id); $this->dispatch('purchase.context', property: 'form.company_gateway_id', value: $company_gateway_id);
$this->dispatch('purchase.context', property: 'form.payment_method_id', value: $gateway_type_id); $this->dispatch('purchase.context', property: 'form.payment_method_id', value: $gateway_type_id);
$this->dispatch('purchase.context', property: 'form.invoice_hashed_id', value: $invoice->hashed_id); $this->dispatch('purchase.context', property: 'form.invoice_hashed_id', value: $invoice->hashed_id);

View File

@ -161,6 +161,7 @@ class Purchase extends Component
#[On('purchase.next')] #[On('purchase.next')]
public function handleNext(): void public function handleNext(): void
{ {
if ($this->step < count($this->steps) - 1) { if ($this->step < count($this->steps) - 1) {
$this->step++; $this->step++;
} }

View File

@ -30,30 +30,34 @@ class RFF extends Component
$validated = $this->validate([ $validated = $this->validate([
'contact_first_name' => ['required'], 'contact_first_name' => ['required'],
'contact_last_name' => ['required'], 'contact_last_name' => ['required'],
'contact_email' => ['required', 'email'], // 'contact_email' => ['sometimes', 'email'],
]); ]);
$this->contact = auth()->guard('contact')->user();
$this->contact->first_name = $validated['contact_first_name']; $this->contact->first_name = $validated['contact_first_name'];
$this->contact->last_name = $validated['contact_last_name']; $this->contact->last_name = $validated['contact_last_name'];
$this->contact->email = $validated['contact_email'];
$this->contact->save(); $this->contact->save();
$this->contact_first_name = $this->contact->first_name;
$this->contact_last_name = $this->contact->last_name;
$this->contact_email = $this->contact->email;
$this->dispatch('purchase.context', property: 'contact.first_name', value: $this->contact->first_name);
$this->dispatch('purchase.context', property: 'contact.last_name', value: $this->contact->last_name);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
public function mount() public function mount()
{ {
if (auth()->guard('contact')->user()->showRff() === false) { /** @var \App\Models\ClientContact $contact */
$contact = auth()->guard('contact')->user();
if ($contact->showRff() === false) {
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
$this->contact = auth()->guard('contact')->user();
$this->contact_first_name = $this->contact->first_name;
$this->contact_last_name = $this->contact->last_name;
$this->contact_email = $this->contact->email;
} }
public function render() public function render()
{ {
return view('billing-portal.v3.rff'); return view('billing-portal.v3.rff');

View File

@ -40,6 +40,7 @@ class Summary extends Component
'quantity' => $bundle['recurring_products'][$product->hashed_id]['quantity'] ?? 1, 'quantity' => $bundle['recurring_products'][$product->hashed_id]['quantity'] ?? 1,
'notes' => $product->markdownNotes(), 'notes' => $product->markdownNotes(),
]; ];
$bundle['recurring_products'][$product->hashed_id]['product']['is_recurring'] = true;
} }
foreach ($this->subscription->service()->products() as $key => $product) { foreach ($this->subscription->service()->products() as $key => $product) {
@ -48,6 +49,7 @@ class Summary extends Component
'quantity' => $bundle['one_time_products'][$product->hashed_id]['quantity'] ?? 1, 'quantity' => $bundle['one_time_products'][$product->hashed_id]['quantity'] ?? 1,
'notes' => $product->markdownNotes(), 'notes' => $product->markdownNotes(),
]; ];
$bundle['one_time_products'][$product->hashed_id]['product']['is_recurring'] = false;
} }
foreach ($this->subscription->service()->optional_recurring_products() as $key => $product) { foreach ($this->subscription->service()->optional_recurring_products() as $key => $product) {
@ -56,6 +58,7 @@ class Summary extends Component
'quantity' => $bundle['optional_recurring_products'][$product->hashed_id]['quantity'] ?? 0, 'quantity' => $bundle['optional_recurring_products'][$product->hashed_id]['quantity'] ?? 0,
'notes' => $product->markdownNotes(), 'notes' => $product->markdownNotes(),
]; ];
$bundle['optional_recurring_products'][$product->hashed_id]['product']['is_recurring'] = true;
} }
foreach ($this->subscription->service()->optional_products() as $key => $product) { foreach ($this->subscription->service()->optional_products() as $key => $product) {
@ -64,6 +67,7 @@ class Summary extends Component
'quantity' => $bundle['optional_one_time_products'][$product->hashed_id]['quantity'] ?? 0, 'quantity' => $bundle['optional_one_time_products'][$product->hashed_id]['quantity'] ?? 0,
'notes' => $product->markdownNotes(), 'notes' => $product->markdownNotes(),
]; ];
$bundle['optional_one_time_products'][$product->hashed_id]['product']['is_recurring'] = false;
} }
$this->dispatch('purchase.context', property: 'bundle', value: $bundle); $this->dispatch('purchase.context', property: 'bundle', value: $bundle);
@ -76,11 +80,11 @@ class Summary extends Component
} }
$one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) { $one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) {
return $item['product']['cost'] * $item['quantity']; return $item['product']['price'] * $item['quantity'];
}); });
$one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) { $one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) {
return $item['product']['cost'] * $item['quantity']; return $item['product']['price'] * $item['quantity'];
}); });
if ($raw) { if ($raw) {
@ -98,11 +102,11 @@ class Summary extends Component
} }
$recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) { $recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) {
return $item['product']['cost'] * $item['quantity']; return $item['product']['price'] * $item['quantity'];
}); });
$recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) { $recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) {
return $item['product']['cost'] * $item['quantity']; return $item['product']['price'] * $item['quantity'];
}); });
if ($raw) { if ($raw) {
@ -140,8 +144,8 @@ class Summary extends Component
$products[] = [ $products[] = [
'product_key' => $item['product']['product_key'], 'product_key' => $item['product']['product_key'],
'quantity' => $item['quantity'], 'quantity' => $item['quantity'],
'total_raw' => $item['product']['cost'] * $item['quantity'], 'total_raw' => $item['product']['price'] * $item['quantity'],
'total' => Number::formatMoney($item['product']['cost'] * $item['quantity'], $this->subscription->company) . ' / ' . RecurringInvoice::frequencyForKey($this->subscription->frequency_id), 'total' => Number::formatMoney($item['product']['price'] * $item['quantity'], $this->subscription->company) . ' / ' . RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
]; ];
} }
@ -149,8 +153,8 @@ class Summary extends Component
$products[] = [ $products[] = [
'product_key' => $item['product']['product_key'], 'product_key' => $item['product']['product_key'],
'quantity' => $item['quantity'], 'quantity' => $item['quantity'],
'total_raw' => $item['product']['cost'] * $item['quantity'], 'total_raw' => $item['product']['price'] * $item['quantity'],
'total' => Number::formatMoney($item['product']['cost'] * $item['quantity'], $this->subscription->company) . ' / ' . RecurringInvoice::frequencyForKey($this->subscription->frequency_id), 'total' => Number::formatMoney($item['product']['price'] * $item['quantity'], $this->subscription->company) . ' / ' . RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
]; ];
} }
@ -158,8 +162,8 @@ class Summary extends Component
$products[] = [ $products[] = [
'product_key' => $item['product']['product_key'], 'product_key' => $item['product']['product_key'],
'quantity' => $item['quantity'], 'quantity' => $item['quantity'],
'total_raw' => $item['product']['cost'] * $item['quantity'], 'total_raw' => $item['product']['price'] * $item['quantity'],
'total' => Number::formatMoney($item['product']['cost'] * $item['quantity'], $this->subscription->company), 'total' => Number::formatMoney($item['product']['price'] * $item['quantity'], $this->subscription->company),
]; ];
} }
@ -167,8 +171,8 @@ class Summary extends Component
$products[] = [ $products[] = [
'product_key' => $item['product']['product_key'], 'product_key' => $item['product']['product_key'],
'quantity' => $item['quantity'], 'quantity' => $item['quantity'],
'total_raw' => $item['product']['cost'] * $item['quantity'], 'total_raw' => $item['product']['price'] * $item['quantity'],
'total' => Number::formatMoney($item['product']['cost'] * $item['quantity'], $this->subscription->company), 'total' => Number::formatMoney($item['product']['price'] * $item['quantity'], $this->subscription->company),
]; ];
} }

View File

@ -118,9 +118,54 @@ class SubscriptionRepository extends BaseRepository
return $line_items; return $line_items;
} }
/**
* ConvertV3Bundle
*
* Removing the nested keys of the items array
*
* @param array $bundle
* @return array
*/
private function convertV3Bundle($bundle): array
{
if(is_object($bundle))
$bundle = json_decode(json_encode($bundle),1);
$items = [];
foreach($bundle['recurring_products'] as $key => $value) {
$line_item = new \stdClass;
$line_item->product_key = $value['product']['product_key'];
$line_item->qty = (float) $value['quantity'];
$line_item->unit_cost = (float) $value['product']['price'];
$line_item->description = $value['product']['notes'];
$line_item->is_recurring = $value['product']['is_recurring'] ?? false;
$items[] = $line_item;
}
foreach($bundle['recurring_products'] as $key => $value) {
$line_item = new \stdClass;
$line_item->product_key = $value['product']['product_key'];
$line_item->qty = (float) $value['quantity'];
$line_item->unit_cost = (float) $value['product']['price'];
$line_item->description = $value['product']['notes'];
$line_item->is_recurring = $value['product']['is_recurring'] ?? false;
}
return $items;
}
public function generateBundleLineItems($bundle, $is_recurring = false, $is_credit = false) public function generateBundleLineItems($bundle, $is_recurring = false, $is_credit = false)
{ {
if(isset($bundle->recurring_products))
$bundle = $this->convertV3Bundle($bundle);
$multiplier = $is_credit ? -1 : 1; $multiplier = $is_credit ? -1 : 1;
$line_items = []; $line_items = [];

View File

@ -71,21 +71,40 @@ class SubscriptionCalculator
$recurring = array_merge(isset($bundle['recurring_products']) ? $bundle['recurring_products'] : [], isset($bundle['optional_recurring_products']) ? $bundle['optional_recurring_products'] : []); $recurring = array_merge(isset($bundle['recurring_products']) ? $bundle['recurring_products'] : [], isset($bundle['optional_recurring_products']) ? $bundle['optional_recurring_products'] : []);
$one_time = array_merge(isset($bundle['one_time_products']) ? $bundle['one_time_products'] : [], isset($bundle['optional_one_time_products']) ? $bundle['optional_one_time_products'] : []); $one_time = array_merge(isset($bundle['one_time_products']) ? $bundle['one_time_products'] : [], isset($bundle['optional_one_time_products']) ? $bundle['optional_one_time_products'] : []);
$items = array_filter(array_merge($recurring, $one_time), function ($product) { $items = [];
return $product['quantity'] >= 1;
}); foreach($recurring as $item) {
if($item['quantity'] < 1)
continue;
return collect($items)->map(function ($item){
$line_item = new InvoiceItem(); $line_item = new InvoiceItem();
$line_item->product_key = $item['product']['product_key']; $line_item->product_key = $item['product']['product_key'];
$line_item->quantity = (float) $item['quantity']; $line_item->quantity = (float) $item['quantity'];
$line_item->cost = (float) $item['product']['price']; $line_item->cost = (float) $item['product']['price'];
$line_item->notes = $item['product']['notes']; $line_item->notes = $item['product']['notes'];
return $line_item; $items[] = $line_item;
})->flatten()->toArray(); }
foreach($one_time as $item) {
if($item['quantity'] < 1) {
continue;
}
$line_item = new InvoiceItem();
$line_item->product_key = $item['product']['product_key'];
$line_item->quantity = (float) $item['quantity'];
$line_item->cost = (float) $item['product']['price'];
$line_item->notes = $item['product']['notes'];
$items[] = $line_item;
}
return $items;
} }

View File

@ -3,7 +3,7 @@
<div class="flex flex-col space-y-3 my-3"> <div class="flex flex-col space-y-3 my-3">
@foreach($methods as $method) @foreach($methods as $method)
<button class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border" wire:click="handleSelect('{{ $method['company_gateway_id'] }}', '{{ $method['gateway_type_id'] }}')"> <button class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border" wire:click="handleSelect('{{ $method['company_gateway_id'] }}', '{{ $method['gateway_type_id'] }}'); $wire.$refresh();">
{{ $method['label'] }} {{ $method['label'] }}
</button> </button>
@endforeach @endforeach