Skip to content

Commit

Permalink
Merge branch '0.7' into hub-products-conditional-explicit-binding
Browse files Browse the repository at this point in the history
  • Loading branch information
repl6669 committed Dec 19, 2023
2 parents 9eba7aa + 049954c commit b679eec
Show file tree
Hide file tree
Showing 99 changed files with 2,002 additions and 727 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: "\U0001F41B Bug report"
about: Report something that's broken.
title: ''
labels: bug
labels: bug,unconfirmed
assignees: ''

---
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This repository serves as a monorepo for the main packages that make up Lunar.
## Community

- [Join our discord server](https://discord.gg/v6qVWaf) and chat to the developers and people using Lunar.
- [We have a roadmap](https://github.com/orgs/lunarphp/projects/1) where we will be detailing which features are next.
- [We have a roadmap](https://github.com/orgs/lunarphp/projects/8) where we will be detailing which features are next.

## Packages in this monorepo

Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default defineConfig({
]
},
{
text: '0.6',
text: '0.7',
items: [
{text: 'Changelog', link: '/core/upgrading'},
{text: 'Contributing', link: '/core/contributing'},
Expand Down
2 changes: 1 addition & 1 deletion docs/core/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Lunar uses a monorepo [lunarphp/lunar](https://github.com/lunarphp/lunar) approa

## Repository Branching

**Bug Fixes** should target the latest compatible branch version i.e `0.6`. The `main` branch should never have bug fix PR's unless they fix features that are in an upcoming release.
**Bug Fixes** should target the latest compatible branch version i.e `0.7`. The `main` branch should never have bug fix PR's unless they fix features that are in an upcoming release.

**Features** that bring new (or enhance current) functionality to Lunar should always target the `main` branch.

Expand Down
12 changes: 12 additions & 0 deletions docs/core/extending/shipping.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ class CustomShippingModifier extends ShippingModifier
)
);

ShippingManifest::addOption(
new ShippingOption(
name: 'Pick up in store',
description: 'Pick your order up in store',
identifier: 'PICKUP',
price: new Price(0, $cart->currency, 1),
taxClass: $taxClass,
// This is for your reference, so you can check if a collection option has been selected.
collect: true
)
);

// Or add multiple options, it's your responsibility to ensure the identifiers are unique
ShippingManifest::addOptions(collect([
new ShippingOption(
Expand Down
52 changes: 51 additions & 1 deletion docs/core/reference/carts.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ CartSession::setCustomer($customer);
```


### Adding shipping/billing address
## Adding shipping/billing address

As outlined above, you can add shipping / billing addresses to the cart using
the following methods:
Expand Down Expand Up @@ -376,6 +376,56 @@ $cart->shippingAddress;
$cart->billingAddress;
```

### ShippingOption override

In some cases you might want to present an estimated shipping cost without users having to fill out a full shipping address, this is where the `ShippingOptionOverride` comes in, if set on the cart it can be used to calculate shipping for a single request.

```php
$shippingOption = $cart->getEstimatedShipping([
'postcode' => '123456',
'state' => 'Essex',
'country' => Country::first(),
]);
````

This will return an estimated (cheapest) shipping option for the cart, based on it's current totals. By default this will not be taken into account when calculating shipping in the cart pipelines, in order to enable that we need to pass an extra parameter.

```php
$shippingOption = $cart->getEstimatedShipping([
'postcode' => '123456',
'state' => 'Essex',
'country' => Country::first(),
], setOverride: true);
````

Now when the pipelines are run, the option which was returned by `getEstimatedShipping` will be used when calculating shipping totals, bypassing any other logic, note this will only happen for that one request.

If you are using the `CartSession` manager, you can easily set the parameters you want to estimate shipping so you don't need to pass them each time:

```php
CartSession::estimateShippingUsing([
'postcode' => '123456',
'state' => 'Essex',
'country' => Country::first(),
]);
```

You can also manually set the shipping method override directly on the cart.

```php
$cart->shippingOptionOverride = new \Lunar\DataTypes\ShippingOption(/* .. */);
```

Calling `CartSession::current()` by itself won't trigger the shipping override, but you can pass the `estimateShipping` parameter to enable it:

```php
// Will not use the shipping override, default behaviour.
CartSession::current();

// Will use the shipping override, based on what is set using `estimateShippingUsing`
CartSession::current(estimateShipping: true);
```

## Handling User Login

When a user logs in, you will likely want to check if they have a cart
Expand Down
4 changes: 2 additions & 2 deletions docs/core/reference/orders.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Lunar\Models\Order
| discount_breakdown | A json field for the discount breakdown e.g. `[{"discount_id": 1, "lines": [{"id": 1, "qty": 1}]], "total": 200}]`
| discount_total | Any discount amount excl. tax
| shipping_total | The shipping total excl. tax
| tax_breakdown | A json field for the tax breakdown e.g. `[{"name": "VAT", "total": 123, "percentage": 20}]`
| tax_breakdown | A json field for the tax breakdown e.g. `[{"description": "VAT", "identifier" : "vat", "value": 123, "percentage": 20, "currency_code": "GBP"}]`
| tax_total | The total amount of tax applied
| total | The grand total with tax
| notes | Any additional order notes
Expand Down Expand Up @@ -210,7 +210,7 @@ Lunar\Models\OrderLine
| quantity | The amount of this item purchased
| sub_total | The sub total minus any discounts, excl. tax
| discount_total | Any discount amount excl. tax
| tax_breakdown | A json field for the tax breakdown e.g. `[{"name": "VAT", "total": 123, "percentage": 20}]`
| tax_breakdown | A json field for the tax breakdown e.g. `[{"description": "VAT", "identifier" : "vat", "value": 123, "percentage": 20, "currency_code": "GBP"}]`
| shipping_breakdown| A json field for the shipping breakdown e.g. `[{"name": "Standard Delivery", "identifier": "STD", "price": 123}]`
| tax_total | The total amount of tax applied
| total | The grand total with tax
Expand Down
56 changes: 55 additions & 1 deletion docs/core/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,61 @@ php artisan lunar:hub:install

## Support Policy

Lunar currently provides bug fixes and security updates for only the latest minor release, e.g. `0.6`.
Lunar currently provides bug fixes and security updates for only the latest minor release, e.g. `0.7`.

## 0.7

### High Impact

#### TaxBreakdown casting has been refactored

Database columns which have `tax_breakdown` casting will now actually cast back into the `TaxBreakdown` object. This means you will need to update any storefront views or API transformers to accommodate this.

Before:

```php
@foreach ($order->tax_breakdown as $tax)
{{ $tax->total->formatted }}
@endforeach
```

```php
@foreach ($order->tax_breakdown->amounts as $tax)
{{ $tax->price->formatted }}
@endforeach
```

When migrations are run, a state update routine will trigger to convert all existing `tax_breakdown` column. Please ensure you take a backup of your database beforehand and avoid running in production until you are satisfied the data is correct.

### Medium Impact

#### Discount updates

Limitations and exclusions on discounts have had a revamp, please double-check all discounts you have in Lunar to ensure they are all correct. Generally speaking the integrity should be unaffected, but it's better to be sure.

#### Calculate lines pipeline update

If you are using unit quantities greater than `1`, there was an issue in the calculate lines pipeline which resulted in the unit quantity being applied twice, so if the price was `10` with a unit quantity of `100` it would show the unit price as `0.001` instead of `0.01`. This should be resolved going forward to show correctly.

### Low Impact

#### Click & Collect parameter added to `ShippingOption`

The `Lunar\DataTypes\ShippingOption` class now has an additional `collect` parameter. This can be used to determine whether the shipping option is considered "collect in store". This defaults to `false` so there are no additional steps if your store doesn't offer click and collect.

```php
ShippingManifest::addOption(
new ShippingOption(
name: 'Pick up in store',
description: 'Pick your order up in store',
identifier: 'PICKUP',
price: new Price(/** .. */),
taxClass: $taxClass,
collect: true
)
);
```


## 0.6

Expand Down
11 changes: 11 additions & 0 deletions packages/admin/resources/lang/en/components.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
'product-search.title' => 'Search for products',
'product-search.associate_self' => 'You cannot associate the same product',
'product-search.commit_btn' => 'Select Products',
'product-variant-search.btn' => 'Add Variants',
'product-variant-search.first_tab' => 'Search variants',
'product-variant-search.second_tab' => 'Selected variants',
'product-variant-search.max_results_exceeded' => 'Showing the first :max of :total variants. Try being more specific in your search.',
'product-variant-search.exists_in_collection' => 'Already associated',
'product-variant-search.no_results' => 'No results found.',
'product-variant-search.pre_search_message' => 'Search for variants by SKU.',
'product-variant-search.select_empty' => 'When you select variants, they will appear here.',
'product-variant-search.title' => 'Search for variants',
'product-variant-search.associate_self' => 'You cannot associate the same variants',
'product-variant-search.commit_btn' => 'Select Variants',
/**
* Option Value Create Modal.
*/
Expand Down
14 changes: 9 additions & 5 deletions packages/admin/resources/lang/en/partials.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,18 @@
/**
* Discounts
*/
'discounts.limitations.heading' => 'Limitations',
'discounts.limitations.by_collection' => 'Limit by collection',
'discounts.limitations.by_brand' => 'Limit by brand',
'discounts.limitations.by_product' => 'Limit by product',
'discounts.limitations.heading' => 'Limitations and Exclusions',
'discounts.limitations.by_collection' => 'By collection',
'discounts.limitations.by_brand' => 'By brand',
'discounts.limitations.by_product' => 'By product',
'discounts.limitations.by_product_variant' => 'By product variant',
'discounts.limitations.view_brand' => 'View Brand',
'discounts.limitations.view_product' => 'View Product',

'discounts.limitations.view_product_variant' => 'View Product Variant',
'discounts.limitations.limitation' => 'Limitation',
'discounts.limitations.exclusion' => 'Exclusion',
/**
* Product Collections.
*/
'products.collections.heading' => 'Collections',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<div>
@if($showBtn)
<x-hub::button type="button" wire:click.prevent="$set('showBrowser', true)">
@if(!empty($label))
{{ $label }}
@else
{{ __('adminhub::components.product-variant-search.btn') }}
@endif
</x-hub::button>
@endif

<x-hub::slideover :title="__('adminhub::components.product-variant-search.title')" wire:model="showBrowser">
<div
class="space-y-4"
x-data="{
tab: 'search'
}"
>
<div>
<nav class="flex space-x-4" aria-label="Tabs">
<button
x-on:click.prevent="tab = 'search'"
class="px-3 py-2 text-sm font-medium rounded-md"
:class="{
'bg-sky-100 text-sky-700': tab == 'search',
'text-gray-500 hover:text-gray-700': tab != 'search'
}"
>
{{ __('adminhub::components.product-variant-search.first_tab') }}
</button>

<button
class="px-3 py-2 text-sm font-medium rounded-md"
@click.prevent="tab = 'selected'"
:class="{
'bg-sky-100 text-sky-700': tab == 'selected',
'text-gray-500 hover:text-gray-700': tab != 'selected'
}"
>
{{ __('adminhub::components.product-variant-search.second_tab') }} ({{ $this->selectedModels->count() }})
</button>
</nav>
</div>

<div x-show="tab == 'search'">
<x-hub::input.text wire:model.debounce.300ms="searchTerm" />
@if($this->searchTerm)
@if($this->results->total() > $maxResults)
<span class="block p-3 my-2 text-xs text-sky-600 rounded bg-sky-50">
{{ __('adminhub::components.product-variant-search.max_results_exceeded', [
'max' => $maxResults,
'total' => $this->results->total()
]) }}
</span>
@endif
<div class="mt-4 space-y-1">
@forelse($this->results as $variant)
<div
class="
flex w-full items-center justify-between rounded shadow-sm text-left border px-2 py-2 text-sm
@if($this->existingIds->contains($variant->id) || collect($this->exclude)->contains($variant->id))
opacity-25
@endif
"
>
<div class="truncate">{{ $variant->sku }} {{ $variant->deleted_at }}</div>
@if(!$this->existingIds->contains($variant->id) && !collect($this->exclude)->contains($variant->id))
@if(collect($this->selected)->contains($variant->id))
<button
class="px-2 py-1 text-xs text-red-700 border border-red-200 rounded shadow-sm hover:bg-red-50"
wire:click.prevent="removeProductVariant('{{ $variant->id }}')"
>
{{ __('adminhub::global.deselect') }}
</button>
@elseif (!collect($this->exclude)->contains($variant->id))
<button
class="px-2 py-1 text-xs text-sky-700 border border-sky-200 rounded shadow-sm hover:bg-sky-50"
wire:click.prevent="selectProductVariant('{{ $variant->id }}')"
>
{{ __('adminhub::global.select') }}
</button>
@endif
@elseif(collect($this->exclude)->contains($variant->id))
<span class="text-xs">
{{ __('adminhub::components.product-variant-search.associate_self') }}
</span>
@else
<span class="text-xs">
{{ __('adminhub::components.product-variant-search.exists_in_collection') }}
</span>
@endif
</div>
@empty
{{ __('adminhub::components.product-variant-search.no_results') }}
@endforelse
</div>
@else
<div class="px-3 py-2 mt-4 text-sm text-gray-500 bg-gray-100 rounded">
{{ __('adminhub::components.product-variant-search.pre_search_message') }}
</div>
@endif
</div>

<div x-show="tab == 'selected'" class="space-y-2">
@forelse($this->selectedModels as $variant)
<div
class="flex items-center justify-between w-full px-2 py-2 text-sm text-left border rounded shadow-sm "
wire:key="selected_{{ $variant->id }}"
>
{{ $variant->sku }}
<button
class="px-2 py-1 text-xs text-red-700 border border-red-200 rounded shadow-sm hover:bg-red-50"
wire:click.prevent="removeProductVariant('{{ $variant->id }}')"
>
{{ __('adminhub::global.deselect') }}
</button>
</div>
@empty
<div class="px-3 py-2 mt-4 text-sm text-gray-500 bg-gray-100 rounded">
{{ __('adminhub::components.product-variant-search.select_empty') }}
</div>
@endforelse
</div>
</div>

<x-slot name="footer">
<x-hub::button wire:click.prevent="triggerSelect">
{{ __('adminhub::components.product-variant-search.commit_btn') }}
</x-hub::button>
</x-slot>
</x-hub::slideover>
</div>
Loading

0 comments on commit b679eec

Please sign in to comment.