introduce guest checkout configuration

This commit is contained in:
Annika Wolff 2020-01-17 14:42:47 +01:00
parent 840ae7b2d8
commit 132dd6c0f0
29 changed files with 812 additions and 40 deletions

View File

@ -13,12 +13,16 @@
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.0.0",
"popper.js": "^1.12",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^2.0",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.4",
"vue": "^2.5.7"
"popper.js": "^1.12",
"resolve-url-loader": "^3.1.0",
"sass": "^1.24.5",
"sass-loader": "^8.0.2",
"vue": "^2.5.7",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"opencollective-postinstall": "^2.0.1",

View File

@ -87,10 +87,21 @@ return [
'key' => 'catalog.products',
'name' => 'admin::app.admin.system.products',
'sort' => 2
], [
'key' => 'catalog.products.guest-checkout',
'name' => 'admin::app.admin.system.guest-checkout',
'sort' => 1,
'fields' => [
[
'name' => 'allow-guest-checkout',
'title' => 'admin::app.admin.system.allow-guest-checkout',
'type' => 'boolean'
]
]
], [
'key' => 'catalog.products.review',
'name' => 'admin::app.admin.system.review',
'sort' => 1,
'sort' => 2,
'fields' => [
[
'name' => 'guest_review',

View File

@ -1202,6 +1202,9 @@ return [
'system' => [
'catalog' => 'Catalog',
'products' => 'Products',
'guest-checkout' => 'Guest Checkout',
'allow-guest-checkout' => 'Allow Guest Checkout',
'allow-guest-checkout-hint' => 'Hint: If turned on, this option can be configured for each product specifically.',
'review' => 'Review',
'allow-guest-review' => 'Allow Guest Review',
'inventory' => 'Inventory',

View File

@ -77,6 +77,10 @@
@foreach ($customAttributes as $attribute)
<?php
if ($attribute->code == 'guest_checkout' && ! core()->getConfigData('catalog.products.guest-checkout.allow-guest-checkout')) {
continue;
}
$validations = [];
if ($attribute->is_required) {

View File

@ -65,6 +65,11 @@
@include ('admin::configuration.field-type', ['field' => $field])
@php ($hint = $field['title'] . '-hint')
@if ($hint !== __($hint))
{{ __($hint) }}
@endif
@endforeach
</div>

View File

@ -3,16 +3,20 @@
namespace Webkul\Attribute\Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Illuminate\Support\Facades\DB;
class AttributeFamilyTableSeeder extends Seeder
{
public function run()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
DB::table('attribute_families')->delete();
DB::table('attribute_families')->insert([
['id' => '1','code' => 'default','name' => 'Default','status' => '0','is_user_defined' => '1']
]);
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
}

View File

@ -3,12 +3,17 @@
namespace Webkul\Attribute\Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Illuminate\Support\Facades\DB;
class AttributeGroupTableSeeder extends Seeder
{
public function run()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
DB::table('attribute_groups')->delete();
DB::table('attribute_group_mappings')->delete();
DB::table('attribute_groups')->delete();
DB::table('attribute_groups')->insert([
@ -42,9 +47,12 @@ class AttributeGroupTableSeeder extends Seeder
['attribute_id' => '20','attribute_group_id' => '5','position' => '2'],
['attribute_id' => '21','attribute_group_id' => '5','position' => '3'],
['attribute_id' => '22','attribute_group_id' => '5','position' => '4'],
['attribute_id' => '23','attribute_group_id' => '1','position' => '9'],
['attribute_id' => '24','attribute_group_id' => '1','position' => '10'],
['attribute_id' => '25','attribute_group_id' => '1','position' => '11']
['attribute_id' => '23','attribute_group_id' => '1','position' => '10'],
['attribute_id' => '24','attribute_group_id' => '1','position' => '11'],
['attribute_id' => '25','attribute_group_id' => '1','position' => '12'],
['attribute_id' => '26','attribute_group_id' => '1','position' => '9']
]);
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
}
}

View File

@ -3,7 +3,7 @@
namespace Webkul\Attribute\Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Illuminate\Support\Facades\DB;
class AttributeOptionTableSeeder extends Seeder
{
@ -11,6 +11,7 @@ class AttributeOptionTableSeeder extends Seeder
public function run()
{
DB::table('attribute_options')->delete();
DB::table('attribute_option_translations')->delete();
DB::table('attribute_options')->insert([
['id' => '1', 'admin_name' => 'Red', 'sort_order' => '1', 'attribute_id' => '23'],

View File

@ -2,9 +2,9 @@
namespace Webkul\Attribute\Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class AttributeTableSeeder extends Seeder
{
@ -12,6 +12,7 @@ class AttributeTableSeeder extends Seeder
public function run()
{
DB::table('attributes')->delete();
DB::table('attribute_translations')->delete();
$now = Carbon::now();
@ -59,9 +60,11 @@ class AttributeTableSeeder extends Seeder
['id' => '23','code' => 'color','admin_name' => 'Color','type' => 'select','validation' => NULL,'position' => '23','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '24','code' => 'size','admin_name' => 'Size','type' => 'select','validation' => NULL,'position' => '24','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '25','code' => 'brand','admin_name' => 'Brand','type' => 'select','validation' => NULL,'position' => '25','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '1',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now]
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '26','code' => 'guest_checkout','admin_name' => 'Guest Checkout','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
]);
@ -90,7 +93,8 @@ class AttributeTableSeeder extends Seeder
['id' => '22','locale' => 'en','name' => 'Weight','attribute_id' => '22'],
['id' => '23','locale' => 'en','name' => 'Color','attribute_id' => '23'],
['id' => '24','locale' => 'en','name' => 'Size','attribute_id' => '24'],
['id' => '25','locale' => 'en','name' => 'Brand','attribute_id' => '25']
['id' => '25','locale' => 'en','name' => 'Brand','attribute_id' => '25'],
['id' => '26','locale' => 'en','name' => 'Allow Guest Checkout','attribute_id' => '26']
]);
}
}

View File

@ -13,9 +13,9 @@ class DatabaseSeeder extends Seeder
*/
public function run()
{
$this->call(AttributeTableSeeder::class);
$this->call(AttributeOptionTableSeeder::class);
$this->call(AttributeFamilyTableSeeder::class);
$this->call(AttributeGroupTableSeeder::class);
$this->call(AttributeTableSeeder::class);
$this->call(AttributeOptionTableSeeder::class);
}
}

View File

@ -2,15 +2,16 @@
namespace Webkul\CMS\Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class CMSPagesTableSeeder extends Seeder
{
public function run()
{
DB::table('cms_pages')->delete();
DB::table('cms_page_translations')->delete();
DB::table('cms_pages')->insert([
[

View File

@ -116,11 +116,11 @@ class Cart extends Model implements CartContract
}
/**
* Checks if cart have downloadable items
* Checks if cart has downloadable items
*
* @return boolean
*/
public function haveDownloadableItems()
public function hasDownloadableItems()
{
foreach ($this->items as $item) {
if ($item->type == 'downloadable')
@ -129,4 +129,20 @@ class Cart extends Model implements CartContract
return false;
}
/**
* Checks if cart has items that allow guest checkout
*
* @return boolean
*/
public function hasGuestCheckoutItems()
{
foreach ($this->items as $item) {
if ($item->product->getAttribute('guest_checkout') === 0) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Webkul\Core\Database\Seeders;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ConfigTableSeeder extends Seeder
{
public function run()
{
DB::table('core_config')->delete();
$now = Carbon::now();
DB::table('core_config')->insert([
'id' => 1,
'code' => 'catalog.products.guest-checkout.allow-guest-checkout',
'value' => '1',
'channel_code' => null,
'locale_code' => null,
'created_at' => $now,
'updated_at' => $now
]);
}
}

View File

@ -18,5 +18,6 @@ class DatabaseSeeder extends Seeder
$this->call(CountriesTableSeeder::class);
$this->call(StatesTableSeeder::class);
$this->call(ChannelTableSeeder::class);
$this->call(ConfigTableSeeder::class);
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Webkul\Core\Helpers;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
use Codeception\Module\Laravel5;
use Illuminate\Support\Facades\Event;
use Webkul\Product\Models\Product;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Product\Models\ProductInventory;
class Laravel5Helper extends Laravel5
{
/**
* Returns field name of given attribute.
*
* @param string $attribute
*
* @return string|null
* @part ORM
*/
public static function getAttributeFieldName(string $attribute): ?string
{
$attributes = [
'product_id' => 'integer_value',
'sku' => 'text_value',
'name' => 'text_value',
'url_key' => 'text_value',
'tax_category_id' => 'integer_value',
'new' => 'boolean_value',
'featured' => 'boolean_value',
'visible_individually' => 'boolean_value',
'status' => 'boolean_value',
'short_description' => 'text_value',
'description' => 'text_value',
'price' => 'float_value',
'cost' => 'float_value',
'special_price' => 'float_value',
'special_price_from' => 'date_value',
'special_price_to' => 'date_value',
'meta_title' => 'text_value',
'meta_keywords' => 'text_value',
'meta_description' => 'text_value',
'width' => 'integer_value',
'height' => 'integer_value',
'depth' => 'integer_value',
'weight' => 'integer_value',
'color' => 'integer_value',
'size' => 'integer_value',
'brand' => 'text_value',
'guest_checkout' => 'boolean_value',
];
if (!array_key_exists($attribute, $attributes)) {
return null;
}
return $attributes[$attribute];
}
/**
* @param array $attributeValueStates
*
* @return \Webkul\Product\Models\Product
* @part ORM
*/
public function haveProduct(
array $configs = [],
array $productStates = []
): Product {
$I = $this;
/** @var Product $product */
$product = factory(Product::class)->states($productStates)->create($configs['productAttributes'] ?? []);;
$I->createAttributeValues($product->id,$configs['attributeValues'] ?? []);
$I->have(ProductInventory::class, array_merge($configs['productInventory'] ?? [], [
'product_id' => $product->id,
'inventory_source_id' => 1,
]));
Event::fire('catalog.product.create.after', $product);
return $product;
}
private function createAttributeValues($id, array $attributeValues = [])
{
$I = $this;
$productAttributeValues = [
'sku',
'url_key',
'tax_category_id',
'price',
'cost',
'name',
'new',
'visible_individually',
'featured',
'status',
'guest_checkout',
'short_description',
'description',
'meta_title',
'meta_keywords',
'meta_description',
'weight',
];
foreach ($productAttributeValues as $attribute) {
$data = ['product_id' => $id];
if (array_key_exists($attribute, $attributeValues)) {
$fieldName = self::getAttributeFieldName($attribute);
if (! array_key_exists($fieldName, $data)) {
$data[$fieldName] = $attributeValues[$attribute];
} else {
$data = [$fieldName => $attributeValues[$attribute]];
}
}
$I->have(ProductAttributeValue::class, $data, $attribute);
}
}
}

View File

@ -0,0 +1,27 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Inventory\Models\InventorySource;
$factory->define(InventorySource::class, function (Faker $faker) {
$now = date("Y-m-d H:i:s");
$code = $faker->unique()->word;
return [
'code' => $faker->unique()->word,
'name' => $code,
'description' => $faker->sentence,
'contact_name' => $faker->name,
'contact_email' => $faker->safeEmail,
'contact_number' => $faker->phoneNumber,
'country' => $faker->countryCode,
'state' => $faker->state,
'city' => $faker->city,
'street' => $faker->streetAddress,
'postcode' => $faker->postcode,
'priority' => 0,
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
];
});

View File

@ -0,0 +1,261 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Product\Models\Product;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Attribute\Models\AttributeOption;
$factory->defineAs(ProductAttributeValue::class, 'sku', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'text_value' => $faker->uuid,
'attribute_id' => 1,
];
});
$factory->defineAs(ProductAttributeValue::class, 'name', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->words(2, true),
'attribute_id' => 2,
];
});
$factory->defineAs(ProductAttributeValue::class, 'url_key', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'text_value' => $faker->unique()->slug,
'attribute_id' => 3,
];
});
$factory->defineAs(ProductAttributeValue::class, 'tax_category_id', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'channel' => 'default',
'integer_value' => null, // ToDo
'attribute_id' => 4,
];
});
$factory->defineAs(ProductAttributeValue::class, 'new', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'boolean_value' => 1,
'attribute_id' => 5,
];
});
$factory->defineAs(ProductAttributeValue::class, 'featured', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'boolean_value' => 1,
'attribute_id' => 6,
];
});
$factory->defineAs(ProductAttributeValue::class, 'visible_individually', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'boolean_value' => 1,
'attribute_id' => 7,
];
});
$factory->defineAs(ProductAttributeValue::class, 'status', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'boolean_value' => 1,
'attribute_id' => 8,
];
});
$factory->defineAs(ProductAttributeValue::class, 'short_description', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->sentence,
'attribute_id' => 9,
];
});
$factory->defineAs(ProductAttributeValue::class, 'description', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->sentences(3, true),
'attribute_id' => 10,
];
});
$factory->defineAs(ProductAttributeValue::class, 'price', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'float_value' => $faker->randomFloat(4, 0, 1000),
'attribute_id' => 11,
];
});
$factory->defineAs(ProductAttributeValue::class, 'cost', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'channel' => 'default',
'float_value' => $faker->randomFloat(4, 0, 10),
'attribute_id' => 12,
];
});
$factory->defineAs(ProductAttributeValue::class, 'special_price', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'float_value' => $faker->randomFloat(4, 0, 100),
'attribute_id' => 13,
];
});
$factory->defineAs(ProductAttributeValue::class, 'special_price_from', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'channel' => 'default',
'date_value' => $faker->dateTimeBetween('-5 days', 'now', 'Europe/Berlin'),
'attribute_id' => 14,
];
});
$factory->defineAs(ProductAttributeValue::class, 'special_price_to', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'channel' => 'default',
'date_value' => $faker->dateTimeBetween('now', '+ 5 days', 'Europe/Berlin'),
'attribute_id' => 15,
];
});
$factory->defineAs(ProductAttributeValue::class, 'meta_title', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->words(2, true),
'attribute_id' => 16,
];
});
$factory->defineAs(ProductAttributeValue::class, 'meta_keywords', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->words(5, true),
'attribute_id' => 17,
];
});
$factory->defineAs(ProductAttributeValue::class, 'meta_description', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'locale' => 'en', //$faker->languageCode,
'channel' => 'default',
'text_value' => $faker->sentence,
'attribute_id' => 18,
];
});
$factory->defineAs(ProductAttributeValue::class, 'width', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 50),
'attribute_id' => 19,
];
});
$factory->defineAs(ProductAttributeValue::class, 'height', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 50),
'attribute_id' => 20,
];
});
$factory->defineAs(ProductAttributeValue::class, 'depth', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 50),
'attribute_id' => 21,
];
});
$factory->defineAs(ProductAttributeValue::class, 'weight', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 50),
'attribute_id' => 22,
];
});
$factory->defineAs(ProductAttributeValue::class, 'color', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 5),
'attribute_id' => 23,
];
});
$factory->defineAs(ProductAttributeValue::class, 'size', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'integer_value' => $faker->numberBetween(1, 5),
'attribute_id' => 24,
];
});
$factory->defineAs(ProductAttributeValue::class, 'brand', function (Faker $faker) {
return [
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'attribute_id' => 25,
'integer_value' => function () {
return factory(AttributeOption::class)->create()->id;
},
];
});
$factory->defineAs(ProductAttributeValue::class, 'guest_checkout', function ( Faker $faker) {
return [
'product_id' => function() {
return factory(Product::class)->create()->id;
},
'boolean_value' => 1,
'attribute_id' => 26,
];
});

View File

@ -0,0 +1,23 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Product\Models\Product;
$factory->define(Product::class, function (Faker $faker) {
$now = date("Y-m-d H:i:s");
return [
'sku' => $faker->uuid,
'created_at' => $now,
'updated_at' => $now,
'attribute_family_id' => 1,
];
});
$factory->state(Product::class, 'simple', [
'type' => 'simple',
]);
$factory->state(Product::class, 'downloadable_with_stock', [
'type' => 'downloadable',
]);

View File

@ -0,0 +1,20 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Inventory\Models\InventorySource;
use Webkul\Product\Models\Product;
use Webkul\Product\Models\ProductInventory;
$factory->define(ProductInventory::class, function (Faker $faker) {
return [
'qty' => $faker->numberBetween(1, 20),
'product_id' => function () {
return factory(Product::class)->create()->id;
},
'inventory_source_id' => function () {
return factory(InventorySource::class)->create()->id;
},
];
});

View File

@ -2,6 +2,7 @@
namespace Webkul\Product\Providers;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
use Illuminate\Support\ServiceProvider;
use Webkul\Product\Models\ProductProxy;
use Webkul\Product\Observers\ProductObserver;
@ -32,14 +33,21 @@ class ProductServiceProvider extends ServiceProvider
*
* @return void
*/
public function register()
public function register(): void
{
$this->registerConfig();
$this->registerCommands();
$this->registerEloquentFactoriesFrom(__DIR__ . '/../Database/Factories');
}
public function registerConfig() {
/**
* Register Configuration
*
* @return void
*/
public function registerConfig(): void {
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/product_types.php', 'product_types'
);
@ -47,10 +55,24 @@ class ProductServiceProvider extends ServiceProvider
/**
* Register the console commands of this package
*
* @return void
*/
protected function registerCommands()
protected function registerCommands(): void
{
if ($this->app->runningInConsole())
if ($this->app->runningInConsole()) {
$this->commands([PriceUpdate::class,]);
}
}
/**
* Register factories.
*
* @param string $path
* @return void
*/
protected function registerEloquentFactoriesFrom($path): void
{
$this->app->make(EloquentFactory::class)->load($path);
}
}

View File

@ -22,14 +22,14 @@ class Downloadable extends AbstractType
{
/**
* ProductDownloadableLinkRepository instance
*
*
* @var ProductDownloadableLinkRepository
*/
protected $productDownloadableLinkRepository;
/**
* ProductDownloadableSampleRepository instance
*
*
* @var ProductDownloadableSampleRepository
*/
protected $productDownloadableSampleRepository;
@ -39,11 +39,11 @@ class Downloadable extends AbstractType
*
* @var array
*/
protected $skipAttributes = ['width', 'height', 'depth', 'weight'];
protected $skipAttributes = ['width', 'height', 'depth', 'weight', 'guest_checkout'];
/**
* These blade files will be included in product edit page
*
*
* @var array
*/
protected $additionalViews = [
@ -111,7 +111,7 @@ class Downloadable extends AbstractType
if (request()->route()->getName() != 'admin.catalog.products.massupdate') {
$this->productDownloadableLinkRepository->saveLinks($data, $product);
$this->productDownloadableSampleRepository->saveSamples($data, $product);
}
@ -127,11 +127,11 @@ class Downloadable extends AbstractType
{
if (! $this->product->status)
return false;
if ($this->product->downloadable_links()->count())
return true;
return false;
return false;
}
/**
@ -177,7 +177,7 @@ class Downloadable extends AbstractType
return $products;
}
/**
*
* @param array $options1

View File

@ -64,13 +64,22 @@ class OnepageController extends Controller
*/
public function index()
{
if (! auth()->guard('customer')->check() && ! core()->getConfigData('catalog.products.guest-checkout.allow-guest-checkout')) {
return redirect()->route('customer.session.index');
}
if (Cart::hasError())
return redirect()->route('shop.checkout.cart.index');
$cart = Cart::getCart();
if (! auth()->guard('customer')->check() && $cart->haveDownloadableItems())
if (! auth()->guard('customer')->check() && $cart->hasDownloadableItems()) {
return redirect()->route('customer.session.index');
}
if (! auth()->guard('customer')->check() && ! $cart->hasGuestCheckoutItems()) {
return redirect()->route('customer.session.index');
}
Cart::collectTotals();

View File

@ -23,4 +23,20 @@ class AcceptanceTester extends \Codeception\Actor
/**
* Define custom actions here
*/
/**
* Logging in as an Admin
*/
public function loginAsAdmin()
{
$I = $this;
$I->amOnPage('/admin');
$I->see('Sign In');
$I->fillField('email', 'admin@example.com');
$I->fillField('password', 'admin123');
$I->dontSee('The "Email" field is required.');
$I->dontSee('The "Password" field is required.');
$I->click('Sign In');
$I->see('Dashboard', '//h1');
}
}

View File

@ -2,6 +2,7 @@
use Illuminate\Routing\RouteCollection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Webkul\User\Models\Admin;
@ -58,4 +59,26 @@ class FunctionalTester extends \Codeception\Actor
$I->assertContains('admin', $middlewares, 'check that admin middleware is applied');
}
/**
* Set specific Webkul/Core configuration keys to a given value
*
* // TODO: change method as soon as there is a method to set core config data
*
* @param $data array containing 'code => value' pairs
* @return void
*/
public function setConfigData($data): void {
foreach ($data as $key => $value) {
if (DB::table('core_config')->where('code', '=', $key)->exists()) {
DB::table('core_config')->where('code', '=', $key)->update(['value' => $value]);
} else {
DB::table('core_config')->insert([
'code' => $key,
'value' => $value,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
}
}
}
}

View File

@ -7,7 +7,23 @@
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost
- \Helper\Acceptance
step_decorators: ~
- \Helper\Acceptance
- Asserts
- WebDriver:
url: http://nginx/
host: selenium-chrome
browser: chrome
window_size: 1920x1080
restart: true
wait: 20
pageload_timeout: 10
connection_timeout: 60
request_timeout: 60
log_js_errors: true
- Laravel5:
part: ORM
cleanup: false
environment_file: .env
database_seeder_class: DatabaseSeeder
url: http://nginx
step_decorators: ~

View File

@ -0,0 +1,59 @@
<?php
namespace Tests\Acceptance;
use AcceptanceTester;
use Faker\Factory;
class GuestCheckoutCest
{
private $faker;
public function _before(AcceptanceTester $I)
{
$this->faker = Factory::create();
}
function testToConfigureGlobalGuestCheckout(AcceptanceTester $I)
{
$I->loginAsAdmin();
$I->amGoingTo('turn ON the global guest checkout configuration');
$I->amOnPage('/admin/configuration/catalog/products');
$I->see(__('admin::app.admin.system.allow-guest-checkout'));
$I->selectOption('catalog[products][guest-checkout][allow-guest-checkout]', 1);
$I->click(__('admin::app.configuration.save-btn-title'));
$I->seeRecord('core_config', ['code' => 'catalog.products.guest-checkout.allow-guest-checkout', 'value' => 1]);
$I->amGoingTo('assert that the product guest checkout configuration is shown');
$I->amOnPage('admin/catalog/products');
$I->click(__('admin::app.catalog.products.add-product-btn-title'));
$I->selectOption('attribute_family_id', 1);
$I->fillField('sku', $this->faker->uuid);
$I->dontSeeInSource('<span class="control-error">The "SKU" field is required.</span>');
$I->click(__('admin::app.catalog.products.save-btn-title'));
$I->seeInCurrentUrl('admin/catalog/products/edit');
$I->scrollTo('#new');
$I->see('Guest Checkout');
$I->seeInSource('<input type="checkbox" id="guest_checkout" name="guest_checkout"');
$I->amGoingTo('turn OFF the global guest checkout configuration');
$I->amOnPage('/admin/configuration/catalog/products');
$I->see(__('admin::app.admin.system.allow-guest-checkout'));
$I->selectOption('catalog[products][guest-checkout][allow-guest-checkout]', 0);
$I->click(__('admin::app.configuration.save-btn-title'));
$I->seeRecord('core_config', ['code' => 'catalog.products.guest-checkout.allow-guest-checkout', 'value' => 0]);
$I->amGoingTo('assert that the product guest checkout configuration is not shown');
$I->amOnPage('admin/catalog/products');
$I->click(__('admin::app.catalog.products.add-product-btn-title'));
$I->selectOption('attribute_family_id', 1);
$I->fillField('sku', $this->faker->uuid);
$I->dontSeeInSource('<span class="control-error">The "SKU" field is required.</span>');
$I->click(__('admin::app.catalog.products.save-btn-title'));
$I->seeInCurrentUrl('admin/catalog/products/edit');
$I->scrollTo('#new');
$I->dontSee('Guest Checkout');
$I->dontSeeInSource('<input type="checkbox" id="guest_checkout" name="guest_checkout"');
}
}

View File

@ -11,8 +11,10 @@ modules:
# add a framework module here
- \Helper\Functional
- Asserts
- Laravel5:
- Webkul\Core\Helpers\Laravel5Helper:
environment_file: .env.testing
packages: packages
cleanup: false
run_database_migrations: true
run_database_seeder: true
database_seeder_class: DatabaseSeeder

View File

@ -70,7 +70,7 @@ class ProductCest
$I->selectOption('select#attribute_family_id', $attributeFamily->id);
$sku = $this->faker->randomNumber(3);
$sku = $this->faker->uuid;
$I->fillField('sku', $sku);
$I->click(__('admin::app.catalog.products.save-btn-title'));

View File

@ -0,0 +1,90 @@
<?php
namespace Tests\Webkul\Unit\Shop;
use FunctionalTester;
use Faker\Factory;
use Cart;
class GuestCheckoutCest
{
private $faker,
$productNoGuestCheckout, $productGuestCheckout;
function _before(FunctionalTester $I) {
$this->faker = Factory::create();
$pConfigDefault = [
'productInventory' => ['qty' => $this->faker->randomNumber(2)],
'attributeValues' => [
'status' => true,
'new' => 1,
'guest_checkout' => 0
],
];
$pConfigGuestCheckout = [
'productInventory' => ['qty' => $this->faker->randomNumber(2)],
'attributeValues' => [
'status' => true,
'new' => 1,
'guest_checkout' => 1
],
];
$this->productNoGuestCheckout = $I->haveProduct($pConfigDefault, ['simple']);
$this->productNoGuestCheckout->refresh();
$this->productGuestCheckout = $I->haveProduct($pConfigGuestCheckout, ['simple']);
$this->productGuestCheckout->refresh();
}
public function testGuestCheckout(FunctionalTester $I) {
$I->amGoingTo('try to add products to cart with guest checkout turned on or off');
$scenarios = [
[
'name' => 'false / false',
'globalConfig' => 0,
'product' => $this->productNoGuestCheckout,
'expectedRoute' => 'customer.session.index'
],
[
'name' => 'false / true',
'globalConfig' => 0,
'product' => $this->productGuestCheckout,
'expectedRoute' => 'customer.session.index'
],
[
'name' => 'true / false',
'globalConfig' => 1,
'product' => $this->productNoGuestCheckout,
'expectedRoute' => 'customer.session.index'
],
[
'name' => 'true / true',
'globalConfig' => 1,
'product' => $this->productGuestCheckout,
'expectedRoute' => 'shop.checkout.onepage.index'
],
];
foreach ($scenarios as $scenario) {
$I->wantTo('test conjunction "' . $scenario['name'] . '" with globalConfig = ' . $scenario['globalConfig'] . ' && product config = ' . $scenario['product']->getAttribute('guest_checkout'));
$I->setConfigData(['catalog.products.guest-checkout.allow-guest-checkout' => $scenario['globalConfig']]);
$I->assertEquals($scenario['globalConfig'], core()->getConfigData('catalog.products.guest-checkout.allow-guest-checkout'));
$I->amOnRoute('shop.home.index');
$I->see($scenario['product']->name, '//div[@class="product-information"]/div[@class="product-name"]');
$I->click(__('shop::app.products.add-to-cart'),
'//form[input[@name="product_id"][@value="' . $scenario['product']->id . '"]]/button');
$I->seeInSource(__('shop::app.checkout.cart.item.success'));
$I->amOnRoute('shop.checkout.cart.index');
$I->see('Shopping Cart', '//div[@class="title"]');
$I->makeHtmlSnapshot('guestCheckout_'.$scenario['globalConfig'].'_'.$scenario['product']->getAttribute('guest_checkout'));
$I->see($scenario['product']->name, '//div[@class="item-title"]');
$I->click( __('shop::app.checkout.cart.proceed-to-checkout'), '//a[@href="' . route('shop.checkout.onepage.index') . '"]');
$I->seeCurrentRouteIs($scenario['expectedRoute']);
$cart = Cart::getCart();
$I->assertTrue(Cart::removeItem($cart->items[0]->id));
}
}
}