From 00e408b1cf4add9eaf2e2e8bf7cdd569fa02d901 Mon Sep 17 00:00:00 2001 From: Devansh Date: Tue, 8 Feb 2022 14:14:19 +0530 Subject: [PATCH] Test Case Updated And Cleaned --- tests/_support/Actions/CartAction.php | 31 ++ tests/_support/Actions/ProductAction.php | 493 +++++++++++++++++ .../Actions/ProductActionContract.php | 34 ++ tests/_support/ApiTester.php | 252 +-------- tests/_support/Helper/Bagisto.php | 518 +----------------- 5 files changed, 567 insertions(+), 761 deletions(-) create mode 100644 tests/_support/Actions/CartAction.php create mode 100644 tests/_support/Actions/ProductAction.php create mode 100644 tests/_support/Actions/ProductActionContract.php diff --git a/tests/_support/Actions/CartAction.php b/tests/_support/Actions/CartAction.php new file mode 100644 index 000000000..be7dac336 --- /dev/null +++ b/tests/_support/Actions/CartAction.php @@ -0,0 +1,31 @@ +adjustCustomer()->create(); + } + + /** + * Generate cart items. + * + * @param array $attributes + * @return \Webkul\Checkout\Contracts\CartItem + */ + public function haveCartItems($attributes = []) + { + return CartItem::factory($attributes)->adjustProduct()->create(); + } +} diff --git a/tests/_support/Actions/ProductAction.php b/tests/_support/Actions/ProductAction.php new file mode 100644 index 000000000..02e780a46 --- /dev/null +++ b/tests/_support/Actions/ProductAction.php @@ -0,0 +1,493 @@ + 'text_value', + 'select' => 'integer_value', + 'boolean' => 'boolean_value', + 'textarea' => 'text_value', + 'price' => 'float_value', + 'date' => 'date_value', + 'checkbox' => 'text_value', + ]; + + return $possibleTypes[$type]; + } + + /** + * Prepare for cart. + * + * @param array $options + * @return array + */ + public function prepareCart(array $options = []): array + { + $I = $this; + + $faker = Factory::create(); + + $product = $I->haveProduct(self::SIMPLE_PRODUCT, $options['productOptions'] ?? []); + + if (isset($options['customer'])) { + $customer = $options['customer']; + } else { + $customer = $I->have(Customer::class); + } + + $I->have(CustomerAddress::class, [ + 'default_address' => 1, + 'customer_id' => $customer->id, + 'first_name' => $customer->first_name, + 'last_name' => $customer->last_name, + 'company_name' => $faker->company, + ]); + + if (isset($options['payment_method']) + && $options['payment_method'] === 'free_of_charge') { + $grand_total = '0.0000'; + + $base_grand_total = '0.0000'; + } else { + $grand_total = (string) $faker->numberBetween(1, 666); + + $base_grand_total = $grand_total; + } + + $cart = $I->have(Cart::class, [ + 'customer_id' => $customer->id, + 'customer_first_name' => $customer->first_name, + 'customer_last_name' => $customer->last_name, + 'customer_email' => $customer->email, + 'is_active' => $options['is_active'] ?? 1, + 'channel_id' => $options['channel_id'] ?? 1, + 'grand_total' => $grand_total, + 'base_grand_total' => $base_grand_total, + ]); + + $cartAddress = $I->have(CartAddress::class, ['cart_id' => $cart->id]); + + $type = $options['product_type'] ?? 'simple'; + + $totalQtyOrdered = 0; + + $cartItems = []; + + $generatedCartItems = random_int(3, 10); + + for ($i = 2; $i <= $generatedCartItems; $i++) { + $quantity = random_int(1, 10); + + $cartItem = $I->have(CartItem::class, [ + 'type' => $type, + 'quantity' => $quantity, + 'cart_id' => $cart->id, + 'product_id' => $product->id, + ]); + + $totalQtyOrdered += $quantity; + + $cartItems[] = $cartItem; + } + + // actually set the cart to the user's session + // when in an functional test: + $stub = new StdClass(); + $stub->id = $cart->id; + $I->setSession(['cart' => $stub]); + + return [ + 'cart' => $cart, + 'product' => $product, + 'customer' => $customer, + 'cartAddress' => $cartAddress, + 'cartItems' => $cartItems, + 'totalQtyOrdered' => $totalQtyOrdered, + ]; + } + + /** + * Helper function to generate products for testing. + * + * By default, the product will be generated as saleable, this means it has a price, + * weight, is active and has a positive inventory stock, if necessary. + * + * @param int $productType (See constants in this class for usage.) + * @param array $configs + * @param array $productStates + * @return \Webkul\Product\Models\Product + */ + public function haveProduct(int $productType, array $configs = [], array $productStates = []): Product + { + $I = $this; + + switch ($productType) { + case self::BOOKING_EVENT_PRODUCT: + $product = $I->haveBookingEventProduct($configs, $productStates); + break; + + case self::DOWNLOADABLE_PRODUCT: + $product = $I->haveDownloadableProduct($configs, $productStates); + break; + + case self::VIRTUAL_PRODUCT: + $product = $I->haveVirtualProduct($configs, $productStates); + break; + + case self::SIMPLE_PRODUCT: + default: + $product = $I->haveSimpleProduct($configs, $productStates); + } + + if ($product !== null) { + Event::dispatch('catalog.product.create.after', $product); + } + + return $product; + } + + /** + * Generate simple product. + * + * @param array $configs + * @param array $productStates + * @return \Webkul\Product\Models\Product + */ + public function haveSimpleProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + + if (! in_array('simple', $productStates)) { + $productStates = array_merge($productStates, ['simple']); + } + + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product, $configs['attributeValues'] ?? []); + + $I->createInventory($product->id, $configs['productInventory'] ?? []); + + return $product->refresh(); + } + + /** + * Generate virtual product. + * + * @param array $configs + * @param array $productStates + * @return \Webkul\Product\Models\Product + */ + public function haveVirtualProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + + if (! in_array('virtual', $productStates)) { + $productStates = array_merge($productStates, ['virtual']); + } + + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product, $configs['attributeValues'] ?? []); + + $I->createInventory($product->id, $configs['productInventory'] ?? []); + + return $product->refresh(); + } + + /** + * Generate downloadable product. + * + * @param array $configs + * @param array $productStates + * @return \Webkul\Product\Models\Product + */ + public function haveDownloadableProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + + if (! in_array('downloadable', $productStates)) { + $productStates = array_merge($productStates, ['downloadable']); + } + + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product, $configs['attributeValues'] ?? []); + + $I->createDownloadableLink($product->id); + + return $product->refresh(); + } + + /** + * Generate booking product. + * + * @param array $configs + * @param array $productStates + * @return \Webkul\Product\Models\Product + */ + public function haveBookingEventProduct(array $configs = [], array $productStates = []): Product + { + $I = $this; + + if (! in_array('booking', $productStates)) { + $productStates = array_merge($productStates, ['booking']); + } + + $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); + + $I->createAttributeValues($product, $configs['attributeValues'] ?? []); + + $I->createBookingEventProduct($product->id); + + return $product->refresh(); + } + + /** + * Create product. + * + * @param array $attributes + * @param array $states + * @return \Webkul\Product\Models\Product + */ + protected function createProduct(array $attributes = [], array $states = []): Product + { + return Product::factory() + ->state(function () use ($states) { + return [ + 'type' => $states[0], + ]; + }) + ->create($attributes); + } + + /** + * Create inventory. + * + * @param int $productId + * @param array $inventoryConfig + * @return void + */ + protected function createInventory(int $productId, array $inventoryConfig = []): void + { + $I = $this; + + $I->have(ProductInventory::class, array_merge($inventoryConfig, [ + 'product_id' => $productId, + 'inventory_source_id' => 1, + ])); + } + + /** + * Create downloadable link. + * + * @param int $productId + * @return void + */ + protected function createDownloadableLink(int $productId): void + { + $I = $this; + + $link = $I->have(ProductDownloadableLink::class, [ + 'product_id' => $productId, + ]); + + $I->have(ProductDownloadableLinkTranslation::class, [ + 'product_downloadable_link_id' => $link->id, + ]); + } + + /** + * Create booking event. + * + * @param int $productId + * @return void + */ + protected function createBookingEventProduct(int $productId): void + { + $I = $this; + + $bookingProduct = $I->have(BookingProduct::class, [ + 'product_id' => $productId, + ]); + + $I->have(BookingProductEventTicket::class, [ + 'booking_product_id' => $bookingProduct->id, + ]); + } + + /** + * Create attribute values. + * + * @param \Webkul\Product\Models\Product $product + * @param array $attributeValues + * @return void + */ + protected function createAttributeValues(Product $product, array $attributeValues = []): void + { + $I = $this; + + $faker = Factory::create(); + + $brand = Attribute::query() + ->where(['code' => 'brand']) + ->firstOrFail(); // usually 25 + + if (! AttributeOption::query() + ->where(['attribute_id' => $brand->id]) + ->exists()) { + AttributeOption::create([ + 'admin_name' => 'Webkul Demo Brand (c) 2020', + 'attribute_id' => $brand->id, + ]); + } + + /** + * Some defaults that should apply to all generated products. + * By defaults products will be generated as saleable. + * If you do not want this, this defaults can be overriden by $attributeValues. + */ + $defaultAttributeValues = [ + 'name' => $faker->words(3, true), + 'description' => $faker->sentence, + 'short_description' => $faker->sentence, + 'sku' => $product->sku, + 'url_key' => $faker->slug, + 'status' => true, + 'guest_checkout' => true, + 'visible_individually' => true, + 'special_price_from' => null, + 'special_price_to' => null, + 'special_price' => null, + 'price' => $faker->randomFloat(2, 1, 1000), + 'weight' => '1.00', + 'brand' => AttributeOption::query()->firstWhere('attribute_id', $brand->id)->id, + ]; + + $attributeValues = array_merge($defaultAttributeValues, $attributeValues); + + /** + * List of the possible attributes a product can have. + * + * @var array + */ + $possibleAttributeValues = DB::table('attributes') + ->select('id', 'code', 'type') + ->get() + ->toArray(); + + foreach ($possibleAttributeValues as $attributeSet) { + $data = [ + 'product_id' => $product->id, + 'attribute_id' => $attributeSet->id, + ]; + + $fieldName = self::getAttributeFieldName($attributeSet->type); + + $data[$fieldName] = $attributeValues[$attributeSet->code] ?? null; + + $data = $this->appendAttributeDependencies($attributeSet->code, $data); + + $I->have(ProductAttributeValue::class, $data); + } + } + + /** + * Append attribute dependencies. + * + * @param string $attributeCode + * @param array $data + * @return array + */ + protected function appendAttributeDependencies(string $attributeCode, array $data): array + { + $locale = core()->getCurrentLocale()->code; + + $channel = core()->getCurrentChannelCode(); + + $attributeSetDependencies = [ + 'name' => [ + 'locale', + 'channel', + ], + 'tax_category_id' => [ + 'channel', + ], + 'short_description' => [ + 'locale', + 'channel', + ], + 'description' => [ + 'locale', + 'channel', + ], + 'cost' => [ + 'channel', + ], + 'special_price_from' => [ + 'channel', + ], + 'special_price_to' => [ + 'channel', + ], + 'meta_title' => [ + 'locale', + 'channel', + ], + 'meta_keywords' => [ + 'locale', + 'channel', + ], + 'meta_description' => [ + 'locale', + 'channel', + ], + 'custom_sale_badge' => [ + 'locale', + ], + ]; + + if (array_key_exists($attributeCode, $attributeSetDependencies)) { + foreach ($attributeSetDependencies[$attributeCode] as $key) { + if ($key === 'locale') { + $data['locale'] = $locale; + } + + if ($key === 'channel') { + $data['channel'] = $channel; + } + } + } + + return $data; + } +} diff --git a/tests/_support/Actions/ProductActionContract.php b/tests/_support/Actions/ProductActionContract.php new file mode 100644 index 000000000..6ce128a41 --- /dev/null +++ b/tests/_support/Actions/ProductActionContract.php @@ -0,0 +1,34 @@ +adjustCustomer()->create(); - } - - /** - * Generate cart items. - * - * @param array $attributes - * @return \Webkul\Checkout\Contracts\CartItem - */ - public function haveCartItems($attributes = []) - { - return CartItem::factory($attributes)->adjustProduct()->create(); - } - - /** - * Generate simple product. - * - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Contracts\Product - */ - public function haveSimpleProduct(array $configs = [], array $productStates = []): Product - { - $I = $this; - - if (! in_array('simple', $productStates)) { - $productStates = array_merge($productStates, ['simple']); - } - - $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); - - $I->createAttributeValues($product, $configs['attributeValues'] ?? []); - - $I->createInventory($product->id, $configs['productInventory'] ?? []); - - return $product->refresh(); - } - - /** - * Create product. - * - * @param array $attributes - * @param array $states - * @return \Webkul\Product\Contracts\Product - */ - public function createProduct(array $attributes = [], array $states = []): Product - { - return Product::factory() - ->state(function () use ($states) { - return [ - 'type' => $states[0], - ]; - }) - ->create($attributes); - } - - /** - * Create product inventory. - * - * @param int $productId - * @param array $inventoryConfig - * @return void - */ - public function createInventory(int $productId, array $inventoryConfig = []): void - { - $I = $this; - - $I->have(ProductInventory::class, array_merge($inventoryConfig, [ - 'product_id' => $productId, - 'inventory_source_id' => 1, - ])); - } - - /** - * Create attribute values. - * - * @param \Webkul\Product\Contracts\Product $product - * @param array $attributeValues - * @return void - */ - public function createAttributeValues(Product $product, array $attributeValues = []): void - { - $I = $this; - - $brand = Attribute::query()->where(['code' => 'brand'])->firstOrFail(); - - if (! AttributeOption::query()->where(['attribute_id' => $brand->id])->exists()) { - AttributeOption::create([ - 'admin_name' => 'Webkul Demo Brand (c) 2020', - 'attribute_id' => $brand->id, - ]); - } - - /** - * Some defaults that should apply to all generated products. - * By defaults products will be generated as saleable. - * If you do not want this, this defaults can be overriden by $attributeValues. - */ - $defaultAttributeValues = [ - 'name' => $I->fake()->words(3, true), - 'description' => $I->fake()->sentence, - 'short_description' => $I->fake()->sentence, - 'sku' => $product->sku, - 'url_key' => $I->fake()->slug, - 'status' => true, - 'guest_checkout' => true, - 'visible_individually' => true, - 'special_price_from' => null, - 'special_price_to' => null, - 'special_price' => null, - 'price' => $I->fake()->randomFloat(2, 1, 1000), - 'weight' => '1.00', - 'brand' => AttributeOption::query()->firstWhere('attribute_id', $brand->id)->id, - ]; - - $attributeValues = array_merge($defaultAttributeValues, $attributeValues); - - $possibleAttributeValues = DB::table('attributes') - ->select('id', 'code', 'type') - ->get() - ->toArray(); - - foreach ($possibleAttributeValues as $attributeSet) { - $data = [ - 'product_id' => $product->id, - 'attribute_id' => $attributeSet->id, - ]; - - $fieldName = self::getAttributeFieldName($attributeSet->type); - - $data[$fieldName] = $attributeValues[$attributeSet->code] ?? null; - - $data = $this->appendAttributeDependencies($attributeSet->code, $data); - - $I->have(ProductAttributeValue::class, $data); - } - } - - /** - * Get attribute field names. - * - * @param string $type - * @return string|void - */ - private static function getAttributeFieldName(string $type): ?string - { - $possibleTypes = [ - 'text' => 'text_value', - 'select' => 'integer_value', - 'boolean' => 'boolean_value', - 'textarea' => 'text_value', - 'price' => 'float_value', - 'date' => 'date_value', - 'checkbox' => 'text_value', - ]; - - return $possibleTypes[$type]; - } - - /** - * Append attribute dependencies. - * - * @param string $attributeCode - * @param array $data - * @return array - */ - private function appendAttributeDependencies(string $attributeCode, array $data): array - { - $locale = core()->getCurrentLocale()->code; - - $channel = core()->getCurrentChannelCode(); - - $attributeSetDependencies = [ - 'name' => [ - 'locale', - 'channel', - ], - 'tax_category_id' => [ - 'channel', - ], - 'short_description' => [ - 'locale', - 'channel', - ], - 'description' => [ - 'locale', - 'channel', - ], - 'cost' => [ - 'channel', - ], - 'special_price_from' => [ - 'channel', - ], - 'special_price_to' => [ - 'channel', - ], - 'meta_title' => [ - 'locale', - 'channel', - ], - 'meta_keywords' => [ - 'locale', - 'channel', - ], - 'meta_description' => [ - 'locale', - 'channel', - ], - 'custom_sale_badge' => [ - 'locale', - ], - ]; - - if (array_key_exists($attributeCode, $attributeSetDependencies)) { - foreach ($attributeSetDependencies[$attributeCode] as $key) { - if ($key === 'locale') { - $data['locale'] = $locale; - } - - if ($key === 'channel') { - $data['channel'] = $channel; - } - } - } - - return $data; - } } diff --git a/tests/_support/Helper/Bagisto.php b/tests/_support/Helper/Bagisto.php index 50e846c6e..7bc275cc5 100644 --- a/tests/_support/Helper/Bagisto.php +++ b/tests/_support/Helper/Bagisto.php @@ -2,55 +2,13 @@ namespace Helper; +use Actions\ProductAction; +use Actions\ProductActionContract; use Codeception\Module\Laravel; -use Faker\Factory; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Event; -use StdClass; -use Webkul\Attribute\Models\Attribute; -use Webkul\Attribute\Models\AttributeOption; -use Webkul\BookingProduct\Models\BookingProduct; -use Webkul\BookingProduct\Models\BookingProductEventTicket; -use Webkul\Checkout\Models\Cart; -use Webkul\Checkout\Models\CartAddress; -use Webkul\Checkout\Models\CartItem; -use Webkul\Customer\Models\Customer; -use Webkul\Customer\Models\CustomerAddress; -use Webkul\Product\Models\Product; -use Webkul\Product\Models\ProductAttributeValue; -use Webkul\Product\Models\ProductDownloadableLink; -use Webkul\Product\Models\ProductDownloadableLinkTranslation; -use Webkul\Product\Models\ProductInventory; -class Bagisto extends Laravel +class Bagisto extends Laravel implements ProductActionContract { - /** - * Simple product code. - * - * @var int - */ - public const SIMPLE_PRODUCT = 1; - - /** - * Virtual product code. - * - * @var int - */ - public const VIRTUAL_PRODUCT = 2; - - /** - * Downloadable product code. - * - * @var int - */ - public const DOWNLOADABLE_PRODUCT = 3; - - /** - * Booking product code. - * - * @var int - */ - public const BOOKING_EVENT_PRODUCT = 4; + use ProductAction; /** * Set all session with the given key and value in the array. @@ -73,472 +31,4 @@ class Bagisto extends Laravel { session()->invalidate(); } - - /** - * Returns the field name of the given attribute in which a value should be saved inside - * the 'product_attribute_values' table. Depends on the type. - * - * @param string $type - * @return string|null - */ - public static function getAttributeFieldName(string $type): ?string - { - $possibleTypes = [ - 'text' => 'text_value', - 'select' => 'integer_value', - 'boolean' => 'boolean_value', - 'textarea' => 'text_value', - 'price' => 'float_value', - 'date' => 'date_value', - 'checkbox' => 'text_value', - ]; - - return $possibleTypes[$type]; - } - - /** - * Prepare for cart. - * - * @param array $options - * @return array - */ - public function prepareCart(array $options = []): array - { - $I = $this; - - $faker = Factory::create(); - - $product = $I->haveProduct(self::SIMPLE_PRODUCT, $options['productOptions'] ?? []); - - if (isset($options['customer'])) { - $customer = $options['customer']; - } else { - $customer = $I->have(Customer::class); - } - - $I->have(CustomerAddress::class, [ - 'default_address' => 1, - 'customer_id' => $customer->id, - 'first_name' => $customer->first_name, - 'last_name' => $customer->last_name, - 'company_name' => $faker->company, - ]); - - if (isset($options['payment_method']) - && $options['payment_method'] === 'free_of_charge') { - $grand_total = '0.0000'; - - $base_grand_total = '0.0000'; - } else { - $grand_total = (string) $faker->numberBetween(1, 666); - - $base_grand_total = $grand_total; - } - - $cart = $I->have(Cart::class, [ - 'customer_id' => $customer->id, - 'customer_first_name' => $customer->first_name, - 'customer_last_name' => $customer->last_name, - 'customer_email' => $customer->email, - 'is_active' => $options['is_active'] ?? 1, - 'channel_id' => $options['channel_id'] ?? 1, - 'grand_total' => $grand_total, - 'base_grand_total' => $base_grand_total, - ]); - - $cartAddress = $I->have(CartAddress::class, ['cart_id' => $cart->id]); - - $type = $options['product_type'] ?? 'simple'; - - $totalQtyOrdered = 0; - - $cartItems = []; - - $generatedCartItems = random_int(3, 10); - - for ($i = 2; $i <= $generatedCartItems; $i++) { - $quantity = random_int(1, 10); - - $cartItem = $I->have(CartItem::class, [ - 'type' => $type, - 'quantity' => $quantity, - 'cart_id' => $cart->id, - 'product_id' => $product->id, - ]); - - $totalQtyOrdered += $quantity; - - $cartItems[] = $cartItem; - } - - // actually set the cart to the user's session - // when in an functional test: - $stub = new StdClass(); - $stub->id = $cart->id; - $I->setSession(['cart' => $stub]); - - return [ - 'cart' => $cart, - 'product' => $product, - 'customer' => $customer, - 'cartAddress' => $cartAddress, - 'cartItems' => $cartItems, - 'totalQtyOrdered' => $totalQtyOrdered, - ]; - } - - /** - * Helper function to generate products for testing. - * - * By default, the product will be generated as saleable, this means it has a price, - * weight, is active and has a positive inventory stock, if necessary. - * - * @param int $productType (See constants in this class for usage.) - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Models\Product - */ - public function haveProduct(int $productType, array $configs = [], array $productStates = []): Product - { - $I = $this; - - switch ($productType) { - case self::BOOKING_EVENT_PRODUCT: - $product = $I->haveBookingEventProduct($configs, $productStates); - break; - - case self::DOWNLOADABLE_PRODUCT: - $product = $I->haveDownloadableProduct($configs, $productStates); - break; - - case self::VIRTUAL_PRODUCT: - $product = $I->haveVirtualProduct($configs, $productStates); - break; - - case self::SIMPLE_PRODUCT: - default: - $product = $I->haveSimpleProduct($configs, $productStates); - } - - if ($product !== null) { - Event::dispatch('catalog.product.create.after', $product); - } - - return $product; - } - - /** - * Generate simple product. - * - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Models\Product - */ - private function haveSimpleProduct(array $configs = [], array $productStates = []): Product - { - $I = $this; - - if (! in_array('simple', $productStates)) { - $productStates = array_merge($productStates, ['simple']); - } - - $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); - - $I->createAttributeValues($product, $configs['attributeValues'] ?? []); - - $I->createInventory($product->id, $configs['productInventory'] ?? []); - - return $product->refresh(); - } - - /** - * Generate virtual product. - * - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Models\Product - */ - private function haveVirtualProduct(array $configs = [], array $productStates = []): Product - { - $I = $this; - - if (! in_array('virtual', $productStates)) { - $productStates = array_merge($productStates, ['virtual']); - } - - $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); - - $I->createAttributeValues($product, $configs['attributeValues'] ?? []); - - $I->createInventory($product->id, $configs['productInventory'] ?? []); - - return $product->refresh(); - } - - /** - * Generate downloadable product. - * - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Models\Product - */ - private function haveDownloadableProduct(array $configs = [], array $productStates = []): Product - { - $I = $this; - - if (! in_array('downloadable', $productStates)) { - $productStates = array_merge($productStates, ['downloadable']); - } - - $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); - - $I->createAttributeValues($product, $configs['attributeValues'] ?? []); - - $I->createDownloadableLink($product->id); - - return $product->refresh(); - } - - /** - * Generate booking product. - * - * @param array $configs - * @param array $productStates - * @return \Webkul\Product\Models\Product - */ - private function haveBookingEventProduct(array $configs = [], array $productStates = []): Product - { - $I = $this; - - if (! in_array('booking', $productStates)) { - $productStates = array_merge($productStates, ['booking']); - } - - $product = $I->createProduct($configs['productAttributes'] ?? [], $productStates); - - $I->createAttributeValues($product, $configs['attributeValues'] ?? []); - - $I->createBookingEventProduct($product->id); - - return $product->refresh(); - } - - /** - * Create product. - * - * @param array $attributes - * @param array $states - * @return \Webkul\Product\Models\Product - */ - private function createProduct(array $attributes = [], array $states = []): Product - { - return Product::factory() - ->state(function () use ($states) { - return [ - 'type' => $states[0], - ]; - }) - ->create($attributes); - } - - /** - * Create inventory. - * - * @param int $productId - * @param array $inventoryConfig - * @return void - */ - private function createInventory(int $productId, array $inventoryConfig = []): void - { - $I = $this; - - $I->have(ProductInventory::class, array_merge($inventoryConfig, [ - 'product_id' => $productId, - 'inventory_source_id' => 1, - ])); - } - - /** - * Create downloadable link. - * - * @param int $productId - * @return void - */ - private function createDownloadableLink(int $productId): void - { - $I = $this; - - $link = $I->have(ProductDownloadableLink::class, [ - 'product_id' => $productId, - ]); - - $I->have(ProductDownloadableLinkTranslation::class, [ - 'product_downloadable_link_id' => $link->id, - ]); - } - - /** - * Create booking event. - * - * @param int $productId - * @return void - */ - private function createBookingEventProduct(int $productId): void - { - $I = $this; - - $bookingProduct = $I->have(BookingProduct::class, [ - 'product_id' => $productId, - ]); - - $I->have(BookingProductEventTicket::class, [ - 'booking_product_id' => $bookingProduct->id, - ]); - } - - /** - * Create attribute values. - * - * @param \Webkul\Product\Models\Product $product - * @param array $attributeValues - * @return void - */ - private function createAttributeValues(Product $product, array $attributeValues = []): void - { - $I = $this; - - $faker = Factory::create(); - - $brand = Attribute::query() - ->where(['code' => 'brand']) - ->firstOrFail(); // usually 25 - - if (! AttributeOption::query() - ->where(['attribute_id' => $brand->id]) - ->exists()) { - AttributeOption::create([ - 'admin_name' => 'Webkul Demo Brand (c) 2020', - 'attribute_id' => $brand->id, - ]); - } - - /** - * Some defaults that should apply to all generated products. - * By defaults products will be generated as saleable. - * If you do not want this, this defaults can be overriden by $attributeValues. - */ - $defaultAttributeValues = [ - 'name' => $faker->words(3, true), - 'description' => $faker->sentence, - 'short_description' => $faker->sentence, - 'sku' => $product->sku, - 'url_key' => $faker->slug, - 'status' => true, - 'guest_checkout' => true, - 'visible_individually' => true, - 'special_price_from' => null, - 'special_price_to' => null, - 'special_price' => null, - 'price' => $faker->randomFloat(2, 1, 1000), - 'weight' => '1.00', - 'brand' => AttributeOption::query()->firstWhere('attribute_id', $brand->id)->id, - ]; - - $attributeValues = array_merge($defaultAttributeValues, $attributeValues); - - /** - * List of the possible attributes a product can have. - * - * @var array - */ - $possibleAttributeValues = DB::table('attributes') - ->select('id', 'code', 'type') - ->get() - ->toArray(); - - foreach ($possibleAttributeValues as $attributeSet) { - $data = [ - 'product_id' => $product->id, - 'attribute_id' => $attributeSet->id, - ]; - - $fieldName = self::getAttributeFieldName($attributeSet->type); - - $data[$fieldName] = $attributeValues[$attributeSet->code] ?? null; - - $data = $this->appendAttributeDependencies($attributeSet->code, $data); - - $I->have(ProductAttributeValue::class, $data); - } - } - - /** - * Append attribute dependencies. - * - * @param string $attributeCode - * @param array $data - * @return array - */ - private function appendAttributeDependencies(string $attributeCode, array $data): array - { - $locale = core()->getCurrentLocale()->code; - - $channel = core()->getCurrentChannelCode(); - - $attributeSetDependencies = [ - 'name' => [ - 'locale', - 'channel', - ], - 'tax_category_id' => [ - 'channel', - ], - 'short_description' => [ - 'locale', - 'channel', - ], - 'description' => [ - 'locale', - 'channel', - ], - 'cost' => [ - 'channel', - ], - 'special_price_from' => [ - 'channel', - ], - 'special_price_to' => [ - 'channel', - ], - 'meta_title' => [ - 'locale', - 'channel', - ], - 'meta_keywords' => [ - 'locale', - 'channel', - ], - 'meta_description' => [ - 'locale', - 'channel', - ], - 'custom_sale_badge' => [ - 'locale', - ], - ]; - - if (array_key_exists($attributeCode, $attributeSetDependencies)) { - foreach ($attributeSetDependencies[$attributeCode] as $key) { - if ($key === 'locale') { - $data['locale'] = $locale; - } - - if ($key === 'channel') { - $data['channel'] = $channel; - } - } - } - - return $data; - } }