Merge pull request #13 from Haendlerbund/merge-bagisto-master
Merge bagisto master
This commit is contained in:
commit
4d578b0b4c
|
|
@ -4,8 +4,9 @@ APP_VERSION=0.1.8
|
|||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
APP_TIMEZONE='Asia/Kolkata'
|
||||
LOG_CHANNEL=stack
|
||||
APP_CURRENCY=USD
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
|
|
|
|||
|
|
@ -2,6 +2,70 @@
|
|||
|
||||
#### This changelog consists the bug & security fixes and new features being included in the releases listed below.
|
||||
|
||||
## **v0.1.9 (20th of December, 2019)** - *Release*
|
||||
|
||||
* #1875 [fixed] - Discount gets applied on cart if condition is "Visible Individually" is set to yes and product added in cart is not visible individually.
|
||||
|
||||
* #1868 [fixed] - Getting exception on checkout if action Buy X Get Y free is selected in cart rule.
|
||||
|
||||
* #1838 [fixed] - Cart rule not working for condition sku(children only) and sku(parent only).
|
||||
|
||||
* #1835 [fixed] - Getting exception if condition value remains blank.
|
||||
|
||||
* #1831 [fixed] - Negative sign is not required in discount amount.
|
||||
|
||||
* #1830 [fixed] - If Coupon type is selected as "No Coupon" then coupon code should not generate for that particular cart rule.
|
||||
|
||||
* #1904 [fixed] - Existing tax should display as list on creating catalog rule if in condition "Tax Category" is selected.
|
||||
|
||||
* #1903 [fixed] - UI issue in condition field
|
||||
|
||||
* #1895 [fixed] - Translation issue Action Type field while creating catalog rule.
|
||||
|
||||
* #1883 [fixed] - Free shipping not applied on cart, if from action "Free Shipping" is selected and discount amount is given as zero.
|
||||
|
||||
* #1882 [fixed] - If from Action "Apply on shipping " is selected as yes then the discounted amount is applying on both product and shipping charge.
|
||||
|
||||
* #1861 [fixed] - Getting exception on checkout if applying invalid coupon code and proceed for checkout.
|
||||
|
||||
* #1857 [fixed] - Getting exception when creating cart rule with condition URL KEY(children only).
|
||||
|
||||
* #1856 [fixed] - Getting exception on creating cart rule with condition Name(children only).
|
||||
|
||||
* #1847 [fixed] - If cart rule condition does not match the cart then on applying coupon it should display message "Coupon cannot be applied".
|
||||
|
||||
* #1839 [fixed] - Getting exception on filtering cart rule through id.
|
||||
|
||||
* #1836 [fixed] - Back button on Edit cart rule page doesn't work.
|
||||
|
||||
* #1834 [fixed] - On editing any cart rule, its priority updates to 1.
|
||||
|
||||
* #1833 [fixed] - Discount not applied if "Payment Method", "Shipping Method", "Shipping State" or "Shipping Country" is selected in condition.
|
||||
|
||||
* #1832 [fixed] - Able to use coupon irrespective of the number given in "Uses per coupon" field.
|
||||
|
||||
* #1828 [fixed] - Updated changes are not saved on editing cart rule.
|
||||
|
||||
* #1825 [fixed] - Not able to generate coupon code while creating cart rule.
|
||||
|
||||
* #1823 [fixed] - Getting exception after clicking on developement.
|
||||
|
||||
* #1929 [fixed] - Actual product amount and discounted amount both should display on product page for configurable product
|
||||
|
||||
* #1928 [fixed] - Catalog rule should not apply if any of the condition doesn't match, if condition type"All Condition are true"
|
||||
|
||||
* #1931 [fixed] - Catalog rule not applying if in condition type"Any Condition is true" is selected, and some of the condition doesn't match the product.
|
||||
|
||||
* #1935 [fixed] - Categories are not displaying if in condition Categories(children only) or Categories(Parent Only) is selected.
|
||||
|
||||
* #1938 [fixed] - multiple cart rules are getting applied by using only single coupon.
|
||||
|
||||
* #1939 [fixed] - Invalid coupon gets applied, if clicking on apply coupon multiple time, although there is no discount amount but its displaying message that coupon code applied successfully.
|
||||
|
||||
* #1942 [fixed] - When editing the cart rule, selected category is not checked.
|
||||
|
||||
|
||||
|
||||
## **v0.1.8 (4th of October, 2019)** - *Release*
|
||||
|
||||
* [feature] - Refund is added for orders.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# CHANGELOG for v0.2.x
|
||||
|
||||
#### This changelog consists the bug & security fixes and new features being included in the releases listed below.
|
||||
|
||||
## **v0.2.0 (23th of December, 2019)** - *Release*
|
||||
|
||||
* #1955 [fixed] - Message need to be changed on mouse hover on cross symbol next to applied coupon.
|
||||
|
||||
* #1959 [fixed] - if admin has set the same condition twice, then catalog rule is not getting apply
|
||||
|
||||
* #1958 [fixed] - getting exception on front end, if action type is Buy x get y free in non couponable cart rule.
|
||||
|
||||
* #1957 [fixed] - if action type is Fixed Amount to Whole Cart, then apply to shipping option should get hide.
|
||||
|
||||
* #1954 [fixed] - If any different tax category has been assigned to variants in configurable product, then while using tax category condition in cart rule, rule is not working properly.
|
||||
|
||||
* #1950 [fixed] - multiple catalog rule should not get get applied, if 1st one has been created as End Other Rules = yes
|
||||
35
README.md
35
README.md
|
|
@ -21,20 +21,20 @@
|
|||
|
||||
### Introduction
|
||||
|
||||
[Bagisto](https://www.bagisto.com) is a hand tailored E-Commerce framework designed on some of the hottest opensource technologies
|
||||
such as [Laravel](https://laravel.com) a [PHP](https://secure.php.net/) framework, [Vue.js](https://vuejs.org)
|
||||
[Bagisto](https://www.bagisto.com) is a hand tailored E-Commerce framework built on some of the hottest opensource technologies
|
||||
such as [Laravel](https://laravel.com) (a [PHP](https://secure.php.net/) framework) and [Vue.js](https://vuejs.org)
|
||||
a progressive Javascript framework.
|
||||
|
||||
**Bagisto is viable attempt to cut down your time, cost and workforce for building online stores or migrating from physical stores
|
||||
to the ever demanding online world. Your business whether small or huge it suits all and very simple to set it up.**
|
||||
**Bagisto can help you to cut down your time, cost, and workforce for building online stores or migrating from physical stores
|
||||
to the ever demanding online world. Your business -- whether small or huge -- can benefit. And it's very simple to set it up.**
|
||||
|
||||
**Read our documentation: [Bagisto Docs](https://devdocs.bagisto.com/)**
|
||||
|
||||
**We are also having a forum for any type of your concern, feature request discussions. Please visit: [Bagisto Forums](https://forums.bagisto.com/)**
|
||||
**We also have a forum for any type of concerns, feature requests, or discussions. Please visit: [Bagisto Forums](https://forums.bagisto.com/)**
|
||||
|
||||
# Visit our live [Demo](https://demo.bagisto.com)
|
||||
|
||||
It packs in lots of demanding features that allows your business to scale in no time:
|
||||
It packs in lots of features that will allow your E-Commerce business to scale in no time:
|
||||
|
||||
* Multiple Channels, Locale, Currencies.
|
||||
* Built-in Access Control Layer.
|
||||
|
|
@ -50,11 +50,10 @@ It packs in lots of demanding features that allows your business to scale in no
|
|||
* Simple and Configurable Products.
|
||||
* Price rules (Discount) inbuilt.
|
||||
* CMS Pages.
|
||||
* Check out [click here](https://bagisto.com/features/).
|
||||
* Check out [these features and more](https://bagisto.com/features/).
|
||||
|
||||
**For Developers**:
|
||||
Dev guys can take advantage of two of the hottest frameworks used in this project Laravel and Vue.js, both of these frameworks have been used in Bagisto.
|
||||
Bagisto is using power of both of these frameworks and making best out of it out of the box.
|
||||
Take advantage of two of the hottest frameworks used in this project -- Laravel and Vue.js -- both of which have been used in Bagisto.
|
||||
|
||||
### Documentation
|
||||
|
||||
|
|
@ -80,7 +79,7 @@ Bagisto is using power of both of these frameworks and making best out of it out
|
|||
|
||||
[Download](https://github.com/bagisto/bagisto/archive/v0.1.6.zip)
|
||||
|
||||
##### b. Extract the contents of zip and execute the project in browser:
|
||||
##### b. Extract the contents of zip and execute the project in your browser:
|
||||
|
||||
~~~
|
||||
http(s)://localhost/bagisto/public
|
||||
|
|
@ -94,15 +93,15 @@ http(s)://example.com/public
|
|||
|
||||
**2. Try our old fashioned way to install Bagisto:**
|
||||
|
||||
##### Execute these commands below as in their order
|
||||
##### Execute these commands below, in order
|
||||
|
||||
~~~
|
||||
1. composer create-project bagisto/bagisto
|
||||
~~~
|
||||
|
||||
**Now configure your database:**
|
||||
**Now, configure your database:**
|
||||
|
||||
If the above command was completed successfully, then you'll find directory **bagisto** and all of the code will be inside it.
|
||||
If the above command was completed successfully, then you'll find directory **bagisto** with all of the code inside it.
|
||||
|
||||
Find file **.env** inside **bagisto** directory and set the environment variables listed below:
|
||||
|
||||
|
|
@ -114,7 +113,7 @@ Find file **.env** inside **bagisto** directory and set the environment variable
|
|||
* **DB_USERNAME**
|
||||
* **DB_PASSWORD**
|
||||
|
||||
Although, mailer environment variables are also required to be set up as **Bagisto** requires emails to send to customers and admins for various functionalities that are built in.
|
||||
Mailer environment variables are also required to be set up. This is because **Bagisto** needs to send emails to customers and admins depending on what events require notification.
|
||||
|
||||
~~~
|
||||
2. php artisan migrate
|
||||
|
|
@ -142,13 +141,13 @@ Although, mailer environment variables are also required to be set up as **Bagis
|
|||
|
||||
##### On server:
|
||||
|
||||
Warning: Before going full on production mode we recommend you to uninstall developer dependencies.
|
||||
Warning: Before going into production mode we recommend you uninstall developer dependencies.
|
||||
In order to do that, run the command below:
|
||||
|
||||
> composer install --no-dev
|
||||
|
||||
~~~
|
||||
Open the specified entry point in your hosts file in browser or make entry in hosts file if not done.
|
||||
Open the specified entry point in your hosts file in your browser or make an entry in hosts file if not done.
|
||||
~~~
|
||||
|
||||
##### On local:
|
||||
|
|
@ -178,13 +177,13 @@ password:admin123
|
|||
Bagisto is a truly opensource E-Commerce framework which will always be free under the [MIT License](https://github.com/bagisto/bagisto/blob/master/LICENSE).
|
||||
|
||||
### Security Vulnerabilities
|
||||
Please don't disclose security vulnerabilities publicly. If you find any security vulnerability in Bagisto then please write us mail: mailto:support@bagisto.com.
|
||||
Please don't disclose security vulnerabilities publicly. If you find any security vulnerability in Bagisto then please email us: mailto:support@bagisto.com.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
#### Contributors
|
||||
|
||||
This project is on [Open Collective](https://opencollective.com/bagisto) and it exists thanks to this people who contribute.
|
||||
This project is on [Open Collective](https://opencollective.com/bagisto) and it exists thanks to the people who contribute.
|
||||
|
||||
<a href="https://github.com/bagisto/bagisto/graphs/contributors"><img src="https://opencollective.com/bagisto/contributors.svg?width=890&button=false"/></a>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
"laravel/framework": "5.6.*",
|
||||
"laravel/tinker": "^1.0",
|
||||
"maatwebsite/excel": "3.1.11",
|
||||
"nwidart/laravel-modules": "^3.2",
|
||||
"prettus/l5-repository": "2.6.32",
|
||||
"tymon/jwt-auth": "1.0.0-rc.4"
|
||||
},
|
||||
|
|
@ -69,33 +68,35 @@
|
|||
},
|
||||
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"database/seeds",
|
||||
"database/factories"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Webkul\\User\\": "packages/Webkul/User/src",
|
||||
"Webkul\\Admin\\": "packages/Webkul/Admin/src",
|
||||
"Webkul\\Ui\\": "packages/Webkul/Ui/src",
|
||||
"Webkul\\Category\\": "packages/Webkul/Category/src",
|
||||
"Webkul\\Checkout\\": "packages/Webkul/Checkout/src",
|
||||
"Webkul\\Attribute\\": "packages/Webkul/Attribute/src",
|
||||
"Webkul\\Shop\\": "packages/Webkul/Shop/src",
|
||||
"Webkul\\Core\\": "packages/Webkul/Core/src",
|
||||
"Webkul\\Customer\\": "packages/Webkul/Customer/src",
|
||||
"Webkul\\Inventory\\": "packages/Webkul/Inventory/src",
|
||||
"Webkul\\Product\\": "packages/Webkul/Product/src",
|
||||
"Webkul\\Theme\\": "packages/Webkul/Theme/src",
|
||||
"Webkul\\Shipping\\": "packages/Webkul/Shipping/src",
|
||||
"Webkul\\Payment\\": "packages/Webkul/Payment/src",
|
||||
"Webkul\\Paypal\\": "packages/Webkul/Paypal/src",
|
||||
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
|
||||
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
|
||||
"Webkul\\API\\": "packages/Webkul/API",
|
||||
"Webkul\\Discount\\": "packages/Webkul/Discount/src",
|
||||
"Webkul\\CMS\\": "packages/Webkul/CMS/src"
|
||||
}
|
||||
"classmap": [
|
||||
"database/seeds",
|
||||
"database/factories"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Webkul\\User\\": "packages/Webkul/User/src",
|
||||
"Webkul\\Admin\\": "packages/Webkul/Admin/src",
|
||||
"Webkul\\Ui\\": "packages/Webkul/Ui/src",
|
||||
"Webkul\\Category\\": "packages/Webkul/Category/src",
|
||||
"Webkul\\Checkout\\": "packages/Webkul/Checkout/src",
|
||||
"Webkul\\Attribute\\": "packages/Webkul/Attribute/src",
|
||||
"Webkul\\Shop\\": "packages/Webkul/Shop/src",
|
||||
"Webkul\\Core\\": "packages/Webkul/Core/src",
|
||||
"Webkul\\Customer\\": "packages/Webkul/Customer/src",
|
||||
"Webkul\\Inventory\\": "packages/Webkul/Inventory/src",
|
||||
"Webkul\\Product\\": "packages/Webkul/Product/src",
|
||||
"Webkul\\Theme\\": "packages/Webkul/Theme/src",
|
||||
"Webkul\\Shipping\\": "packages/Webkul/Shipping/src",
|
||||
"Webkul\\Payment\\": "packages/Webkul/Payment/src",
|
||||
"Webkul\\Paypal\\": "packages/Webkul/Paypal/src",
|
||||
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
|
||||
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
|
||||
"Webkul\\API\\": "packages/Webkul/API",
|
||||
"Webkul\\CatalogRule\\": "packages/Webkul/CatalogRule/src",
|
||||
"Webkul\\CartRule\\": "packages/Webkul/CartRule/src",
|
||||
"Webkul\\Rule\\": "packages/Webkul/Rule/src",
|
||||
"Webkul\\CMS\\": "packages/Webkul/CMS/src"
|
||||
}
|
||||
},
|
||||
|
||||
"autoload-dev": {
|
||||
|
|
@ -131,7 +132,8 @@
|
|||
"set -e",
|
||||
"@php artisan migrate:fresh --env=testing",
|
||||
"vendor/bin/codecept run unit",
|
||||
"vendor/bin/codecept run functional"
|
||||
"vendor/bin/codecept run functional",
|
||||
"vendor/bin/codecept run trigger"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'Asia/Kolkata',
|
||||
'timezone' => env('APP_TIMEZONE','Asia/Kolkata'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -102,7 +102,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'currency' => 'USD',
|
||||
'currency' => env('APP_CURRENCY','USD'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -219,6 +219,8 @@ return [
|
|||
//Laravel Maatwebsite
|
||||
Maatwebsite\Excel\ExcelServiceProvider::class,
|
||||
|
||||
Barryvdh\Debugbar\ServiceProvider::class,
|
||||
|
||||
//Repository
|
||||
Prettus\Repository\Providers\RepositoryServiceProvider::class,
|
||||
Konekt\Concord\ConcordServiceProvider::class,
|
||||
|
|
@ -245,7 +247,9 @@ return [
|
|||
Webkul\Sales\Providers\SalesServiceProvider::class,
|
||||
Webkul\Tax\Providers\TaxServiceProvider::class,
|
||||
Webkul\API\Providers\APIServiceProvider::class,
|
||||
Webkul\Discount\Providers\DiscountServiceProvider::class,
|
||||
Webkul\CatalogRule\Providers\CatalogRuleServiceProvider::class,
|
||||
Webkul\CartRule\Providers\CartRuleServiceProvider::class,
|
||||
Webkul\Rule\Providers\RuleServiceProvider::class,
|
||||
Webkul\CMS\Providers\CMSServiceProvider::class
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ return [
|
|||
\Webkul\Sales\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\Tax\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\User\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\Discount\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\CatalogRule\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\CartRule\Providers\ModuleServiceProvider::class,
|
||||
\Webkul\CMS\Providers\ModuleServiceProvider::class
|
||||
]
|
||||
];
|
||||
|
|
@ -10,14 +10,14 @@
|
|||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.18",
|
||||
"cross-env": "^5.1.4",
|
||||
"laravel-mix": "^2.1",
|
||||
"laravel-mix-merge-manifest": "^0.1.1",
|
||||
"jquery": "^3.2",
|
||||
"vue": "^2.1.10"
|
||||
"axios": "^0.19.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"jquery": "^3.4.1",
|
||||
"laravel-mix": "^5.0.0",
|
||||
"laravel-mix-merge-manifest": "^0.1.2",
|
||||
"vue": "^2.6.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"vee-validate": "2.0.0-rc.26"
|
||||
"vee-validate": "^2.2.15"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/js/admin.js": "/js/admin.js?id=1a04ed2a8f0437dbe740",
|
||||
"/js/admin.js": "/js/admin.js?id=d1daece26673ab30942b",
|
||||
"/css/admin.css": "/css/admin.css?id=c845e7c275d4df7fa03f"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,27 +394,27 @@ return [
|
|||
], [
|
||||
'key' => 'promotions',
|
||||
'name' => 'admin::app.acl.promotions',
|
||||
'route' => 'admin.cart-rule.index',
|
||||
'route' => 'admin.cart-rules.index',
|
||||
'sort' => 7
|
||||
], [
|
||||
'key' => 'promotions.cart-rule',
|
||||
'key' => 'promotions.cart-rules',
|
||||
'name' => 'admin::app.acl.cart-rules',
|
||||
'route' => 'admin.cart-rule.index',
|
||||
'route' => 'admin.cart-rules.index',
|
||||
'sort' => 1
|
||||
], [
|
||||
'key' => 'promotions.cart-rule.create',
|
||||
'key' => 'promotions.cart-rules.create',
|
||||
'name' => 'admin::app.acl.create',
|
||||
'route' => 'admin.cart-rule.create',
|
||||
'route' => 'admin.cart-rules.create',
|
||||
'sort' => 1
|
||||
], [
|
||||
'key' => 'promotions.cart-rule.edit',
|
||||
'key' => 'promotions.cart-rules.edit',
|
||||
'name' => 'admin::app.acl.edit',
|
||||
'route' => 'admin.cart-rule.edit',
|
||||
'route' => 'admin.cart-rules.edit',
|
||||
'sort' => 2
|
||||
], [
|
||||
'key' => 'promotions.cart-rule.delete',
|
||||
'key' => 'promotions.cart-rules.delete',
|
||||
'name' => 'admin::app.acl.delete',
|
||||
'route' => 'admin.cart-rule.delete',
|
||||
'route' => 'admin.cart-rules.delete',
|
||||
'sort' => 3
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -189,22 +189,22 @@ return [
|
|||
'icon-class' => ''
|
||||
],[
|
||||
'key' => 'promotions',
|
||||
'name' => 'admin::app.layouts.promotion',
|
||||
'route' => 'admin.cart-rule.index',
|
||||
'name' => 'admin::app.layouts.promotions',
|
||||
'route' => 'admin.catalog-rules.index',
|
||||
'sort' => 5,
|
||||
'icon-class' => 'promotion-icon'
|
||||
], [
|
||||
'key' => 'promotions.cart-rule',
|
||||
'name' => 'admin::app.promotion.cart-rule',
|
||||
'route' => 'admin.cart-rule.index',
|
||||
'key' => 'promotions.catalog-rules',
|
||||
'name' => 'admin::app.promotions.catalog-rules.title',
|
||||
'route' => 'admin.catalog-rules.index',
|
||||
'sort' => 1,
|
||||
'icon-class' => ''
|
||||
], [
|
||||
'key' => 'promotions.catalog-rule',
|
||||
'name' => 'admin::app.promotion.catalog-rule',
|
||||
'route' => 'admin.catalog-rule.index',
|
||||
'sort' => 1,
|
||||
'icon-class' => '',
|
||||
'key' => 'promotions.cart-rules',
|
||||
'name' => 'admin::app.promotions.cart-rules.title',
|
||||
'route' => 'admin.cart-rules.index',
|
||||
'sort' => 2,
|
||||
'icon-class' => ''
|
||||
], [
|
||||
'key' => 'cms',
|
||||
'name' => 'admin::app.layouts.cms',
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class AddressDataGrid extends DataGrid
|
|||
$queryBuilder = DB::table('customer_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.address1', 'ca.country', DB::raw(''.DB::getTablePrefix().'countries.name as country_name'), 'ca.state', 'ca.city', 'ca.postcode', 'ca.phone', 'ca.default_address')
|
||||
->addSelect('ca.id as address_id', '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('c.id', $customer->id);
|
||||
|
||||
$queryBuilder = $queryBuilder->leftJoin('country_states', function($qb) {
|
||||
|
|
@ -62,13 +62,13 @@ class AddressDataGrid extends DataGrid
|
|||
|
||||
$queryBuilder
|
||||
->groupBy('ca.id')
|
||||
->addSelect(DB::raw(''.DB::getTablePrefix().'country_states.default_name as state_name'));
|
||||
->addSelect(DB::raw(DB::getTablePrefix() . 'country_states.default_name as state_name'));
|
||||
|
||||
$this->addFilter('address_id', 'ca.id');
|
||||
$this->addFilter('address1', 'ca.address1');
|
||||
$this->addFilter('city', 'ca.city');
|
||||
$this->addFilter('state_name', DB::raw(''.DB::getTablePrefix().'country_states.default_name'));
|
||||
$this->addFilter('country_name', DB::raw(''.DB::getTablePrefix().'countries.name'));
|
||||
$this->addFilter('state_name', DB::raw(DB::getTablePrefix() . 'country_states.default_name'));
|
||||
$this->addFilter('country_name', DB::raw(DB::getTablePrefix() . 'countries.name'));
|
||||
$this->addFilter('postcode', 'ca.postcode');
|
||||
$this->addFilter('default_address', 'ca.default_address');
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Admin\DataGrids;
|
||||
|
||||
use Webkul\Ui\DataGrid\DataGrid;
|
||||
use DB;
|
||||
|
||||
/**
|
||||
* CartRuleCouponDataGrid class
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleCouponDataGrid extends DataGrid
|
||||
{
|
||||
protected $index = 'id';
|
||||
|
||||
protected $sortOrder = 'desc';
|
||||
|
||||
public function prepareQueryBuilder()
|
||||
{
|
||||
$queryBuilder = DB::table('cart_rule_coupons')
|
||||
->addSelect('id', 'code', 'created_at', 'expired_at', 'times_used')
|
||||
->where('cart_rule_coupons.cart_rule_id', request('id'));
|
||||
|
||||
$this->setQueryBuilder($queryBuilder);
|
||||
}
|
||||
|
||||
public function addColumns()
|
||||
{
|
||||
$this->addColumn([
|
||||
'index' => 'id',
|
||||
'label' => trans('admin::app.datagrid.id'),
|
||||
'type' => 'number',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'code',
|
||||
'label' => trans('admin::app.datagrid.coupon-code'),
|
||||
'type' => 'string',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'created_at',
|
||||
'label' => trans('admin::app.datagrid.created-date'),
|
||||
'type' => 'datetime',
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'expired_at',
|
||||
'label' => trans('admin::app.datagrid.expiration-date'),
|
||||
'type' => 'datetime',
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'times_used',
|
||||
'label' => trans('admin::app.datagrid.times-used'),
|
||||
'type' => 'number',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public function prepareMassActions()
|
||||
{
|
||||
$this->addMassAction([
|
||||
'type' => 'delete',
|
||||
'action' => route('admin.cart-rule-coupons.mass-delete'),
|
||||
'label' => trans('admin::app.datagrid.delete'),
|
||||
'method' => 'DELETE'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,20 +8,27 @@ use DB;
|
|||
/**
|
||||
* Cart Rule DataGrid class
|
||||
*
|
||||
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleDataGrid extends DataGrid
|
||||
{
|
||||
protected $index = 'id'; //the column that needs to be treated as index column
|
||||
protected $index = 'id';
|
||||
|
||||
protected $sortOrder = 'desc'; //asc or desc
|
||||
protected $sortOrder = 'desc';
|
||||
|
||||
public function prepareQueryBuilder()
|
||||
{
|
||||
$queryBuilder = DB::table('cart_rules')
|
||||
->select('id')
|
||||
->addSelect('id', 'name', 'status', 'end_other_rules', 'action_type', 'disc_amount', 'use_coupon');
|
||||
->leftJoin('cart_rule_coupons', function($leftJoin) {
|
||||
$leftJoin->on('cart_rule_coupons.cart_rule_id', '=', 'cart_rules.id')
|
||||
->where('cart_rule_coupons.is_primary', 1);
|
||||
})
|
||||
->addSelect('cart_rules.id', 'name', 'cart_rule_coupons.code as coupon_code', 'status', 'starts_from', 'ends_till', 'sort_order');
|
||||
|
||||
$this->addFilter('id', 'cart_rules.id');
|
||||
|
||||
$this->addFilter('coupon_code', 'cart_rule_coupons.code');
|
||||
|
||||
$this->setQueryBuilder($queryBuilder);
|
||||
}
|
||||
|
|
@ -30,7 +37,7 @@ class CartRuleDataGrid extends DataGrid
|
|||
{
|
||||
$this->addColumn([
|
||||
'index' => 'id',
|
||||
'label' => trans('admin::app.id'),
|
||||
'label' => trans('admin::app.datagrid.id'),
|
||||
'type' => 'number',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
|
|
@ -39,13 +46,40 @@ class CartRuleDataGrid extends DataGrid
|
|||
|
||||
$this->addColumn([
|
||||
'index' => 'name',
|
||||
'label' => trans('admin::app.name'),
|
||||
'label' => trans('admin::app.datagrid.name'),
|
||||
'type' => 'string',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'coupon_code',
|
||||
'label' => trans('admin::app.datagrid.coupon-code'),
|
||||
'type' => 'string',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'starts_from',
|
||||
'label' => trans('admin::app.datagrid.start'),
|
||||
'type' => 'datetime',
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'ends_till',
|
||||
'label' => trans('admin::app.datagrid.end'),
|
||||
'type' => 'datetime',
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'status',
|
||||
'label' => trans('admin::app.status'),
|
||||
|
|
@ -55,89 +89,36 @@ class CartRuleDataGrid extends DataGrid
|
|||
'filterable' => true,
|
||||
'wrapper' => function($value) {
|
||||
if ($value->status == 1)
|
||||
return 'Active';
|
||||
return trans('admin::app.datagrid.active');
|
||||
else
|
||||
return 'In Active';
|
||||
return trans('admin::app.datagrid.inactive');
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'end_other_rules',
|
||||
'label' => 'End Other Rules',
|
||||
'type' => 'boolean',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'filterable' => true,
|
||||
'wrapper' => function($value) {
|
||||
if ($value->end_other_rules == 1)
|
||||
return 'True';
|
||||
else
|
||||
return 'False';
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'action_type',
|
||||
'label' => 'Action Type',
|
||||
'type' => 'string',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true,
|
||||
'wrapper' => function($value) {
|
||||
return config('pricerules.cart.actions')[$value->action_type];
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'disc_amount',
|
||||
'label' => 'Discount Amount',
|
||||
'index' => 'sort_order',
|
||||
'label' => trans('admin::app.datagrid.priority'),
|
||||
'type' => 'number',
|
||||
'searchable' => false,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'use_coupon',
|
||||
'label' => 'Use Coupon',
|
||||
'type' => 'boolean',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true,
|
||||
'wrapper' => function($value) {
|
||||
if ($value->use_coupon == 1) {
|
||||
return 'True';
|
||||
} else {
|
||||
return 'False';
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
public function prepareActions()
|
||||
{
|
||||
$this->addAction([
|
||||
'title' => 'Edit CartRule',
|
||||
'method' => 'GET', //use post only for redirects only
|
||||
'route' => 'admin.cart-rule.edit',
|
||||
'title' => 'Edit Cart Rule',
|
||||
'method' => 'GET',
|
||||
'route' => 'admin.cart-rules.edit',
|
||||
'icon' => 'icon pencil-lg-icon'
|
||||
]);
|
||||
|
||||
$this->addAction([
|
||||
'title' => 'Delete CartRule',
|
||||
'method' => 'POST', //use post only for requests other than redirects
|
||||
'route' => 'admin.cart-rule.delete',
|
||||
'title' => 'Delete Cart Rule',
|
||||
'method' => 'POST',
|
||||
'route' => 'admin.cart-rules.delete',
|
||||
'icon' => 'icon trash-icon'
|
||||
]);
|
||||
}
|
||||
|
||||
public function prepareMassActions()
|
||||
{
|
||||
// $this->addMassAction([
|
||||
// 'type' => 'delete',
|
||||
// 'action' => route('admin.catalog.attributes.massdelete'),
|
||||
// 'label' => 'Delete',
|
||||
// 'method' => 'DELETE'
|
||||
// ]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,20 +8,19 @@ use DB;
|
|||
/**
|
||||
* Catalog Rule DataGrid class
|
||||
*
|
||||
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CatalogRuleDataGrid extends DataGrid
|
||||
{
|
||||
protected $index = 'id'; //the column that needs to be treated as index column
|
||||
protected $index = 'id';
|
||||
|
||||
protected $sortOrder = 'desc'; //asc or desc
|
||||
protected $sortOrder = 'desc';
|
||||
|
||||
public function prepareQueryBuilder()
|
||||
{
|
||||
$queryBuilder = DB::table('catalog_rules')
|
||||
->select('id')
|
||||
->addSelect('id', 'name', 'starts_from', 'ends_till', 'status', 'end_other_rules', 'action_code');
|
||||
->addSelect('catalog_rules.id', 'name', 'status', 'starts_from', 'ends_till', 'sort_order');
|
||||
|
||||
$this->setQueryBuilder($queryBuilder);
|
||||
}
|
||||
|
|
@ -48,56 +47,41 @@ class CatalogRuleDataGrid extends DataGrid
|
|||
|
||||
$this->addColumn([
|
||||
'index' => 'starts_from',
|
||||
'label' => trans('admin::app.datagrid.starts-from'),
|
||||
'label' => trans('admin::app.datagrid.start'),
|
||||
'type' => 'datetime',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'ends_till',
|
||||
'label' => trans('admin::app.datagrid.ends-till'),
|
||||
'label' => trans('admin::app.datagrid.end'),
|
||||
'type' => 'datetime',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'searchable' => false,
|
||||
'filterable' => true
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'status',
|
||||
'label' => trans('admin::app.datagrid.status'),
|
||||
'label' => trans('admin::app.status'),
|
||||
'type' => 'boolean',
|
||||
'searchable' => false,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true,
|
||||
'wrapper' => function ($value) {
|
||||
'wrapper' => function($value) {
|
||||
if ($value->status == 1)
|
||||
return 'True';
|
||||
return trans('admin::app.datagrid.active');
|
||||
else
|
||||
return 'False';
|
||||
return trans('admin::app.datagrid.inactive');
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'end_other_rules',
|
||||
'label' => 'End Other Rules',
|
||||
'type' => 'boolean',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'filterable' => true,
|
||||
'wrapper' => function ($value) {
|
||||
if ($value->end_other_rules == 1)
|
||||
return 'True';
|
||||
else
|
||||
return 'False';
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
'index' => 'action_code',
|
||||
'label' => 'Action Type',
|
||||
'type' => 'string',
|
||||
'index' => 'sort_order',
|
||||
'label' => trans('admin::app.datagrid.priority'),
|
||||
'type' => 'number',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
|
|
@ -107,27 +91,17 @@ class CatalogRuleDataGrid extends DataGrid
|
|||
public function prepareActions()
|
||||
{
|
||||
$this->addAction([
|
||||
'title' => 'Edit CatalogRule',
|
||||
'method' => 'GET', //use post only for redirects only
|
||||
'route' => 'admin.catalog-rule.edit',
|
||||
'title' => 'Edit Catalog Rule',
|
||||
'method' => 'GET',
|
||||
'route' => 'admin.catalog-rules.edit',
|
||||
'icon' => 'icon pencil-lg-icon'
|
||||
]);
|
||||
|
||||
$this->addAction([
|
||||
'title' => 'Delete CatalogRule',
|
||||
'method' => 'POST', //use post only for requests other than redirects
|
||||
'route' => 'admin.catalog-rule.delete',
|
||||
'title' => 'Delete Catalog Rule',
|
||||
'method' => 'POST',
|
||||
'route' => 'admin.catalog-rules.delete',
|
||||
'icon' => 'icon trash-icon'
|
||||
]);
|
||||
}
|
||||
|
||||
public function prepareMassActions()
|
||||
{
|
||||
// $this->addMassAction([
|
||||
// 'type' => 'delete',
|
||||
// 'action' => route('admin.catalog.attributes.massdelete'),
|
||||
// 'label' => 'Delete',
|
||||
// 'method' => 'DELETE'
|
||||
// ]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class CategoryDataGrid extends DataGrid
|
|||
{
|
||||
$queryBuilder = DB::table('categories as cat')
|
||||
->select('cat.id as category_id', 'ct.name', 'cat.position', 'cat.status', 'ct.locale',
|
||||
DB::raw('COUNT(DISTINCT '.DB::getTablePrefix().'pc.product_id) as count'))
|
||||
DB::raw('COUNT(DISTINCT ' . DB::getTablePrefix() . 'pc.product_id) as count'))
|
||||
->leftJoin('category_translations as ct', function($leftJoin) {
|
||||
$leftJoin->on('cat.id', '=', 'ct.category_id')
|
||||
->where('ct.locale', app()->getLocale());
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ class CustomerDataGrid extends DataGrid
|
|||
$queryBuilder = DB::table('customers')
|
||||
->leftJoin('customer_groups', 'customers.customer_group_id', '=', 'customer_groups.id')
|
||||
->addSelect('customers.id as customer_id', 'customers.email', 'customer_groups.name', 'customers.phone', 'customers.gender', 'status')
|
||||
->addSelect(DB::raw('CONCAT('.DB::getTablePrefix().'customers.first_name, " ", '.DB::getTablePrefix().'customers.last_name) as full_name'));
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'customers.first_name, " ", ' . DB::getTablePrefix() . 'customers.last_name) as full_name'));
|
||||
|
||||
$this->addFilter('customer_id', 'customers.id');
|
||||
$this->addFilter('full_name', DB::raw('CONCAT('.DB::getTablePrefix().'customers.first_name, " ", '.DB::getTablePrefix().'customers.last_name)'));
|
||||
$this->addFilter('full_name', DB::raw('CONCAT(' . DB::getTablePrefix() . 'customers.first_name, " ", ' . DB::getTablePrefix() . 'customers.last_name)'));
|
||||
$this->addFilter('phone', 'customers.phone');
|
||||
$this->addFilter('gender', 'customers.gender');
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ class OrderDataGrid extends DataGrid
|
|||
->where('order_address_billing.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'))
|
||||
->addSelect(DB::raw('CONCAT('.DB::getTablePrefix().'order_address_shipping.first_name, " ", '.DB::getTablePrefix().'order_address_shipping.last_name) as shipped_to'));
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name) as billed_to'))
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_shipping.first_name, " ", ' . DB::getTablePrefix() . 'order_address_shipping.last_name) as shipped_to'));
|
||||
|
||||
$this->addFilter('billed_to', DB::raw('CONCAT('.DB::getTablePrefix().'order_address_billing.first_name, " ", '.DB::getTablePrefix().'order_address_billing.last_name)'));
|
||||
$this->addFilter('shipped_to', DB::raw('CONCAT('.DB::getTablePrefix().'order_address_shipping.first_name, " ", '.DB::getTablePrefix().'order_address_shipping.last_name)'));
|
||||
$this->addFilter('billed_to', DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name)'));
|
||||
$this->addFilter('shipped_to', DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_shipping.first_name, " ", ' . DB::getTablePrefix() . 'order_address_shipping.last_name)'));
|
||||
$this->addFilter('increment_id', 'orders.increment_id');
|
||||
$this->addFilter('created_at', 'orders.created_at');
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ class OrderRefundDataGrid extends DataGrid
|
|||
$leftJoin->on('order_address_billing.order_id', '=', 'orders.id')
|
||||
->where('order_address_billing.address_type', 'billing');
|
||||
})
|
||||
->addSelect(DB::raw('CONCAT('.DB::getTablePrefix().'order_address_billing.first_name, " ", '.DB::getTablePrefix().'order_address_billing.last_name) as billed_to'));
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name) as billed_to'));
|
||||
|
||||
$this->addFilter('billed_to', DB::raw('CONCAT('.DB::getTablePrefix().'order_address_billing.first_name, " ", '.DB::getTablePrefix().'order_address_billing.last_name)'));
|
||||
$this->addFilter('billed_to', DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_billing.first_name, " ", ' . DB::getTablePrefix() . 'order_address_billing.last_name)'));
|
||||
$this->addFilter('id', 'refunds.id');
|
||||
$this->addFilter('increment_id', 'orders.increment_id');
|
||||
$this->addFilter('state', 'refunds.state');
|
||||
|
|
|
|||
|
|
@ -26,16 +26,17 @@ class OrderShipmentsDataGrid extends DataGrid
|
|||
})
|
||||
->leftJoin('orders as ors', 'shipments.order_id', '=', 'ors.id')
|
||||
->leftJoin('inventory_sources as is', 'shipments.inventory_source_id', '=', 'is.id')
|
||||
->select('shipments.id as shipment_id', 'ors.increment_id as shipment_order_id', 'shipments.total_qty as shipment_total_qty', 'is.name as inventory_source_name', 'ors.created_at as order_date', 'shipments.created_at as shipment_created_at')
|
||||
->addSelect(DB::raw('CONCAT('.DB::getTablePrefix().'order_address_shipping.first_name, " ", '.DB::getTablePrefix().'order_address_shipping.last_name) as shipped_to'));
|
||||
->select('shipments.id as shipment_id', 'ors.increment_id as shipment_order_id', 'shipments.total_qty as shipment_total_qty', 'ors.created_at as order_date', 'shipments.created_at as shipment_created_at')
|
||||
->addSelect(DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_shipping.first_name, " ", ' . DB::getTablePrefix() . 'order_address_shipping.last_name) as shipped_to'))
|
||||
->selectRaw('IF(' . DB::getTablePrefix() . 'shipments.inventory_source_id IS NOT NULL,' . DB::getTablePrefix() . 'is.name, ' . DB::getTablePrefix() . 'shipments.inventory_source_name) as inventory_source_name');
|
||||
|
||||
$this->addFilter('shipment_id', 'shipments.id');
|
||||
$this->addFilter('shipment_order_id', 'ors.increment_id');
|
||||
$this->addFilter('shipment_total_qty', 'shipments.total_qty');
|
||||
$this->addFilter('inventory_source_name', 'is.name');
|
||||
$this->addFilter('inventory_source_name', DB::raw('IF(' . DB::getTablePrefix() . 'shipments.inventory_source_id IS NOT NULL,' . DB::getTablePrefix() . 'is.name, ' . DB::getTablePrefix() . 'shipments.inventory_source_name)'));
|
||||
$this->addFilter('order_date', 'ors.created_at');
|
||||
$this->addFilter('shipment_created_at', 'shipments.created_at');
|
||||
$this->addFilter('shipped_to', DB::raw(''.DB::getTablePrefix().'CONCAT(order_address_shipping.first_name, " ", '.DB::getTablePrefix().'order_address_shipping.last_name)'));
|
||||
$this->addFilter('shipped_to', DB::raw('CONCAT(' . DB::getTablePrefix() . 'order_address_shipping.first_name, " ", ' . DB::getTablePrefix() . 'order_address_shipping.last_name)'));
|
||||
|
||||
$this->setQueryBuilder($queryBuilder);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class ProductDataGrid extends DataGrid
|
|||
->leftJoin('products', 'product_flat.product_id', '=', 'products.id')
|
||||
->leftJoin('attribute_families', 'products.attribute_family_id', '=', 'attribute_families.id')
|
||||
->leftJoin('product_inventories', 'product_flat.product_id', '=', 'product_inventories.product_id')
|
||||
->select('product_flat.product_id as product_id', 'product_flat.sku as product_sku', 'product_flat.name as product_name', 'products.type as product_type', 'product_flat.status', 'product_flat.price', 'attribute_families.name as attribute_family', DB::raw('SUM('.DB::getTablePrefix().'product_inventories.qty) as quantity'))
|
||||
->select('product_flat.product_id as product_id', 'product_flat.sku as product_sku', 'product_flat.name as product_name', 'products.type as product_type', 'product_flat.status', 'product_flat.price', 'attribute_families.name as attribute_family', DB::raw('SUM(' . DB::getTablePrefix() . 'product_inventories.qty) as quantity'))
|
||||
->where('channel', core()->getCurrentChannelCode())
|
||||
->where('locale', app()->getLocale())
|
||||
->groupBy('product_flat.product_id');
|
||||
|
|
|
|||
|
|
@ -50,7 +50,13 @@ class TaxRateDataGrid extends DataGrid
|
|||
'type' => 'string',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'filterable' => true
|
||||
'filterable' => true,
|
||||
'wrapper' => function($value) {
|
||||
if (empty($value->state))
|
||||
return '*';
|
||||
else
|
||||
return $value->state;
|
||||
}
|
||||
]);
|
||||
|
||||
$this->addColumn([
|
||||
|
|
|
|||
|
|
@ -120,9 +120,11 @@ class ConfigurationController extends Controller
|
|||
{
|
||||
Event::fire('core.configuration.save.before');
|
||||
|
||||
$this->validate(request(), [
|
||||
'general.design.admin_logo.logo_image' => 'mimes:jpeg,bmp,png,jpg'
|
||||
]);
|
||||
if (request()->hasFile('general.design.admin_logo.logo_image')) {
|
||||
$this->validate(request(), [
|
||||
'general.design.admin_logo.logo_image' => 'required|mimes:jpeg,bmp,png,jpg'
|
||||
]);
|
||||
}
|
||||
|
||||
$this->coreConfigRepository->create(request()->all());
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ class DashboardController extends Controller
|
|||
->where('order_items.created_at', '>=', $this->startDate)
|
||||
->where('order_items.created_at', '<=', $this->endDate)
|
||||
->addSelect(DB::raw('SUM(qty_invoiced - qty_refunded) as total_qty_invoiced'))
|
||||
->addSelect(DB::raw('COUNT('.DB::getTablePrefix().'products.id) as total_products'))
|
||||
->addSelect(DB::raw('COUNT(' . DB::getTablePrefix() . 'products.id) as total_products'))
|
||||
->addSelect('order_items.id', 'categories.id as category_id', 'category_translations.name')
|
||||
->groupBy('categories.id')
|
||||
->havingRaw('SUM(qty_invoiced - qty_refunded) > 0')
|
||||
|
|
|
|||
|
|
@ -669,60 +669,56 @@ Route::group(['middleware' => ['web']], function () {
|
|||
//DataGrid Export
|
||||
Route::post('admin/export', 'Webkul\Admin\Http\Controllers\ExportController@export')->name('admin.datagrid.export');
|
||||
|
||||
Route::prefix('promotion')->group(function () {
|
||||
Route::get('/catalog-rules', 'Webkul\Discount\Http\Controllers\CatalogRuleController@index')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rule.index'
|
||||
])->name('admin.catalog-rule.index');
|
||||
Route::prefix('promotions')->group(function () {
|
||||
Route::get('cart-rules', 'Webkul\CartRule\Http\Controllers\CartRuleController@index')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rules.index'
|
||||
])->name('admin.cart-rules.index');
|
||||
|
||||
Route::get('/catalog-rules/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@create')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rule.create'
|
||||
])->name('admin.catalog-rule.create');
|
||||
Route::get('cart-rules/create', 'Webkul\CartRule\Http\Controllers\CartRuleController@create')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rules.create'
|
||||
])->name('admin.cart-rules.create');
|
||||
|
||||
Route::post('/catalog-rules/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@store')->defaults('_config', [
|
||||
'redirect' => 'admin.catalog-rule.index'
|
||||
])->name('admin.catalog-rule.store');
|
||||
Route::post('cart-rules/create', 'Webkul\CartRule\Http\Controllers\CartRuleController@store')->defaults('_config', [
|
||||
'redirect' => 'admin.cart-rules.index'
|
||||
])->name('admin.cart-rules.store');
|
||||
|
||||
Route::get('/catalog-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@edit')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rule.edit'
|
||||
])->name('admin.catalog-rule.edit');
|
||||
Route::get('cart-rules/edit/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@edit')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rules.edit'
|
||||
])->name('admin.cart-rules.edit');
|
||||
|
||||
Route::post('/catalog-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@update')->defaults('_config', [
|
||||
'redirect' => 'admin.catalog-rule.index'
|
||||
])->name('admin.catalog-rule.update');
|
||||
Route::post('cart-rules/edit/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@update')->defaults('_config', [
|
||||
'redirect' => 'admin.cart-rules.index'
|
||||
])->name('admin.cart-rules.update');
|
||||
|
||||
Route::get('/catalog-rules/apply', 'Webkul\Discount\Http\Controllers\CatalogRuleController@applyRules')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rule.index'
|
||||
])->name('admin.catalog-rule.apply');
|
||||
Route::post('cart-rules/delete/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@destroy')->name('admin.cart-rules.delete');
|
||||
|
||||
Route::post('/catalog-rules/delete/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@destroy')->name('admin.catalog-rule.delete');
|
||||
Route::post('cart-rules/generate-coupons/{id?}', 'Webkul\CartRule\Http\Controllers\CartRuleController@generateCoupons')->name('admin.cart-rules.generate-coupons');
|
||||
|
||||
Route::get('/catalog-rules/declutter', 'Webkul\Discount\Http\Controllers\CatalogRuleController@deClutter')->defaults('_config', [
|
||||
'redirect' => 'admin.catalog-rule.index'
|
||||
])->name('admin.catalog-rule.declut');
|
||||
Route::post('/massdelete', 'Webkul\CartRule\Http\Controllers\CartRuleCouponController@massDelete')->name('admin.cart-rule-coupons.mass-delete');
|
||||
|
||||
Route::post('fetch/options', 'Webkul\Discount\Http\Controllers\CatalogRuleController@fetchAttributeOptions')->name('admin.catalog-rule.options');
|
||||
|
||||
Route::get('cart-rules', 'Webkul\Discount\Http\Controllers\CartRuleController@index')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rule.index'
|
||||
])->name('admin.cart-rule.index');
|
||||
//Catalog rules
|
||||
Route::get('catalog-rules', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@index')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rules.index'
|
||||
])->name('admin.catalog-rules.index');
|
||||
|
||||
Route::get('cart-rules/create', 'Webkul\Discount\Http\Controllers\CartRuleController@create')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rule.create'
|
||||
])->name('admin.cart-rule.create');
|
||||
Route::get('catalog-rules/create', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@create')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rules.create'
|
||||
])->name('admin.catalog-rules.create');
|
||||
|
||||
Route::post('cart-rules/store', 'Webkul\Discount\Http\Controllers\CartRuleController@store')->defaults('_config', [
|
||||
'redirect' => 'admin.cart-rule.index'
|
||||
])->name('admin.cart-rule.store');
|
||||
Route::post('catalog-rules/create', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@store')->defaults('_config', [
|
||||
'redirect' => 'admin.catalog-rules.index'
|
||||
])->name('admin.catalog-rules.store');
|
||||
|
||||
Route::get('cart-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@edit')->defaults('_config', [
|
||||
'view' => 'admin::promotions.cart-rule.edit'
|
||||
])->name('admin.cart-rule.edit');
|
||||
Route::get('catalog-rules/edit/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@edit')->defaults('_config', [
|
||||
'view' => 'admin::promotions.catalog-rules.edit'
|
||||
])->name('admin.catalog-rules.edit');
|
||||
|
||||
Route::post('cart-rules/update/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@update')->defaults('_config', [
|
||||
'redirect' => 'admin.cart-rule.index'
|
||||
])->name('admin.cart-rule.update');
|
||||
Route::post('catalog-rules/edit/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@update')->defaults('_config', [
|
||||
'redirect' => 'admin.catalog-rules.index'
|
||||
])->name('admin.catalog-rules.update');
|
||||
|
||||
Route::post('cart-rules/delete/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@destroy')->name('admin.cart-rule.delete');
|
||||
Route::post('catalog-rules/delete/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@destroy')->name('admin.catalog-rules.delete');
|
||||
});
|
||||
|
||||
Route::prefix('cms')->group(function () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
require("./bootstrap");
|
||||
import Vue from 'vue';
|
||||
import VeeValidate from 'vee-validate';
|
||||
|
||||
window.Vue = require("vue");
|
||||
window.VeeValidate = require("vee-validate");
|
||||
import './bootstrap';
|
||||
|
||||
window.Vue = Vue;
|
||||
window.VeeValidate = VeeValidate;
|
||||
|
||||
Vue.use(VeeValidate);
|
||||
Vue.prototype.$http = axios
|
||||
|
|
@ -82,6 +85,10 @@ $(document).ready(function () {
|
|||
},
|
||||
|
||||
addFlashMessages() {
|
||||
if (typeof flashMessages !== 'undefined') {
|
||||
return;
|
||||
};
|
||||
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
flashMessages.forEach(function(flash) {
|
||||
|
|
|
|||
|
|
@ -49,3 +49,28 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-rule-conditions,
|
||||
.catalog-rule-conditions {
|
||||
table {
|
||||
td {
|
||||
&.attribute {
|
||||
width: 250px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&.operator,
|
||||
&.value {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
&.actions {
|
||||
width: 44px;
|
||||
|
||||
.icon {
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -852,7 +852,7 @@ return [
|
|||
],
|
||||
|
||||
'footer' => [
|
||||
'copy-right' => '© Copyright 2018 Webkul Software, All rights reserved.'
|
||||
'copy-right' => ' مدعوم من <a href="https://bagisto.com/" target="_blank"> Bagisto </a> ، مشروع مجتمع بواسطة <a href="https://webkul.com/" target="_blank">Webkul</a>'
|
||||
],
|
||||
|
||||
'admin' => [
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ return [
|
|||
'taxes' => 'Taxes',
|
||||
'tax-categories' => 'Tax Categories',
|
||||
'tax-rates' => 'Tax Rates',
|
||||
'promotion' => 'Promotions',
|
||||
'promotions' => 'Promotions',
|
||||
'discount' => 'Discount',
|
||||
'cms' => 'CMS'
|
||||
],
|
||||
|
|
@ -110,7 +110,8 @@ return [
|
|||
'create' => 'Add',
|
||||
'delete' => 'Delete',
|
||||
'promotions' => 'Promotions',
|
||||
'cart-rules' => 'Cart Rules'
|
||||
'cart-rules' => 'Cart Rules',
|
||||
'catalog-rules' => 'Catalog Rules',
|
||||
],
|
||||
|
||||
'dashboard' => [
|
||||
|
|
@ -203,7 +204,16 @@ return [
|
|||
'for-guest' => 'For Guest',
|
||||
'order_number' => 'Order Number',
|
||||
'refund-date' => 'Refund Date',
|
||||
'refunded' => 'Refunded'
|
||||
'refunded' => 'Refunded',
|
||||
'start' => 'Start',
|
||||
'end' => 'End',
|
||||
'active' => 'Active',
|
||||
'inactive' => 'Inactive',
|
||||
'coupon-code' => 'Coupon Code',
|
||||
'times-used' => 'Times Used',
|
||||
'created-date' => 'Created Date',
|
||||
'expiration-date' => 'Expiration Date',
|
||||
'delete' => 'Delete'
|
||||
],
|
||||
|
||||
'account' => [
|
||||
|
|
@ -944,125 +954,138 @@ return [
|
|||
]
|
||||
],
|
||||
|
||||
'promotion' => [
|
||||
'information' => 'Information',
|
||||
'conditions' => 'Conditions',
|
||||
'actions' => 'Actions',
|
||||
'coupons' => 'Coupons',
|
||||
'zero-unlimited' => 'Zero denotes unlimited usage here',
|
||||
'catalog-rule' => 'Catalog Rules',
|
||||
'cart-rule' => 'Cart Rules',
|
||||
'add-catalog-rule' => 'Add Rule',
|
||||
'add-cart-rule' => 'Add Cart Rule',
|
||||
'edit-cart-rule' => 'Edit Cart Rule',
|
||||
'edit-catalog-rule' => 'Edit Catalog Rule',
|
||||
'create-catalog-rule' => 'Create Catalog Rule',
|
||||
'create-cart-rule' => 'Create Cart Rule',
|
||||
'save-btn-title' => 'Create',
|
||||
'edit-btn-title' => 'Save',
|
||||
'save' => 'Save',
|
||||
'select-cart-attr' => 'Select Cart Attribute',
|
||||
'select-products' => 'How to choose products ?',
|
||||
'select-category' => 'Select by Categories',
|
||||
'select-attribute' => 'Select by Attributes',
|
||||
'cannot-activate-catalog-rule' => 'Cannot activate catalog rule',
|
||||
'catalog-rule-already-activated' => 'Catalog rule is already activated',
|
||||
'catalog-rule-activated' => 'Catalog rule is activated',
|
||||
'select-attribute' => 'Select :attribute',
|
||||
'enter-attribute' => 'Enter :attribute',
|
||||
'add-condition' => 'Add Condition',
|
||||
'cart-properties' => 'Cart Properties',
|
||||
'yes' => 'Yes',
|
||||
'no' => 'No',
|
||||
'note' => 'Note',
|
||||
'apply' => 'Apply',
|
||||
'rule-name' => 'Enter Rule Name',
|
||||
'rule-desc' => 'Enter Rule Description',
|
||||
'convert-x-note' => 'If this section is left empty, then rule will get applied to all the products in the cart.',
|
||||
'declut' => 'Declutter',
|
||||
'processing-done' => 'Rules processing done',
|
||||
'declut-success' => 'Catalog rules decluttering successful',
|
||||
'declut-failure' => 'Catalog rules decluttering failed',
|
||||
'add-attr-condition' => 'Add Attribute Condition',
|
||||
'general-info' => [
|
||||
'sku-like' => 'SKU Like',
|
||||
'on-shipping' => 'If applied on shipping',
|
||||
'discount' => 'Discount',
|
||||
'shipping-apply-info' => 'It signifies how rule behaves when it is used for shipping',
|
||||
'general-info' => 'General Info',
|
||||
'options' => 'Options',
|
||||
'name' => 'Rule Name',
|
||||
'description' => 'Description',
|
||||
'starts-from' => 'Start',
|
||||
'ends-till' => 'End',
|
||||
'channels' => 'Channels',
|
||||
'channels-req' => 'Channels',
|
||||
'cust-groups' => 'Customer Groups',
|
||||
'priority' => 'Priority',
|
||||
'add-condition' => 'Add Conditions',
|
||||
'disc_amt' => 'Discount Amount',
|
||||
'disc_percent' => 'Discount Percentage',
|
||||
'is-coupon' => 'Use Coupon',
|
||||
'is-coupon-yes' => 'Yes',
|
||||
'is-coupon-no' => 'No',
|
||||
'uses-per-cust' => 'Uses per customer',
|
||||
'all' => 'All',
|
||||
'any' => 'Any',
|
||||
'end-other-rules' => 'End other rules',
|
||||
'status' => 'Is Active',
|
||||
'all-conditions-true' => 'Assuming all conditions are true',
|
||||
'assuming' => 'Assuming',
|
||||
'any' => 'Any',
|
||||
'all' => 'All',
|
||||
'conditions' => 'Conditions',
|
||||
'apply' => 'Apply',
|
||||
'are' => 'are',
|
||||
'true' => 'true',
|
||||
'false' => 'false',
|
||||
'limit' => 'Usage Limit',
|
||||
'specific-coupon' => 'Specific Coupon(Check) / Auto Generated(Unheck)',
|
||||
'free-shipping' => 'Free Shipping',
|
||||
'is-guest' => 'For Guests',
|
||||
'disc_qty' => 'Max. Quantity Allowed To Be Discounted',
|
||||
'test-mode' => 'Choose how to test conditions',
|
||||
'labels' => 'Labels',
|
||||
'prefix' => 'Prefix',
|
||||
'suffix' => 'Suffix',
|
||||
'code' => 'Code',
|
||||
'global-label' => 'Global Label',
|
||||
'label' => 'Label'
|
||||
],
|
||||
|
||||
'status' => [
|
||||
'success' => 'Success! rule created',
|
||||
'success-coupon' => 'Success! rule created along with coupon',
|
||||
'failed' => 'Error! failed to create rule',
|
||||
'update-success' => 'Success! rule updated',
|
||||
'update-coupon-success' => 'Success! rule updated along with coupon',
|
||||
'update-failed' => 'Error! cannot update',
|
||||
'delete-success' => 'Success! rule deleted',
|
||||
'delete-failed' => 'Error! cannot delete',
|
||||
'coupon-applied' => 'Coupon used',
|
||||
'coupon-failed' => 'Coupon failed to apply',
|
||||
'no-coupon' => '* Coupon not applicable',
|
||||
'coupon-removed' => 'Coupon removed successfully',
|
||||
'coupon-remove-failed' => 'Coupon removal failed',
|
||||
'duplicate-coupon' => 'Coupon already exists, please try again with a different coupon'
|
||||
],
|
||||
|
||||
'catalog' => [
|
||||
'promotions' => [
|
||||
'cart-rules' => [
|
||||
'title' => 'Cart Rules',
|
||||
'add-title' => 'Add Cart Rule',
|
||||
'edit-title' => 'Edit Cart Rule',
|
||||
'save-btn-title' => 'Save Cart Rule',
|
||||
'rule-information' => 'Rule Information',
|
||||
'name' => 'Name',
|
||||
'description' => 'Description',
|
||||
'apply-percent' => 'Apply as percentage',
|
||||
'apply-fixed' => 'Apply as fixed amount',
|
||||
'adjust-to-percent' => 'Adjust to percentage',
|
||||
'adjust-to-value' => 'Adjust to discount value',
|
||||
'condition-missing' => 'Please check conditons, some values might be missing'
|
||||
'status' => 'Status',
|
||||
'is-active' => 'Cart Rule is Active',
|
||||
'channels' => 'Channels',
|
||||
'customer-groups' => 'Customer Groups',
|
||||
'coupon-type' => 'Coupon Type',
|
||||
'no-coupon' => 'No Coupon',
|
||||
'specific-coupon' => 'Specific Coupon',
|
||||
'auto-generate-coupon' => 'Auto Generate Coupon',
|
||||
'no' => 'No',
|
||||
'yes' => 'Yes',
|
||||
'coupon-code' => 'Coupon Code',
|
||||
'uses-per-coupon' => 'Uses Per Coupon',
|
||||
'uses-per-customer' => 'Uses Per Customer',
|
||||
'uses-per-customer-control-info' => 'Will be used for logged in customers only.',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'priority' => 'Priority',
|
||||
'conditions' => 'Conditions',
|
||||
'condition-type' => 'Condition Type',
|
||||
'all-conditions-true' => 'All Conditions are True',
|
||||
'any-condition-true' => 'Any Condition is True',
|
||||
'add-condition' => 'Add Condition',
|
||||
'choose-condition-to-add' => 'Choose a condition to add',
|
||||
'cart-attribute' => 'Cart Attribute',
|
||||
'subtotal' => 'Subtotal',
|
||||
'total-items-qty' => 'Total Items Qty',
|
||||
'total-weight' => 'Total Weight',
|
||||
'payment-method' => 'Payment Method',
|
||||
'shipping-method' => 'Shipping Method',
|
||||
'shipping-postcode' => 'Shipping Zip/Postcode',
|
||||
'shipping-state' => 'Shipping State',
|
||||
'shipping-country' => 'Shipping Country',
|
||||
'cart-item-attribute' => 'Cart Item Attribute',
|
||||
'price-in-cart' => 'Price in Cart',
|
||||
'qty-in-cart' => 'Qty in Cart',
|
||||
'product-attribute' => 'Product Attribute',
|
||||
'attribute-name-children-only' => ':attribute_name (Children Only)',
|
||||
'attribute-name-parent-only' => ':attribute_name (Parent Only)',
|
||||
'is-equal-to' => 'Is equal to',
|
||||
'is-not-equal-to' => 'Is not equal to',
|
||||
'equals-or-greater-than' => 'Equals or greater than',
|
||||
'equals-or-less-than' => 'Equals or less than',
|
||||
'greater-than' => 'Greater than',
|
||||
'less-than' => 'Less than',
|
||||
'contain' => 'Contain',
|
||||
'contains' => 'Contains',
|
||||
'does-not-contain' => 'Does not contain',
|
||||
'actions' => 'Actions',
|
||||
'action-type' => 'Action Type',
|
||||
'percentage-product-price' => 'Percentage of Product Price',
|
||||
'fixed-amount' => 'Fixed Amount',
|
||||
'fixed-amount-whole-cart' => 'Fixed Amount to Whole Cart',
|
||||
'buy-x-get-y-free' => 'Buy X Get Y Free',
|
||||
'discount-amount' => 'Discount Amount',
|
||||
'discount-quantity' => 'Maximum Quantity Allowed to be Discounted',
|
||||
'discount-step' => 'Buy X Quantity',
|
||||
'free-shipping' => 'Free Shipping',
|
||||
'apply-to-shipping' => 'Apply to Shipping',
|
||||
'coupon-codes' => 'Coupon Codes',
|
||||
'coupon-qty' => 'Coupon Qty',
|
||||
'code-length' => 'Code Length',
|
||||
'code-format' => 'Code Format',
|
||||
'alphanumeric' => 'Alphanumeric',
|
||||
'alphabetical' => 'Alphabetical',
|
||||
'numeric' => 'Numeric',
|
||||
'code-prefix' => 'Code Prefix',
|
||||
'code-suffix' => 'Code Suffix',
|
||||
'generate' => 'Generate',
|
||||
'cart-rule-not-defind-error' => 'Cart rule is not defined',
|
||||
'mass-delete-success' => 'All the selected index of coupons have been deleted successfully.',
|
||||
'end-other-rules' => 'End Other Rules',
|
||||
'children-categories' => 'Categories (Children Only)',
|
||||
'parent-categories' => 'Categories (Parent Only)',
|
||||
'categories' => 'Categories',
|
||||
'attribute_family' => 'Attribute Family'
|
||||
],
|
||||
|
||||
'cart' => [
|
||||
'buy-atleast' => 'Buy Atleast',
|
||||
'apply-to-shipping' => 'Apply to shipping'
|
||||
'catalog-rules' => [
|
||||
'title' => 'Catalog Rules',
|
||||
'add-title' => 'Add Catalog Rule',
|
||||
'edit-title' => 'Edit Catalog Rule',
|
||||
'save-btn-title' => 'Save Catalog Rule',
|
||||
'rule-information' => 'Rule Information',
|
||||
'name' => 'Name',
|
||||
'description' => 'Description',
|
||||
'status' => 'Status',
|
||||
'is-active' => 'Catalog Rule is Active',
|
||||
'channels' => 'Channels',
|
||||
'customer-groups' => 'Customer Groups',
|
||||
'no' => 'No',
|
||||
'yes' => 'Yes',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'priority' => 'Priority',
|
||||
'conditions' => 'Conditions',
|
||||
'condition-type' => 'Condition Type',
|
||||
'all-conditions-true' => 'All Conditions are True',
|
||||
'any-condition-true' => 'Any Condition is True',
|
||||
'add-condition' => 'Add Condition',
|
||||
'choose-condition-to-add' => 'Choose a condition to add',
|
||||
'product-attribute' => 'Product Attribute',
|
||||
'attribute-name-children-only' => ':attribute_name (Children Only)',
|
||||
'attribute-name-parent-only' => ':attribute_name (Parent Only)',
|
||||
'is-equal-to' => 'Is equal to',
|
||||
'is-not-equal-to' => 'Is not equal to',
|
||||
'equals-or-greater-than' => 'Equals or greater than',
|
||||
'equals-or-less-than' => 'Equals or less than',
|
||||
'greater-than' => 'Greater than',
|
||||
'less-than' => 'Less than',
|
||||
'contain' => 'Contain',
|
||||
'contains' => 'Contains',
|
||||
'does-not-contain' => 'Does not contain',
|
||||
'actions' => 'Actions',
|
||||
'action-type' => 'Action Type',
|
||||
'percentage-product-price' => 'Percentage of Product Price',
|
||||
'fixed-amount' => 'Fixed Amount',
|
||||
'fixed-amount-whole-cart' => 'Fixed Amount to Whole Catalog',
|
||||
'buy-x-get-y-free' => 'Buy X Get Y Free',
|
||||
'discount-amount' => 'Discount Amount',
|
||||
'mass-delete-success' => 'All the selected index of coupons have been deleted successfully.',
|
||||
'end-other-rules' => 'End Other Rules',
|
||||
'categories' => 'Categories',
|
||||
'attribute_family' => 'Attribute Family'
|
||||
]
|
||||
],
|
||||
|
||||
|
|
@ -1172,7 +1195,7 @@ return [
|
|||
],
|
||||
|
||||
'footer' => [
|
||||
'copy-right' => '© Copyright 2018 Webkul Software, All rights reserved.'
|
||||
'copy-right' => 'Powered by <a href="https://bagisto.com/" target="_blank">Bagisto</a>, A Community Project by <a href="https://webkul.com/" target="_blank">Webkul</a>',
|
||||
],
|
||||
|
||||
'admin' => [
|
||||
|
|
|
|||
|
|
@ -998,7 +998,7 @@ return [
|
|||
],
|
||||
|
||||
'footer' => [
|
||||
'copy-right' => '© کپی رایت 2019 کلیه حقوق محفوظ است.'
|
||||
'copy-right' => 'طراحی شده توسط <a href="https://bagisto.com/" target="_blank">Bagisto</a> ، یک پروژه عمومی توسط <a href="https://webkul.com/" target="_blank">Webkul</a>'
|
||||
],
|
||||
|
||||
'admin' => [
|
||||
|
|
|
|||
|
|
@ -976,7 +976,7 @@ return [
|
|||
],
|
||||
|
||||
'footer' => [
|
||||
'copy-right' => '© Copyright '.date('Y').' Webkul Software, Todos os direitos reservados.'
|
||||
'copy-right' => 'Desenvolvido por <a href="https://bagisto.com/" target="_blank">Bagisto</a>, um projeto comunitário da <a href="https://webkul.com/" target="_blank">Webkul</a>'
|
||||
],
|
||||
|
||||
'admin' => [
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
|
||||
<div class="control-group">
|
||||
<label for="locale-{{ $locale->code }}">{{ $locale->name . ' (' . $locale->code . ')' }}</label>
|
||||
<input type="text" class="control" id="locale-{{ $locale->code }}" name="<?php echo $locale->code; ?>[name]" value="{{ old($locale->code)['name'] }}"/>
|
||||
<input type="text" class="control" id="locale-{{ $locale->code }}" name="<?php echo $locale->code; ?>[name]" value="{{ old($locale->code)['name'] ?? '' }}"/>
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
|
||||
<div class="control-group">
|
||||
<label for="locale-{{ $locale->code }}">{{ $locale->name . ' (' . $locale->code . ')' }}</label>
|
||||
<input type="text" class="control" id="locale-{{ $locale->code }}" name="<?php echo $locale->code; ?>[name]" value="{{ old($locale->code)['name'] ?: $attribute->translate($locale->code)['name'] }}"/>
|
||||
<input type="text" class="control" id="locale-{{ $locale->code }}" name="<?php echo $locale->code; ?>[name]" value="{{ old($locale->code)['name'] ?? $attribute->translate($locale->code)['name'] }}"/>
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[name]') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.catalog.categories.name') }}</label>
|
||||
<input type="text" v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" value="{{ old($locale)['name'] ?: $category->translate($locale)['name'] }}" data-vv-as=""{{ __('admin::app.catalog.categories.name') }}""/>
|
||||
<input type="text" v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" value="{{ old($locale)['name'] ?? $category->translate($locale)['name'] }}" data-vv-as=""{{ __('admin::app.catalog.categories.name') }}""/>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[name]')">@{{ errors.first('{!!$locale!!}[name]') }}</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -180,23 +180,23 @@
|
|||
|
||||
<div class="control-group">
|
||||
<label for="meta_title">{{ __('admin::app.catalog.categories.meta_title') }}</label>
|
||||
<input type="text" class="control" id="meta_title" name="{{$locale}}[meta_title]" value="{{ old($locale)['meta_title'] ?: $category->translate($locale)['meta_title'] }}"/>
|
||||
<input type="text" class="control" id="meta_title" name="{{$locale}}[meta_title]" value="{{ old($locale)['meta_title'] ?? $category->translate($locale)['meta_title'] }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[slug]') ? 'has-error' : '']">
|
||||
<label for="slug" class="required">{{ __('admin::app.catalog.categories.slug') }}</label>
|
||||
<input type="text" v-validate="'required'" class="control" id="slug" name="{{$locale}}[slug]" value="{{ old($locale)['slug'] ?: $category->translate($locale)['slug'] }}" data-vv-as=""{{ __('admin::app.catalog.categories.slug') }}"" v-slugify/>
|
||||
<input type="text" v-validate="'required'" class="control" id="slug" name="{{$locale}}[slug]" value="{{ old($locale)['slug'] ?? $category->translate($locale)['slug'] }}" data-vv-as=""{{ __('admin::app.catalog.categories.slug') }}"" v-slugify/>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[slug]')">@{{ errors.first('{!!$locale!!}[slug]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="meta_description">{{ __('admin::app.catalog.categories.meta_description') }}</label>
|
||||
<textarea class="control" id="meta_description" name="{{$locale}}[meta_description]">{{ old($locale)['meta_description'] ?: $category->translate($locale)['meta_description'] }}</textarea>
|
||||
<textarea class="control" id="meta_description" name="{{$locale}}[meta_description]">{{ old($locale)['meta_description'] ?? $category->translate($locale)['meta_description'] }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="meta_keywords">{{ __('admin::app.catalog.categories.meta_keywords') }}</label>
|
||||
<textarea class="control" id="meta_keywords" name="{{$locale}}[meta_keywords]">{{ old($locale)['meta_keywords'] ?: $category->translate($locale)['meta_keywords'] }}</textarea>
|
||||
<textarea class="control" id="meta_keywords" name="{{$locale}}[meta_keywords]">{{ old($locale)['meta_keywords'] ?? $category->translate($locale)['meta_keywords'] }}</textarea>
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.category.edit_form_accordian.seo.controls.after', ['category' => $category]) !!}
|
||||
|
|
@ -220,7 +220,7 @@
|
|||
|
||||
<div class="control-group" :class="[errors.has('{{$locale}}[description]') ? 'has-error' : '']">
|
||||
<label for="description" :class="isRequired ? 'required' : ''">{{ __('admin::app.catalog.categories.description') }}</label>
|
||||
<textarea v-validate="isRequired ? 'required' : ''" class="control" id="description" name="{{$locale}}[description]" data-vv-as=""{{ __('admin::app.catalog.categories.description') }}"">{{ old($locale)['description'] ?: $category->translate($locale)['description'] }}</textarea>
|
||||
<textarea v-validate="isRequired ? 'required' : ''" class="control" id="description" name="{{$locale}}[description]" data-vv-as=""{{ __('admin::app.catalog.categories.description') }}"">{{ old($locale)['description'] ?? $category->translate($locale)['description'] }}</textarea>
|
||||
<span class="control-error" v-if="errors.has('{{$locale}}[description]')">@{{ errors.first('{!!$locale!!}[description]') }}</span>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
@if (core()->getConfigData('general.content.footer.footer_content'))
|
||||
{{ core()->getConfigData('general.content.footer.footer_content') }}
|
||||
@else
|
||||
{{ trans('admin::app.footer.copy-right') }}
|
||||
{!! trans('admin::app.footer.copy-right') !!}
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,630 +0,0 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.add-cart-rule') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="content">
|
||||
<cart-rule></cart-rule>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/x-template" id="cart-rule-form-template">
|
||||
<form method="POST" action="{{ route('admin.cart-rule.store') }}" @submit.prevent="onSubmit" autocomplete="off">
|
||||
@csrf
|
||||
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
|
||||
|
||||
{{ __('admin::app.promotion.add-cart-rule') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
<div>
|
||||
@csrf()
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
|
||||
|
||||
<input type="text" class="control" name="name" v-model="name" v-validate="'required'" value="{{ old('name') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.name') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
|
||||
<label for="description">{{ __('admin::app.promotion.general-info.description') }}</label>
|
||||
|
||||
<textarea class="control" name="description" v-model="description" value="{{ old('description') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.description') }}""></textarea>
|
||||
|
||||
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
|
||||
</div>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
|
||||
<label for="starts_from">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as=""{{ __('admin::app.promotion.general-info.starts-from') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
|
||||
<label for="ends_till">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as=""{{ __('admin::app.promotion.general-info.ends-till') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
|
||||
|
||||
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" value="{{ old('customer_groups[]') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.cust-groups') }}"" multiple="multiple">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Customer Group']) }}</option>
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
|
||||
|
||||
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" value="{{ old('channels[]') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.channels-req') }}"" multiple="multiple">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Channels']) }}</option>
|
||||
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.first('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
|
||||
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
|
||||
|
||||
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.status') }}"">
|
||||
<option value="1">Yes</option>
|
||||
<option value="0">No</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('use_coupon') ? 'has-error' :
|
||||
'']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.is-coupon') }}</label>
|
||||
|
||||
<select type="text" class="control" name="use_coupon" v-model="use_coupon" v-validate="'required'" value="{{ old('use_coupon')}}" data-vv-as=""{{ __('admin::app.promotion.general-info.is-coupon') }}"">
|
||||
<option value="1" :selected="use_coupon == 1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
<option value="0" :selected="use_coupon == 0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('use_coupon')">@{{ errors.first('use_coupon') }}</span>
|
||||
</div>
|
||||
|
||||
{{-- <div class="control-group" :class="[errors.has('auto_generation') ? 'has-error' : '']" v-if="use_coupon == 1">
|
||||
<label for="auto_generation" class="required">{{ __('admin::app.promotion.general-info.specific-coupon') }}</label>
|
||||
|
||||
<input type="checkbox" class="control" name="auto_generation" v-model="auto_generation" value="{{ old('auto_generation') }}" data-vv-as=""Specific Coupon"" v-on:change="checkAutogen">
|
||||
|
||||
<span class="control-error" v-if="errors.has('auto_generation')">@{{ errors.first('auto_generation') }}</span>
|
||||
</div> --}}
|
||||
|
||||
{{-- <input type="hidden" name="auto_generation" v-model="auto_generation"> --}}
|
||||
|
||||
{{-- <div class="control-group" :class="[errors.has('per_customer') ? 'has-error' : '']">
|
||||
<label for="per_customer" class="required">{{ __('admin::app.promotion.general-info.uses-per-cust') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="per_customer" v-model="per_customer" v-validate="'required|numeric|min_value:0'" value="{{ old('per_customer') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.uses-per-cust') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('per_customer')">@{{ errors.first('per_customer') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
|
||||
<label for="usage_limit" class="required">{{ __('admin::app.promotion.general-info.limit') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="usage_limit" v-model="usage_limit" v-validate="'required|numeric|min_value:0'" value="{{ old('usage_limit') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.uses-per-cust') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('usage_limit')">@{{ errors.first('usage_limit') }}</span>
|
||||
</div> --}}
|
||||
|
||||
<div class="control-group" :class="[errors.has('priority') ? 'has-error' : '']">
|
||||
<label for="priority" class="required">{{ __('admin::app.promotion.general-info.priority') }}</label>
|
||||
|
||||
<input type="number" class="control" step="1" name="priority" v-model="priority" v-validate="'required|numeric|min_value:1'" value="{{ old('priority') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.priority') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('priority')">@{{ errors.first('priority') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_conditions" v-model="all_conditions">
|
||||
|
||||
{{-- <div class="add-condition">
|
||||
<div class="control-group">
|
||||
<label for="criteria" class="required">{{ __('admin::app.promotion.general-info.add-condition') }}</label>
|
||||
|
||||
<select type="text" class="control" v-model="criteria">
|
||||
<option value="cart">{{ __('admin::app.promotion.cart-properties') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="control-group">
|
||||
{{ __('admin::app.promotion.general-info.test-mode') }}
|
||||
<select class="control" v-model="match_criteria" style="margin-right: 15px;">
|
||||
{{ $i = 0 }}
|
||||
@foreach(config('pricerules.test_mode') as $key => $value)
|
||||
<option value="{{ $key }}">{{ $value }}</option>
|
||||
{{ $i++ }}
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="condition-set">
|
||||
<!-- Cart Attributes -->
|
||||
<div class="control-container mt-20" v-for="(condition, index) in conditions_list" :key="index">
|
||||
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.select-option') }}</option>
|
||||
<option v-for="(cart_ip, index1) in cart_input" :value="cart_ip.code" :key="index1">@{{ cart_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<div v-if='conditions_list[index].type == "string"' style="display: flex">
|
||||
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-if='conditions_list[index].attribute == "shipping_state"'>
|
||||
<select class="control" v-model="conditions_list[index].value">
|
||||
<option disabled="disabled">{{ __('admin::app.select-option') }}</option>
|
||||
<optgroup v-for='(state, code) in country_and_states.states' :label="code">
|
||||
<option v-for="(stateObj, index) in state" :value="stateObj.code">@{{ stateObj.default_name }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if='conditions_list[index].attribute == "shipping_country"'>
|
||||
<select class="control" v-model="conditions_list[index].value">
|
||||
<option disabled="disabled">{{ __('admin::app.select-option') }}</option>
|
||||
<option v-for="(country, index) in country_and_states.countries" :value="country.code">@{{ country.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<input class="control" type="text" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value" v-if='conditions_list[index].attribute != "shipping_state" && conditions_list[index].attribute != "shipping_country"'>
|
||||
</div>
|
||||
|
||||
<div v-if='conditions_list[index].type == "numeric"' style="display: flex">
|
||||
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.numeric" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<input class="control" type="number" step="0.1000" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeCartAttr(index)"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">{{ __('admin::app.promotion.add-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.action') }}</label>
|
||||
|
||||
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.apply') }}"" v-on:change="detectApply">
|
||||
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
|
||||
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
|
||||
|
||||
<input type="number" step="0.0001" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_amt') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
|
||||
</div>
|
||||
|
||||
{{-- <div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
|
||||
<label for="disc_threshold" class="required">{{ __('admin::app.promotion.cart.buy-atleast') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="disc_threshold" v-model="disc_threshold" v-validate="'required|numeric|min_value:1'" value="{{ old('disc_threshold') }}" data-vv-as=""{{ __('admin::app.promotion.cart.buy-atleast') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_threshold')">@{{ errors.first('disc_threshold') }}</span>
|
||||
</div> --}}
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
|
||||
<label for="disc_quantity" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="disc_quantity" v-model="disc_quantity" v-validate="'required|decimal|min_value:1'" value="{{ old('disc_quantity') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_qty') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_quantity')">@{{ errors.first('disc_quantity') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="boolean-control-container">
|
||||
<div class="control-group" :class="[errors.has('free_shipping') ? 'has-error' : '']">
|
||||
<label for="free_shipping" class="required">{{ __('admin::app.promotion.general-info.free-shipping') }}</label>
|
||||
|
||||
<select type="text" class="control" name="free_shipping" v-model="free_shipping" v-validate="'required'" value="{{ old('free_shipping') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.free-shipping') }}"">
|
||||
<option value="1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
|
||||
<option value="0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('free_shipping')">@{{ errors.first('free_shipping') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('apply_to_shipping') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.cart.apply-to-shipping') }}</label>
|
||||
|
||||
<select type="text" class="control" name="apply_to_shipping" v-model="apply_to_shipping" v-validate="'required'" value="{{ old('apply_to_shipping') }}" data-vv-as=""{{ __('admin::app.promotion.cart.apply-to-shipping') }}"">
|
||||
<option value="1" :selected="apply_to_shipping == 0">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
|
||||
<option value="0" :selected="apply_to_shipping == 1">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('apply_to_shipping')">@{{ errors.first('apply_to_shipping') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
|
||||
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
|
||||
|
||||
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" value="{{ old('end_other_rules')}}" data-vv-as=""{{ __('admin::app.promotion.general-info.end-other-rules') }}"">
|
||||
<option value="1" :selected="end_other_rules == 1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
<option value="0" :selected="end_other_rules == 0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.coupons') }}" v-if="use_coupon == 1">
|
||||
<div slot="body">
|
||||
|
||||
{{-- <div v-if="!auto_generation">
|
||||
<div class="control-group" :class="[errors.has('prefix') ? 'has-error' : '']">
|
||||
<label for="prefix" class="required">{{ __('admin::app.promotion.general-info.prefix') }}</label>
|
||||
|
||||
<input type="text" class="control" name="prefix" v-model="prefix" v-validate="'alpha'" value="{{ old('prefix') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.prefix') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('prefix')">@{{ errors.first('prefix') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('suffix') ? 'has-error' : '']"">
|
||||
<label for="suffix" class="required">{{ __('admin::app.promotion.general-info.suffix') }}</label>
|
||||
|
||||
<input type="text" class="control" name="suffix" v-model="suffix" v-validate="'alpha'" value="{{ old('suffix') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.suffix') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('suffix')">@{{ errors.first('suffix') }}</span>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div>
|
||||
<div class="control-group" :class="[errors.has('code') ? 'has-error' : '']">
|
||||
<label for="code" class="required">{{ __('admin::app.promotion.general-info.code') }}</label>
|
||||
|
||||
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.code') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.select-products') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_attributes" v-model="all_attributes">
|
||||
|
||||
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
|
||||
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
|
||||
|
||||
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
|
||||
</div>
|
||||
|
||||
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
|
||||
<select class="control" v-model="attribute_values[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
|
||||
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<select class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
|
||||
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
|
||||
<option :disabled="true">
|
||||
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
|
||||
</option>
|
||||
|
||||
<option v-for="(label, index2) in attribute_values[index].options" :value="label.id" :key="index2">@{{ label.admin_name }}</option>
|
||||
</select>
|
||||
|
||||
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
|
||||
</div>
|
||||
|
||||
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
|
||||
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" :title="'{{ __('admin::app.promotion.general-info.labels') }}'">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('label') ? 'has-error' : '']" v-if="dedicated_label">
|
||||
<label for="label">{{ __('admin::app.promotion.general-info.global-label') }}</label>
|
||||
|
||||
<input type="text" class="control" name="label[global]" v-model="label.global" data-vv-as=""{{ __('admin::app.promotion.general-info.label') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('label')">@{{ errors.first('label') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="label.global == null || label.global == ''">
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
@foreach($channel->locales as $locale)
|
||||
<div class="control-group" :class="[errors.has('label') ? 'has-error' : '']">
|
||||
<label for="code">{{ __('admin::app.label') }}<span class="locale">[{{ $channel->code }} - {{ $locale->code }}]</span></label>
|
||||
|
||||
<input type="text" class="control" name="label[{{ $channel->code }}][{{ $locale->code }}]" v-model="label.{{ $channel->code }}.{{ $locale->code }}" data-vv-as=""{{ __('admin::app.promotion.general-info.label') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('label')">@{{ errors.first('label') }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cart-rule', {
|
||||
template: '#cart-rule-form-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
name: null,
|
||||
description: null,
|
||||
conditions_list: [],
|
||||
channels: ['{{ core()->getCurrentChannel()->id }}'],
|
||||
customer_groups: ['{{ app('Webkul\Customer\Repositories\CustomerGroupRepository')->findOneWhere(["code" => "general"])->id }}'],
|
||||
ends_till: null,
|
||||
starts_from: null,
|
||||
priority: 0,
|
||||
per_customer: 0,
|
||||
status: 0,
|
||||
use_coupon: 0,
|
||||
auto_generation: false,
|
||||
usage_limit: 0,
|
||||
|
||||
action_type: null,
|
||||
apply: null,
|
||||
apply_to_shipping: 0,
|
||||
disc_amount: 1,
|
||||
// disc_threshold: null,
|
||||
disc_quantity: 1,
|
||||
end_other_rules: 0,
|
||||
coupon_type: null,
|
||||
free_shipping: 0,
|
||||
|
||||
all_conditions: [],
|
||||
match_criteria: 'all_are_true',
|
||||
|
||||
all_attributes: {
|
||||
'categories' : [],
|
||||
'attributes' : []
|
||||
},
|
||||
|
||||
code: null,
|
||||
suffix: null,
|
||||
prefix: null,
|
||||
dedicated_label: true,
|
||||
|
||||
label: {
|
||||
global: null,
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
@foreach($channel->locales as $locale)
|
||||
{{ trim($channel->code) }} : {
|
||||
{{ trim($locale->code) }}: ''
|
||||
},
|
||||
@endforeach
|
||||
@endforeach
|
||||
},
|
||||
|
||||
criteria: 'cart',
|
||||
conditions: @json($cart_rule[0]).conditions,
|
||||
cart_input: @json($cart_rule[0]).attributes,
|
||||
actions: @json($cart_rule[0]).actions,
|
||||
cart_object: {
|
||||
attribute: [],
|
||||
condition: [],
|
||||
value: []
|
||||
},
|
||||
country_and_states: @json($cart_rule[2]),
|
||||
|
||||
category_options: @json($cart_rule[1]),
|
||||
category_values: [],
|
||||
|
||||
attribute_values: [],
|
||||
attr_object: {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
},
|
||||
attribute_input: @json($cart_rule[3]),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
categoryLabel (option) {
|
||||
return option.name + ' [ ' + option.slug + ' ]';
|
||||
},
|
||||
|
||||
attributeListLabel(option) {
|
||||
return option.label;
|
||||
},
|
||||
|
||||
addCondition () {
|
||||
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
|
||||
this.condition_on = this.criteria;
|
||||
} else {
|
||||
alert('Please select type of condition');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_on == 'cart') {
|
||||
this.conditions_list.push(this.cart_object);
|
||||
|
||||
this.cart_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: []
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
addAttributeCondition() {
|
||||
this.attribute_values.push(this.attr_object);
|
||||
|
||||
this.attr_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
};
|
||||
},
|
||||
|
||||
checkAutogen() {
|
||||
},
|
||||
|
||||
detectApply() {
|
||||
return;
|
||||
},
|
||||
|
||||
enableCondition(event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for (i in this.cart_input) {
|
||||
if (i == selectedIndex) {
|
||||
this.conditions_list[index].type = this.cart_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
enableAttributeCondition (event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for(i in this.attribute_input) {
|
||||
if (i == selectedIndex) {
|
||||
if (this.attribute_input[i].has_options == true) {
|
||||
this.attribute_values[index].options = this.attribute_input[i].options;
|
||||
}
|
||||
|
||||
this.attribute_values[index].type = this.attribute_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// useCoupon() {
|
||||
// if (this.use_coupon == 0) {
|
||||
// this.auto_generation = null;
|
||||
// } else {
|
||||
// this.auto_generation = true;
|
||||
// }
|
||||
// },
|
||||
|
||||
removeCartAttr(index) {
|
||||
this.conditions_list.splice(index, 1);
|
||||
},
|
||||
|
||||
removeAttr(index) {
|
||||
this.attribute_values.splice(index, 1);
|
||||
},
|
||||
|
||||
onSubmit: function (e) {
|
||||
if (this.attribute_values.length != 0 || this.category_values.length != 0) {
|
||||
for (i in this.attribute_values) {
|
||||
delete this.attribute_values[i].options;
|
||||
}
|
||||
|
||||
this.all_attributes.categories = this.category_values;
|
||||
|
||||
this.all_attributes.attributes = this.attribute_values;
|
||||
|
||||
}
|
||||
|
||||
this.all_attributes = JSON.stringify(this.all_attributes);
|
||||
|
||||
if (this.conditions_list != null && this.conditions_list.length != 0) {
|
||||
this.conditions_list.push({'criteria': this.match_criteria});
|
||||
|
||||
this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
|
||||
this.conditions_list.pop();
|
||||
}
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
e.target.submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addFlashMessages() {
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
flashMessages.forEach(function(flash) {
|
||||
flashes.addFlash(flash);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@stop
|
||||
|
|
@ -1,740 +0,0 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.edit-cart-rule') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="content">
|
||||
<cart-rule></cart-rule>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/x-template" id="cart-rule-form-template">
|
||||
<form method="POST" action="{{ route('admin.cart-rule.update', $cart_rule[3]->id) }}" @submit.prevent="onSubmit">
|
||||
@csrf
|
||||
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
|
||||
|
||||
{{ __('admin::app.promotion.edit-cart-rule') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
<div>
|
||||
@csrf()
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_conditions" v-model="all_conditions">
|
||||
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
|
||||
|
||||
<input type="text" class="control" name="name" v-model="name" v-validate="'required'" value="{{ old('name') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.name') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
|
||||
<label for="description">{{ __('admin::app.promotion.general-info.description') }}</label>
|
||||
|
||||
<textarea class="control" name="description" v-model="description" value="{{ old('description') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.description') }}""></textarea>
|
||||
|
||||
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
|
||||
</div>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
|
||||
<label for="starts_from">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as=""{{ __('admin::app.promotion.general-info.starts-from') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
|
||||
<label for="ends_till">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as=""{{ __('admin::app.promotion.general-info.ends-till') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
|
||||
|
||||
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" value="{{ old('customer_groups[]') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.cust-groups') }}"" multiple="multiple">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Customer Group']) }}</option>
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}">{{ $customerGroup->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
|
||||
|
||||
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" value="{{ old('channels[]') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.channels-req') }}"" multiple="multiple">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Channels']) }}</option>
|
||||
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.first('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
|
||||
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
|
||||
|
||||
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.status') }}"">
|
||||
{{-- <option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Status']) }}</option> --}}
|
||||
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotion.no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('use_coupon') ? 'has-error' :
|
||||
'']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.is-coupon') }}</label>
|
||||
|
||||
<select type="text" class="control" name="use_coupon" v-model="use_coupon" v-validate="'required'" value="{{ old('use_coupon')}}" data-vv-as=""{{ __('admin::app.promotion.general-info.is-coupon') }}"" v-on:change="useCoupon">
|
||||
<option value="1" :selected="use_coupon == 1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
<option value="0" :selected="use_coupon == 0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('use_coupon')">@{{ errors.first('use_coupon') }}</span>
|
||||
</div>
|
||||
|
||||
{{-- <div class="control-group" :class="[errors.has('auto_generation') ? 'has-error' : '']" v-if="use_coupon == 1">
|
||||
<label for="auto_generation" class="required">{{ __('admin::app.promotion.general-info.specific-coupon') }}</label>
|
||||
|
||||
<input type="checkbox" class="control" name="auto_generation" v-model="auto_generation" value="{{ old('auto_generation') }}" data-vv-as=""Specific Coupon"" v-on:change="checkAutogen">
|
||||
|
||||
<span class="control-error" v-if="errors.has('auto_generation')">@{{ errors.first('auto_generation') }}</span>
|
||||
</div> --}}
|
||||
|
||||
{{-- <input type="hidden" name="auto_generation" v-model="auto_generation"> --}}
|
||||
|
||||
{{-- <div class="control-group" :class="[errors.has('per_customer') ? 'has-error' : '']">
|
||||
<label for="per_customer" class="required">{{ __('admin::app.promotion.general-info.uses-per-cust') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="per_customer" v-model="per_customer" v-validate="'required|numeric|min_value:0'" value="{{ old('per_customer') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.uses-per-cust') }}"">
|
||||
|
||||
<figcaption class="required">* {{ __('admin::app.promotion.zero-unlimited') }}</figcaption>
|
||||
|
||||
<span class="control-error" v-if="errors.has('per_customer')">@{{ errors.first('per_customer') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
|
||||
<label for="usage_limit" class="required">{{ __('admin::app.promotion.general-info.limit') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="usage_limit" v-model="usage_limit" v-validate="'required|numeric|min_value:0'" value="{{ old('usage_limit') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.uses-per-cust') }}"">
|
||||
|
||||
<figcaption class="required">* {{ __('admin::app.promotion.zero-unlimited') }}</figcaption>
|
||||
|
||||
<span class="control-error" v-if="errors.has('usage_limit')">@{{ errors.first('usage_limit') }}</span>
|
||||
</div> --}}
|
||||
|
||||
<div class="control-group" :class="[errors.has('priority') ? 'has-error' : '']">
|
||||
<label for="priority" class="required">{{ __('admin::app.promotion.general-info.priority') }}</label>
|
||||
|
||||
<input type="number" class="control" step="1" name="priority" v-model="priority" v-validate="'required|numeric|min_value:1'" value="{{ old('priority') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.priority') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('priority')">@{{ errors.first('priority') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_conditions" v-model="all_conditions">
|
||||
|
||||
{{-- <div class="add-condition">
|
||||
<div class="control-group">
|
||||
<label for="criteria" class="required">{{ __('admin::app.promotion.general-info.add-condition') }}</label>
|
||||
|
||||
<select type="text" class="control" v-model="criteria">
|
||||
<option value="cart">Cart Properties</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="control-group">
|
||||
{{ __('admin::app.promotion.general-info.test-mode') }}
|
||||
<select class="control" v-model="match_criteria" style="margin-right: 15px;">
|
||||
{{ $i = 0 }}
|
||||
@foreach(config('pricerules.test_mode') as $key => $value)
|
||||
<option value="{{ $key }}">{{ $value }}</option>
|
||||
{{ $i++ }}
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="condition-set">
|
||||
<!-- Cart Attributes -->
|
||||
<div class="control-container mt-20" v-for="(condition, index) in conditions_list" :key="index">
|
||||
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
<option v-for="(cart_ip, index1) in cart_input" :value="cart_ip.code" :key="index1">@{{ cart_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<div v-if='conditions_list[index].type == "string"' style="display: flex">
|
||||
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-if='conditions_list[index].attribute == "shipping_state"'>
|
||||
<select class="control" v-model="conditions_list[index].value">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'State']) }}</option>
|
||||
<optgroup v-for='(state, code) in country_and_states.states' :label="code">
|
||||
<option v-for="(stateObj, index) in state" :value="stateObj.code">@{{ stateObj.default_name }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if='conditions_list[index].attribute == "shipping_country"'>
|
||||
<select class="control" v-model="conditions_list[index].value">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Country']) }}</option>
|
||||
<option v-for="(country, index) in country_and_states.countries" :value="country.code">@{{ country.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<input class="control" type="text" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="{{ __('admin::app.promotion.enter-attribtue', ['attrbibute' => 'Value']) }}" v-if='conditions_list[index].attribute != "shipping_state" && conditions_list[index].attribute != "shipping_country"'>
|
||||
</div>
|
||||
|
||||
<div v-if='conditions_list[index].type == "numeric"' style="display: flex">
|
||||
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.numeric" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<input class="control" type="number" step="0.1000" name="cart_attributes[]" v-model="conditions_list[index].value">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeCartAttr(index)"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">{{ __('admin::app.promotion.add-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.action') }}</label>
|
||||
|
||||
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as=""Apply As"" v-on:change="detectApply">
|
||||
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
|
||||
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
|
||||
|
||||
<input type="number" step="0.0001" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|decimal|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_amt') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
|
||||
<label for="disc_quantity" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
|
||||
|
||||
<input type="number" step="1" class="control" name="disc_quantity" v-model="disc_quantity" v-validate="'required|decimal|min_value:1'" value="{{ old('disc_quantity') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_qty') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_quantity')">@{{ errors.first('disc_quantity') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="boolean-control-container">
|
||||
<div class="control-group" :class="[errors.has('free_shipping') ? 'has-error' : '']">
|
||||
<label for="free_shipping" class="required">{{ __('admin::app.promotion.general-info.free-shipping') }}</label>
|
||||
|
||||
<select type="text" class="control" name="free_shipping" v-model="free_shipping" v-validate="'required'" value="{{ old('free_shipping') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.free-shipping') }}"">
|
||||
<option value="1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
|
||||
<option value="0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('free_shipping')">@{{ errors.first('free_shipping') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('apply_to_shipping') ? 'has-error' : '']">
|
||||
<label for="apply_to_shipping" class="required">{{ __('admin::app.promotion.cart.apply-to-shipping') }}</label>
|
||||
|
||||
<select type="text" class="control" name="apply_to_shipping" v-model="apply_to_shipping" v-validate="'required'" value="{{ old('apply_to_shipping') }}" data-vv-as=""{{ __('admin::app.promotion.cart.apply-to-shipping') }}"">
|
||||
<option value="1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
|
||||
<option value="0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('apply_to_shipping')">@{{ errors.first('apply_to_shipping') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
|
||||
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
|
||||
|
||||
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" value="{{ old('end_other_rules')}}" data-vv-as=""{{ __('admin::app.promotion.general-info.end-other-rules') }}"">
|
||||
<option value="1" :selected="end_other_rules == 1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
|
||||
<option value="0" :selected="end_other_rules == 0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.coupons') }}" v-if="use_coupon == 1">
|
||||
<div slot="body">
|
||||
{{-- <div v-if="!auto_generation">
|
||||
<div class="control-group" :class="[errors.has('prefix') ? 'has-error' : '']">
|
||||
<label for="prefix" class="required">{{ __('admin::app.promotion.general-info.prefix') }}</label>
|
||||
|
||||
<input type="text" class="control" name="prefix" v-model="prefix" value="{{ old('prefix') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.prefix') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('prefix')">@{{ errors.first('prefix') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('suffix') ? 'has-error' : '']"">
|
||||
<label for="suffix" class="required">{{ __('admin::app.promotion.general-info.suffix') }}</label>
|
||||
|
||||
<input type="text" class="control" name="suffix" v-model="suffix" value="{{ old('suffix') }}" data-vv-as=""suffix"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('suffix')">@{{ errors.first('suffix') }}</span>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
{{-- <div v-if="auto_generation != 0"> --}}
|
||||
<div class="control-group" :class="[errors.has('code') ? 'has-error' : '']">
|
||||
<label for="code" class="required">{{ __('admin::app.promotion.general-info.code') }}</label>
|
||||
|
||||
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.code') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
|
||||
</div>
|
||||
{{-- </div> --}}
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.select-products') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_attributes" v-model="all_attributes">
|
||||
|
||||
<span class="info mb-20" style="display: block;">
|
||||
<b>{{ __('admin::app.promotion.note') }}:</b>
|
||||
|
||||
{{ __('admin::app.promotion.convert-x-note') }}
|
||||
</span>
|
||||
|
||||
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
|
||||
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
|
||||
|
||||
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Categories']) }}" track-by="slug" :multiple="true"></multiselect>
|
||||
</div>
|
||||
|
||||
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
|
||||
<select class="control" v-model="attribute_values[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
|
||||
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<select class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
|
||||
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
|
||||
<option :disabled="true">
|
||||
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
|
||||
</option>
|
||||
|
||||
<option v-for="(label, index2) in attribute_values[index].options" :value="label.id" :key="index2">@{{ label.admin_name }}</option>
|
||||
</select>
|
||||
|
||||
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
|
||||
</div>
|
||||
|
||||
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
|
||||
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" :title="'{{ __('admin::app.promotion.general-info.labels') }}'">
|
||||
<div slot="body">
|
||||
@foreach($cart_rule[3]->labels as $label)
|
||||
<div class="control-group" :class="[errors.has('label') ? 'has-error' : '']">
|
||||
<label for="code">{{ __('admin::app.label') }}
|
||||
<span class="locale">[{{ $label->channel->code }} - {{ $label->locale->code }}]</span>
|
||||
</label>
|
||||
|
||||
<input type="text" class="control" name="label[{{ $label->channel->code }}][{{ $label->locale->code }}]" value="{{ $label->label }}" data-vv-as=""Label"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('label')">@{{ errors.first('label') }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</accordian>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cart-rule', {
|
||||
template: '#cart-rule-form-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
name: '{{ __('admin::app.promotion.rule-name') }}',
|
||||
description: '{{ __('admin::app.promotion.rule-desc') }}',
|
||||
channels: [],
|
||||
customer_groups: [],
|
||||
ends_till: null,
|
||||
starts_from: null,
|
||||
priority: 0,
|
||||
per_customer: 0,
|
||||
status: null,
|
||||
use_coupon: null,
|
||||
// auto_generation: 0,
|
||||
usage_limit: 0,
|
||||
|
||||
action_type: null,
|
||||
apply: null,
|
||||
apply_to_shipping: null,
|
||||
disc_amount: null,
|
||||
disc_quantity: null,
|
||||
end_other_rules: null,
|
||||
coupon_type: null,
|
||||
free_shipping: null,
|
||||
|
||||
all_conditions: null,
|
||||
match_criteria: 'all_are_true',
|
||||
|
||||
all_attributes: {
|
||||
'categories' : null,
|
||||
'attributes' : null
|
||||
},
|
||||
|
||||
code: null,
|
||||
suffix: null,
|
||||
prefix: null,
|
||||
dedicated_label: true,
|
||||
|
||||
global_label: null,
|
||||
labels: [],
|
||||
// label: {
|
||||
// @foreach(core()->getAllChannels() as $channel)
|
||||
// @foreach($channel->locales as $locale)
|
||||
// {{ trim($channel->code) }} : null,
|
||||
// @endforeach
|
||||
// @endforeach
|
||||
// },
|
||||
|
||||
criteria: 'cart',
|
||||
conditions: @json($cart_rule[0]).conditions,
|
||||
cart_input: @json($cart_rule[0]).attributes,
|
||||
actions: @json($cart_rule[0]).actions,
|
||||
conditions_list:[],
|
||||
cart_object: {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: []
|
||||
},
|
||||
country_and_states: @json($cart_rule[2]),
|
||||
|
||||
category_options: @json($cart_rule[1]),
|
||||
|
||||
category_values: [],
|
||||
attribute_values: [],
|
||||
|
||||
attr_object: {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
},
|
||||
attribute_input: @json($cart_rule[4]),
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
data = @json($cart_rule[3]);
|
||||
|
||||
this.name = data.name;
|
||||
|
||||
this.description = data.description;
|
||||
|
||||
this.channels = [];
|
||||
|
||||
for (i in data.channels) {
|
||||
this.channels.push(data.channels[i].channel_id);
|
||||
}
|
||||
|
||||
this.customer_groups = data.customer_groups;
|
||||
|
||||
for (i in data.customer_groups) {
|
||||
this.customer_groups.push(data.customer_groups[i].customer_group_id);
|
||||
}
|
||||
|
||||
this.ends_till = data.ends_till;
|
||||
|
||||
this.starts_from = data.starts_from;
|
||||
|
||||
this.priority = data.priority;
|
||||
|
||||
this.per_customer = data.per_customer;
|
||||
|
||||
this.status = data.status;
|
||||
|
||||
if (data.use_coupon == 0) {
|
||||
// this.auto_generation = null;
|
||||
this.use_coupon = 0;
|
||||
} else {
|
||||
this.use_coupon = 1;
|
||||
// this.auto_generation = data.auto_generation;
|
||||
this.code = data.coupons.code;
|
||||
// this.suffix = data.coupons.suffix;
|
||||
// this.prefix = data.coupons.prefix;
|
||||
|
||||
// if (data.auto_generation == 0)
|
||||
// this.auto_generation = true;
|
||||
// else
|
||||
// this.auto_generation = false;
|
||||
}
|
||||
|
||||
this.usage_limit = data.usage_limit;
|
||||
|
||||
this.is_guest = data.is_guest;
|
||||
|
||||
this.action_type = data.action_type;
|
||||
|
||||
this.apply = null;
|
||||
|
||||
this.apply_to_shipping = data.apply_to_shipping;
|
||||
|
||||
this.disc_amount = data.disc_amount;
|
||||
|
||||
// this.disc_threshold = data.disc_threshold;
|
||||
|
||||
this.disc_quantity = data.disc_quantity;
|
||||
|
||||
this.end_other_rules = data.end_other_rules;
|
||||
|
||||
this.coupon_type = data.coupon_type;
|
||||
|
||||
this.free_shipping = data.free_shipping;
|
||||
|
||||
this.all_conditions = null;
|
||||
|
||||
if (data.hasOwnProperty('conditions') && data.conditions != null) {
|
||||
this.conditions_list = JSON.parse(JSON.parse(data.conditions));
|
||||
|
||||
this.match_criteria = this.conditions_list.pop().criteria;
|
||||
}
|
||||
|
||||
hasSubSelectionConditions = JSON.parse(data.actions).hasOwnProperty('attribute_conditions');
|
||||
|
||||
if (hasSubSelectionConditions) {
|
||||
|
||||
if (JSON.parse(data.actions).attribute_conditions.hasOwnProperty('categories')) {
|
||||
this.category_values = JSON.parse(data.actions).attribute_conditions.categories;
|
||||
} else {
|
||||
this.category_values = [];
|
||||
}
|
||||
|
||||
if (JSON.parse(data.actions).attribute_conditions.hasOwnProperty('attributes')) {
|
||||
this.attribute_values = JSON.parse(data.actions).attribute_conditions.attributes;
|
||||
} else {
|
||||
this.attribute_values = [];
|
||||
}
|
||||
|
||||
// creating options and has option param on the frontend
|
||||
for (i in this.attribute_values) {
|
||||
for (j in this.attribute_input) {
|
||||
if (this.attribute_input[j].code == this.attribute_values[i].attribute) {
|
||||
if (this.attribute_input[j].has_options == true) {
|
||||
this.attribute_values[i].has_options = true;
|
||||
|
||||
this.attribute_values[i].options = this.attribute_input[j].options;
|
||||
} else {
|
||||
this.attribute_values[i].has_options = false;
|
||||
|
||||
this.attribute_values[i].options = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
criteria = null;
|
||||
},
|
||||
|
||||
methods: {
|
||||
categoryLabel (option) {
|
||||
return option.name + ' [ ' + option.slug + ' ]';
|
||||
},
|
||||
|
||||
attributeListLabel(option) {
|
||||
return option.label;
|
||||
},
|
||||
|
||||
addCondition () {
|
||||
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
|
||||
this.condition_on = this.criteria;
|
||||
} else {
|
||||
alert('please select type of condition');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_on == 'cart') {
|
||||
this.conditions_list.push(this.cart_object);
|
||||
|
||||
this.cart_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: []
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
addAttributeCondition() {
|
||||
this.attribute_values.push(this.attr_object);
|
||||
|
||||
this.attr_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
};
|
||||
},
|
||||
|
||||
checkAutogen() {
|
||||
},
|
||||
|
||||
detectApply() {
|
||||
return;
|
||||
},
|
||||
|
||||
enableCondition(event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for (i in this.cart_input) {
|
||||
if (i == selectedIndex) {
|
||||
this.conditions_list[index].type = this.cart_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
enableAttributeCondition (event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for(i in this.attribute_input) {
|
||||
if (i == selectedIndex) {
|
||||
if (this.attribute_input[i].has_options == true) {
|
||||
this.attribute_values[index].options = this.attribute_input[i].options;
|
||||
}
|
||||
|
||||
this.attribute_values[index].type = this.attribute_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
useCoupon() {
|
||||
if (this.use_coupon == 0) {
|
||||
this.auto_generation = null;
|
||||
} else {
|
||||
this.auto_generation = true;
|
||||
}
|
||||
},
|
||||
|
||||
removeCartAttr(index) {
|
||||
this.conditions_list.splice(index, 1);
|
||||
},
|
||||
|
||||
removeCat(index) {
|
||||
this.cats.splice(index, 1);
|
||||
},
|
||||
|
||||
removeAttr(index) {
|
||||
this.attribute_values.splice(index, 1);
|
||||
},
|
||||
|
||||
onSubmit: function (e) {
|
||||
if (this.attribute_values.length != 0 || this.category_values.length != 0) {
|
||||
for (i in this.attribute_values) {
|
||||
delete this.attribute_values[i].options;
|
||||
}
|
||||
|
||||
this.all_attributes.categories = this.category_values;
|
||||
|
||||
this.all_attributes.attributes = this.attribute_values;
|
||||
|
||||
this.all_attributes = JSON.stringify(this.all_attributes);
|
||||
} else {
|
||||
this.all_attributes = null;
|
||||
}
|
||||
|
||||
if (this.conditions_list.length != 0) {
|
||||
this.conditions_list.push({'criteria': this.match_criteria});
|
||||
|
||||
this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
|
||||
this.conditions_list.pop();
|
||||
}
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
e.target.submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addFlashMessages() {
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
flashMessages.forEach(function(flash) {
|
||||
flashes.addFlash(flash);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@stop
|
||||
|
|
@ -0,0 +1,614 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotions.cart-rules.add-title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
|
||||
<cart-rule></cart-rule>
|
||||
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="cart-rule-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.cart-rules.store') }}" @submit.prevent="onSubmit">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" @click="redirectBack('{{ url('/admin/dashboard') }}')"></i>
|
||||
|
||||
{{ __('admin::app.promotions.cart-rules.add-title') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.cart-rules.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.cart-rules.create.before') !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.rule-information') }}'" :active="true">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotions.cart-rules.name') }}</label>
|
||||
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as=""{{ __('admin::app.promotions.cart-rules.name') }}"" value="{{ old('name') }}"/>
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="description">{{ __('admin::app.promotions.cart-rules.description') }}</label>
|
||||
<textarea class="control" id="description" name="description">{{ old('description') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="status">{{ __('admin::app.promotions.cart-rules.status') }}</label>
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="status" name="status" value="1">
|
||||
<label class="checkbox-view" for="status"></label>
|
||||
{{ __('admin::app.promotions.cart-rules.is-active') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotions.cart-rules.channels') }}</label>
|
||||
|
||||
<select class="control" id="channels" name="channels[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.channels') }}"" multiple="multiple">
|
||||
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
<option value="{{ $channel->id }}" {{ old('channels') && in_array($channel->id, old('channels')) ? 'selected' : '' }}>
|
||||
{{ $channel->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotions.cart-rules.customer-groups') }}</label>
|
||||
|
||||
<select class="control" id="customer_groups" name="customer_groups[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.customer-groups') }}"" multiple="multiple">
|
||||
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}" {{ old('customer_groups') && in_array($customerGroup->id, old('customer_groups')) ? 'selected' : '' }}>
|
||||
{{ $customerGroup->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('coupon_type') ? 'has-error' : '']">
|
||||
<label for="coupon_type" class="required">{{ __('admin::app.promotions.cart-rules.coupon-type') }}</label>
|
||||
|
||||
<select class="control" id="coupon_type" name="coupon_type" v-model="coupon_type" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.coupon-type') }}"">
|
||||
<option value="0" {{ old('coupon_type') == 0 ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.no-coupon') }}</option>
|
||||
<option value="1" {{ old('coupon_type') == 1 ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.specific-coupon') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('coupon_type')">@{{ errors.first('coupon_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="parseInt(coupon_type)">
|
||||
<div class="control-group" :class="[errors.has('use_auto_generation') ? 'has-error' : '']">
|
||||
<label for="use_auto_generation" class="required">{{ __('admin::app.promotions.cart-rules.auto-generate-coupon') }}</label>
|
||||
|
||||
<select class="control" id="use_auto_generation" name="use_auto_generation" v-model="use_auto_generation" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.auto-generate-coupon') }}"">
|
||||
<option value="0">{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('use_auto_generation')">@{{ errors.first('use_auto_generation') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="! parseInt(use_auto_generation)">
|
||||
<div class="control-group" :class="[errors.has('coupon_code') ? 'has-error' : '']">
|
||||
<label for="coupon_code" class="required">{{ __('admin::app.promotions.cart-rules.coupon-code') }}</label>
|
||||
<input v-validate="'required'" class="control" id="coupon_code" name="coupon_code" data-vv-as=""{{ __('admin::app.promotions.cart-rules.coupon-code') }}"" value="{{ old('coupon_code') }}"/>
|
||||
<span class="control-error" v-if="errors.has('coupon_code')">@{{ errors.first('coupon_code') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="uses_per_coupon">{{ __('admin::app.promotions.cart-rules.uses-per-coupon') }}</label>
|
||||
<input class="control" id="uses_per_coupon" name="uses_per_coupon" value="{{ old('uses_per_coupon') }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="usage_per_customer">{{ __('admin::app.promotions.cart-rules.uses-per-customer') }}</label>
|
||||
<input class="control" id="usage_per_customer" name="usage_per_customer" value="{{ old('usage_per_customer') }}"/>
|
||||
<span class="control-info">{{ __('admin::app.promotions.cart-rules.uses-per-customer-control-info') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="starts_from">{{ __('admin::app.promotions.cart-rules.from') }}</label>
|
||||
<date>
|
||||
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="ends_till">{{ __('admin::app.promotions.cart-rules.to') }}</label>
|
||||
<date>
|
||||
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="sort_order">{{ __('admin::app.promotions.cart-rules.priority') }}</label>
|
||||
<input type="text" class="control" id="sort_order" name="sort_order" value="{{ old('sort_order') ?? 0 }}"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.conditions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group">
|
||||
<label for="condition_type">{{ __('admin::app.promotions.cart-rules.condition-type') }}</label>
|
||||
|
||||
<select class="control" id="condition_type" name="condition_type" v-model="condition_type">
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.all-conditions-true') }}</option>
|
||||
<option value="2">{{ __('admin::app.promotions.cart-rules.any-condition-true') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="table cart-rule-conditions" style="margin-top: 20px; overflow-x: unset;">
|
||||
<table>
|
||||
<tbody>
|
||||
<cart-rule-condition-item
|
||||
v-for='(condition, index) in conditions'
|
||||
:condition="condition"
|
||||
:key="index"
|
||||
:index="index"
|
||||
@onRemoveCondition="removeCondition($event)">
|
||||
</cart-rule-condition-item>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-lg btn-primary" style="margin-top: 20px;" @click="addCondition">
|
||||
{{ __('admin::app.promotions.cart-rules.add-condition') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.actions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotions.cart-rules.action-type') }}</label>
|
||||
|
||||
<select class="control" id="action_type" name="action_type" v-validate="'required'" v-model="action_type" data-vv-as=""{{ __('admin::app.promotions.cart-rules.action-type') }}"">
|
||||
<option value="by_percent" {{ old('action_type') == 'by_percent' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.percentage-product-price') }}
|
||||
</option>
|
||||
<option value="by_fixed" {{ old('action_type') == 'by_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.fixed-amount') }}
|
||||
</option>
|
||||
<option value="cart_fixed" {{ old('action_type') == 'cart_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.fixed-amount-whole-cart') }}
|
||||
</option>
|
||||
<option value="buy_x_get_y" {{ old('action_type') == 'buy_x_get_y' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.buy-x-get-y-free') }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('discount_amount') ? 'has-error' : '']">
|
||||
<label for="discount_amount" class="required">{{ __('admin::app.promotions.cart-rules.discount-amount') }}</label>
|
||||
<input v-validate="'required'" class="control" id="discount_amount" name="discount_amount" data-vv-as=""{{ __('admin::app.promotions.cart-rules.discount-amount') }}"" value="{{ old('discount_amount') ?? 0 }}"/>
|
||||
<span class="control-error" v-if="errors.has('discount_amount')">@{{ errors.first('discount_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="discount_quantity">{{ __('admin::app.promotions.cart-rules.discount-quantity') }}</label>
|
||||
<input class="control" id="discount_quantity" name="discount_quantity" value="{{ old('discount_quantity') ?? 0 }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="discount_step">{{ __('admin::app.promotions.cart-rules.discount-step') }}</label>
|
||||
<input class="control" id="discount_step" name="discount_step" value="{{ old('discount_step') ?? 0 }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="apply_to_shipping">{{ __('admin::app.promotions.cart-rules.apply-to-shipping') }}</label>
|
||||
|
||||
<select class="control" id="apply_to_shipping" name="apply_to_shipping" :disabled="action_type == 'cart_fixed'">
|
||||
<option value="0" {{ ! old('apply_to_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
<option value="1" {{ old('apply_to_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="free_shipping">{{ __('admin::app.promotions.cart-rules.free-shipping') }}</label>
|
||||
|
||||
<select class="control" id="free_shipping" name="free_shipping">
|
||||
<option value="0" {{ ! old('free_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
<option value="1" {{ old('free_shipping') ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="end_other_rules">{{ __('admin::app.promotions.cart-rules.end-other-rules') }}</label>
|
||||
|
||||
<select class="control" id="end_other_rules" name="end_other_rules">
|
||||
<option value="0" {{ ! old('end_other_rules') ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ old('end_other_rules') ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.cart-rules.create.after') !!}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="cart-rule-condition-item-template">
|
||||
<tr>
|
||||
<td class="attribute">
|
||||
<div class="control-group">
|
||||
<select :name="['conditions[' + index + '][attribute]']" class="control" v-model="condition.attribute">
|
||||
<option value="">{{ __('admin::app.promotions.cart-rules.choose-condition-to-add') }}</option>
|
||||
<optgroup v-for='(conditionAttribute, index) in condition_attributes' :label="conditionAttribute.label">
|
||||
<option v-for='(childAttribute, index) in conditionAttribute.children' :value="childAttribute.key">
|
||||
@{{ childAttribute.label }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="operator">
|
||||
<div class="control-group" v-if="matchedAttribute">
|
||||
<select :name="['conditions[' + index + '][operator]']" class="control" v-model="condition.operator">
|
||||
<option v-for='operator in condition_operators[matchedAttribute.type]' :value="operator.operator">
|
||||
@{{ operator.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="value">
|
||||
<div v-if="matchedAttribute">
|
||||
<input type="hidden" :name="['conditions[' + index + '][attribute_type]']" v-model="matchedAttribute.type">
|
||||
|
||||
<div v-if="matchedAttribute.key == 'product|category_ids' || matchedAttribute.key == 'product|category_ids' || matchedAttribute.key == 'product|parent::category_ids'">
|
||||
<tree-view value-field="id" id-field="id" :name-field="'conditions[' + index + '][value]'" input-type="checkbox" :items='matchedAttribute.options' :behavior="'no'"></tree-view>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'text' || matchedAttribute.type == 'price' || matchedAttribute.type == 'decimal' || matchedAttribute.type == 'integer'">
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'date'">
|
||||
<date>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'datetime'">
|
||||
<datetime>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</datetime>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'boolean'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value">
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'select' || matchedAttribute.type == 'radio'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-if="matchedAttribute.key != 'cart|state'">
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-else>
|
||||
<optgroup v-for='option in matchedAttribute.options' :label="option.admin_name">
|
||||
<option v-for='state in option.states' :value="state.code">
|
||||
@{{ state.admin_name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'multiselect' || matchedAttribute.type == 'checkbox'">
|
||||
<select :name="['conditions[' + index + '][value][]']" class="control" v-model="condition.value" multiple>
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="actions">
|
||||
<i class="icon trash-icon" @click="removeCondition"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cart-rule', {
|
||||
|
||||
template: '#cart-rule-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
coupon_type: 0,
|
||||
|
||||
use_auto_generation: 0,
|
||||
|
||||
condition_type: 1,
|
||||
|
||||
conditions: [],
|
||||
|
||||
action_type: "{{ old('action_type') ?: 'by_percent' }}"
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addCondition: function() {
|
||||
this.conditions.push({
|
||||
'attribute': '',
|
||||
'operator': '==',
|
||||
'value': '',
|
||||
});
|
||||
},
|
||||
|
||||
removeCondition: function(condition) {
|
||||
let index = this.conditions.indexOf(condition)
|
||||
|
||||
this.conditions.splice(index, 1)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
redirectBack: function(fallbackUrl) {
|
||||
this.$root.redirectBack(fallbackUrl)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('cart-rule-condition-item', {
|
||||
|
||||
template: '#cart-rule-condition-item-template',
|
||||
|
||||
props: ['index', 'condition'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_attributes: @json(app('\Webkul\CartRule\Repositories\CartRuleRepository')->getConditionAttributes()),
|
||||
|
||||
attribute_type_indexes: {
|
||||
'cart': 0,
|
||||
|
||||
'cart_item': 1,
|
||||
|
||||
'product': 2
|
||||
},
|
||||
|
||||
condition_operators: {
|
||||
'price': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'decimal': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'integer': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'text': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contain') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}],
|
||||
'boolean': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'date': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'datetime': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'select': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'radio': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'multiselect': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}],
|
||||
'checkbox': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
matchedAttribute: function () {
|
||||
if (this.condition.attribute == '')
|
||||
return;
|
||||
|
||||
var this_this = this;
|
||||
|
||||
var attributeIndex = this.attribute_type_indexes[this.condition.attribute.split("|")[0]];
|
||||
|
||||
matchedAttribute = this.condition_attributes[attributeIndex]['children'].filter(function (attribute) {
|
||||
return attribute.key == this_this.condition.attribute;
|
||||
});
|
||||
|
||||
if (matchedAttribute[0]['type'] == 'multiselect' || matchedAttribute[0]['type'] == 'checkbox') {
|
||||
this.condition.operator = '{}';
|
||||
|
||||
this.condition.value = [];
|
||||
}
|
||||
|
||||
return matchedAttribute[0];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeCondition: function() {
|
||||
this.$emit('onRemoveCondition', this.condition)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,753 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotions.cart-rules.edit-title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
|
||||
<cart-rule></cart-rule>
|
||||
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="cart-rule-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.cart-rules.update', $cartRule->id) }}" @submit.prevent="onSubmit">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" @click="redirectBack('{{ url('/admin/dashboard') }}')"></i>
|
||||
|
||||
{{ __('admin::app.promotions.cart-rules.edit-title') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.cart-rules.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.cart-rules.create.before') !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.rule-information') }}'" :active="true">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotions.cart-rules.name') }}</label>
|
||||
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as=""{{ __('admin::app.promotions.cart-rules.name') }}"" value="{{ old('name') ?: $cartRule->name }}"/>
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="description">{{ __('admin::app.promotions.cart-rules.description') }}</label>
|
||||
<textarea class="control" id="description" name="description">{{ old('description') ?: $cartRule->description }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="status">{{ __('admin::app.promotions.cart-rules.status') }}</label>
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="status" name="status" value="{{ $cartRule->status }}" {{ $cartRule->status ? 'checked' : '' }}>
|
||||
<label class="checkbox-view" for="status"></label>
|
||||
{{ __('admin::app.promotions.cart-rules.is-active') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotions.cart-rules.channels') }}</label>
|
||||
|
||||
<?php $selectedOptionIds = old('channels') ?: $cartRule->channels->pluck('id')->toArray() ?>
|
||||
|
||||
<select class="control" id="channels" name="channels[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.channels') }}"" multiple="multiple">
|
||||
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
<option value="{{ $channel->id }}" {{ in_array($channel->id, $selectedOptionIds) ? 'selected' : '' }}>
|
||||
{{ $channel->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotions.cart-rules.customer-groups') }}</label>
|
||||
|
||||
<?php $selectedOptionIds = old('customer_groups') ?: $cartRule->customer_groups->pluck('id')->toArray() ?>
|
||||
|
||||
<select class="control" id="customer_groups" name="customer_groups[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.customer-groups') }}"" multiple="multiple">
|
||||
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}" {{ in_array($customerGroup->id, $selectedOptionIds) ? 'selected' : '' }}>
|
||||
{{ $customerGroup->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('coupon_type') ? 'has-error' : '']">
|
||||
<label for="coupon_type" class="required">{{ __('admin::app.promotions.cart-rules.coupon-type') }}</label>
|
||||
|
||||
<select class="control" id="coupon_type" name="coupon_type" v-model="coupon_type" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.coupon-type') }}"">
|
||||
<option value="0" {{ old('coupon_type') == 0 ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.no-coupon') }}</option>
|
||||
<option value="1" {{ old('coupon_type') == 1 ? 'selected' : '' }}>{{ __('admin::app.promotions.cart-rules.specific-coupon') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('coupon_type')">@{{ errors.first('coupon_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="parseInt(coupon_type)">
|
||||
<div class="control-group" :class="[errors.has('use_auto_generation') ? 'has-error' : '']">
|
||||
<label for="use_auto_generation" class="required">{{ __('admin::app.promotions.cart-rules.auto-generate-coupon') }}</label>
|
||||
|
||||
<select class="control" id="use_auto_generation" name="use_auto_generation" v-model="use_auto_generation" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.auto-generate-coupon') }}"">
|
||||
<option value="0">{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('use_auto_generation')">@{{ errors.first('use_auto_generation') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="! parseInt(use_auto_generation)">
|
||||
<div class="control-group" :class="[errors.has('coupon_code') ? 'has-error' : '']">
|
||||
<label for="coupon_code" class="required">{{ __('admin::app.promotions.cart-rules.coupon-code') }}</label>
|
||||
<input v-validate="'required'" class="control" id="coupon_code" name="coupon_code" data-vv-as=""{{ __('admin::app.promotions.cart-rules.coupon-code') }}"" value="{{ old('coupon_code') ?: $cartRule->coupon_code }}"/>
|
||||
<span class="control-error" v-if="errors.has('coupon_code')">@{{ errors.first('coupon_code') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="uses_per_coupon">{{ __('admin::app.promotions.cart-rules.uses-per-coupon') }}</label>
|
||||
<input class="control" id="uses_per_coupon" name="uses_per_coupon" value="{{ old('uses_per_coupon') ?: $cartRule->uses_per_coupon }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="usage_per_customer">{{ __('admin::app.promotions.cart-rules.uses-per-customer') }}</label>
|
||||
<input class="control" id="usage_per_customer" name="usage_per_customer" value="{{ old('usage_per_customer') ?: $cartRule->usage_per_customer }}"/>
|
||||
<span class="control-info">{{ __('admin::app.promotions.cart-rules.uses-per-customer-control-info') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="starts_from">{{ __('admin::app.promotions.cart-rules.from') }}</label>
|
||||
<date>
|
||||
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') ?: $cartRule->starts_from }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="ends_till">{{ __('admin::app.promotions.cart-rules.to') }}</label>
|
||||
<date>
|
||||
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') ?: $cartRule->ends_till }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="sort_order">{{ __('admin::app.promotions.cart-rules.priority') }}</label>
|
||||
<input type="text" class="control" id="sort_order" name="sort_order" value="{{ $cartRule->sort_order }}" {{ $cartRule->sort_order ? 'checked' : '' }}/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.conditions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group">
|
||||
<label for="condition_type">{{ __('admin::app.promotions.cart-rules.condition-type') }}</label>
|
||||
|
||||
<select class="control" id="condition_type" name="condition_type" v-model="condition_type">
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.all-conditions-true') }}</option>
|
||||
<option value="2">{{ __('admin::app.promotions.cart-rules.any-condition-true') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="table cart-rule-conditions" style="margin-top: 20px; overflow-x: unset;">
|
||||
<table>
|
||||
<tbody>
|
||||
<cart-rule-condition-item
|
||||
v-for='(condition, index) in conditions'
|
||||
:condition="condition"
|
||||
:key="index"
|
||||
:index="index"
|
||||
@onRemoveCondition="removeCondition($event)">
|
||||
</cart-rule-condition-item>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-lg btn-primary" style="margin-top: 20px;" @click="addCondition">
|
||||
{{ __('admin::app.promotions.cart-rules.add-condition') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.actions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotions.cart-rules.action-type') }}</label>
|
||||
|
||||
<?php $selectedOption = old('action_type') ?: $cartRule->action_type ?>
|
||||
|
||||
<select class="control" id="action_type" name="action_type" v-validate="'required'" v-model="action_type" data-vv-as=""{{ __('admin::app.promotions.cart-rules.action-type') }}"">
|
||||
<option value="by_percent" {{ $selectedOption == 'by_percent' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.percentage-product-price') }}
|
||||
</option>
|
||||
<option value="by_fixed" {{ $selectedOption == 'by_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.fixed-amount') }}
|
||||
</option>
|
||||
<option value="cart_fixed" {{ $selectedOption == 'cart_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.fixed-amount-whole-cart') }}
|
||||
</option>
|
||||
<option value="buy_x_get_y" {{ $selectedOption == 'buy_x_get_y' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.buy-x-get-y-free') }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('discount_amount') ? 'has-error' : '']">
|
||||
<label for="discount_amount" class="required">{{ __('admin::app.promotions.cart-rules.discount-amount') }}</label>
|
||||
|
||||
<input v-validate="'required'" class="control" id="discount_amount" name="discount_amount" data-vv-as=""{{ __('admin::app.promotions.cart-rules.discount-amount') }}"" value="{{ old('discount_amount') ?: $cartRule->discount_amount }}"/>
|
||||
|
||||
<span class="control-error" v-if="errors.has('discount_amount')">@{{ errors.first('discount_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="discount_quantity">{{ __('admin::app.promotions.cart-rules.discount-quantity') }}</label>
|
||||
<input class="control" id="discount_quantity" name="discount_quantity" value="{{ old('discount_quantity') ?: $cartRule->discount_quantity }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="discount_step">{{ __('admin::app.promotions.cart-rules.discount-step') }}</label>
|
||||
<input class="control" id="discount_step" name="discount_step" value="{{ old('discount_step') ?: $cartRule->discount_step }}"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="apply_to_shipping">{{ __('admin::app.promotions.cart-rules.apply-to-shipping') }}</label>
|
||||
|
||||
<?php $selectedOption = old('apply_to_shipping') ?: $cartRule->apply_to_shipping ?>
|
||||
|
||||
<select class="control" id="apply_to_shipping" name="apply_to_shipping" :disabled="action_type == 'cart_fixed'">
|
||||
<option value="0" {{ ! $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="free_shipping">{{ __('admin::app.promotions.cart-rules.free-shipping') }}</label>
|
||||
|
||||
<?php $selectedOption = old('free_shipping') ?: $cartRule->free_shipping ?>
|
||||
|
||||
<select class="control" id="free_shipping" name="free_shipping">
|
||||
<option value="0" {{ ! $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="end_other_rules">{{ __('admin::app.promotions.cart-rules.end-other-rules') }}</label>
|
||||
|
||||
<?php $selectedOption = old('end_other_rules') ?: $cartRule->end_other_rules ?>
|
||||
|
||||
<select class="control" id="end_other_rules" name="end_other_rules">
|
||||
<option value="0" {{ ! $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.cart-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.cart-rules.create.after') !!}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.cart-rules.coupon-codes') }}'" :active="false" v-if="coupon_type && use_auto_generation">
|
||||
<div slot="body">
|
||||
|
||||
<create-coupon-form></create-coupon-form>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="cart-rule-condition-item-template">
|
||||
<tr>
|
||||
<td class="attribute">
|
||||
<div class="control-group">
|
||||
<select :name="['conditions[' + index + '][attribute]']" class="control" v-model="condition.attribute">
|
||||
<option value="">{{ __('admin::app.promotions.cart-rules.choose-condition-to-add') }}</option>
|
||||
<optgroup v-for='conditionAttribute in condition_attributes' :label="conditionAttribute.label">
|
||||
<option v-for='childAttribute in conditionAttribute.children' :value="childAttribute.key">
|
||||
@{{ childAttribute.label }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="operator">
|
||||
<div class="control-group" v-if="matchedAttribute">
|
||||
<select :name="['conditions[' + index + '][operator]']" class="control" v-model="condition.operator">
|
||||
<option v-for='operator in condition_operators[matchedAttribute.type]' :value="operator.operator">
|
||||
@{{ operator.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="value">
|
||||
<div v-if="matchedAttribute">
|
||||
<input type="hidden" :name="['conditions[' + index + '][attribute_type]']" v-model="matchedAttribute.type">
|
||||
|
||||
<div v-if="matchedAttribute.key == 'product|children::category_ids' || matchedAttribute.key == 'product|category_ids' || matchedAttribute.key == 'product|parent::category_ids'">
|
||||
<tree-view value-field="id" id-field="id" :name-field="'conditions[' + index + '][value]'" input-type="checkbox" :items='matchedAttribute.options' :value='condition.value' :behavior="'no'"></tree-view>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'text' || matchedAttribute.type == 'price' || matchedAttribute.type == 'decimal' || matchedAttribute.type == 'integer'">
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'date'">
|
||||
<date>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'datetime'">
|
||||
<datetime>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</datetime>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'boolean'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value">
|
||||
<option value="1">{{ __('admin::app.promotions.cart-rules.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotions.cart-rules.no') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'select' || matchedAttribute.type == 'radio'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-if="matchedAttribute.key != 'cart|state'">
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-else>
|
||||
<optgroup v-for='option in matchedAttribute.options' :label="option.admin_name">
|
||||
<option v-for='state in option.states' :value="state.code">
|
||||
@{{ state.admin_name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'multiselect' || matchedAttribute.type == 'checkbox'">
|
||||
<select :name="['conditions[' + index + '][value][]']" class="control" v-model="condition.value" multiple>
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="actions">
|
||||
<i class="icon trash-icon" @click="removeCondition"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="create-coupon-form-template">
|
||||
<div class="">
|
||||
<form method="POST" data-vv-scope="create-coupun-form" @submit.prevent="generateCopuns('create-coupun-form')">
|
||||
|
||||
<div class="control-group" :class="[errors.has('create-coupun-form.coupon_qty') ? 'has-error' : '']">
|
||||
<label for="coupon_qty" class="required">{{ __('admin::app.promotions.cart-rules.coupon-qty') }}</label>
|
||||
|
||||
<input v-validate="'required|min_value:1'" class="control" id="coupon_qty" name="coupon_qty" v-model="coupon_format.coupon_qty" data-vv-as=""{{ __('admin::app.promotions.cart-rules.coupon-qty') }}""/>
|
||||
|
||||
<span class="control-error" v-if="errors.has('create-coupun-form.coupon_qty')">
|
||||
@{{ errors.first('create-coupun-form.coupon_qty') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('create-coupun-form.code_length') ? 'has-error' : '']">
|
||||
<label for="code_length" class="required">{{ __('admin::app.promotions.cart-rules.code-length') }}</label>
|
||||
|
||||
<input v-validate="'required|min_value:10'" class="control" id="code_length" name="code_length" v-model="coupon_format.code_length" data-vv-as=""{{ __('admin::app.promotions.cart-rules.code-length') }}""/>
|
||||
|
||||
<span class="control-error" v-if="errors.has('create-coupun-form.code_length')">
|
||||
@{{ errors.first('create-coupun-form.code_length') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('create-coupun-form.code_format') ? 'has-error' : '']">
|
||||
<label for="code_format" class="required">{{ __('admin::app.promotions.cart-rules.code-format') }}</label>
|
||||
|
||||
<select class="control" id="code_format" name="code_format" v-model="coupon_format.code_format" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.cart-rules.code-format') }}"">
|
||||
<option value="alphanumeric">{{ __('admin::app.promotions.cart-rules.alphanumeric') }}</option>
|
||||
<option value="alphabetical">{{ __('admin::app.promotions.cart-rules.alphabetical') }}</option>
|
||||
<option value="numeric">{{ __('admin::app.promotions.cart-rules.numeric') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('create-coupun-form.code_format')">
|
||||
@{{ errors.first('create-coupun-form.code_format') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="code_prefix">{{ __('admin::app.promotions.cart-rules.code-prefix') }}</label>
|
||||
<input class="control" id="code_prefix" name="code_prefix" v-model="coupon_format.code_prefix"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="code_suffix">{{ __('admin::app.promotions.cart-rules.code-suffix') }}</label>
|
||||
<input class="control" id="code_suffix" name="code_suffix" v-model="coupon_format.code_suffix"/>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="btn btn-xl btn-primary">{{ __('admin::app.promotions.cart-rules.generate') }}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@inject('cartRuleCouponGrid','Webkul\Admin\DataGrids\CartRuleCouponDataGrid')
|
||||
|
||||
{!! $cartRuleCouponGrid->render() !!}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cart-rule', {
|
||||
|
||||
template: '#cart-rule-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
coupon_type: {{ old('coupon_type') ?: $cartRule->coupon_type }},
|
||||
|
||||
use_auto_generation: {{ old('use_auto_generation') ?: $cartRule->use_auto_generation }},
|
||||
|
||||
condition_type: {{ old('condition_type') ?: $cartRule->condition_type }},
|
||||
|
||||
conditions: @json($cartRule->conditions ?: []),
|
||||
|
||||
action_type: "{{ old('action_type') ?: $cartRule->action_type }}"
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addCondition: function() {
|
||||
this.conditions.push({
|
||||
'attribute': '',
|
||||
'operator': '==',
|
||||
'value': '',
|
||||
});
|
||||
},
|
||||
|
||||
removeCondition: function(condition) {
|
||||
let index = this.conditions.indexOf(condition)
|
||||
|
||||
this.conditions.splice(index, 1)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
redirectBack: function(fallbackUrl) {
|
||||
this.$root.redirectBack(fallbackUrl)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('cart-rule-condition-item', {
|
||||
|
||||
template: '#cart-rule-condition-item-template',
|
||||
|
||||
props: ['index', 'condition'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_attributes: @json(app('\Webkul\CartRule\Repositories\CartRuleRepository')->getConditionAttributes()),
|
||||
|
||||
attribute_type_indexes: {
|
||||
'cart': 0,
|
||||
|
||||
'cart_item': 1,
|
||||
|
||||
'product': 2
|
||||
},
|
||||
|
||||
condition_operators: {
|
||||
'price': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'decimal': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'integer': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'text': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contain') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}],
|
||||
'boolean': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'date': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'datetime': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.less-than') }}'
|
||||
}],
|
||||
'select': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'radio': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'multiselect': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}],
|
||||
'checkbox': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.cart-rules.does-not-contain') }}'
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
matchedAttribute: function () {
|
||||
if (this.condition.attribute == '')
|
||||
return;
|
||||
|
||||
var this_this = this;
|
||||
|
||||
var attributeIndex = this.attribute_type_indexes[this.condition.attribute.split("|")[0]];
|
||||
|
||||
matchedAttribute = this.condition_attributes[attributeIndex]['children'].filter(function (attribute) {
|
||||
return attribute.key == this_this.condition.attribute;
|
||||
});
|
||||
|
||||
if (matchedAttribute[0]['type'] == 'multiselect' || matchedAttribute[0]['type'] == 'checkbox') {
|
||||
this.condition.operator = '{}';
|
||||
|
||||
this.condition.value = this.condition.value == '' && this.condition.value != undefined ? [] : this.condition.value;
|
||||
}
|
||||
|
||||
return matchedAttribute[0];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeCondition: function() {
|
||||
this.$emit('onRemoveCondition', this.condition)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('create-coupon-form', {
|
||||
|
||||
template: '#create-coupon-form-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
coupon_format: {
|
||||
coupon_qty: '',
|
||||
|
||||
code_length: 12,
|
||||
|
||||
code_format: 'alphanumeric',
|
||||
|
||||
code_prefix: '',
|
||||
|
||||
code_suffix: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
generateCopuns: function(formScope) {
|
||||
var this_this = this;
|
||||
|
||||
this.$validator.validateAll(formScope).then(function (result) {
|
||||
if (result) {
|
||||
this_this.$http.post("{{ route('admin.cart-rules.generate-coupons', $cartRule->id) }}", this_this.coupon_format)
|
||||
.then(function(response) {
|
||||
window.flashMessages = [{
|
||||
'type': 'alert-success',
|
||||
'message': response.data.message
|
||||
}];
|
||||
|
||||
this_this.$root.addFlashMessages()
|
||||
})
|
||||
.catch(function (error) {
|
||||
window.flashMessages = [{
|
||||
'type': 'alert-error',
|
||||
'message': error.response.data.message
|
||||
}];
|
||||
|
||||
this_this.$root.addFlashMessages()
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.cart-rule') }}
|
||||
{{ __('admin::app.promotions.cart-rules.title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
|
@ -9,12 +9,12 @@
|
|||
<div class="content">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>{{ __('admin::app.promotion.cart-rule') }}</h1>
|
||||
<h1>{{ __('admin::app.promotions.cart-rules.title') }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<a href="{{ route('admin.cart-rule.create') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.add-cart-rule') }}
|
||||
<a href="{{ route('admin.cart-rules.create') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.cart-rules.add-title') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,415 +0,0 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.add-catalog-rule') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
<catalog-rule></catalog-rule>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/x-template" id="catalog-rule-form-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.catalog-rule.store') }}" @submit.prevent="onSubmit">
|
||||
@csrf
|
||||
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
|
||||
|
||||
{{ __('admin::app.promotion.add-catalog-rule') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
|
||||
|
||||
<input type="text" class="control" name="name" v-model="name" v-validate="'required'" value="{{ old('name') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.name') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
|
||||
<label for="description" class="required">{{ __('admin::app.promotion.general-info.description') }}</label>
|
||||
|
||||
<textarea class="control" name="description" v-model="description" v-validate="'required'" value="{{ old('description') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.description') }}""></textarea>
|
||||
|
||||
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
|
||||
|
||||
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.cust-groups') }}"" multiple="multiple">
|
||||
<option disabled="disabled">Select Customer Groups</option>
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
|
||||
|
||||
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.channels') }}"" multiple="multiple">
|
||||
<option disabled="disabled">Select Channels</option>
|
||||
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
|
||||
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
|
||||
|
||||
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.status') }}"">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotion.no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
|
||||
<label for="starts_from">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as=""{{ __('admin::app.promotion.general-info.starts-from') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
|
||||
<datetime :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
|
||||
<label for="ends_till">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as=""{{ __('admin::app.promotion.general-info.ends-till') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
|
||||
</div>
|
||||
</datetime>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_conditions" v-model="all_conditions">
|
||||
|
||||
<!-- Categories selection input block -->
|
||||
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
|
||||
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
|
||||
|
||||
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
|
||||
</div>
|
||||
|
||||
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Product attributes conditions block -->
|
||||
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
|
||||
<select class="control" v-model="attribute_values[index].attribute" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
|
||||
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<select v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.select" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<select v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
|
||||
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
|
||||
<option :disabled="true">
|
||||
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
|
||||
</option>
|
||||
|
||||
<option v-for="(label, index2) in attribute_values[index].options" :value="index2" :key="index2">@{{ label.admin_name }}</option>
|
||||
</select>
|
||||
|
||||
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
|
||||
</div>
|
||||
|
||||
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
|
||||
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
|
||||
|
||||
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.apply') }}"" v-on:change="detectApply">
|
||||
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
|
||||
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
|
||||
|
||||
<input type="number" step="0.5000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_amt') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
|
||||
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
|
||||
|
||||
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.end-other-rules') }}"">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotion.no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('catalog-rule', {
|
||||
template: '#catalog-rule-form-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
name: null,
|
||||
description: null,
|
||||
conditions_list: [],
|
||||
channels: [],
|
||||
customer_groups: [],
|
||||
ends_till: null,
|
||||
starts_from: null,
|
||||
per_customer: 0,
|
||||
status: 1,
|
||||
|
||||
action_type: null,
|
||||
apply: null,
|
||||
apply_amt: false,
|
||||
disc_amount: null,
|
||||
end_other_rules: 0,
|
||||
|
||||
all_conditions: [],
|
||||
|
||||
all_attributes: {
|
||||
'categories' : [],
|
||||
'attributes' : []
|
||||
},
|
||||
|
||||
criteria: 'cart',
|
||||
actions: @json($catalog_rule[0]).actions,
|
||||
|
||||
category_options: @json($catalog_rule[1]),
|
||||
category_values: [],
|
||||
conditions: @json($catalog_rule[0]).conditions,
|
||||
attribute_values: [],
|
||||
attr_object: {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
},
|
||||
attribute_input: @json($catalog_rule[3])
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
|
||||
methods: {
|
||||
categoryLabel (option) {
|
||||
return option.name + ' [ ' + option.slug + ' ]';
|
||||
},
|
||||
|
||||
attributeListLabel(option) {
|
||||
return option.label;
|
||||
},
|
||||
|
||||
addCondition () {
|
||||
if (this.criteria == 'attribute' || this.criteria == 'attribute_family' || this.criteria == 'category') {
|
||||
this.condition_on = this.criteria;
|
||||
} else {
|
||||
alert('please try again');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_on == 'attribute') {
|
||||
this.conditions_list.push(this.attr_object);
|
||||
|
||||
this.attr_object = {
|
||||
criteria: this.condition_on,
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: null,
|
||||
type: null,
|
||||
options: null
|
||||
};
|
||||
} else if (this.condition_on == 'category') {
|
||||
this.conditions_list.push(this.cat_object);
|
||||
|
||||
this.cat_object = {
|
||||
criteria: this.condition_on,
|
||||
category: 'category',
|
||||
condition: null,
|
||||
value: []
|
||||
};
|
||||
} else if (this.condition_on == 'attribute_family') {
|
||||
this.conditions_list.push(this.fam_object);
|
||||
|
||||
this.fam_object = {
|
||||
criteria: this.condition_on,
|
||||
family: 'attribute_family',
|
||||
condition: null,
|
||||
value: null
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
addAttributeCondition() {
|
||||
this.attribute_values.push(this.attr_object);
|
||||
|
||||
this.attr_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
};
|
||||
},
|
||||
|
||||
enableCondition(event, index) {
|
||||
this.conditions_list[index].type = this.attrs_input[event.target.selectedIndex - 1].type;
|
||||
var this_this = this;
|
||||
|
||||
if (this.attrs_input[event.target.selectedIndex - 1].type == 'select' || this.attrs_input[event.target.selectedIndex - 1].type == 'multiselect') {
|
||||
|
||||
this.conditions_list[index].options = this.attrs_options[this.attrs_input[event.target.selectedIndex - 1].code];
|
||||
this.conditions_list[index].value = [];
|
||||
}
|
||||
},
|
||||
|
||||
enableAttributeCondition (event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for(i in this.attribute_input) {
|
||||
if (i == selectedIndex) {
|
||||
if (this.attribute_input[i].has_options == true) {
|
||||
this.selectedIndex
|
||||
this.attribute_values[index].options = this.attribute_input[i].options;
|
||||
}
|
||||
|
||||
this.attribute_values[index].type = this.attribute_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
detectApply() {
|
||||
if (this.apply == 0 || this.apply == 2) {
|
||||
this.apply_prct = true;
|
||||
this.apply_amt = false;
|
||||
} else if (this.apply == 1 || this.apply == 3) {
|
||||
this.apply_prct = false;
|
||||
this.apply_amt = true;
|
||||
}
|
||||
},
|
||||
|
||||
removeAttr(index) {
|
||||
this.attribute_values.splice(index, 1);
|
||||
},
|
||||
|
||||
removeCat(index) {
|
||||
this.cats.splice(index, 1);
|
||||
},
|
||||
|
||||
onSubmit: function (e) {
|
||||
if (this.attribute_values.length > 0 || this.category_values.length > 0) {
|
||||
for (i in this.attribute_values) {
|
||||
delete this.attribute_values[i].options;
|
||||
}
|
||||
|
||||
if (this.category_values.length > 0) {
|
||||
this.all_attributes.categories = this.category_values;
|
||||
}
|
||||
|
||||
if (this.attribute_values.length > 0) {
|
||||
this.all_attributes.attributes = this.attribute_values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.all_conditions = JSON.stringify(this.all_attributes);
|
||||
|
||||
// this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
|
||||
// if (this.conditions_list.length != 0) {
|
||||
// this.conditions_list.push({'criteria': this.match_criteria});
|
||||
|
||||
// this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
e.target.submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
genericGroupCondition() {
|
||||
this.generic_condition = false;
|
||||
},
|
||||
|
||||
addFlashMessages() {
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
flashMessages.forEach(function(flash) {
|
||||
flashes.addFlash(flash);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@stop
|
||||
|
|
@ -1,414 +0,0 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.edit-catalog-rule') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
<catalog-rule></catalog-rule>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/x-template" id="catalog-rule-form-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.catalog-rule.update', $catalog_rule[5]->id) }}" @submit.prevent="onSubmit">
|
||||
@csrf
|
||||
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
|
||||
|
||||
{{ __('admin::app.promotion.edit-catalog-rule') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.edit-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
|
||||
|
||||
<input type="text" class="control" name="name" v-model="name" v-validate="'required'" value="{{ old('name') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.name') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
|
||||
<label for="description" class="required">{{ __('admin::app.promotion.general-info.description') }}</label>
|
||||
|
||||
<textarea class="control" name="description" v-model="description" v-validate="'required'" value="{{ old('description') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.description') }}""></textarea>
|
||||
|
||||
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
|
||||
|
||||
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.cust-groups') }}"" multiple="multiple">
|
||||
<option disabled="disabled">Select Customer Groups</option>
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
|
||||
|
||||
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.channels') }}"" multiple="multiple">
|
||||
<option disabled="disabled">Select Channels</option>
|
||||
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
|
||||
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
|
||||
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
|
||||
|
||||
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.status') }}"">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotion.no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$now = new \Carbon\Carbon();
|
||||
@endphp
|
||||
|
||||
<date :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
|
||||
<label for="starts_from">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as=""{{ __('admin::app.promotion.general-info.starts-from') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
|
||||
</div>
|
||||
</date>
|
||||
|
||||
<date :name="starts_from">
|
||||
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
|
||||
<label for="ends_till">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
|
||||
|
||||
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as=""{{ __('admin::app.promotion.general-info.ends-till') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
|
||||
</div>
|
||||
</date>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
|
||||
<div slot="body">
|
||||
<input type="hidden" name="all_conditions" v-model="all_conditions">
|
||||
|
||||
<!-- Categories selection input block -->
|
||||
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
|
||||
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
|
||||
|
||||
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
|
||||
</div>
|
||||
|
||||
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<!-- Product attributes conditions block -->
|
||||
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
|
||||
<select class="control" v-model="attribute_values[index].attribute" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
|
||||
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
|
||||
</select>
|
||||
|
||||
<select v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.select" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<select v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
|
||||
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
|
||||
</select>
|
||||
|
||||
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
|
||||
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
|
||||
<option :disabled="true">
|
||||
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
|
||||
</option>
|
||||
|
||||
<option v-for="(label, index2) in attribute_values[index].options" :value="index2" :key="index2">@{{ label.admin_name }}</option>
|
||||
</select>
|
||||
|
||||
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
|
||||
</div>
|
||||
|
||||
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
|
||||
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
|
||||
</div>
|
||||
|
||||
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
|
||||
<div slot="body">
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
|
||||
|
||||
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.apply') }}"" v-on:change="detectApply">
|
||||
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
|
||||
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
|
||||
|
||||
<input type="number" step="0.5000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as=""{{ __('admin::app.promotion.general-info.disc_amt') }}"">
|
||||
|
||||
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
|
||||
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
|
||||
|
||||
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotion.general-info.end-other-rules') }}"">
|
||||
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
|
||||
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotion.no') }}</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('catalog-rule', {
|
||||
template: '#catalog-rule-form-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
name: '{{ $catalog_rule[5]->name }}',
|
||||
description: '{{ $catalog_rule[5]->description }}',
|
||||
conditions_list: [],
|
||||
channels: [],
|
||||
customer_groups: [],
|
||||
ends_till: '{{ $catalog_rule[5]->ends_till }}',
|
||||
starts_from: '{{ $catalog_rule[5]->starts_from }}',
|
||||
status: '{{ $catalog_rule[5]->status }}',
|
||||
|
||||
actions: @json($catalog_rule[3]).actions,
|
||||
action_type: '{{ $catalog_rule[5]->action_code }}',
|
||||
disc_amount: null,
|
||||
end_other_rules: '{{ $catalog_rule[5]->end_other_rules }}',
|
||||
|
||||
all_conditions: [],
|
||||
|
||||
all_attributes: {
|
||||
'categories' : [],
|
||||
'attributes' : []
|
||||
},
|
||||
|
||||
criteria: 'cart',
|
||||
|
||||
category_options: @json($catalog_rule[1]),
|
||||
category_values: [],
|
||||
conditions: @json($catalog_rule[3]).conditions,
|
||||
attribute_values: [],
|
||||
attr_object: {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
},
|
||||
attribute_input: @json($catalog_rule[0])
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
catalog_rule = @json($catalog_rule[5]);
|
||||
channels = @json($catalog_rule[5]->channels);
|
||||
|
||||
this.channels = [];
|
||||
for (i in channels) {
|
||||
this.channels.push(channels[i].channel_id);
|
||||
}
|
||||
|
||||
customer_groups = @json($catalog_rule[5]->customer_groups);
|
||||
|
||||
for (i in customer_groups) {
|
||||
this.customer_groups.push(customer_groups[i].customer_group_id);
|
||||
}
|
||||
|
||||
data = @json($catalog_rule[5]->conditions);
|
||||
|
||||
if (JSON.parse(JSON.parse(data))) {
|
||||
this.category_values = JSON.parse(JSON.parse(data)).categories;
|
||||
|
||||
this.attribute_values = JSON.parse(JSON.parse(data)).attributes;
|
||||
|
||||
// creating options and has option param on the frontend
|
||||
for (i in this.attribute_values) {
|
||||
for (j in this.attribute_input) {
|
||||
if (this.attribute_input[j].code == this.attribute_values[i].attribute) {
|
||||
if (this.attribute_input[j].has_options == true) {
|
||||
this.attribute_values[i].has_options = true;
|
||||
|
||||
this.attribute_values[i].options = this.attribute_input[j].options;
|
||||
} else {
|
||||
this.attribute_values[i].has_options = false;
|
||||
|
||||
this.attribute_values[i].options = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.action_type = '{{ $catalog_rule[5]->action_code }}';
|
||||
this.disc_amount = catalog_rule.discount_amount;
|
||||
this.end_other_rules = '{{ $catalog_rule[5]->end_other_rules }}';
|
||||
},
|
||||
|
||||
methods: {
|
||||
created() {
|
||||
VeeValidate.Validator.extend('is_time', {
|
||||
getMessage: field => `The format must be HH:MM:SS`,
|
||||
validate: (value) => new Promise(resolve => {
|
||||
let regex = new RegExp("([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])");
|
||||
resolve({
|
||||
valid: value && regex.test(value)
|
||||
});
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
categoryLabel (option) {
|
||||
return option.name + ' [ ' + option.slug + ' ]';
|
||||
},
|
||||
|
||||
attributeListLabel(option) {
|
||||
return option.label;
|
||||
},
|
||||
|
||||
addAttributeCondition() {
|
||||
this.attribute_values.push(this.attr_object);
|
||||
|
||||
this.attr_object = {
|
||||
attribute: null,
|
||||
condition: null,
|
||||
value: [],
|
||||
options: []
|
||||
};
|
||||
},
|
||||
|
||||
enableAttributeCondition (event, index) {
|
||||
selectedIndex = event.target.selectedIndex - 1;
|
||||
|
||||
for(i in this.attribute_input) {
|
||||
if (i == selectedIndex) {
|
||||
if (this.attribute_input[i].has_options == true) {
|
||||
this.attribute_values[index].options = this.attribute_input[i].options;
|
||||
}
|
||||
|
||||
this.attribute_values[index].type = this.attribute_input[i].type;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
detectApply() {
|
||||
if (this.apply == 0 || this.apply == 2) {
|
||||
this.apply_prct = true;
|
||||
this.apply_amt = false;
|
||||
} else if (this.apply == 1 || this.apply == 3) {
|
||||
this.apply_prct = false;
|
||||
this.apply_amt = true;
|
||||
}
|
||||
},
|
||||
|
||||
removeAttr(index) {
|
||||
this.attribute_values.splice(index, 1);
|
||||
},
|
||||
|
||||
removeCat(index) {
|
||||
this.cats.splice(index, 1);
|
||||
},
|
||||
|
||||
onSubmit: function (e) {
|
||||
if (this.attribute_values.length > 0 || this.category_values.length > 0) {
|
||||
for (i in this.attribute_values) {
|
||||
delete this.attribute_values[i].options;
|
||||
}
|
||||
|
||||
if (this.category_values.length > 0) {
|
||||
this.all_attributes.categories = this.category_values;
|
||||
}
|
||||
|
||||
this.all_attributes.attributes = this.attribute_values;
|
||||
}
|
||||
|
||||
this.all_conditions = JSON.stringify(this.all_attributes);
|
||||
|
||||
// this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
|
||||
// if (this.conditions_list.length != 0) {
|
||||
// this.conditions_list.push({'criteria': this.match_criteria});
|
||||
|
||||
// this.all_conditions = JSON.stringify(this.conditions_list);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
|
||||
this.$validator.validateAll().then(result => {
|
||||
if (result) {
|
||||
e.target.submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
genericGroupCondition() {
|
||||
this.generic_condition = false;
|
||||
},
|
||||
|
||||
addFlashMessages() {
|
||||
const flashes = this.$refs.flashes;
|
||||
|
||||
flashMessages.forEach(function(flash) {
|
||||
flashes.addFlash(flash);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@stop
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotion.catalog-rule') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="content">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>{{ __('admin::app.promotion.catalog-rule') }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<a href="{{ route('admin.catalog-rule.create') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.add-catalog-rule') }}
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.catalog-rule.apply') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.apply') }}
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.catalog-rule.declut') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotion.declut') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
@inject('catalogRuleGrid','Webkul\Admin\DataGrids\CatalogRuleDataGrid')
|
||||
{!! $catalogRuleGrid->render() !!}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,528 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotions.catalog-rules.add-title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
|
||||
<catalog-rule></catalog-rule>
|
||||
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="catalog-rule-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.catalog-rules.store') }}" @submit.prevent="onSubmit">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" @click="redirectBack('{{ url('/admin/dashboard') }}')"></i>
|
||||
|
||||
{{ __('admin::app.promotions.catalog-rules.add-title') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.catalog-rules.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.catalog-rules.create.before') !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.rule-information') }}'" :active="true">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotions.catalog-rules.name') }}</label>
|
||||
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.name') }}"" value="{{ old('name') }}"/>
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="description">{{ __('admin::app.promotions.catalog-rules.description') }}</label>
|
||||
<textarea class="control" id="description" name="description">{{ old('description') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="status">{{ __('admin::app.promotions.catalog-rules.status') }}</label>
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="status" name="status" value="1">
|
||||
<label class="checkbox-view" for="status"></label>
|
||||
{{ __('admin::app.promotions.catalog-rules.is-active') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotions.catalog-rules.channels') }}</label>
|
||||
|
||||
<select class="control" id="channels" name="channels[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.channels') }}"" multiple="multiple">
|
||||
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
<option value="{{ $channel->id }}" {{ old('channels') && in_array($channel->id, old('channels')) ? 'selected' : '' }}>
|
||||
{{ $channel->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotions.catalog-rules.customer-groups') }}</label>
|
||||
|
||||
<select class="control" id="customer_groups" name="customer_groups[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.customer-groups') }}"" multiple="multiple">
|
||||
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}" {{ old('customer_groups') && in_array($customerGroup->id, old('customer_groups')) ? 'selected' : '' }}>
|
||||
{{ $customerGroup->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="starts_from">{{ __('admin::app.promotions.catalog-rules.from') }}</label>
|
||||
<date>
|
||||
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="ends_till">{{ __('admin::app.promotions.catalog-rules.to') }}</label>
|
||||
<date>
|
||||
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="sort_order">{{ __('admin::app.promotions.catalog-rules.priority') }}</label>
|
||||
<input type="text" class="control" id="sort_order" name="sort_order" value="{{ old('sort_order') ?? 0 }}"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.conditions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group">
|
||||
<label for="condition_type">{{ __('admin::app.promotions.catalog-rules.condition-type') }}</label>
|
||||
|
||||
<select class="control" id="condition_type" name="condition_type" v-model="condition_type">
|
||||
<option value="1">{{ __('admin::app.promotions.catalog-rules.all-conditions-true') }}</option>
|
||||
<option value="2">{{ __('admin::app.promotions.catalog-rules.any-condition-true') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="table catalog-rule-conditions" style="margin-top: 20px; overflow-x: unset;">
|
||||
<table>
|
||||
<tbody>
|
||||
<catalog-rule-condition-item
|
||||
v-for='(condition, index) in conditions'
|
||||
:condition="condition"
|
||||
:key="index"
|
||||
:index="index"
|
||||
@onRemoveCondition="removeCondition($event)">
|
||||
</catalog-rule-condition-item>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-lg btn-primary" style="margin-top: 20px;" @click="addCondition">
|
||||
{{ __('admin::app.promotions.catalog-rules.add-condition') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.actions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotions.catalog-rules.action-type') }}</label>
|
||||
|
||||
<select class="control" id="action_type" name="action_type" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.action-type') }}"">
|
||||
<option value="by_percent" {{ old('action_type') == 'by_percent' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.percentage-product-price') }}
|
||||
</option>
|
||||
<option value="by_fixed" {{ old('action_type') == 'by_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.fixed-amount') }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('discount_amount') ? 'has-error' : '']">
|
||||
<label for="discount_amount" class="required">{{ __('admin::app.promotions.catalog-rules.discount-amount') }}</label>
|
||||
<input v-validate="'required'" class="control" id="discount_amount" name="discount_amount" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.discount-amount') }}"" value="{{ old('discount_amount') ?? 0 }}"/>
|
||||
<span class="control-error" v-if="errors.has('discount_amount')">@{{ errors.first('discount_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="end_other_rules">{{ __('admin::app.promotions.catalog-rules.end-other-rules') }}</label>
|
||||
|
||||
<select class="control" id="end_other_rules" name="end_other_rules">
|
||||
<option value="0" {{ ! old('end_other_rules') ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ old('end_other_rules') ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.catalog-rules.create.after') !!}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="catalog-rule-condition-item-template">
|
||||
<tr>
|
||||
<td class="attribute">
|
||||
<div class="control-group">
|
||||
<select :name="['conditions[' + index + '][attribute]']" class="control" v-model="condition.attribute">
|
||||
<option value="">{{ __('admin::app.promotions.catalog-rules.choose-condition-to-add') }}</option>
|
||||
<optgroup v-for='(conditionAttribute, index) in condition_attributes' :label="conditionAttribute.label">
|
||||
<option v-for='(childAttribute, index) in conditionAttribute.children' :value="childAttribute.key">
|
||||
@{{ childAttribute.label }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="operator">
|
||||
<div class="control-group" v-if="matchedAttribute">
|
||||
<select :name="['conditions[' + index + '][operator]']" class="control" v-model="condition.operator">
|
||||
<option v-for='operator in condition_operators[matchedAttribute.type]' :value="operator.operator">
|
||||
@{{ operator.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="value">
|
||||
<div v-if="matchedAttribute">
|
||||
<input type="hidden" :name="['conditions[' + index + '][attribute_type]']" v-model="matchedAttribute.type">
|
||||
|
||||
<div v-if="matchedAttribute.key == 'product|category_ids'">
|
||||
<tree-view value-field="id" id-field="id" :name-field="'conditions[' + index + '][value]'" input-type="checkbox" :items='matchedAttribute.options' :behavior="'no'"></tree-view>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'text' || matchedAttribute.type == 'price' || matchedAttribute.type == 'decimal' || matchedAttribute.type == 'integer'">
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'date'">
|
||||
<date>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'datetime'">
|
||||
<datetime>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</datetime>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'boolean'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value">
|
||||
<option value="1">{{ __('admin::app.promotions.catalog-rules.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotions.catalog-rules.no') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'select' || matchedAttribute.type == 'radio'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-if="matchedAttribute.key != 'catalog|state'">
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-else>
|
||||
<optgroup v-for='option in matchedAttribute.options' :label="option.admin_name">
|
||||
<option v-for='state in option.states' :value="state.code">
|
||||
@{{ state.admin_name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'multiselect' || matchedAttribute.type == 'checkbox'">
|
||||
<select :name="['conditions[' + index + '][value][]']" class="control" v-model="condition.value" multiple>
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="actions">
|
||||
<i class="icon trash-icon" @click="removeCondition"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('catalog-rule', {
|
||||
|
||||
template: '#catalog-rule-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_type: 1,
|
||||
|
||||
conditions: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addCondition: function() {
|
||||
this.conditions.push({
|
||||
'attribute': '',
|
||||
'operator': '==',
|
||||
'value': '',
|
||||
});
|
||||
},
|
||||
|
||||
removeCondition: function(condition) {
|
||||
let index = this.conditions.indexOf(condition)
|
||||
|
||||
this.conditions.splice(index, 1)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
redirectBack: function(fallbackUrl) {
|
||||
this.$root.redirectBack(fallbackUrl)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('catalog-rule-condition-item', {
|
||||
|
||||
template: '#catalog-rule-condition-item-template',
|
||||
|
||||
props: ['index', 'condition'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_attributes: @json(app('\Webkul\CatalogRule\Repositories\CatalogRuleRepository')->getConditionAttributes()),
|
||||
|
||||
attribute_type_indexes: {
|
||||
'product': 0
|
||||
},
|
||||
|
||||
condition_operators: {
|
||||
'price': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'decimal': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'integer': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'text': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contain') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}],
|
||||
'boolean': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'date': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'datetime': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'select': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'radio': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'multiselect': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}],
|
||||
'checkbox': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
matchedAttribute: function () {
|
||||
if (this.condition.attribute == '')
|
||||
return;
|
||||
|
||||
var this_this = this;
|
||||
|
||||
var attributeIndex = this.attribute_type_indexes[this.condition.attribute.split("|")[0]];
|
||||
|
||||
matchedAttribute = this.condition_attributes[attributeIndex]['children'].filter(function (attribute) {
|
||||
return attribute.key == this_this.condition.attribute;
|
||||
});
|
||||
|
||||
if (matchedAttribute[0]['type'] == 'multiselect' || matchedAttribute[0]['type'] == 'checkbox') {
|
||||
this.condition.operator = '{}';
|
||||
|
||||
this.condition.value = [];
|
||||
}
|
||||
|
||||
return matchedAttribute[0];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeCondition: function() {
|
||||
this.$emit('onRemoveCondition', this.condition)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,533 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotions.catalog-rules.edit-title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="content">
|
||||
|
||||
<catalog-rule></catalog-rule>
|
||||
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="catalog-rule-template">
|
||||
<div>
|
||||
<form method="POST" action="{{ route('admin.catalog-rules.update', $catalogRule->id) }}" @submit.prevent="onSubmit">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>
|
||||
<i class="icon angle-left-icon back-link" @click="redirectBack('{{ url('/admin/dashboard') }}')"></i>
|
||||
|
||||
{{ __('admin::app.promotions.catalog-rules.edit-title') }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<button type="submit" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.catalog-rules.save-btn-title') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="form-container">
|
||||
@csrf()
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.catalog-rules.create.before') !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.rule-information') }}'" :active="true">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
|
||||
<label for="name" class="required">{{ __('admin::app.promotions.catalog-rules.name') }}</label>
|
||||
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.name') }}"" value="{{ old('name') ?: $catalogRule->name }}"/>
|
||||
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="description">{{ __('admin::app.promotions.catalog-rules.description') }}</label>
|
||||
<textarea class="control" id="description" name="description">{{ old('description') ?: $catalogRule->description }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="status">{{ __('admin::app.promotions.catalog-rules.status') }}</label>
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="status" name="status" value="{{ $catalogRule->status }}" {{ $catalogRule->status ? 'checked' : '' }}>
|
||||
<label class="checkbox-view" for="status"></label>
|
||||
{{ __('admin::app.promotions.catalog-rules.is-active') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
|
||||
<label for="channels" class="required">{{ __('admin::app.promotions.catalog-rules.channels') }}</label>
|
||||
|
||||
<?php $selectedOptionIds = old('channels') ?: $catalogRule->channels->pluck('id')->toArray() ?>
|
||||
|
||||
<select class="control" id="channels" name="channels[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.channels') }}"" multiple="multiple">
|
||||
|
||||
@foreach(core()->getAllChannels() as $channel)
|
||||
<option value="{{ $channel->id }}" {{ in_array($channel->id, $selectedOptionIds) ? 'selected' : '' }}>
|
||||
{{ $channel->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('customer_groups[]') ? 'has-error' : '']">
|
||||
<label for="customer_groups" class="required">{{ __('admin::app.promotions.catalog-rules.customer-groups') }}</label>
|
||||
|
||||
<?php $selectedOptionIds = old('customer_groups') ?: $catalogRule->customer_groups->pluck('id')->toArray() ?>
|
||||
|
||||
<select class="control" id="customer_groups" name="customer_groups[]" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.customer-groups') }}"" multiple="multiple">
|
||||
|
||||
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}" {{ in_array($customerGroup->id, $selectedOptionIds) ? 'selected' : '' }}>
|
||||
{{ $customerGroup->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('customer_groups[]')">@{{ errors.first('customer_groups[]') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="starts_from">{{ __('admin::app.promotions.catalog-rules.from') }}</label>
|
||||
<date>
|
||||
<input type="text" name="starts_from" class="control" value="{{ old('starts_from') ?: $catalogRule->starts_from }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date">
|
||||
<label for="ends_till">{{ __('admin::app.promotions.catalog-rules.to') }}</label>
|
||||
<date>
|
||||
<input type="text" name="ends_till" class="control" value="{{ old('ends_till') ?: $catalogRule->ends_till }}"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="sort_order">{{ __('admin::app.promotions.catalog-rules.priority') }}</label>
|
||||
<input type="text" class="control" id="sort_order" name="sort_order" value="{{ $catalogRule->sort_order }}" {{ $catalogRule->status ? 'checked' : '' }}/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.conditions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group">
|
||||
<label for="condition_type">{{ __('admin::app.promotions.catalog-rules.condition-type') }}</label>
|
||||
|
||||
<select class="control" id="condition_type" name="condition_type" v-model="condition_type">
|
||||
<option value="1">{{ __('admin::app.promotions.catalog-rules.all-conditions-true') }}</option>
|
||||
<option value="2">{{ __('admin::app.promotions.catalog-rules.any-condition-true') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="table catalog-rule-conditions" style="margin-top: 20px; overflow-x: unset;">
|
||||
<table>
|
||||
<tbody>
|
||||
<catalog-rule-condition-item
|
||||
v-for='(condition, index) in conditions'
|
||||
:condition="condition"
|
||||
:key="index"
|
||||
:index="index"
|
||||
@onRemoveCondition="removeCondition($event)">
|
||||
</catalog-rule-condition-item>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-lg btn-primary" style="margin-top: 20px;" @click="addCondition">
|
||||
{{ __('admin::app.promotions.catalog-rules.add-condition') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
<accordian :title="'{{ __('admin::app.promotions.catalog-rules.actions') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
|
||||
<label for="action_type" class="required">{{ __('admin::app.promotions.catalog-rules.action-type') }}</label>
|
||||
|
||||
<?php $selectedOption = old('action_type') ?: $catalogRule->action_type ?>
|
||||
|
||||
<select class="control" id="action_type" name="action_type" v-validate="'required'" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.action-type') }}"">
|
||||
<option value="by_percent" {{ $selectedOption == 'by_percent' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.percentage-product-price') }}
|
||||
</option>
|
||||
<option value="by_fixed" {{ $selectedOption == 'by_fixed' ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.fixed-amount') }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('discount_amount') ? 'has-error' : '']">
|
||||
<label for="discount_amount" class="required">{{ __('admin::app.promotions.catalog-rules.discount-amount') }}</label>
|
||||
|
||||
<input v-validate="'required'" class="control" id="discount_amount" name="discount_amount" data-vv-as=""{{ __('admin::app.promotions.catalog-rules.discount-amount') }}"" value="{{ old('discount_amount') ?: $catalogRule->discount_amount }}"/>
|
||||
|
||||
<span class="control-error" v-if="errors.has('discount_amount')">@{{ errors.first('discount_amount') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="end_other_rules">{{ __('admin::app.promotions.catalog-rules.end-other-rules') }}</label>
|
||||
|
||||
<?php $selectedOption = old('end_other_rules') ?: $catalogRule->end_other_rules ?>
|
||||
|
||||
<select class="control" id="end_other_rules" name="end_other_rules">
|
||||
<option value="0" {{ ! $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.no') }}
|
||||
</option>
|
||||
|
||||
<option value="1" {{ $selectedOption ? 'selected' : '' }}>
|
||||
{{ __('admin::app.promotions.catalog-rules.yes') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
{!! view_render_event('bagisto.admin.promotions.catalog-rules.create.after') !!}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="catalog-rule-condition-item-template">
|
||||
<tr>
|
||||
<td class="attribute">
|
||||
<div class="control-group">
|
||||
<select :name="['conditions[' + index + '][attribute]']" class="control" v-model="condition.attribute">
|
||||
<option value="">{{ __('admin::app.promotions.catalog-rules.choose-condition-to-add') }}</option>
|
||||
<optgroup v-for='(conditionAttribute, index) in condition_attributes' :label="conditionAttribute.label">
|
||||
<option v-for='(childAttribute, index) in conditionAttribute.children' :value="childAttribute.key">
|
||||
@{{ childAttribute.label }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="operator">
|
||||
<div class="control-group" v-if="matchedAttribute">
|
||||
<select :name="['conditions[' + index + '][operator]']" class="control" v-model="condition.operator">
|
||||
<option v-for='operator in condition_operators[matchedAttribute.type]' :value="operator.operator">
|
||||
@{{ operator.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="value">
|
||||
<div v-if="matchedAttribute">
|
||||
<input type="hidden" :name="['conditions[' + index + '][attribute_type]']" v-model="matchedAttribute.type">
|
||||
|
||||
<div v-if="matchedAttribute.key == 'product|category_ids'">
|
||||
<tree-view value-field="id" id-field="id" :name-field="'conditions[' + index + '][value]'" input-type="checkbox" :items='matchedAttribute.options' :value='condition.value' :behavior="'no'"></tree-view>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'text' || matchedAttribute.type == 'price' || matchedAttribute.type == 'decimal' || matchedAttribute.type == 'integer'">
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'date'">
|
||||
<date>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</date>
|
||||
</div>
|
||||
|
||||
<div class="control-group date" v-if="matchedAttribute.type == 'datetime'">
|
||||
<datetime>
|
||||
<input class="control" :name="['conditions[' + index + '][value]']" v-model="condition.value"/>
|
||||
</datetime>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'boolean'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value">
|
||||
<option value="1">{{ __('admin::app.promotions.catalog-rules.yes') }}</option>
|
||||
<option value="0">{{ __('admin::app.promotions.catalog-rules.no') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'select' || matchedAttribute.type == 'radio'">
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-if="matchedAttribute.key != 'catalog|state'">
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select :name="['conditions[' + index + '][value]']" class="control" v-model="condition.value" v-else>
|
||||
<optgroup v-for='option in matchedAttribute.options' :label="option.admin_name">
|
||||
<option v-for='state in option.states' :value="state.code">
|
||||
@{{ state.admin_name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group" v-if="matchedAttribute.type == 'multiselect' || matchedAttribute.type == 'checkbox'">
|
||||
<select :name="['conditions[' + index + '][value][]']" class="control" v-model="condition.value" multiple>
|
||||
<option v-for='option in matchedAttribute.options' :value="option.id">
|
||||
@{{ option.admin_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="actions">
|
||||
<i class="icon trash-icon" @click="removeCondition"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('catalog-rule', {
|
||||
|
||||
template: '#catalog-rule-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_type: {{ old('condition_type') ?: $catalogRule->condition_type }},
|
||||
|
||||
conditions: @json($catalogRule->conditions ?: [])
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addCondition: function() {
|
||||
this.conditions.push({
|
||||
'attribute': '',
|
||||
'operator': '==',
|
||||
'value': '',
|
||||
});
|
||||
},
|
||||
|
||||
removeCondition: function(condition) {
|
||||
let index = this.conditions.indexOf(condition)
|
||||
|
||||
this.conditions.splice(index, 1)
|
||||
},
|
||||
|
||||
onSubmit: function(e) {
|
||||
this.$root.onSubmit(e)
|
||||
},
|
||||
|
||||
redirectBack: function(fallbackUrl) {
|
||||
this.$root.redirectBack(fallbackUrl)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('catalog-rule-condition-item', {
|
||||
|
||||
template: '#catalog-rule-condition-item-template',
|
||||
|
||||
props: ['index', 'condition'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
condition_attributes: @json(app('\Webkul\CatalogRule\Repositories\CatalogRuleRepository')->getConditionAttributes()),
|
||||
|
||||
attribute_type_indexes: {
|
||||
'product': 0
|
||||
},
|
||||
|
||||
condition_operators: {
|
||||
'price': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'decimal': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'integer': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'text': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contain') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}],
|
||||
'boolean': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'date': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'datetime': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}, {
|
||||
'operator': '>=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-greater-than') }}'
|
||||
}, {
|
||||
'operator': '<=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.equals-or-less-than') }}'
|
||||
}, {
|
||||
'operator': '>',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.greater-than') }}'
|
||||
}, {
|
||||
'operator': '<',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.less-than') }}'
|
||||
}],
|
||||
'select': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'radio': [{
|
||||
'operator': '==',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-equal-to') }}'
|
||||
}, {
|
||||
'operator': '!=',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.is-not-equal-to') }}'
|
||||
}],
|
||||
'multiselect': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}],
|
||||
'checkbox': [{
|
||||
'operator': '{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.contains') }}'
|
||||
}, {
|
||||
'operator': '!{}',
|
||||
'label': '{{ __('admin::app.promotions.catalog-rules.does-not-contain') }}'
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
matchedAttribute: function () {
|
||||
if (this.condition.attribute == '')
|
||||
return;
|
||||
|
||||
var this_this = this;
|
||||
|
||||
var attributeIndex = this.attribute_type_indexes[this.condition.attribute.split("|")[0]];
|
||||
|
||||
matchedAttribute = this.condition_attributes[attributeIndex]['children'].filter(function (attribute) {
|
||||
return attribute.key == this_this.condition.attribute;
|
||||
});
|
||||
|
||||
if (matchedAttribute[0]['type'] == 'multiselect' || matchedAttribute[0]['type'] == 'checkbox') {
|
||||
this.condition.operator = '{}';
|
||||
|
||||
this.condition.value = this.condition.value == '' && this.condition.value != undefined ? [] : this.condition.value;
|
||||
}
|
||||
|
||||
return matchedAttribute[0];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeCondition: function() {
|
||||
this.$emit('onRemoveCondition', this.condition)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
@extends('admin::layouts.content')
|
||||
|
||||
@section('page_title')
|
||||
{{ __('admin::app.promotions.catalog-rules.title') }}
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="content">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h1>{{ __('admin::app.promotions.catalog-rules.title') }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-action">
|
||||
<a href="{{ route('admin.catalog-rules.create') }}" class="btn btn-lg btn-primary">
|
||||
{{ __('admin::app.promotions.catalog-rules.add-title') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
@inject('catalogRuleGrid','Webkul\Admin\DataGrids\CatalogRuleDataGrid')
|
||||
{!! $catalogRuleGrid->render() !!}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -332,7 +332,13 @@
|
|||
|
||||
@if ($order->base_discount_amount > 0)
|
||||
<tr>
|
||||
<td>{{ __('admin::app.sales.orders.discount') }}</td>
|
||||
<td>
|
||||
{{ __('admin::app.sales.orders.discount') }}
|
||||
|
||||
@if ($order->coupon_code)
|
||||
({{ $order->coupon_code }})
|
||||
@endif
|
||||
</td>
|
||||
<td>-</td>
|
||||
<td>{{ core()->formatBasePrice($order->base_discount_amount) }}</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -195,14 +195,14 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
@if ($shipment->inventory_source)
|
||||
@if ($shipment->inventory_source || $shipment->inventory_source_name)
|
||||
<div class="row">
|
||||
<span class="title">
|
||||
{{ __('admin::app.sales.shipments.inventory-source') }}
|
||||
</span>
|
||||
|
||||
<span class="value">
|
||||
{{ $shipment->inventory_source->name }}
|
||||
{{ $shipment->inventory_source ? $shipment->inventory_source->name : $shipment->inventory_source_name }}
|
||||
</span>
|
||||
</div>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<span class="control-error" v-if="errors.has('identifier')">@{{ errors.first('identifier') }}</span>
|
||||
</div>
|
||||
|
||||
@include ('admin::customers.country-state', ['countryCode' => old('country'), 'stateCode' => old('state')])
|
||||
<country-state></country-state>
|
||||
|
||||
<div class="control-group">
|
||||
<span class="checkbox">
|
||||
|
|
@ -83,6 +83,50 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="country-state-template">
|
||||
<div>
|
||||
<div class="control-group" :class="[errors.has('country') ? 'has-error' : '']">
|
||||
<label for="country" class="required">
|
||||
{{ __('admin::app.customers.customers.country') }}
|
||||
</label>
|
||||
|
||||
<select type="text" v-validate="'required'" class="control" id="country" name="country" v-model="country" data-vv-as=""{{ __('admin::app.customers.customers.country') }}"">
|
||||
<option value=""></option>
|
||||
|
||||
@foreach (core()->countries() as $country)
|
||||
|
||||
<option value="{{ $country->code }}">{{ $country->name }}</option>
|
||||
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('country')">
|
||||
@{{ errors.first('country') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('state') ? 'has-error' : '']">
|
||||
<label for="state">
|
||||
{{ __('admin::app.customers.customers.state') }}
|
||||
</label>
|
||||
|
||||
<select class="control" id="state" name="state" v-model="state">
|
||||
|
||||
<option value="" :selected="! haveStates()">*</option>
|
||||
|
||||
<option v-for='(state, index) in countryStates[country]' :value="state.code">
|
||||
@{{ state.default_name }}
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('state')">
|
||||
@{{ errors.first('state') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('tax-rate-form', {
|
||||
|
||||
|
|
@ -96,5 +140,31 @@
|
|||
}
|
||||
},
|
||||
});
|
||||
|
||||
Vue.component('country-state', {
|
||||
|
||||
template: '#country-state-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
country: "{{ old('country') }}",
|
||||
|
||||
state: "{{ old('state') }}",
|
||||
|
||||
countryStates: @json(core()->groupedStatesByCountries())
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
haveStates: function () {
|
||||
if (this.countryStates[this.country] && this.countryStates[this.country].length)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<span class="control-error" v-if="errors.has('identifier')">@{{ errors.first('identifier') }}</span>
|
||||
</div>
|
||||
|
||||
@include ('admin::customers.country-state', ['countryCode' => old('country') ?? $taxRate->country, 'stateCode' => old('state') ?? $taxRate->state])
|
||||
<country-state></country-state>
|
||||
|
||||
@if ($taxRate->is_zip)
|
||||
<input type="hidden" id="is_zip" name="is_zip" value="{{ $taxRate->is_zip }}">
|
||||
|
|
@ -71,3 +71,78 @@
|
|||
</form>
|
||||
</div>
|
||||
@stop
|
||||
|
||||
@push('scripts')
|
||||
|
||||
<script type="text/x-template" id="country-state-template">
|
||||
<div>
|
||||
<div class="control-group" :class="[errors.has('country') ? 'has-error' : '']">
|
||||
<label for="country" class="required">
|
||||
{{ __('admin::app.customers.customers.country') }}
|
||||
</label>
|
||||
|
||||
<select type="text" v-validate="'required'" class="control" id="country" name="country" v-model="country" data-vv-as=""{{ __('admin::app.customers.customers.country') }}"">
|
||||
<option value=""></option>
|
||||
|
||||
@foreach (core()->countries() as $country)
|
||||
|
||||
<option value="{{ $country->code }}">{{ $country->name }}</option>
|
||||
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('country')">
|
||||
@{{ errors.first('country') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" :class="[errors.has('state') ? 'has-error' : '']">
|
||||
<label for="state">
|
||||
{{ __('admin::app.customers.customers.state') }}
|
||||
</label>
|
||||
|
||||
<select class="control" id="state" name="state" v-model="state">
|
||||
|
||||
<option value="" :selected="! haveStates()">*</option>
|
||||
|
||||
<option v-for='(state, index) in countryStates[country]' :value="state.code">
|
||||
@{{ state.default_name }}
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('state')">
|
||||
@{{ errors.first('state') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('country-state', {
|
||||
|
||||
template: '#country-state-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
country: "{{ old('country') ?? $taxRate->country }}",
|
||||
|
||||
state: "{{ old('state') ?? $taxRate->state }}",
|
||||
|
||||
countryStates: @json(core()->groupedStatesByCountries())
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
haveStates: function () {
|
||||
if (this.countryStates[this.country] && this.countryStates[this.country].length)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -22,6 +22,10 @@ mix.js(__dirname + "/src/Resources/assets/js/app.js", "js/admin.js")
|
|||
processCssUrls: false
|
||||
});
|
||||
|
||||
if (!mix.inProduction()) {
|
||||
mix.sourceMaps();
|
||||
}
|
||||
|
||||
if (mix.inProduction()) {
|
||||
mix.version();
|
||||
}
|
||||
|
|
@ -3,9 +3,8 @@
|
|||
namespace Webkul\CMS\Http\Controllers\Shop;
|
||||
|
||||
use Webkul\CMS\Http\Controllers\Controller;
|
||||
use Webkul\CMS\Repositories\CMSRepository as CMS;
|
||||
use Webkul\Core\Repositories\ChannelRepository as Channel;
|
||||
use Webkul\Core\Repositories\LocaleRepository as Locale;
|
||||
use Webkul\CMS\Repositories\CMSRepository;
|
||||
use Webkul\Core\Repositories\LocaleRepository;
|
||||
|
||||
/**
|
||||
* PagePresenter controller
|
||||
|
|
@ -13,73 +12,58 @@ use Webkul\Core\Repositories\LocaleRepository as Locale;
|
|||
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class PagePresenterController extends Controller
|
||||
class PagePresenterController extends Controller
|
||||
{
|
||||
/**
|
||||
* To hold the request variables from route file
|
||||
* CMSRepository object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $_config;
|
||||
protected $cmsRepository;
|
||||
|
||||
/**
|
||||
* To hold the channel reposotry instance
|
||||
* LocaleRepository object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $channel;
|
||||
protected $localeRepository;
|
||||
|
||||
/**
|
||||
* To hold the locale reposotry instance
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Webkul\CMS\Repositories\CMSRepository $cmsRepository
|
||||
* @param \Webkul\Core\Repositories\LocaleRepository $localeRepository
|
||||
* @return void
|
||||
*/
|
||||
protected $locale;
|
||||
|
||||
/**
|
||||
* To hold the CMSRepository instance
|
||||
*/
|
||||
protected $cms;
|
||||
|
||||
public function __construct(Channel $channel, Locale $locale, CMS $cms)
|
||||
public function __construct(
|
||||
CMSRepository $cmsRepository,
|
||||
LocaleRepository $localeRepository
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Channel repository instance
|
||||
*/
|
||||
$this->channel = $channel;
|
||||
$this->cmsRepository = $cmsRepository;
|
||||
|
||||
/**
|
||||
* Locale repository instance
|
||||
*/
|
||||
$this->locale = $locale;
|
||||
|
||||
/**
|
||||
* CMS repository instance
|
||||
*/
|
||||
$this->cms = $cms;
|
||||
|
||||
$this->_config = request('_config');
|
||||
$this->localeRepository = $localeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* To extract the page content and load it in the respective view file\
|
||||
* To extract the page content and load it in the respective view file
|
||||
*
|
||||
* @return view
|
||||
* @param string $slug
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function presenter($slug)
|
||||
{
|
||||
$currentChannel = core()->getCurrentChannel();
|
||||
$currentLocale = app()->getLocale();
|
||||
$currentLocale = $this->localeRepository->findOneByField('code', app()->getLocale());
|
||||
|
||||
$currentLocale = $this->locale->findOneWhere([
|
||||
'code' => $currentLocale
|
||||
]);
|
||||
$page = $this->cmsRepository->findOneWhere([
|
||||
'url_key' => $slug,
|
||||
'locale_id' => $currentLocale->id,
|
||||
'channel_id' => core()->getCurrentChannel()->id
|
||||
]);
|
||||
|
||||
$page = $this->cms->findOneWhere([
|
||||
'url_key' => $slug,
|
||||
'locale_id' => $currentLocale->id,
|
||||
'channel_id' => $currentChannel->id
|
||||
]);
|
||||
|
||||
if ($page) {
|
||||
return view('shop::cms.page')->with('page', $page);
|
||||
} else {
|
||||
if (! $page)
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return view('shop::cms.page')->with('page', $page);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Contracts;
|
||||
|
||||
interface CartRule
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Contracts;
|
||||
|
||||
interface CartRuleCoupon
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Contracts;
|
||||
|
||||
interface CartRuleCouponUsage
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Contracts;
|
||||
|
||||
interface CartRuleCustomer
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Contracts;
|
||||
|
||||
interface CartRuleTranslation
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RemoveTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('cart_rule_cart');
|
||||
|
||||
Schema::dropIfExists('cart_rule_labels');
|
||||
|
||||
Schema::dropIfExists('cart_rule_channels');
|
||||
|
||||
Schema::dropIfExists('cart_rule_customer_groups');
|
||||
|
||||
Schema::dropIfExists('cart_rule_customers');
|
||||
|
||||
Schema::dropIfExists('cart_rule_coupons');
|
||||
|
||||
Schema::dropIfExists('cart_rule_coupon_usage');
|
||||
|
||||
Schema::dropIfExists('cart_rule_coupons_usage');
|
||||
|
||||
Schema::dropIfExists('cart_rules');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Schema;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCartRuleTable extends Migration
|
||||
class CreateCartRulesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
|
|
@ -13,38 +13,29 @@ class CreateCartRuleTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('discount_customer_group');
|
||||
Schema::dropIfExists('discount_channels');
|
||||
Schema::dropIfExists('discount_rules');
|
||||
Schema::dropIfExists('discounts');
|
||||
Schema::dropIfExists('products_grid');
|
||||
|
||||
Schema::create('cart_rules', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->datetime('starts_from')->nullable();
|
||||
$table->datetime('ends_till')->nullable();
|
||||
$table->date('starts_from')->nullable();
|
||||
$table->date('ends_till')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->integer('per_customer')->unsigned()->default(0);
|
||||
$table->boolean('is_guest')->default(0);
|
||||
$table->boolean('use_coupon')->default(0);
|
||||
$table->integer('usage_limit')->unsigned()->default(0);
|
||||
$table->json('conditions')->nullable();
|
||||
$table->json('actions')->nullable();
|
||||
$table->boolean('end_other_rules')->default(0);
|
||||
$table->integer('priority')->unsigned()->default(0);
|
||||
$table->boolean('uses_attribute_conditions')->default(0);
|
||||
$table->longtext('product_ids')->nullable();
|
||||
$table->integer('sort_order')->unsigned()->default(0);
|
||||
$table->string('action_type')->nullable();
|
||||
$table->decimal('disc_amount', 12, 4)->default(0);
|
||||
$table->decimal('disc_quantity', 12, 4)->default(1);
|
||||
$table->string('disc_threshold')->default(1);
|
||||
$table->integer('coupon_type')->default(1);
|
||||
$table->boolean('auto_generation')->default(0);
|
||||
$table->boolean('use_auto_generation')->default(0);
|
||||
$table->integer('usage_per_customer')->default(0);
|
||||
$table->integer('uses_per_coupon')->default(0);
|
||||
$table->integer('times_used')->unsigned()->default(0);
|
||||
$table->boolean('condition_type')->default(1);
|
||||
$table->json('conditions')->nullable();
|
||||
$table->boolean('end_other_rules')->default(0);
|
||||
$table->boolean('uses_attribute_conditions')->default(0);
|
||||
$table->string('action_type')->nullable();
|
||||
$table->decimal('discount_amount', 12, 4)->default(0);
|
||||
$table->integer('discount_quantity')->default(1);
|
||||
$table->string('discount_step')->default(1);
|
||||
$table->boolean('apply_to_shipping')->default(0);
|
||||
$table->boolean('free_shipping')->default(0);
|
||||
$table->integer('sort_order')->unsigned()->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -14,12 +14,13 @@ class CreateCartRuleChannelsTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('cart_rule_channels', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->integer('channel_id')->unsigned();
|
||||
|
||||
$table->primary(['cart_rule_id', 'channel_id']);
|
||||
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -14,12 +14,14 @@ class CreateCartRuleCustomerGroupsTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('cart_rule_customer_groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
|
||||
|
||||
$table->primary(['cart_rule_id', 'customer_group_id']);
|
||||
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Schema;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCartRuleCartTable extends Migration
|
||||
class CreateCartRuleTranslationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
|
|
@ -13,13 +13,13 @@ class CreateCartRuleCartTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cart_rule_cart', function (Blueprint $table) {
|
||||
Schema::create('cart_rule_translations', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('cart_rule_id')->unsigned()->nullable();
|
||||
$table->string('locale');
|
||||
$table->text('label')->nullable();
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->unique(['cart_rule_id', 'locale']);
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->integer('cart_id')->unsigned()->nullable();
|
||||
$table->foreign('cart_id')->references('id')->on('cart')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +30,6 @@ class CreateCartRuleCartTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cart_rule_cart');
|
||||
Schema::dropIfExists('cart_rule_translations');
|
||||
}
|
||||
}
|
||||
|
|
@ -15,12 +15,13 @@ class CreateCartruleCustomersTable extends Migration
|
|||
{
|
||||
Schema::create('cart_rule_customers', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->bigInteger('times_used')->unsigned()->default(0);
|
||||
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
|
||||
$table->integer('customer_id')->unsigned();
|
||||
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
|
||||
$table->bigInteger('usage_throttle')->unsigned()->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -31,6 +32,6 @@ class CreateCartruleCustomersTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cart_rule_customers');
|
||||
Schema::dropIfExists('cartrule_customers');
|
||||
}
|
||||
}
|
||||
|
|
@ -15,15 +15,16 @@ class CreateCartruleCouponsTable extends Migration
|
|||
{
|
||||
Schema::create('cart_rule_coupons', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->string('prefix')->nullable();
|
||||
$table->string('suffix')->nullable();
|
||||
$table->string('code')->nullable();
|
||||
$table->integer('usage_limit')->unsigned()->default(0);
|
||||
$table->integer('usage_per_customer')->unsigned()->default(0);
|
||||
$table->integer('usage_throttle')->unsigned()->default(0);
|
||||
$table->integer('times_used')->unsigned()->default(0);
|
||||
$table->integer('type')->unsigned()->default(0);
|
||||
$table->boolean('is_primary')->default(0);
|
||||
$table->date('expired_at')->nullable();
|
||||
|
||||
$table->integer('cart_rule_id')->unsigned();
|
||||
$table->foreign('cart_rule_id')->references('id')->on('cart_rules')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -35,6 +36,6 @@ class CreateCartruleCouponsTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cart_rule_coupons');
|
||||
Schema::dropIfExists('cartrule_coupons');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCartRuleCouponUsageTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cart_rule_coupon_usage', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('times_used')->default(0);
|
||||
|
||||
$table->integer('cart_rule_coupon_id')->unsigned();
|
||||
$table->foreign('cart_rule_coupon_id')->references('id')->on('cart_rule_coupons')->onDelete('cascade');
|
||||
|
||||
$table->integer('customer_id')->unsigned();
|
||||
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cart_rule_coupon_usage');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,523 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Webkul\CartRule\Repositories\CartRuleRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponUsageRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCustomerRepository;
|
||||
use Webkul\Customer\Repositories\CustomerGroupRepository;
|
||||
use Webkul\Rule\Helpers\Validator;
|
||||
use Webkul\Checkout\Facades\Cart;
|
||||
|
||||
class CartRule
|
||||
{
|
||||
/**
|
||||
* CartRuleRepository object
|
||||
*
|
||||
* @var CartRuleRepository
|
||||
*/
|
||||
protected $cartRuleRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponRepository object
|
||||
*
|
||||
* @var CartRuleCouponRepository
|
||||
*/
|
||||
protected $cartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponUsageRepository object
|
||||
*
|
||||
* @var CartRuleCouponUsageRepository
|
||||
*/
|
||||
protected $cartRuleCouponUsageRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCustomerRepository object
|
||||
*
|
||||
* @var CartRuleCustomerRepository
|
||||
*/
|
||||
protected $cartRuleCustomerRepository;
|
||||
|
||||
/**
|
||||
* CustomerGroupRepository object
|
||||
*
|
||||
* @var CustomerGroupRepository
|
||||
*/
|
||||
protected $customerGroupRepository;
|
||||
|
||||
/**
|
||||
* Validator object
|
||||
*
|
||||
* @var Validator
|
||||
*/
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $itemTotals = [];
|
||||
|
||||
/**
|
||||
* Create a new helper instance.
|
||||
*
|
||||
* @param Webkul\CartRule\Repositories\CartRuleRepository $cartRuleRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCouponUsageRepository $cartRuleCouponUsageRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCustomerRepository $cartRuleCustomerRepository
|
||||
* @param Webkul\Customer\Repositories\CustomerGroupRepository $customerGroupRepository
|
||||
* @param Webkul\Rule\Helpers\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
CartRuleRepository $cartRuleRepository,
|
||||
CartRuleCouponRepository $cartRuleCouponRepository,
|
||||
CartRuleCouponUsageRepository $cartRuleCouponUsageRepository,
|
||||
CartRuleCustomerRepository $cartRuleCustomerRepository,
|
||||
CustomerGroupRepository $customerGroupRepository,
|
||||
Validator $validator
|
||||
)
|
||||
{
|
||||
$this->cartRuleRepository = $cartRuleRepository;
|
||||
|
||||
$this->cartRuleCouponRepository = $cartRuleCouponRepository;
|
||||
|
||||
$this->cartRuleCouponUsageRepository = $cartRuleCouponUsageRepository;
|
||||
|
||||
$this->cartRuleCustomerRepository = $cartRuleCustomerRepository;
|
||||
|
||||
$this->customerGroupRepository = $customerGroupRepository;
|
||||
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect discount on cart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$cart = Cart::getCart();
|
||||
|
||||
$this->calculateCartItemTotals($cart->items()->get());
|
||||
|
||||
foreach ($cart->items()->get() as $item) {
|
||||
$this->process($item);
|
||||
|
||||
if ($item->children()->count() && $item->product->getTypeInstance()->isChildrenCalculated())
|
||||
$this->devideDiscount($item);
|
||||
}
|
||||
|
||||
$this->processShippingDiscount($cart);
|
||||
|
||||
$this->processFreeShippingDiscount($cart);
|
||||
|
||||
$this->validateCouponCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cart rules
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCartRules()
|
||||
{
|
||||
static $cartRules;
|
||||
|
||||
if ($cartRules)
|
||||
return $cartRules;
|
||||
|
||||
$customerGroupId = null;
|
||||
|
||||
if (Cart::getCurrentCustomer()->check()) {
|
||||
$customerGroupId = Cart::getCurrentCustomer()->user()->customer_group_id;
|
||||
} else {
|
||||
if ($customerGuestGroup = $this->customerGroupRepository->findOneByField('code', 'guest'))
|
||||
$customerGroupId = $customerGuestGroup->id;
|
||||
}
|
||||
|
||||
$cartRules = $this->cartRuleRepository->scopeQuery(function($query) use ($customerGroupId) {
|
||||
return $query->leftJoin('cart_rule_customer_groups', 'cart_rules.id', '=', 'cart_rule_customer_groups.cart_rule_id')
|
||||
->leftJoin('cart_rule_channels', 'cart_rules.id', '=', 'cart_rule_channels.cart_rule_id')
|
||||
->where('cart_rule_customer_groups.customer_group_id', $customerGroupId)
|
||||
->where('cart_rule_channels.channel_id', core()->getCurrentChannel()->id)
|
||||
->where(function ($query1) {
|
||||
$query1->where('cart_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))->orWhereNull('cart_rules.starts_from');
|
||||
})
|
||||
->where(function ($query2) {
|
||||
$query2->where('cart_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))->orWhereNull('cart_rules.ends_till');
|
||||
})
|
||||
->orderBy('sort_order', 'asc');
|
||||
})->findWhere(['status' => 1]);
|
||||
|
||||
return $cartRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cart rule can be applied
|
||||
*
|
||||
* @param CartRule $rule
|
||||
* @return boolean
|
||||
*/
|
||||
public function canProcessRule($rule)
|
||||
{
|
||||
$cart = Cart::getCart();
|
||||
|
||||
if ($rule->coupon_type) {
|
||||
if (strlen($cart->coupon_code)) {
|
||||
$coupon = $this->cartRuleCouponRepository->findOneWhere([
|
||||
'cart_rule_id' => $rule->id,
|
||||
'code' => $cart->coupon_code,
|
||||
]);
|
||||
|
||||
if ($coupon) {
|
||||
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit)
|
||||
return false;
|
||||
|
||||
if ($cart->customer_id && $coupon->usage_per_customer) {
|
||||
$couponUsage = $this->cartRuleCouponUsageRepository->findOneWhere([
|
||||
'cart_rule_coupon_id' => $coupon->id,
|
||||
'customer_id' => $cart->customer_id
|
||||
]);
|
||||
|
||||
if ($couponUsage && $couponUsage->times_used >= $coupon->usage_per_customer)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($rule->usage_per_customer) {
|
||||
$ruleCustomer = $this->cartRuleCustomerRepository->findOneWhere([
|
||||
'cart_rule_id' => $rule->id,
|
||||
'customer_id' => $cart->customer_id,
|
||||
]);
|
||||
|
||||
if ($ruleCustomer && $ruleCustomer->times_used >= $rule->usage_per_customer)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cart item discount calculation process
|
||||
*
|
||||
* @param CartItem $item
|
||||
* @return void
|
||||
*/
|
||||
public function process($item)
|
||||
{
|
||||
$item->discount_percent = 0;
|
||||
$item->discount_amount = 0;
|
||||
$item->base_discount_amount = 0;
|
||||
|
||||
$cart = $item->cart;
|
||||
|
||||
$cart->applied_cart_rule_ids = null;
|
||||
|
||||
$appliedRuleIds = [];
|
||||
|
||||
foreach ($this->getCartRules() as $rule) {
|
||||
if (! $this->canProcessRule($rule))
|
||||
continue;
|
||||
|
||||
if (! $this->validator->validate($rule, $item))
|
||||
continue;
|
||||
|
||||
$quantity = $rule->discount_quantity ? min($item->quantity, $rule->discount_quantity) : $item->quantity;
|
||||
|
||||
$discountAmount = $baseDiscountAmount = 0;
|
||||
|
||||
switch ($rule->action_type) {
|
||||
case 'by_percent':
|
||||
$rulePercent = min(100, $rule->discount_amount);
|
||||
|
||||
$discountAmount = ($quantity * $item->price - $item->discount_amount) * ($rulePercent / 100);
|
||||
|
||||
$baseDiscountAmount = ($quantity * $item->base_price - $item->base_discount_amount) * ($rulePercent / 100);
|
||||
|
||||
if (! $rule->discount_quantity || $rule->discount_quantity > $quantity) {
|
||||
$discountPercent = min(100, $item->discount_percent + $rulePercent);
|
||||
|
||||
$item->discount_percent = $discountPercent;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'by_fixed':
|
||||
$discountAmount = $quantity * core()->convertPrice($rule->discount_amount);
|
||||
|
||||
$baseDiscountAmount = $quantity * $rule->discount_amount;
|
||||
|
||||
break;
|
||||
|
||||
case 'cart_fixed':
|
||||
if ($this->itemTotals[$rule->id]['total_items'] <= 1) {
|
||||
$discountAmount = core()->convertPrice($rule->discount_amount);
|
||||
|
||||
$baseDiscountAmount = min($item->base_price * $quantity, $rule->discount_amount);
|
||||
} else {
|
||||
$discountRate = $item->base_price * $quantity / $this->itemTotals[$rule->id]['base_total_price'];
|
||||
|
||||
$maxDiscount = $rule->discount_amount * $discountRate;
|
||||
|
||||
$discountAmount = core()->convertPrice($maxDiscount);
|
||||
|
||||
$baseDiscountAmount = min($item->base_price * $quantity, $maxDiscount);
|
||||
}
|
||||
|
||||
$discountAmount = min($item->price * $quantity, $discountAmount);
|
||||
|
||||
break;
|
||||
|
||||
case 'buy_x_get_y':
|
||||
if (! $rule->discount_step || $rule->discount_amount > $rule->discount_step)
|
||||
break;
|
||||
|
||||
$buyAndDiscountQty = $rule->discount_step + $rule->discount_amount;
|
||||
|
||||
$qtyPeriod = floor($quantity / $buyAndDiscountQty);
|
||||
|
||||
$freeQty = $quantity - $qtyPeriod * $buyAndDiscountQty;
|
||||
|
||||
$discountQty = $qtyPeriod * $rule->discount_amount;
|
||||
|
||||
if ($freeQty > $rule->discount_step)
|
||||
$discountQty += $freeQty - $rule->discount_step;
|
||||
|
||||
$discountAmount = $discountQty * $item->price;
|
||||
|
||||
$baseDiscountAmount = $discountQty * $item->base_price;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$item->discount_amount = min($item->discount_amount + $discountAmount, $item->price * $quantity);
|
||||
$item->base_discount_amount = min($item->base_discount_amount + $baseDiscountAmount, $item->base_price * $quantity);
|
||||
|
||||
$appliedRuleIds[$rule->id] = $rule->id;
|
||||
|
||||
if ($rule->end_other_rules)
|
||||
break;
|
||||
}
|
||||
|
||||
$item->applied_cart_rule_ids = join(',', $appliedRuleIds);
|
||||
|
||||
$item->save();
|
||||
|
||||
$cartAppliedCartRuleIds = array_merge(explode(',', $cart->applied_cart_rule_ids), $appliedRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_filter($cartAppliedCartRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_unique($cartAppliedCartRuleIds);
|
||||
|
||||
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
|
||||
|
||||
$cart->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cart shipping discount calculation process
|
||||
*
|
||||
* @param Cart $cart
|
||||
* @return void
|
||||
*/
|
||||
public function processShippingDiscount($cart)
|
||||
{
|
||||
if (! $selectedShipping = $cart->selected_shipping_rate)
|
||||
return;
|
||||
|
||||
$selectedShipping->discount_amount = 0;
|
||||
$selectedShipping->base_discount_amount = 0;
|
||||
|
||||
$appliedRuleIds = [];
|
||||
|
||||
foreach ($this->getCartRules() as $rule) {
|
||||
if (! $this->canProcessRule($rule))
|
||||
continue;
|
||||
|
||||
if (! $this->validator->validate($rule, $cart))
|
||||
continue;
|
||||
|
||||
if (! $rule || ! $rule->apply_to_shipping)
|
||||
continue;
|
||||
|
||||
$discountAmount = $baseDiscountAmount = 0;
|
||||
|
||||
switch ($rule->action_type) {
|
||||
case 'by_percent':
|
||||
$rulePercent = min(100, $rule->discount_amount);
|
||||
|
||||
$discountAmount = ($selectedShipping->price - $selectedShipping->discount_amount) * $rulePercent / 100;
|
||||
|
||||
$baseDiscountAmount = ($selectedShipping->base_price - $selectedShipping->base_discount_amount) * $rulePercent / 100;
|
||||
|
||||
break;
|
||||
|
||||
case 'by_fixed':
|
||||
$discountAmount = core()->convertPrice($rule->discount_amount);
|
||||
|
||||
$baseDiscountAmount = $rule->discount_amount;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$selectedShipping->discount_amount = min($selectedShipping->discount_amount + $discountAmount, $selectedShipping->price);
|
||||
|
||||
$selectedShipping->base_discount_amount = min(
|
||||
$selectedShipping->base_discount_amount + $baseDiscountAmount,
|
||||
$selectedShipping->base_price
|
||||
);
|
||||
|
||||
$selectedShipping->save();
|
||||
|
||||
$appliedRuleIds[$rule->id] = $rule->id;
|
||||
|
||||
if ($rule->end_other_rules)
|
||||
break;
|
||||
}
|
||||
|
||||
$selectedShipping->save();
|
||||
|
||||
$cartAppliedCartRuleIds = array_merge(explode(',', $cart->applied_cart_rule_ids), $appliedRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_filter($cartAppliedCartRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_unique($cartAppliedCartRuleIds);
|
||||
|
||||
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
|
||||
|
||||
$cart->save();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cart free shipping discount calculation process
|
||||
*
|
||||
* @param Cart $cart
|
||||
* @return void
|
||||
*/
|
||||
public function processFreeShippingDiscount($cart)
|
||||
{
|
||||
if (! $selectedShipping = $cart->selected_shipping_rate)
|
||||
return;
|
||||
|
||||
$selectedShipping->discount_amount = 0;
|
||||
|
||||
$selectedShipping->base_discount_amount = 0;
|
||||
|
||||
$appliedRuleIds = [];
|
||||
|
||||
foreach ($this->getCartRules() as $rule) {
|
||||
if (! $this->canProcessRule($rule))
|
||||
continue;
|
||||
|
||||
if (! $this->validator->validate($rule, $cart))
|
||||
continue;
|
||||
|
||||
if (! $rule || ! $rule->free_shipping)
|
||||
continue;
|
||||
|
||||
$selectedShipping->price = 0;
|
||||
|
||||
$selectedShipping->base_price = 0;
|
||||
|
||||
$selectedShipping->save();
|
||||
|
||||
$appliedRuleIds[$rule->id] = $rule->id;
|
||||
|
||||
if ($rule->end_other_rules)
|
||||
break;
|
||||
}
|
||||
|
||||
$cartAppliedCartRuleIds = array_merge(explode(',', $cart->applied_cart_rule_ids), $appliedRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_filter($cartAppliedCartRuleIds);
|
||||
|
||||
$cartAppliedCartRuleIds = array_unique($cartAppliedCartRuleIds);
|
||||
|
||||
$cart->applied_cart_rule_ids = join(',', $cartAppliedCartRuleIds);
|
||||
|
||||
$cart->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate cart item totals for each rule
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return Validator
|
||||
*/
|
||||
public function calculateCartItemTotals($items)
|
||||
{
|
||||
foreach ($this->getCartRules() as $rule) {
|
||||
if ($rule->action_type == 'cart_fixed') {
|
||||
$totalPrice = $totalBasePrice = $validCount = 0;
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (! $this->canProcessRule($rule, $item))
|
||||
continue;
|
||||
|
||||
$quantity = $rule->discount_quantity ? min($item->quantity, $rule->discount_quantity) : $item->quantity;
|
||||
|
||||
$totalBasePrice += $item->base_price * $quantity;
|
||||
|
||||
$validCount++;
|
||||
}
|
||||
|
||||
$this->itemTotals[$rule->id] = [
|
||||
'base_total_price' => $totalBasePrice,
|
||||
'total_items' => $validCount,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if coupon code is valid or not, if not remove from cart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validateCouponCode()
|
||||
{
|
||||
$cart = Cart::getCart();
|
||||
|
||||
if (! $cart->coupon_code)
|
||||
return;
|
||||
|
||||
$coupon = $this->cartRuleCouponRepository->findOneByField('code', $cart->coupon_code);
|
||||
|
||||
if (! $coupon || ! in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids)))
|
||||
Cart::removeCouponCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Devide discount amount to children
|
||||
*
|
||||
* @param CartItem $item
|
||||
* @return void
|
||||
*/
|
||||
protected function devideDiscount($item)
|
||||
{
|
||||
foreach ($item->children as $child) {
|
||||
$ratio = $item->base_total != 0 ? $child->base_total / $item->base_total : 0;
|
||||
|
||||
foreach (['discount_amount', 'base_discount_amount'] as $column) {
|
||||
if (! $item->{$column})
|
||||
continue;
|
||||
|
||||
$child->{$column} = round(($item->{$column} * $ratio), 4);
|
||||
|
||||
$child->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Webkul\CartRule\Repositories\CartRuleRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* Cart Rule controller
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleController extends Controller
|
||||
{
|
||||
/**
|
||||
* Initialize _config, a default request parameter with route
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* To hold Cart repository instance
|
||||
*
|
||||
* @var CartRuleRepository
|
||||
*/
|
||||
protected $cartRuleRepository;
|
||||
|
||||
/**
|
||||
* To hold CartRuleCouponRepository repository instance
|
||||
*
|
||||
* @var CartRuleCouponRepository
|
||||
*/
|
||||
protected $cartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Webkul\CartRule\Repositories\CartRuleRepository $cartRuleRepository
|
||||
* @param \Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
CartRuleRepository $cartRuleRepository,
|
||||
CartRuleCouponRepository $cartRuleCouponRepository
|
||||
)
|
||||
{
|
||||
$this->_config = request('_config');
|
||||
|
||||
$this->cartRuleRepository = $cartRuleRepository;
|
||||
|
||||
$this->cartRuleCouponRepository = $cartRuleCouponRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view($this->_config['view']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view($this->_config['view']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
$this->validate(request(), [
|
||||
'name' => 'required',
|
||||
'channels' => 'required|array|min:1',
|
||||
'customer_groups' => 'required|array|min:1',
|
||||
'coupon_type' => 'required',
|
||||
'use_auto_generation' => 'required_if:coupon_type,==,1',
|
||||
'coupon_code' => 'required_if:use_auto_generation,==,0',
|
||||
'starts_from' => 'nullable|date',
|
||||
'ends_till' => 'nullable|date|after_or_equal:starts_from',
|
||||
'action_type' => 'required',
|
||||
'discount_amount' => 'required|numeric'
|
||||
]);
|
||||
|
||||
$data = request()->all();
|
||||
|
||||
Event::fire('promotions.cart_rule.create.before');
|
||||
|
||||
$cartRule = $this->cartRuleRepository->create($data);
|
||||
|
||||
Event::fire('promotions.cart_rule.create.after', $cartRule);
|
||||
|
||||
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Cart Rule']));
|
||||
|
||||
return redirect()->route($this->_config['redirect']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$cartRule = $this->cartRuleRepository->findOrFail($id);
|
||||
|
||||
return view($this->_config['view'], compact('cartRule'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$this->validate(request(), [
|
||||
'name' => 'required',
|
||||
'channels' => 'required|array|min:1',
|
||||
'customer_groups' => 'required|array|min:1',
|
||||
'coupon_type' => 'required',
|
||||
'use_auto_generation' => 'required_if:coupon_type,==,1',
|
||||
'coupon_code' => 'required_if:use_auto_generation,==,0',
|
||||
'starts_from' => 'nullable|date',
|
||||
'ends_till' => 'nullable|date|after_or_equal:starts_from',
|
||||
'action_type' => 'required',
|
||||
'discount_amount' => 'required|numeric'
|
||||
]);
|
||||
|
||||
$cartRule = $this->cartRuleRepository->findOrFail($id);
|
||||
|
||||
Event::fire('promotions.cart_rule.update.before', $cartRule);
|
||||
|
||||
$cartRule = $this->cartRuleRepository->update(request()->all(), $id);
|
||||
|
||||
Event::fire('promotions.cart_rule.update.after', $cartRule);
|
||||
|
||||
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Cart Rule']));
|
||||
|
||||
return redirect()->route($this->_config['redirect']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$cartRule = $this->cartRuleRepository->findOrFail($id);
|
||||
|
||||
try {
|
||||
Event::fire('promotions.cart_rule.delete.before', $id);
|
||||
|
||||
$this->cartRuleRepository->delete($id);
|
||||
|
||||
Event::fire('promotions.cart_rule.delete.after', $id);
|
||||
|
||||
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Cart Rule']));
|
||||
|
||||
return response()->json(['message' => true], 200);
|
||||
} catch(\Exception $e) {
|
||||
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Cart Rule']));
|
||||
}
|
||||
|
||||
return response()->json(['message' => false], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate coupon code for cart rule
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function generateCoupons()
|
||||
{
|
||||
$this->validate(request(), [
|
||||
'coupon_qty' => 'required|integer|min:1',
|
||||
'code_length' => 'required|integer|min:10',
|
||||
'code_format' => 'required'
|
||||
]);
|
||||
|
||||
if (! request('id'))
|
||||
return response()->json(['message' => trans('admin::app.promotions.cart-rules.cart-rule-not-defind-error')], 400);
|
||||
|
||||
$this->cartRuleCouponRepository->generateCoupons(request()->all(), request('id'));
|
||||
|
||||
return response()->json(['message' => trans('admin::app.response.create-success', ['name' => 'Cart rule coupons'])]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* Cart Rule Coupon controller
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleCouponController extends Controller
|
||||
{
|
||||
/**
|
||||
* To hold CartRuleCouponRepository repository instance
|
||||
*
|
||||
* @var CartRuleCouponRepository
|
||||
*/
|
||||
protected $cartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CartRuleCouponRepository $cartRuleCouponRepository)
|
||||
{
|
||||
$this->cartRuleCouponRepository = $cartRuleCouponRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mass Delete the coupons
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function massDelete()
|
||||
{
|
||||
$couponIds = explode(',', request()->input('indexes'));
|
||||
|
||||
foreach ($couponIds as $couponId) {
|
||||
$coupon = $this->cartRuleCouponRepository->find($couponId);
|
||||
|
||||
if ($coupon)
|
||||
$this->cartRuleCouponRepository->delete($couponId);
|
||||
}
|
||||
|
||||
session()->flash('success', trans('admin::app.promotions.cart-rules.mass-delete-success'));
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Discount\Http\Controllers;
|
||||
namespace Webkul\CartRule\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Listeners;
|
||||
|
||||
use Webkul\CartRule\Helpers\CartRule;
|
||||
|
||||
/**
|
||||
* Cart event handler
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class Cart
|
||||
{
|
||||
/**
|
||||
* CartRule object
|
||||
*
|
||||
* @var CartRule
|
||||
*/
|
||||
protected $cartRuleHepler;
|
||||
|
||||
/**
|
||||
* Create a new listener instance.
|
||||
*
|
||||
* @param Webkul\CartRule\Repositories\CartRule $cartRuleHepler
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CartRule $cartRuleHepler)
|
||||
{
|
||||
$this->cartRuleHepler = $cartRuleHepler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aplly valid cart rules to cart
|
||||
*
|
||||
* @param Cart $cart
|
||||
* @return void
|
||||
*/
|
||||
public function applyCartRules($cart)
|
||||
{
|
||||
$this->cartRuleHepler->collect();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Listeners;
|
||||
|
||||
use Webkul\CartRule\Repositories\CartRuleRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCustomerRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
|
||||
use Webkul\CartRule\Repositories\CartRuleCouponUsageRepository;
|
||||
|
||||
/**
|
||||
* Order event handler
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class Order
|
||||
{
|
||||
/**
|
||||
* CartRuleRepository object
|
||||
*
|
||||
* @var CartRuleRepository
|
||||
*/
|
||||
protected $cartRuleRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCustomerRepository object
|
||||
*
|
||||
* @var CartRuleCustomerRepository
|
||||
*/
|
||||
protected $cartRuleCustomerRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponRepository object
|
||||
*
|
||||
* @var CartRuleCouponRepository
|
||||
*/
|
||||
protected $cartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponUsageRepository object
|
||||
*
|
||||
* @var CartRuleCouponUsageRepository
|
||||
*/
|
||||
protected $cartRuleCouponUsageRepository;
|
||||
|
||||
/**
|
||||
* Create a new listener instance.
|
||||
*
|
||||
* @param Webkul\CartRule\Repositories\CartRuleRepository $cartRuleRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCustomerRepository $cartRuleCustomerRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCouponUsageRepository $cartRuleCouponUsageRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
CartRuleRepository $cartRuleRepository,
|
||||
CartRuleCustomerRepository $cartRuleCustomerRepository,
|
||||
CartRuleCouponRepository $cartRuleCouponRepository,
|
||||
CartRuleCouponUsageRepository $cartRuleCouponUsageRepository
|
||||
)
|
||||
{
|
||||
$this->cartRuleRepository = $cartRuleRepository;
|
||||
|
||||
$this->cartRuleCustomerRepository = $cartRuleCustomerRepository;
|
||||
|
||||
$this->cartRuleCouponRepository = $cartRuleCouponRepository;
|
||||
|
||||
$this->cartRuleCouponUsageRepository = $cartRuleCouponUsageRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save cart rule and cart rule coupon properties after place order
|
||||
*
|
||||
* @param Order $order
|
||||
* @return void
|
||||
*/
|
||||
public function manageCartRule($order)
|
||||
{
|
||||
if (! $order->discount_amount)
|
||||
return;
|
||||
|
||||
$cartRuleIds = explode(',', $order->applied_cart_rule_ids);
|
||||
|
||||
$cartRuleIds = array_unique($cartRuleIds);
|
||||
|
||||
foreach ($cartRuleIds as $ruleId) {
|
||||
$rule = $this->cartRuleRepository->find($ruleId);
|
||||
|
||||
if (! $rule)
|
||||
continue;
|
||||
|
||||
$rule->update(['times_used' => $rule->times_used + 1]);
|
||||
|
||||
if (! $order->customer_id)
|
||||
continue;
|
||||
|
||||
$ruleCustomer = $this->cartRuleCustomerRepository->findOneWhere([
|
||||
'customer_id' => $order->customer_id,
|
||||
'cart_rule_id' => $ruleId
|
||||
]);
|
||||
|
||||
if ($ruleCustomer) {
|
||||
$this->cartRuleCustomerRepository->update(['times_used' => $ruleCustomer->times_used + 1], $ruleCustomer->id);
|
||||
} else {
|
||||
$this->cartRuleCustomerRepository->create([
|
||||
'customer_id' => $order->customer_id,
|
||||
'cart_rule_id' => $ruleId,
|
||||
'times_used' => 1
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $order->coupon_code)
|
||||
return;
|
||||
|
||||
$coupon = $this->cartRuleCouponRepository->findOneByField('code', $order->coupon_code);
|
||||
|
||||
if ($coupon) {
|
||||
$this->cartRuleCouponRepository->update(['times_used' => $coupon->times_used + 1], $coupon->id);
|
||||
|
||||
if ($order->customer_id) {
|
||||
$couponUsage = $this->cartRuleCouponUsageRepository->findOneWhere([
|
||||
'customer_id' => $order->customer_id,
|
||||
'cart_rule_coupon_id' => $coupon->id
|
||||
]);
|
||||
|
||||
if ($couponUsage) {
|
||||
$this->cartRuleCouponUsageRepository->update(['times_used' => $couponUsage->times_used + 1], $couponUsage->id);
|
||||
} else {
|
||||
$this->cartRuleCouponUsageRepository->create([
|
||||
'customer_id' => $order->customer_id,
|
||||
'cart_rule_coupon_id' => $coupon->id,
|
||||
'times_used' => 1
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
// use Webkul\Core\Eloquent\TranslatableModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\CartRule\Contracts\CartRule as CartRuleContract;
|
||||
use Webkul\Core\Models\ChannelProxy;
|
||||
use Webkul\Customer\Models\CustomerGroupProxy;
|
||||
|
||||
// class CartRule extends TranslatableModel implements CartRuleContract
|
||||
class CartRule extends Model implements CartRuleContract
|
||||
{
|
||||
protected $fillable = ['name', 'description', 'starts_from', 'ends_till', 'status', 'coupon_type', 'use_auto_generation', 'usage_per_customer', 'uses_per_coupon', 'times_used', 'condition_type', 'conditions', 'actions', 'end_other_rules', 'uses_attribute_conditions', 'action_type', 'discount_amount', 'discount_quantity', 'discount_step', 'apply_to_shipping', 'free_shipping', 'sort_order'];
|
||||
|
||||
protected $casts = [
|
||||
'conditions' => 'array',
|
||||
];
|
||||
|
||||
// public $translatedAttributes = ['name'];
|
||||
|
||||
/**
|
||||
* Get the channels that owns the cart rule.
|
||||
*/
|
||||
public function channels()
|
||||
{
|
||||
return $this->belongsToMany(ChannelProxy::modelClass(), 'cart_rule_channels');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customer groups that owns the cart rule.
|
||||
*/
|
||||
public function customer_groups()
|
||||
{
|
||||
return $this->belongsToMany(CustomerGroupProxy::modelClass(), 'cart_rule_customer_groups');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the coupons that owns the cart rule.
|
||||
*/
|
||||
public function coupons()
|
||||
{
|
||||
return $this->hasOne(CartRuleCouponProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary coupon code for cart rule.
|
||||
*/
|
||||
public function coupon_code()
|
||||
{
|
||||
return $this->coupons()->where('is_primary', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary coupon code for cart rule.
|
||||
*/
|
||||
public function getCouponCodeAttribute()
|
||||
{
|
||||
$coupon = $this->coupon_code()->first();
|
||||
|
||||
if (! $coupon)
|
||||
return;
|
||||
|
||||
return $coupon->code;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\CartRule\Contracts\CartRuleCoupon as CartRuleCouponContract;
|
||||
|
||||
class CartRuleCoupon extends Model implements CartRuleCouponContract
|
||||
{
|
||||
protected $fillable = ['code', 'usage_limit', 'usage_per_customer', 'times_used', 'type', 'cart_rule_id', 'expired_at', 'is_primary'];
|
||||
|
||||
/**
|
||||
* Get the cart rule that owns the cart rule coupon.
|
||||
*/
|
||||
public function cart_rule()
|
||||
{
|
||||
return $this->belongsTo(CartRuleProxy::modelClass());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class CartRuleCouponProxy extends ModelProxy
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\CartRule\Contracts\CartRuleCouponUsage as CartRuleCouponUsageContract;
|
||||
|
||||
class CartRuleCouponUsage extends Model implements CartRuleCouponUsageContract
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $table = 'cart_rule_coupon_usage';
|
||||
|
||||
protected $guarded = ['created_at', 'updated_at'];
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class CartRuleCouponUsageProxy extends ModelProxy
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\CartRule\Contracts\CartRuleCustomer as CartRuleCustomerContract;
|
||||
|
||||
class CartRuleCustomer extends Model implements CartRuleCustomerContract
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['times_used', 'cart_rule_id', 'customer_id'];
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class CartRuleCustomerProxy extends ModelProxy
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Discount\Models;
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Webkul\CartRule\Contracts\CartRuleTranslation as CartRuleTranslationContract;
|
||||
|
||||
class CartRuleTranslation extends Model implements CartRuleTranslationContract
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['label'];
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class CartRuleTranslationProxy extends ModelProxy
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Routing\Router;
|
||||
|
||||
class CartRuleServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot(Router $router)
|
||||
{
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
|
||||
|
||||
$this->app->register(EventServiceProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Event::listen('checkout.order.save.after', 'Webkul\CartRule\Listeners\Order@manageCartRule');
|
||||
|
||||
Event::listen('checkout.cart.collect.totals.before', 'Webkul\CartRule\Listeners\Cart@applyCartRules');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Providers;
|
||||
|
||||
use Konekt\Concord\BaseModuleServiceProvider;
|
||||
|
||||
class ModuleServiceProvider extends BaseModuleServiceProvider
|
||||
{
|
||||
protected $models = [
|
||||
\Webkul\CartRule\Models\CartRule::class,
|
||||
\Webkul\CartRule\Models\CartRuleTranslation::class,
|
||||
\Webkul\CartRule\Models\CartRuleCustomer::class,
|
||||
\Webkul\CartRule\Models\CartRuleCoupon::class,
|
||||
\Webkul\CartRule\Models\CartRuleCouponUsage::class
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Repositories;
|
||||
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
|
||||
/**
|
||||
* CartRuleCoupon Reposotory
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleCouponRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $charsets = [
|
||||
'alphanumeric' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
|
||||
'alphabetical' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'numeric' => '0123456789'
|
||||
];
|
||||
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\CartRule\Contracts\CartRuleCoupon';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates coupons for cart rule
|
||||
*
|
||||
* @param array $data
|
||||
* @param integer $cartRuleId
|
||||
* @return void
|
||||
*/
|
||||
public function generateCoupons($data, $cartRuleId)
|
||||
{
|
||||
$cartRule = app('Webkul\CartRule\Repositories\CartRuleRepository')->findOrFail($cartRuleId);
|
||||
|
||||
for ($i = 0; $i < $data['coupon_qty']; $i++) {
|
||||
parent::create([
|
||||
'cart_rule_id' => $cartRuleId,
|
||||
'code' => $data['code_prefix'] . $this->getRandomString($data['code_format'], $data['code_length']) . $data['code_suffix'],
|
||||
'usage_limit' => $cartRule->uses_per_coupon ?? 0,
|
||||
'usage_per_customer' => $cartRule->usage_per_customer ?? 0,
|
||||
'is_primary' => 0,
|
||||
'expired_at' => $cartRule->ends_till ?: null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates coupons for cart rule
|
||||
*
|
||||
* @param string $format
|
||||
* @param integer $length
|
||||
* @return string
|
||||
*/
|
||||
public function getRandomString($format, $length)
|
||||
{
|
||||
$couponCode = '';
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$couponCode .= $this->charsets[$format][rand(0, strlen($this->charsets[$format]) - 1)];
|
||||
}
|
||||
|
||||
return $couponCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Repositories;
|
||||
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponUsage Reposotory
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleCouponUsageRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\CartRule\Contracts\CartRuleCouponUsage';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Repositories;
|
||||
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
|
||||
/**
|
||||
* CartRuleCustomer Reposotory
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleCustomerRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\CartRule\Contracts\CartRuleCustomer';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,478 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CartRule\Repositories;
|
||||
|
||||
use Illuminate\Container\Container as App;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
use Webkul\Attribute\Repositories\AttributeFamilyRepository;
|
||||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Category\Repositories\CategoryRepository;
|
||||
use Webkul\Tax\Repositories\TaxCategoryRepository;
|
||||
use Webkul\Core\Repositories\CountryRepository;
|
||||
use Webkul\Core\Repositories\CountryStateRepository;
|
||||
|
||||
/**
|
||||
* CartRule Reposotory
|
||||
*
|
||||
* @author Jitendra Singh <jitendra@webkul.com>
|
||||
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
|
||||
*/
|
||||
class CartRuleRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* AttributeFamilyRepository object
|
||||
*
|
||||
* @var AttributeFamilyRepository
|
||||
*/
|
||||
protected $attributeFamilyRepository;
|
||||
|
||||
/**
|
||||
* AttributeRepository object
|
||||
*
|
||||
* @var AttributeRepository
|
||||
*/
|
||||
protected $attributeRepository;
|
||||
|
||||
/**
|
||||
* CategoryRepository class
|
||||
*
|
||||
* @var CategoryRepository
|
||||
*/
|
||||
protected $categoryRepository;
|
||||
|
||||
/**
|
||||
* CartRuleCouponRepository object
|
||||
*
|
||||
* @var CartRuleCouponRepository
|
||||
*/
|
||||
protected $cartRuleCouponRepository;
|
||||
|
||||
/**
|
||||
* TaxCategoryRepository class
|
||||
*
|
||||
* @var TaxCategoryRepository
|
||||
*/
|
||||
protected $taxCategoryRepository;
|
||||
|
||||
/**
|
||||
* CountryRepository class
|
||||
*
|
||||
* @var CountryRepository
|
||||
*/
|
||||
protected $countryRepository;
|
||||
|
||||
/**
|
||||
* CountryStateRepository class
|
||||
*
|
||||
* @var CountryStateRepository
|
||||
*/
|
||||
protected $countryStateRepository;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param Webkul\Attribute\Repositories\AttributeFamilyRepository $attributeFamilyRepository
|
||||
* @param Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
|
||||
* @param Webkul\Category\Repositories\CategoryRepository $categoryRepository
|
||||
* @param Webkul\CartRule\Repositories\CartRuleCouponRepository $cartRuleCouponRepository
|
||||
* @param Webkul\Tax\Repositories\TaxCategoryRepository $taxCategoryRepository
|
||||
* @param Webkul\Core\Repositories\CountryRepository $countryRepository
|
||||
* @param Webkul\Core\Repositories\CountryStateRepository $countryStateRepository
|
||||
* @param Illuminate\Container\Container $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
AttributeFamilyRepository $attributeFamilyRepository,
|
||||
AttributeRepository $attributeRepository,
|
||||
CategoryRepository $categoryRepository,
|
||||
CartRuleCouponRepository $cartRuleCouponRepository,
|
||||
TaxCategoryRepository $taxCategoryRepository,
|
||||
CountryRepository $countryRepository,
|
||||
CountryStateRepository $countryStateRepository,
|
||||
App $app
|
||||
)
|
||||
{
|
||||
$this->attributeFamilyRepository = $attributeFamilyRepository;
|
||||
|
||||
$this->attributeRepository = $attributeRepository;
|
||||
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
|
||||
$this->cartRuleCouponRepository = $cartRuleCouponRepository;
|
||||
|
||||
$this->taxCategoryRepository = $taxCategoryRepository;
|
||||
|
||||
$this->countryRepository = $countryRepository;
|
||||
|
||||
$this->countryStateRepository = $countryStateRepository;
|
||||
|
||||
parent::__construct($app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\CartRule\Contracts\CartRule';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$data['starts_from'] = $data['starts_from'] ?: null;
|
||||
|
||||
$data['ends_till'] = $data['ends_till'] ?: null;
|
||||
|
||||
$data['status'] = ! isset($data['status']) ? 0 : 1;
|
||||
|
||||
$cartRule = parent::create($data);
|
||||
|
||||
$cartRule->channels()->sync($data['channels']);
|
||||
|
||||
$cartRule->customer_groups()->sync($data['customer_groups']);
|
||||
|
||||
if ($data['coupon_type'] && ! $data['use_auto_generation']) {
|
||||
$this->cartRuleCouponRepository->create([
|
||||
'cart_rule_id' => $cartRule->id,
|
||||
'code' => $data['coupon_code'],
|
||||
'usage_limit' => $data['usage_per_customer'] ?? 0,
|
||||
'usage_per_customer' => $data['usage_per_customer'] ?? 0,
|
||||
'is_primary' => 1,
|
||||
'expired_at' => $data['ends_till'] ?: null
|
||||
]);
|
||||
}
|
||||
|
||||
return $cartRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $id
|
||||
* @param string $attribute
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(array $data, $id, $attribute = "id")
|
||||
{
|
||||
$data['starts_from'] = $data['starts_from'] ?: null;
|
||||
|
||||
$data['ends_till'] = $data['ends_till'] ?: null;
|
||||
|
||||
$data['status'] = ! isset($data['status']) ? 0 : 1;
|
||||
|
||||
$data['conditions'] = $data['conditions'] ?? [];
|
||||
|
||||
$cartRule = $this->find($id);
|
||||
|
||||
parent::update($data, $id, $attribute);
|
||||
|
||||
$cartRule->channels()->sync($data['channels']);
|
||||
|
||||
$cartRule->customer_groups()->sync($data['customer_groups']);
|
||||
|
||||
if ($data['coupon_type']) {
|
||||
if (! $data['use_auto_generation']) {
|
||||
$cartRuleCoupon = $this->cartRuleCouponRepository->findOneWhere(['is_primary' => 1, 'cart_rule_id' => $cartRule->id]);
|
||||
|
||||
if ($cartRuleCoupon) {
|
||||
$this->cartRuleCouponRepository->update([
|
||||
'code' => $data['coupon_code'],
|
||||
'usage_limit' => $data['uses_per_coupon'] ?? 0,
|
||||
'usage_per_customer' => $data['usage_per_customer'] ?? 0,
|
||||
'expired_at' => $data['ends_till'] ?: null
|
||||
], $cartRuleCoupon->id);
|
||||
} else {
|
||||
$this->cartRuleCouponRepository->create([
|
||||
'cart_rule_id' => $cartRule->id,
|
||||
'code' => $data['coupon_code'],
|
||||
'usage_limit' => $data['uses_per_coupon'] ?? 0,
|
||||
'usage_per_customer' => $data['usage_per_customer'] ?? 0,
|
||||
'is_primary' => 1,
|
||||
'expired_at' => $data['ends_till'] ?: null
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$this->cartRuleCouponRepository->deleteWhere(['is_primary' => 1, 'cart_rule_id' => $cartRule->id]);
|
||||
|
||||
$this->cartRuleCouponRepository->getModel()->where('cart_rule_id', $cartRule->id)->update([
|
||||
'usage_limit' => $data['uses_per_coupon'] ?? 0,
|
||||
'usage_per_customer' => $data['usage_per_customer'] ?? 0,
|
||||
'expired_at' => $data['ends_till'] ?: null
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$cartRuleCoupon = $this->cartRuleCouponRepository->deleteWhere(['is_primary' => 1, 'cart_rule_id' => $cartRule->id]);
|
||||
}
|
||||
|
||||
return $cartRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns attributes for cart rule conditions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConditionAttributes()
|
||||
{
|
||||
$attributes = [
|
||||
[
|
||||
'key' => 'cart',
|
||||
'label' => trans('admin::app.promotions.cart-rules.cart-attribute'),
|
||||
'children' => [
|
||||
[
|
||||
'key' => 'cart|base_sub_total',
|
||||
'type' => 'price',
|
||||
'label' => trans('admin::app.promotions.cart-rules.subtotal')
|
||||
], [
|
||||
'key' => 'cart|items_qty',
|
||||
'type' => 'integer',
|
||||
'label' => trans('admin::app.promotions.cart-rules.total-items-qty')
|
||||
], [
|
||||
'key' => 'cart|payment_method',
|
||||
'type' => 'select',
|
||||
'options' => $this->getPaymentMethods(),
|
||||
'label' => trans('admin::app.promotions.cart-rules.payment-method')
|
||||
], [
|
||||
'key' => 'cart|shipping_method',
|
||||
'type' => 'select',
|
||||
'options' => $this->getShippingMethods(),
|
||||
'label' => trans('admin::app.promotions.cart-rules.shipping-method')
|
||||
], [
|
||||
'key' => 'cart|postcode',
|
||||
'type' => 'text',
|
||||
'label' => trans('admin::app.promotions.cart-rules.shipping-postcode')
|
||||
], [
|
||||
'key' => 'cart|state',
|
||||
'type' => 'select',
|
||||
'options' => $this->groupedStatesByCountries(),
|
||||
'label' => trans('admin::app.promotions.cart-rules.shipping-state')
|
||||
], [
|
||||
'key' => 'cart|country',
|
||||
'type' => 'select',
|
||||
'options' => $this->getCountries(),
|
||||
'label' => trans('admin::app.promotions.cart-rules.shipping-country')
|
||||
]
|
||||
]
|
||||
], [
|
||||
'key' => 'cart_item',
|
||||
'label' => trans('admin::app.promotions.cart-rules.cart-item-attribute'),
|
||||
'children' => [
|
||||
[
|
||||
'key' => 'cart_item|base_price',
|
||||
'type' => 'price',
|
||||
'label' => trans('admin::app.promotions.cart-rules.price-in-cart')
|
||||
], [
|
||||
'key' => 'cart_item|quantity',
|
||||
'type' => 'integer',
|
||||
'label' => trans('admin::app.promotions.cart-rules.qty-in-cart')
|
||||
], [
|
||||
'key' => 'cart_item|base_total_weight',
|
||||
'type' => 'decimal',
|
||||
'label' => trans('admin::app.promotions.cart-rules.total-weight')
|
||||
], [
|
||||
'key' => 'cart_item|base_total',
|
||||
'type' => 'price',
|
||||
'label' => trans('admin::app.promotions.cart-rules.subtotal')
|
||||
]
|
||||
]
|
||||
], [
|
||||
'key' => 'product',
|
||||
'label' => trans('admin::app.promotions.cart-rules.product-attribute'),
|
||||
'children' => [
|
||||
[
|
||||
'key' => 'product|category_ids',
|
||||
'type' => 'multiselect',
|
||||
'label' => trans('admin::app.promotions.cart-rules.categories'),
|
||||
'options' => $categories = $this->categoryRepository->getCategoryTree()
|
||||
], [
|
||||
'key' => 'product|children::category_ids',
|
||||
'type' => 'multiselect',
|
||||
'label' => trans('admin::app.promotions.cart-rules.children-categories'),
|
||||
'options' => $categories
|
||||
], [
|
||||
'key' => 'product|parent::category_ids',
|
||||
'type' => 'multiselect',
|
||||
'label' => trans('admin::app.promotions.cart-rules.parent-categories'),
|
||||
'options' => $categories
|
||||
], [
|
||||
'key' => 'product|attribute_family_id',
|
||||
'type' => 'select',
|
||||
'label' => trans('admin::app.promotions.cart-rules.attribute_family'),
|
||||
'options' => $this->getAttributeFamilies()
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($this->attributeRepository->findWhereNotIn('type', ['textarea', 'image', 'file']) as $attribute) {
|
||||
$attributeType = $attribute->type;
|
||||
|
||||
if ($attribute->code == 'tax_category_id') {
|
||||
$options = $this->getTaxCategories();
|
||||
} else {
|
||||
$options = $attribute->options;
|
||||
}
|
||||
|
||||
if ($attribute->validation == 'decimal')
|
||||
$attributeType = 'decimal';
|
||||
|
||||
if ($attribute->validation == 'numeric')
|
||||
$attributeType = 'integer';
|
||||
|
||||
$attributes[2]['children'][] = [
|
||||
'key' => 'product|' . $attribute->code,
|
||||
'type' => $attribute->type,
|
||||
'label' => $attribute->name,
|
||||
'options' => $options
|
||||
];
|
||||
|
||||
$attributes[2]['children'][] = [
|
||||
'key' => 'product|children::' . $attribute->code,
|
||||
'type' => $attribute->type,
|
||||
'label' => trans('admin::app.promotions.cart-rules.attribute-name-children-only', ['attribute_name' => $attribute->name]),
|
||||
'options' => $options
|
||||
];
|
||||
|
||||
$attributes[2]['children'][] = [
|
||||
'key' => 'product|parent::' . $attribute->code,
|
||||
'type' => $attribute->type,
|
||||
'label' => trans('admin::app.promotions.cart-rules.attribute-name-parent-only', ['attribute_name' => $attribute->name]),
|
||||
'options' => $options
|
||||
];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all payment methods
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPaymentMethods()
|
||||
{
|
||||
$methods = [];
|
||||
|
||||
foreach (config('paymentmethods') as $paymentMethod) {
|
||||
$object = app($paymentMethod['class']);
|
||||
|
||||
$methods[] = [
|
||||
'id' => $object->getCode(),
|
||||
'admin_name' => $object->getTitle()
|
||||
];
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all shipping methods
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getShippingMethods()
|
||||
{
|
||||
$methods = [];
|
||||
|
||||
foreach (config('carriers') as $shippingMethod) {
|
||||
$object = app($shippingMethod['class']);
|
||||
|
||||
$methods[] = [
|
||||
'id' => $object->getCode(),
|
||||
'admin_name' => $object->getTitle()
|
||||
];
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all countries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTaxCategories()
|
||||
{
|
||||
$taxCategories = [];
|
||||
|
||||
foreach ($this->taxCategoryRepository->all() as $taxCategory) {
|
||||
$taxCategories[] = [
|
||||
'id' => $taxCategory->id,
|
||||
'admin_name' => $taxCategory->name,
|
||||
];
|
||||
}
|
||||
|
||||
return $taxCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all attribute families
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributeFamilies()
|
||||
{
|
||||
$attributeFamilies = [];
|
||||
|
||||
foreach ($this->attributeFamilyRepository->all() as $attributeFamily) {
|
||||
$attributeFamilies[] = [
|
||||
'id' => $attributeFamily->id,
|
||||
'admin_name' => $attributeFamily->name,
|
||||
];
|
||||
}
|
||||
|
||||
return $attributeFamilies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all countries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCountries()
|
||||
{
|
||||
$countries = [];
|
||||
|
||||
foreach ($this->countryRepository->all() as $country) {
|
||||
$countries[] = [
|
||||
'id' => $country->code,
|
||||
'admin_name' => $country->name,
|
||||
];
|
||||
}
|
||||
|
||||
return $countries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all grouped states by country code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function groupedStatesByCountries()
|
||||
{
|
||||
$collection = [];
|
||||
|
||||
foreach ($this->countryRepository->all() as $country) {
|
||||
$countryStates = $this->countryStateRepository->findWhere(
|
||||
['country_id' => $country->id],
|
||||
['code', 'default_name as admin_name']
|
||||
)->toArray();
|
||||
|
||||
if (! count($countryStates))
|
||||
continue;
|
||||
|
||||
$collection[] = [
|
||||
'id' => $country->code,
|
||||
'admin_name' => $country->name,
|
||||
'states' => $countryStates
|
||||
];
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CatalogRule\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Webkul\CatalogRule\Helpers\CatalogRuleIndex;
|
||||
|
||||
class PriceRuleIndex extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'product:price-rule:index';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Automatically updates catalog rule price index information (eg. rule_price)';
|
||||
|
||||
/**
|
||||
* CatalogRuleIndex object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $catalogRuleIndexHelper;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param Webkul\CatalogRuleProduct\Helpers\CatalogRuleIndex $catalogRuleIndexHelper
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CatalogRuleIndex $catalogRuleIndexHelper)
|
||||
{
|
||||
$this->catalogRuleIndexHelper = $catalogRuleIndexHelper;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// $this->catalogRuleIndexHelper->reindexComplete();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CatalogRule\Contracts;
|
||||
|
||||
interface CatalogRule
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CatalogRule\Contracts;
|
||||
|
||||
interface CatalogRuleProduct
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CatalogRule\Contracts;
|
||||
|
||||
interface CatalogRuleProductPrice
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateRemoveCatalogRuleTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('catalog_rule_customer_groups');
|
||||
|
||||
Schema::dropIfExists('catalog_rule_channels');
|
||||
|
||||
Schema::dropIfExists('catalog_rule_products');
|
||||
|
||||
Schema::dropIfExists('catalog_rule_products_price');
|
||||
|
||||
Schema::dropIfExists('catalog_rules');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -15,16 +15,17 @@ class CreateCatalogRulesTable extends Migration
|
|||
{
|
||||
Schema::create('catalog_rules', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->text('description');
|
||||
$table->datetime('starts_from')->nullable();
|
||||
$table->datetime('ends_till')->nullable();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->date('starts_from')->nullable();
|
||||
$table->date('ends_till')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->boolean('condition_type')->default(1);
|
||||
$table->json('conditions')->nullable();
|
||||
$table->json('actions')->nullable();
|
||||
$table->boolean('end_other_rules')->default(0);
|
||||
$table->string('action_code')->nullable();
|
||||
$table->decimal('discount_amount', 20, 4)->default(0.0000);
|
||||
$table->string('action_type')->nullable();
|
||||
$table->decimal('discount_amount', 12, 4)->default(0);
|
||||
$table->integer('sort_order')->unsigned()->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -14,12 +14,13 @@ class CreateCatalogRuleChannelsTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('catalog_rule_channels', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('channel_id')->unsigned();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->integer('channel_id')->unsigned();
|
||||
|
||||
$table->primary(['catalog_rule_id', 'channel_id']);
|
||||
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -14,12 +14,14 @@ class CreateCatalogRuleCustomerGroupsTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('catalog_rule_customer_groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
|
||||
|
||||
$table->primary(['catalog_rule_id', 'customer_group_id'], 'catalog_rule_id_customer_group_id_primary');
|
||||
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -14,20 +14,25 @@ class CreateCatalogRuleProductsTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('catalog_rule_products', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
$table->increments('id');
|
||||
$table->datetime('starts_from')->nullable();
|
||||
$table->datetime('ends_till')->nullable();
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
$table->integer('channel_id')->unsigned();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
$table->boolean('end_other_rules')->default(0);
|
||||
$table->string('action_type')->nullable();
|
||||
$table->decimal('discount_amount', 12, 4)->default(0);
|
||||
$table->integer('sort_order')->unsigned()->default(0);
|
||||
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
|
||||
$table->string('action_code')->nullable();
|
||||
$table->decimal('action_amount', 20, 4)->default(0.0000);
|
||||
$table->timestamps();
|
||||
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
|
||||
$table->integer('channel_id')->unsigned();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Schema;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCatalogRuleProductsPriceTable extends Migration
|
||||
class CreateCatalogRuleProductPricesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
|
|
@ -13,20 +13,24 @@ class CreateCatalogRuleProductsPriceTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('catalog_rule_products_price', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('channel_id')->unsigned();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
$table->decimal('rule_price', 20, 4)->default(0.0000);
|
||||
Schema::create('catalog_rule_product_prices', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->decimal('price', 12, 4)->default(0);
|
||||
$table->date('rule_date');
|
||||
$table->datetime('starts_from')->nullable();
|
||||
$table->datetime('ends_till')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
|
||||
|
||||
$table->integer('customer_group_id')->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
|
||||
$table->integer('catalog_rule_id')->unsigned();
|
||||
$table->foreign('catalog_rule_id')->references('id')->on('catalog_rules')->onDelete('cascade');
|
||||
|
||||
$table->integer('channel_id')->unsigned();
|
||||
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -37,6 +41,6 @@ class CreateCatalogRuleProductsPriceTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('catalog_rule_products_price');
|
||||
Schema::dropIfExists('catalog_rule_product_prices');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\CatalogRule\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Webkul\CatalogRule\Repositories\CatalogRuleRepository;
|
||||
|
||||
class CatalogRuleIndex
|
||||
{
|
||||
/**
|
||||
* CatalogRuleRepository object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $catalogRuleRepository;
|
||||
|
||||
/**
|
||||
* CatalogRuleProduct object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $catalogRuleHelper;
|
||||
|
||||
/**
|
||||
* CatalogRuleProductPrice object
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $catalogRuleProductPriceHelper;
|
||||
|
||||
/**
|
||||
* Create a new helper instance.
|
||||
*
|
||||
* @param Webkul\CatalogRule\Repositories\CatalogRuleRepository $catalogRuleRepository
|
||||
* @param Webkul\CatalogRuleProduct\Helpers\CatalogRuleProduct $catalogRuleProductHelper
|
||||
* @param Webkul\CatalogRuleProduct\Helpers\CatalogRuleProductPrice $catalogRuleProductPriceHelper
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
CatalogRuleRepository $catalogRuleRepository,
|
||||
CatalogRuleProduct $catalogRuleProductHelper,
|
||||
CatalogRuleProductPrice $catalogRuleProductPriceHelper
|
||||
)
|
||||
{
|
||||
$this->catalogRuleRepository = $catalogRuleRepository;
|
||||
|
||||
$this->catalogRuleProductHelper = $catalogRuleProductHelper;
|
||||
|
||||
$this->catalogRuleProductPriceHelper = $catalogRuleProductPriceHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full reindex
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reindexComplete()
|
||||
{
|
||||
try {
|
||||
$this->cleanIndexes();
|
||||
|
||||
foreach ($this->getCatalogRules() as $rule) {
|
||||
$this->catalogRuleProductHelper->insertRuleProduct($rule);
|
||||
}
|
||||
|
||||
$this->catalogRuleProductPriceHelper->indexRuleProductPrice(1000);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Full reindex
|
||||
*
|
||||
* @param Product $product
|
||||
* @return void
|
||||
*/
|
||||
public function reindexProduct($product)
|
||||
{
|
||||
try {
|
||||
if (! $product->getTypeInstance()->priceRuleCanBeApplied())
|
||||
return;
|
||||
|
||||
$productIds = $product->getTypeInstance()->isComposite()
|
||||
? $product->getTypeInstance()->getChildrenIds()
|
||||
: [$product->id];
|
||||
|
||||
$this->cleanIndexes($productIds);
|
||||
|
||||
foreach ($this->getCatalogRules() as $rule) {
|
||||
$this->catalogRuleProductHelper->insertRuleProduct($rule, 1000, $product);
|
||||
}
|
||||
|
||||
$this->catalogRuleProductPriceHelper->indexRuleProductPrice(1000, $product);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes catalog rule product and catalog rule product price indexes
|
||||
*
|
||||
* @param array $productIds
|
||||
* @return void
|
||||
*/
|
||||
public function cleanIndexes($productIds = [])
|
||||
{
|
||||
$this->catalogRuleProductHelper->cleanProductIndex($productIds);
|
||||
|
||||
$this->catalogRuleProductPriceHelper->cleanProductPriceIndex($productIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns catalog rules
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCatalogRules()
|
||||
{
|
||||
static $catalogRules;
|
||||
|
||||
if ($catalogRules)
|
||||
return $catalogRules;
|
||||
|
||||
$catalogRules = $this->catalogRuleRepository->scopeQuery(function($query) {
|
||||
return $query->where(function ($query1) {
|
||||
$query1->where('catalog_rules.starts_from', '<=', Carbon::now()->format('Y-m-d'))->orWhereNull('catalog_rules.starts_from');
|
||||
})
|
||||
->where(function ($query2) {
|
||||
$query2->where('catalog_rules.ends_till', '>=', Carbon::now()->format('Y-m-d'))->orWhereNull('catalog_rules.ends_till');
|
||||
})
|
||||
->orderBy('sort_order', 'asc');
|
||||
})->findWhere(['status' => 1]);
|
||||
|
||||
return $catalogRules;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue