Merge pull request #2910 from Haendlerbund/unified-addresses
Unified addresses (#2902)
This commit is contained in:
commit
7629d85d16
|
|
@ -3,6 +3,7 @@
|
|||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Customer\Models\CustomerAddress;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
use Webkul\Customer\Repositories\CustomerRepository;
|
||||
|
||||
|
|
@ -43,10 +44,11 @@ class AddressDataGrid extends DataGrid
|
|||
{
|
||||
$customer = $this->customerRepository->find(request('id'));
|
||||
|
||||
$queryBuilder = DB::table('customer_addresses as ca')
|
||||
$queryBuilder = DB::table('addresses as ca')
|
||||
->leftJoin('countries', 'ca.country', '=', 'countries.code')
|
||||
->leftJoin('customers as c', 'ca.customer_id', '=', 'c.id')
|
||||
->addSelect('ca.id as address_id', 'ca.company_name', 'ca.address1', 'ca.country', DB::raw('' . DB::getTablePrefix() . 'countries.name as country_name'), 'ca.state', 'ca.city', 'ca.postcode', 'ca.phone', 'ca.default_address')
|
||||
->where('ca.address_type', CustomerAddress::ADDRESS_TYPE)
|
||||
->where('c.id', $customer->id);
|
||||
|
||||
$queryBuilder = $queryBuilder->leftJoin('country_states', function($qb) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Sales\Models\OrderAddress;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
|
||||
class OrderDataGrid extends DataGrid
|
||||
|
|
@ -14,13 +15,13 @@ class OrderDataGrid extends DataGrid
|
|||
public function prepareQueryBuilder()
|
||||
{
|
||||
$queryBuilder = DB::table('orders')
|
||||
->leftJoin('order_address as order_address_shipping', function($leftJoin) {
|
||||
->leftJoin('addresses as order_address_shipping', function($leftJoin) {
|
||||
$leftJoin->on('order_address_shipping.order_id', '=', 'orders.id')
|
||||
->where('order_address_shipping.address_type', 'shipping');
|
||||
->where('order_address_shipping.address_type', OrderAddress::ADDRESS_TYPE_SHIPPING);
|
||||
})
|
||||
->leftJoin('order_address as order_address_billing', function($leftJoin) {
|
||||
->leftJoin('addresses as order_address_billing', function($leftJoin) {
|
||||
$leftJoin->on('order_address_billing.order_id', '=', 'orders.id')
|
||||
->where('order_address_billing.address_type', 'billing');
|
||||
->where('order_address_billing.address_type', OrderAddress::ADDRESS_TYPE_BILLING);
|
||||
})
|
||||
->addSelect('orders.id','orders.increment_id', 'orders.base_sub_total', 'orders.base_grand_total', 'orders.created_at', 'channel_name', 'status')
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name) as billed_to'))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Sales\Models\OrderAddress;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
|
||||
class OrderRefundDataGrid extends DataGrid
|
||||
|
|
@ -16,9 +17,9 @@ class OrderRefundDataGrid extends DataGrid
|
|||
$queryBuilder = DB::table('refunds')
|
||||
->select('refunds.id', 'orders.increment_id', 'refunds.state', 'refunds.base_grand_total', 'refunds.created_at')
|
||||
->leftJoin('orders', 'refunds.order_id', '=', 'orders.id')
|
||||
->leftJoin('order_address as order_address_billing', function($leftJoin) {
|
||||
->leftJoin('addresses as order_address_billing', function($leftJoin) {
|
||||
$leftJoin->on('order_address_billing.order_id', '=', 'orders.id')
|
||||
->where('order_address_billing.address_type', 'billing');
|
||||
->where('order_address_billing.address_type', OrderAddress::ADDRESS_TYPE_BILLING);
|
||||
})
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name) as billed_to'));
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Webkul\Sales\Models\OrderAddress;
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
|
||||
class OrderShipmentsDataGrid extends DataGrid
|
||||
|
|
@ -14,9 +15,9 @@ class OrderShipmentsDataGrid extends DataGrid
|
|||
public function prepareQueryBuilder()
|
||||
{
|
||||
$queryBuilder = DB::table('shipments')
|
||||
->leftJoin('order_address as order_address_shipping', function($leftJoin) {
|
||||
->leftJoin('addresses as order_address_shipping', function($leftJoin) {
|
||||
$leftJoin->on('order_address_shipping.order_id', '=', 'shipments.order_id')
|
||||
->where('order_address_shipping.address_type', 'shipping');
|
||||
->where('order_address_shipping.address_type', OrderAddress::ADDRESS_TYPE_SHIPPING);
|
||||
})
|
||||
->leftJoin('orders as ors', 'shipments.order_id', '=', 'ors.id')
|
||||
->leftJoin('inventory_sources as is', 'shipments.inventory_source_id', '=', 'is.id')
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ class Cart
|
|||
if (! $cart = $this->getCart()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Event::dispatch('checkout.cart.calculate.items.tax.before', $cart);
|
||||
|
||||
foreach ($cart->items()->get() as $item) {
|
||||
|
|
@ -1199,21 +1199,21 @@ class Cart
|
|||
} else {
|
||||
if (isset($billingAddressData['use_for_shipping']) && $billingAddressData['use_for_shipping']) {
|
||||
$this->cartAddressRepository->create(array_merge($billingAddressData,
|
||||
['address_type' => 'shipping']));
|
||||
['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING]));
|
||||
} else {
|
||||
$this->cartAddressRepository->create(array_merge($shippingAddressData,
|
||||
['address_type' => 'shipping']));
|
||||
['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->cartAddressRepository->create(array_merge($billingAddressData, ['address_type' => 'billing']));
|
||||
$this->cartAddressRepository->create(array_merge($billingAddressData, ['address_type' => CartAddress::ADDRESS_TYPE_BILLING]));
|
||||
|
||||
if ($cart->haveStockableItems()) {
|
||||
if (isset($billingAddressData['use_for_shipping']) && $billingAddressData['use_for_shipping']) {
|
||||
$this->cartAddressRepository->create(array_merge($billingAddressData, ['address_type' => 'shipping']));
|
||||
$this->cartAddressRepository->create(array_merge($billingAddressData, ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING]));
|
||||
} else {
|
||||
$this->cartAddressRepository->create(array_merge($shippingAddressData, ['address_type' => 'shipping']));
|
||||
$this->cartAddressRepository->create(array_merge($shippingAddressData, ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,10 @@ use Faker\Generator as Faker;
|
|||
use Webkul\Checkout\Models\CartAddress;
|
||||
|
||||
$factory->define(CartAddress::class, function (Faker $faker) {
|
||||
$now = date("Y-m-d H:i:s");
|
||||
|
||||
return [
|
||||
'first_name' => $faker->firstName(),
|
||||
'last_name' => $faker->lastName,
|
||||
'email' => $faker->email,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'address_type' => 'billing',
|
||||
'address_type' => CartAddress::ADDRESS_TYPE_BILLING,
|
||||
];
|
||||
});
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class Cart extends Model implements CartContract
|
|||
*/
|
||||
public function billing_address()
|
||||
{
|
||||
return $this->addresses()->where('address_type', 'billing');
|
||||
return $this->addresses()->where('address_type', CartAddress::ADDRESS_TYPE_BILLING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +64,7 @@ class Cart extends Model implements CartContract
|
|||
*/
|
||||
public function shipping_address()
|
||||
{
|
||||
return $this->addresses()->where('address_type', 'shipping');
|
||||
return $this->addresses()->where('address_type', CartAddress::ADDRESS_TYPE_SHIPPING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,30 +2,47 @@
|
|||
|
||||
namespace Webkul\Checkout\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Webkul\Checkout\Contracts\CartAddress as CartAddressContract;
|
||||
use Webkul\Core\Models\Address;
|
||||
|
||||
class CartAddress extends Model implements CartAddressContract
|
||||
/**
|
||||
* Class CartAddress
|
||||
* @package Webkul\Checkout\Models
|
||||
*
|
||||
* @property integer $cart_id
|
||||
* @property Cart $cart
|
||||
*
|
||||
*/
|
||||
class CartAddress extends Address implements CartAddressContract
|
||||
{
|
||||
protected $table = 'cart_address';
|
||||
public const ADDRESS_TYPE_SHIPPING = 'cart_shipping';
|
||||
public const ADDRESS_TYPE_BILLING = 'cart_billing';
|
||||
|
||||
protected $fillable = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'company_name',
|
||||
'vat_id',
|
||||
'address1',
|
||||
'city',
|
||||
'state',
|
||||
'postcode',
|
||||
'country',
|
||||
'phone',
|
||||
'address_type',
|
||||
'cart_id',
|
||||
'customer_id',
|
||||
/**
|
||||
* @var array default values
|
||||
*/
|
||||
protected $attributes = [
|
||||
'address_type' => self::ADDRESS_TYPE_BILLING,
|
||||
];
|
||||
|
||||
/**
|
||||
* The "booted" method of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function boot()
|
||||
{
|
||||
static::addGlobalScope('address_type', static function (Builder $builder) {
|
||||
$builder->whereIn('address_type', [
|
||||
self::ADDRESS_TYPE_BILLING,
|
||||
self::ADDRESS_TYPE_SHIPPING
|
||||
]);
|
||||
});
|
||||
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shipping rates for the cart address.
|
||||
*/
|
||||
|
|
@ -35,10 +52,10 @@ class CartAddress extends Model implements CartAddressContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all of the attributes for the attribute groups.
|
||||
* Get the cart record associated with the address.
|
||||
*/
|
||||
public function getNameAttribute()
|
||||
public function cart()
|
||||
{
|
||||
return $this->first_name . ' ' . $this->last_name;
|
||||
return $this->belongsTo(Cart::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ class CartShippingRate extends Model implements CartShippingRateContract
|
|||
*/
|
||||
public function shipping_address()
|
||||
{
|
||||
return $this->belongsTo(CartAddressProxy::modelClass());
|
||||
return $this->belongsTo(CartAddressProxy::modelClass(), 'cart_address_id')
|
||||
->where('address_type', CartAddress::ADDRESS_TYPE_SHIPPING);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Webkul\Checkout\Models\CartAddress;
|
||||
use Webkul\Checkout\Models\CartShippingRate;
|
||||
use Webkul\Sales\Models\Invoice;
|
||||
use Webkul\Sales\Models\OrderAddress;
|
||||
use Webkul\Sales\Models\Shipment;
|
||||
|
||||
class AddTableAddresses extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
try {
|
||||
// transaction is important to prevent loosing data on failure
|
||||
DB::beginTransaction();
|
||||
|
||||
Schema::create('addresses', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('address_type');
|
||||
$table->unsignedInteger('customer_id')->nullable()->comment('null if guest checkout');
|
||||
$table->unsignedInteger('cart_id')->nullable()->comment('only for cart_addresses');
|
||||
$table->unsignedInteger('order_id')->nullable()->comment('only for order_addresses');
|
||||
|
||||
$table->string('first_name');
|
||||
$table->string('last_name');
|
||||
$table->string('gender')->nullable();
|
||||
$table->string('company_name')->nullable();
|
||||
$table->string('address1');
|
||||
$table->string('address2')->nullable();
|
||||
$table->string('postcode');
|
||||
$table->string('city');
|
||||
$table->string('state');
|
||||
$table->string('country');
|
||||
$table->string('email')->nullable();
|
||||
$table->string('phone')->nullable();
|
||||
|
||||
$table->string('vat_id')->nullable();
|
||||
$table->boolean('default_address')
|
||||
->default(false)
|
||||
->comment('only for customer_addresses');
|
||||
|
||||
$table->json('additional')->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign(['customer_id'])->references('id')->on('customers')->onDelete('cascade');
|
||||
$table->foreign(['cart_id'])->references('id')->on('cart')->onDelete('cascade');
|
||||
$table->foreign(['order_id'])->references('id')->on('orders')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::disableForeignKeyConstraints();
|
||||
|
||||
$this->migrateCustomerAddresses();
|
||||
$this->migrateCartAddresses();
|
||||
$this->migrateOrderAddresses();
|
||||
|
||||
$this->migrateForeignKeys();
|
||||
|
||||
Schema::drop('customer_addresses');
|
||||
Schema::drop('cart_address');
|
||||
Schema::drop('order_address');
|
||||
|
||||
Schema::enableForeignKeyConstraints();
|
||||
|
||||
DB::commit();
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
throw new Exception('you cannot revert this migration: data would be lost');
|
||||
}
|
||||
|
||||
private function migrateCustomerAddresses(): void
|
||||
{
|
||||
$dbPrefix = DB::getTablePrefix();
|
||||
|
||||
$insertCustomerAddresses = <<< SQL
|
||||
INSERT INTO ${dbPrefix}addresses(
|
||||
address_type,
|
||||
customer_id,
|
||||
first_name,
|
||||
last_name,
|
||||
gender,
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
email,
|
||||
phone,
|
||||
default_address,
|
||||
additional,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
"customer",
|
||||
customer_id,
|
||||
first_name,
|
||||
last_name,
|
||||
(SELECT gender FROM customers c WHERE c.id=ca.customer_id),
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
null,
|
||||
phone,
|
||||
default_address,
|
||||
JSON_INSERT('{}', '$.old_customer_address_id', id),
|
||||
created_at,
|
||||
updated_at
|
||||
FROM customer_addresses ca;
|
||||
SQL;
|
||||
|
||||
DB::unprepared($insertCustomerAddresses);
|
||||
}
|
||||
|
||||
private function migrateCartAddresses(): void
|
||||
{
|
||||
$dbPrefix = DB::getTablePrefix();
|
||||
|
||||
$insertCustomerAddresses = <<< SQL
|
||||
INSERT INTO ${dbPrefix}addresses(
|
||||
address_type,
|
||||
customer_id,
|
||||
cart_id,
|
||||
first_name,
|
||||
last_name,
|
||||
gender,
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
email,
|
||||
phone,
|
||||
additional,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
(CASE WHEN ca.address_type='billing' THEN "cart_billing" ELSE "cart_shipping" END),
|
||||
customer_id,
|
||||
cart_id,
|
||||
first_name,
|
||||
last_name,
|
||||
(SELECT gender FROM customers c WHERE c.id=ca.customer_id),
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
email,
|
||||
phone,
|
||||
JSON_INSERT('{}', '$.old_cart_address_id', id),
|
||||
created_at,
|
||||
updated_at
|
||||
FROM cart_address ca;
|
||||
SQL;
|
||||
|
||||
DB::unprepared($insertCustomerAddresses);
|
||||
}
|
||||
|
||||
private function migrateOrderAddresses(): void
|
||||
{
|
||||
$dbPrefix = DB::getTablePrefix();
|
||||
|
||||
$insertCustomerAddresses = <<< SQL
|
||||
INSERT INTO ${dbPrefix}addresses(
|
||||
address_type,
|
||||
customer_id,
|
||||
order_id,
|
||||
first_name,
|
||||
last_name,
|
||||
gender,
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
email,
|
||||
phone,
|
||||
additional,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
(CASE WHEN oa.address_type='billing' THEN "order_billing" ELSE "order_shipping" END),
|
||||
customer_id,
|
||||
order_id,
|
||||
first_name,
|
||||
last_name,
|
||||
(SELECT gender FROM customers c WHERE c.id=oa.customer_id),
|
||||
company_name,
|
||||
address1,
|
||||
address2,
|
||||
postcode,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
email,
|
||||
phone,
|
||||
JSON_INSERT('{}', '$.old_order_address_id', id),
|
||||
created_at,
|
||||
updated_at
|
||||
FROM order_address oa;
|
||||
SQL;
|
||||
|
||||
DB::unprepared($insertCustomerAddresses);
|
||||
}
|
||||
|
||||
private function migrateForeignKeys(): void
|
||||
{
|
||||
Schema::table('cart_shipping_rates', static function (Blueprint $table) {
|
||||
$table->dropForeign(['cart_address_id']);
|
||||
|
||||
CartAddress::query()
|
||||
->orderBy('id', 'asc') // for some reason each() needs an orderBy in before
|
||||
->each(static function ($row) {
|
||||
CartShippingRate::query()
|
||||
->where('cart_address_id', $row->additional['old_cart_address_id'])
|
||||
->update(['cart_address_id' => $row->id]);
|
||||
});
|
||||
|
||||
$table->foreign(['cart_address_id'])
|
||||
->references('id')
|
||||
->on('addresses')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('invoices', static function (Blueprint $table) {
|
||||
$table->dropForeign(['order_address_id']);
|
||||
|
||||
OrderAddress::query()
|
||||
->orderBy('id', 'asc') // for some reason each() needs an orderBy in before
|
||||
->each(static function ($row) {
|
||||
Invoice::query()
|
||||
->where('order_address_id', $row->additional['old_order_address_id'])
|
||||
->update(['order_address_id' => $row->id]);
|
||||
});
|
||||
|
||||
$table->foreign(['order_address_id'])
|
||||
->references('id')
|
||||
->on('addresses')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('shipments', static function (Blueprint $table) {
|
||||
$table->dropForeign(['order_address_id']);
|
||||
|
||||
OrderAddress::query()
|
||||
->orderBy('id', 'asc') // for some reason each() needs an orderBy in before
|
||||
->each(static function ($row) {
|
||||
Shipment::query()
|
||||
->where('order_address_id', $row->additional['old_order_address_id'])
|
||||
->update(['order_address_id' => $row->id]);
|
||||
});
|
||||
|
||||
$table->foreign(['order_address_id'])
|
||||
->references('id')
|
||||
->on('addresses')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Webkul\Core\Models;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Webkul\Customer\Models\Customer;
|
||||
|
||||
/**
|
||||
* Class Address
|
||||
* @package Webkul\Core\Models
|
||||
*
|
||||
* @property string $address_type
|
||||
* @property integer $customer_id
|
||||
* @property Customer $customer
|
||||
* @property string $first_name
|
||||
* @property string $last_name
|
||||
* @property string $gender
|
||||
* @property string $company_name
|
||||
* @property string $address1
|
||||
* @property string $address2
|
||||
* @property string $postcode
|
||||
* @property string $city
|
||||
* @property string $state
|
||||
* @property string $country
|
||||
* @property string $email
|
||||
* @property string $phone
|
||||
* @property boolean $default_address
|
||||
* @property array $additional
|
||||
*
|
||||
* @property-read integer $id
|
||||
* @property-read string $name
|
||||
* @property-read Carbon $created_at
|
||||
* @property-read Carbon $updated_at
|
||||
*
|
||||
*/
|
||||
abstract class Address extends Model
|
||||
{
|
||||
protected $table = 'addresses';
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'address_type',
|
||||
'customer_id',
|
||||
'cart_id',
|
||||
'order_id',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'gender',
|
||||
'company_name',
|
||||
'address1',
|
||||
'address2',
|
||||
'postcode',
|
||||
'city',
|
||||
'state',
|
||||
'country',
|
||||
'email',
|
||||
'phone',
|
||||
'default_address',
|
||||
'vat_id',
|
||||
'additional',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'additional' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get all of the attributes for the attribute groups.
|
||||
*/
|
||||
public function getNameAttribute(): string
|
||||
{
|
||||
return $this->first_name . ' ' . $this->last_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customer record associated with the address.
|
||||
*/
|
||||
public function customer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Customer::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ use Webkul\Customer\Models\Customer;
|
|||
use Webkul\Customer\Models\CustomerAddress;
|
||||
|
||||
$factory->define(CustomerAddress::class, function (Faker $faker) {
|
||||
$now = date("Y-m-d H:i:s");
|
||||
|
||||
// use an locale from a country in europe so the vat id can be generated
|
||||
$fakerIt = \Faker\Factory::create('it_IT');
|
||||
|
||||
|
|
@ -27,8 +25,7 @@ $factory->define(CustomerAddress::class, function (Faker $faker) {
|
|||
'postcode' => $faker->postcode,
|
||||
'phone' => $faker->e164PhoneNumber,
|
||||
'default_address' => array_random([0, 1]),
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'address_type' => CustomerAddress::ADDRESS_TYPE,
|
||||
];
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,34 +2,32 @@
|
|||
|
||||
namespace Webkul\Customer\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Webkul\Core\Models\Address;
|
||||
use Webkul\Customer\Contracts\CustomerAddress as CustomerAddressContract;
|
||||
|
||||
class CustomerAddress extends Model implements CustomerAddressContract
|
||||
class CustomerAddress extends Address implements CustomerAddressContract
|
||||
{
|
||||
protected $table = 'customer_addresses';
|
||||
public const ADDRESS_TYPE = 'customer';
|
||||
|
||||
protected $fillable = [
|
||||
'customer_id',
|
||||
'company_name',
|
||||
'vat_id',
|
||||
'address1',
|
||||
'address2',
|
||||
'country',
|
||||
'state',
|
||||
'city',
|
||||
'postcode',
|
||||
'phone',
|
||||
'default_address',
|
||||
'first_name',
|
||||
'last_name',
|
||||
/**
|
||||
* @var array default values
|
||||
*/
|
||||
protected $attributes = [
|
||||
'address_type' => self::ADDRESS_TYPE,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the customer address full name.
|
||||
* The "booted" method of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getNameAttribute()
|
||||
protected static function boot()
|
||||
{
|
||||
return $this->first_name . ' ' . $this->last_name;
|
||||
static::addGlobalScope('address_type', static function (Builder $builder) {
|
||||
$builder->where('address_type', self::ADDRESS_TYPE);
|
||||
});
|
||||
|
||||
parent::boot();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use Webkul\Sales\Models\OrderAddress;
|
|||
|
||||
$factory->define(OrderAddress::class, function (Faker $faker) {
|
||||
$customer = factory(Customer::class)->create();
|
||||
$customerAddress = factory(CustomerAddress::class)->create();
|
||||
$customerAddress = factory(CustomerAddress::class)->make();
|
||||
|
||||
return [
|
||||
'first_name' => $customer->first_name,
|
||||
|
|
@ -22,7 +22,7 @@ $factory->define(OrderAddress::class, function (Faker $faker) {
|
|||
'city' => $customerAddress->city,
|
||||
'postcode' => $customerAddress->postcode,
|
||||
'phone' => $customerAddress->phone,
|
||||
'address_type' => 'billing',
|
||||
'address_type' => OrderAddress::ADDRESS_TYPE_BILLING,
|
||||
'order_id' => function () {
|
||||
return factory(Order::class)->create()->id;
|
||||
},
|
||||
|
|
@ -30,5 +30,5 @@ $factory->define(OrderAddress::class, function (Faker $faker) {
|
|||
});
|
||||
|
||||
$factory->state(OrderAddress::class, 'shipping', [
|
||||
'address_type' => 'shipping',
|
||||
'address_type' => OrderAddress::ADDRESS_TYPE_SHIPPING,
|
||||
]);
|
||||
|
|
@ -34,7 +34,8 @@ class Invoice extends Model implements InvoiceContract
|
|||
/**
|
||||
* Get the invoice items record associated with the invoice.
|
||||
*/
|
||||
public function items() {
|
||||
public function items()
|
||||
{
|
||||
return $this->hasMany(InvoiceItemProxy::modelClass())->whereNull('parent_id');
|
||||
}
|
||||
|
||||
|
|
@ -55,10 +56,11 @@ class Invoice extends Model implements InvoiceContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the addresses for the shipment.
|
||||
* Get the address for the invoice.
|
||||
*/
|
||||
public function address()
|
||||
{
|
||||
return $this->belongsTo(OrderAddressProxy::modelClass(), 'order_address_id');
|
||||
return $this->belongsTo(OrderAddressProxy::modelClass(), 'order_address_id')
|
||||
->where('address_type', OrderAddress::ADDRESS_TYPE_BILLING);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,14 @@ use Webkul\Sales\Contracts\Order as OrderContract;
|
|||
|
||||
class Order extends Model implements OrderContract
|
||||
{
|
||||
public const STATUS_PENDING = 'pending';
|
||||
public const STATUS_PENDING_PAYMENT = 'pending_payment';
|
||||
public const STATUS_PROCESSING = 'processing';
|
||||
public const STATUS_COMPLETED = 'completed';
|
||||
public const STATUS_CANCELED = 'canceled';
|
||||
public const STATUS_CLOSED = 'closed';
|
||||
public const STATUS_FRAUD = 'fraud';
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
'items',
|
||||
|
|
@ -21,13 +29,13 @@ class Order extends Model implements OrderContract
|
|||
];
|
||||
|
||||
protected $statusLabel = [
|
||||
'pending' => 'Pending',
|
||||
'pending_payment' => 'Pending Payment',
|
||||
'processing' => 'Processing',
|
||||
'completed' => 'Completed',
|
||||
'canceled' => 'Canceled',
|
||||
'closed' => 'Closed',
|
||||
'fraud' => 'Fraud',
|
||||
self::STATUS_PENDING => 'Pending',
|
||||
self::STATUS_PENDING_PAYMENT => 'Pending Payment',
|
||||
self::STATUS_PROCESSING => 'Processing',
|
||||
self::STATUS_COMPLETED => 'Completed',
|
||||
self::STATUS_CANCELED => 'Canceled',
|
||||
self::STATUS_CLOSED => 'Closed',
|
||||
self::STATUS_FRAUD => 'Fraud',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -140,7 +148,7 @@ class Order extends Model implements OrderContract
|
|||
*/
|
||||
public function billing_address()
|
||||
{
|
||||
return $this->addresses()->where('address_type', 'billing');
|
||||
return $this->addresses()->where('address_type', OrderAddress::ADDRESS_TYPE_BILLING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -156,7 +164,7 @@ class Order extends Model implements OrderContract
|
|||
*/
|
||||
public function shipping_address()
|
||||
{
|
||||
return $this->addresses()->where('address_type', 'shipping');
|
||||
return $this->addresses()->where('address_type', OrderAddress::ADDRESS_TYPE_SHIPPING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -180,7 +188,7 @@ class Order extends Model implements OrderContract
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function haveStockableItems()
|
||||
public function haveStockableItems(): bool
|
||||
{
|
||||
foreach ($this->items as $item) {
|
||||
if ($item->getTypeInstance()->isStockable()) {
|
||||
|
|
@ -193,10 +201,12 @@ class Order extends Model implements OrderContract
|
|||
|
||||
/**
|
||||
* Checks if new shipment is allow or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canShip()
|
||||
public function canShip(): bool
|
||||
{
|
||||
if ($this->status == 'fraud') {
|
||||
if ($this->status === self::STATUS_FRAUD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -211,10 +221,12 @@ class Order extends Model implements OrderContract
|
|||
|
||||
/**
|
||||
* Checks if new invoice is allow or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canInvoice()
|
||||
public function canInvoice(): bool
|
||||
{
|
||||
if ($this->status == 'fraud') {
|
||||
if ($this->status === self::STATUS_FRAUD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -229,10 +241,12 @@ class Order extends Model implements OrderContract
|
|||
|
||||
/**
|
||||
* Checks if order can be canceled or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canCancel()
|
||||
public function canCancel(): bool
|
||||
{
|
||||
if ($this->status == 'fraud') {
|
||||
if ($this->status === self::STATUS_FRAUD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -247,10 +261,12 @@ class Order extends Model implements OrderContract
|
|||
|
||||
/**
|
||||
* Checks if order can be refunded or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRefund()
|
||||
public function canRefund(): bool
|
||||
{
|
||||
if ($this->status == 'fraud') {
|
||||
if ($this->status === self::STATUS_FRAUD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,47 +2,64 @@
|
|||
|
||||
namespace Webkul\Sales\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\Customer\Models\Customer;
|
||||
use Webkul\Checkout\Models\CartAddress;
|
||||
use Webkul\Core\Models\Address;
|
||||
use Webkul\Sales\Contracts\OrderAddress as OrderAddressContract;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class OrderAddress extends Model implements OrderAddressContract
|
||||
/**
|
||||
* Class OrderAddress
|
||||
* @package Webkul\Sales\Models
|
||||
*
|
||||
* @property integer $order_id
|
||||
* @property Order $order
|
||||
*
|
||||
*/
|
||||
class OrderAddress extends Address implements OrderAddressContract
|
||||
{
|
||||
protected $table = 'order_address';
|
||||
public const ADDRESS_TYPE_SHIPPING = 'order_shipping';
|
||||
public const ADDRESS_TYPE_BILLING = 'order_billing';
|
||||
|
||||
protected $guarded = ['id', 'created_at', 'updated_at'];
|
||||
|
||||
protected $fillable = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'company_name',
|
||||
'vat_id',
|
||||
'address1',
|
||||
'address2',
|
||||
'city',
|
||||
'state',
|
||||
'postcode',
|
||||
'country',
|
||||
'phone',
|
||||
'address_type',
|
||||
'cart_id',
|
||||
'customer_id',
|
||||
/**
|
||||
* @var array default values
|
||||
*/
|
||||
protected $attributes = [
|
||||
'address_type' => self::ADDRESS_TYPE_BILLING,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get of the customer fullname.
|
||||
* The "booted" method of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getNameAttribute()
|
||||
protected static function boot()
|
||||
{
|
||||
return $this->first_name . ' ' . $this->last_name;
|
||||
static::addGlobalScope('address_type', function (Builder $builder) {
|
||||
$builder->whereIn('address_type', [
|
||||
self::ADDRESS_TYPE_BILLING,
|
||||
self::ADDRESS_TYPE_SHIPPING
|
||||
]);
|
||||
});
|
||||
|
||||
static::creating(static function ($address) {
|
||||
switch ($address->address_type) {
|
||||
case CartAddress::ADDRESS_TYPE_BILLING:
|
||||
$address->address_type = self::ADDRESS_TYPE_BILLING;
|
||||
break;
|
||||
case CartAddress::ADDRESS_TYPE_SHIPPING:
|
||||
$address->address_type = self::ADDRESS_TYPE_SHIPPING;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customer record associated with the order.
|
||||
* Get the order record associated with the address.
|
||||
*/
|
||||
public function customer()
|
||||
public function order()
|
||||
{
|
||||
return $this->belongsTo(Customer::class);
|
||||
return $this->belongsTo(Order::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -47,10 +47,11 @@ class Shipment extends Model implements ShipmentContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the addresses for the shipment.
|
||||
* Get the address for the shipment.
|
||||
*/
|
||||
public function address()
|
||||
{
|
||||
return $this->belongsTo(OrderAddressProxy::modelClass(), 'order_address_id');
|
||||
return $this->belongsTo(OrderAddressProxy::modelClass(), 'order_address_id')
|
||||
->where('address_type', OrderAddress::ADDRESS_TYPE_SHIPPING);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ class FlatRate extends AbstractShipping
|
|||
/**
|
||||
* Returns rate for flatrate
|
||||
*
|
||||
* @return array
|
||||
* @return CartShippingRate|false
|
||||
*/
|
||||
public function calculate()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class Free extends AbstractShipping
|
|||
/**
|
||||
* Returns rate for flatrate
|
||||
*
|
||||
* @return array
|
||||
* @return CartShippingRate|false
|
||||
*/
|
||||
public function calculate()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ class OrderCest
|
|||
$I->seeResponseCodeIsSuccessful();
|
||||
|
||||
$I->seeRecord(CartAddress::class, array_merge($addressData, [
|
||||
'address_type' => 'shipping',
|
||||
'address_type' => CartAddress::ADDRESS_TYPE_SHIPPING,
|
||||
'cart_id' => $mocks['cart']->id,
|
||||
'customer_id' => $mocks['customer']->id,
|
||||
]));
|
||||
|
||||
$I->seeRecord(CartAddress::class, array_merge($addressData, [
|
||||
'address_type' => 'billing',
|
||||
'address_type' => CartAddress::ADDRESS_TYPE_BILLING,
|
||||
'cart_id' => $mocks['cart']->id,
|
||||
'customer_id' => $mocks['customer']->id,
|
||||
]));
|
||||
|
|
@ -128,13 +128,13 @@ class OrderCest
|
|||
|
||||
$I->seeRecord(OrderAddress::class, array_merge($addressData, [
|
||||
'order_id' => $order->id,
|
||||
'address_type' => 'shipping',
|
||||
'address_type' => OrderAddress::ADDRESS_TYPE_SHIPPING,
|
||||
'customer_id' => $mocks['customer']->id,
|
||||
]));
|
||||
|
||||
$I->seeRecord(OrderAddress::class, array_merge($addressData, [
|
||||
'order_id' => $order->id,
|
||||
'address_type' => 'billing',
|
||||
'address_type' => OrderAddress::ADDRESS_TYPE_BILLING,
|
||||
'customer_id' => $mocks['customer']->id,
|
||||
]));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Tests\Unit\Core;
|
||||
|
||||
|
||||
use UnitTester;
|
||||
use Webkul\Checkout\Models\Cart;
|
||||
use Webkul\Checkout\Models\CartAddress;
|
||||
use Webkul\Checkout\Models\CartShippingRate;
|
||||
use Webkul\Customer\Models\Customer;
|
||||
use Webkul\Customer\Models\CustomerAddress;
|
||||
use Webkul\Sales\Models\Invoice;
|
||||
use Webkul\Sales\Models\Order;
|
||||
use Webkul\Sales\Models\OrderAddress;
|
||||
use Webkul\Sales\Models\Shipment;
|
||||
use Webkul\Shipping\Carriers\Free;
|
||||
|
||||
class AddressCest
|
||||
{
|
||||
public function testAddressFilters(UnitTester $I): void
|
||||
{
|
||||
$cartAddress = $I->have(CartAddress::class);
|
||||
$customerAddress = $I->have(CustomerAddress::class);
|
||||
$orderAddress = $I->have(OrderAddress::class);
|
||||
|
||||
$cartAddresses = CartAddress::all();
|
||||
$I->assertCount(1, $cartAddresses);
|
||||
$I->assertEquals($cartAddress->id, $cartAddresses[0]->id);
|
||||
|
||||
$customerAddresses = CustomerAddress::all();
|
||||
$I->assertCount(1, $customerAddresses);
|
||||
$I->assertEquals($customerAddress->id, $customerAddresses[0]->id);
|
||||
|
||||
$orderAddresses = OrderAddress::all();
|
||||
$I->assertCount(1, $orderAddresses);
|
||||
$I->assertEquals($orderAddress->id, $orderAddresses[0]->id);
|
||||
}
|
||||
|
||||
public function testCustomerAddressRelations(UnitTester $I): void
|
||||
{
|
||||
/** @var Customer $customer1 */
|
||||
$customer1 = $I->have(Customer::class);
|
||||
CustomerAddress::create(['customer_id' => $customer1->id]);
|
||||
|
||||
/** @var Customer $customer2 */
|
||||
$customer2 = $I->have(Customer::class);
|
||||
$address1 = CustomerAddress::create(['customer_id' => $customer2->id]);
|
||||
|
||||
$customer2->refresh();
|
||||
$I->assertCount(1, $customer2->addresses);
|
||||
$I->assertEquals($address1->id, $customer2->addresses[0]->id);
|
||||
$I->assertNull($customer2->default_address);
|
||||
|
||||
$address2 = CustomerAddress::create(['customer_id' => $customer2->id, 'default_address' => true]);
|
||||
$customer2->refresh();
|
||||
$I->assertCount(2, $customer2->addresses);
|
||||
$I->assertEquals($address2->id, $customer2->default_address->id);
|
||||
}
|
||||
|
||||
public function testCartAddressRelations(UnitTester $I): void
|
||||
{
|
||||
/** @var Cart $cart */
|
||||
$cart = $I->have(Cart::class);
|
||||
$address1 = CartAddress::create(['cart_id' => $cart->id]);
|
||||
$address2 = CartAddress::create([
|
||||
'cart_id' => $cart->id,
|
||||
'address_type' => CartAddress::ADDRESS_TYPE_SHIPPING
|
||||
]);
|
||||
$cart->refresh();
|
||||
|
||||
$I->assertNotNull($address1->address_type);
|
||||
$I->assertEquals($address1->id, $cart->billing_address->id);
|
||||
$I->assertEquals($address2->id, $cart->shipping_address->id);
|
||||
|
||||
/** @var CartShippingRate $freeShipping */
|
||||
$freeShipping = (new Free())->calculate();
|
||||
$freeShipping->cart_address_id = $address2->id;
|
||||
$freeShipping->saveOrFail();
|
||||
|
||||
$freeShipping->refresh();
|
||||
$I->assertEquals($address2->id, $freeShipping->shipping_address->id);
|
||||
}
|
||||
|
||||
public function testOrderAddressRelations(UnitTester $I): void
|
||||
{
|
||||
/** @var Order $order */
|
||||
$order = $I->have(Order::class);
|
||||
$address1 = OrderAddress::create(['order_id' => $order->id]);
|
||||
$address2 = OrderAddress::create([
|
||||
'order_id' => $order->id,
|
||||
'address_type' => OrderAddress::ADDRESS_TYPE_SHIPPING
|
||||
]);
|
||||
$order->refresh();
|
||||
|
||||
$I->assertNotNull($address1->address_type);
|
||||
$I->assertEquals($address1->id, $order->billing_address->id);
|
||||
$I->assertEquals($address2->id, $order->shipping_address->id);
|
||||
|
||||
/** @var Shipment $shipment */
|
||||
$shipment = Shipment::create(['order_address_id' => $address2->id]);
|
||||
$I->assertEquals($address2->id, $shipment->address->id);
|
||||
|
||||
/** @var Invoice $invoice */
|
||||
$invoice = Invoice::create(['order_id' => $order->id, 'order_address_id' => $address1->id]);
|
||||
$I->assertEquals($address1->id, $invoice->address->id);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue