Merge pull request #3 from bagisto/master

merging request
This commit is contained in:
codeinnovers 2019-09-18 22:51:13 +05:30 committed by GitHub
commit b8aaa4fee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 2416 additions and 261 deletions

View File

@ -1,6 +1,6 @@
APP_NAME=Bagisto
APP_ENV=local
APP_VERSION=0.1.6
APP_VERSION=0.1.7
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

View File

@ -2,6 +2,114 @@
#### This changelog consists the bug & security fixes and new features being included in the releases listed below.
## **v0.1.7 (17th of September, 2019)** - *Release*
* [feature] - Fiterable attributes according to category.
* [feature] - New module CMS added for adding static pages.
* [feature] - Dyanamic event firing in datagrid while adding columns, actions and mass actions as well.
* [enhancement] - Customer gets an email after registration.
* [enhancement] - Customer receives cancellation mail if his/her order is cancelled by admin.
* [enhancement] - SEO is now available for home page.
* [enhancement] - If account is created for customer by admin then customer should received an email that his/her account is created with create password link.
* [enhancement] - product_flat will is now scalable according to choice of attributes to be used in it.
* #1258 [fixed] - If payment is done through paypal then invoice should generate automatically and status of Order should be processing.
* #1320 [fixed] - Catalog rule is not working according to selected attributes, if category is not selected.
* #1260 [fixed] - Getting broken image link in email.
* #1434 [fixed] - Incorrect discount amount in case of multicurrency.
* #1288 [fixed] - Getting exception while creating cart rules if any of the dropdown field left blank.
* #1381 [fixed] - Filter is not working properly for action type column in cart rule.
* #1348 [fixed] - Showing incorrect grandtotal in invoice section of admin, if order is placed in currency other than base currency.
* #1259 [fixed] - Getting exception if using same sku for variants..
* #1380 [fixed] - Getting error after refreshing the page.
* #1256 [fixed] - Discounted amount is not displaying in invoice and invoice pdf at both customer end and admin end.
* #1411 [fixed] - Getting exception on updating cart rule.
* #1284 [fixed] - Updated price for variant is not reflected on store.
* #1286 [fixed] - Incorrect discount is showing in cart.
* #1382 [fixed] - In case of "Adjust whole cart to percent" discount amount is getting calculated according to price of one product.
* #1415 [fixed] - Wrong discount applies if Action "Adjust whole cart to percent" is selected.
* #1417 [fixed] - Discount amount is showing in "Quantity" column.
* #973 [fixed] - Edit Slider, get wrong with: An invalid form control with name='image[image_0]' is not focusable.
* #1263 [fixed] - For forgot password Submit button should get disabled if user has already clicked on submit button.
* #1379 [fixed] - Cart rule not working in case of non-coupon if any condition is given.
* #1239 [fixed] - Filterable attributes should not display in layered navigation if there are no product in that particular category.
* #1351 [fixed] - Getting exception when assigning the root category to another category.
* #1372 [fixed] - Getting exception if while updating cart rule , if any option is selected from "How to Choose Products?".
* #1375 [fixed] - Wrong discount applied on cart in case of fixed discount.
* #1226 [fixed] - Product variation that has been ordered should display in customer order section in case of configurable product.
* #1391 [fixed] - By default attribute condition gets saved as 1 in db, because of which cart rule not getting applied.
* #1277 [fixed] - Getting exception on creating cart rules.
* #1334 [fixed] - On editing catalog rule data gets removed from Discount Amount field.
* #778 [fixed] - Error when add item to cart.
* #1253 [fixed] - Selected Channel for products get deselected after saving the product.
* #1319 [fixed] - Getting exception when click on Apply rules if conditions are left empty while creating catalog rule.
* #1295 [fixed] - Getting exception on changing the locale from cms page.
* #1233 [fixed] - Got exception on front-end when first time changes the locale ,the changed locale have rtl direction.
* #1235 [fixed] - Attributes are not visible in category page to select as filterable attribute if attributes name are not provided in particular locales.
* #1177 [fixed] - Getting exception when trying to recover password.
* #1228 [fixed] - Getting issue when entering direct url for customer account profile.
* #1229 [fixed] - Issue with currency in customer order section, currency code doesn't get converted at orders page of customer.
* #1234 [fixed] - After selecting direction to filter locale acc to direction no other field appears to select format.
* #1015 [fixed] - Adjust Paginator Number of Elements.
* #968 [fixed] - sorting is not working (price).
* #1190 [fixed] - After printing invoice at customer end, price is not getting change according to currency in invoice.
* #1209 [fixed] - There is an image issue while ordering any variant of configurable product.
* #1217 [fixed] - Layered navigation for price is not working, when click on bar it shifts to rightmost end.Getting this issue in case of configurable product only.
* #1216 [fixed] - Price filter of layered navigation not working properly in case of Multi Currency.
* #1130 [fixed] - If "does not contain" is used in case of Shipping method, then discount amount get implemented before selecting any shipping method.
* #1129 [fixed] - Discount not getting applied if "does not contain" condition is used from Actions for Payment Methods.
## **v0.1.6(28th of June, 2019)** - *Release*
* [feature] - Cart rules for providing discount with coupons and without coupons.

View File

@ -1,186 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class BagistoInstall extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bagisto:install';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command will try to configure and install new Bagisto instance';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$path = base_path('.env');
$uname = strtolower(\php_uname());
if (str_contains($uname, 'win'))
shell_exec('copy .env.example .env');
else
shell_exec('cp .env.example .env');
$this->line('Hello and welcome to Bagisto command line installer.');
$APP_NAME = $this->ask('[KEY = "APP_NAME"] Please enter name of application instance?');
$this->comment($APP_NAME ?? 'Bagisto');
$this->changeEnvironmentVariable('APP_NAME', $APP_NAME);
$APP_ENV = $this->choice('[KEY = "APP_ENV"] Choose environment for this instance of Bagisto?', ['development', 'production'], 0);
$this->comment($APP_ENV);
$this->changeEnvironmentVariable('APP_ENV', $APP_ENV);
// $APP_DEBUG = $this->ask('Choose APP_DEBUG?', ['true', 'false'], 0);
// $this->comment($APP_DEBUG);
// $this->changeEnvironmentVariable('APP_DEBUG', $APP_DEBUG);
$APP_URL = $this->ask('[KEY = "APP_URL"] Please enter application URL (Optional, default = localhost)?');
$this->comment($APP_URL ?? 'localhost');
$this->changeEnvironmentVariable('APP_URL', $APP_URL ?? 'http://localhost');
$DB_CONNECTION = $this->ask('[KEY = "DB_CONNECTION"] Enter database connection (Optional, default = mysql)?');
$this->comment($DB_CONNECTION ?? 'mysql');
$this->changeEnvironmentVariable('DB_CONNECTION', $DB_CONNECTION ?? 'mysql');
$DB_HOST = $this->ask('[KEY = "DB_HOST"] Enter database host (Optional, default = 127.0.0.1)?');
$this->comment($DB_HOST ?? '127.0.0.1');
$this->changeEnvironmentVariable('DB_HOST', $DB_HOST ?? '127.0.0.1');
$DB_PORT = $this->ask('[KEY = "DB_PORT"] Enter database port (Optional, default = 3306)?');
$this->comment($DB_PORT ?? '3306');
$this->changeEnvironmentVariable('DB_PORT', $DB_PORT ?? '3306');
$DB_DATABASE = null;
while (!isset($DB_DATABASE)) {
$DB_DATABASE = $this->ask('[KEY = "DB_DATABASE"] Enter name of database?');
$this->comment($DB_DATABASE ?? 'forge');
}
$this->changeEnvironmentVariable('DB_DATABASE', $DB_DATABASE ?? 'forge');
$DB_USERNAME = null;
while (!isset($DB_USERNAME)) {
$DB_USERNAME = $this->ask('Enter database username?');
$this->comment($DB_USERNAME ?? 'root');
}
$this->changeEnvironmentVariable('DB_USERNAME', $DB_USERNAME ?? root);
$DB_PASSWORD = $this->ask('Please enter database password?');
$this->comment($DB_PASSWORD);
$this->changeEnvironmentVariable('DB_PASSWORD', $DB_PASSWORD);
$this->info('We are done with application and database params, good job!');
$this->info('Do you want me to be mail ready, i am loaded with notifications!');
$MAIL_DRIVER = $this->ask('[KEY = "MAIL_DRIVER"] Enter MAIL_DRIVER (Optional, default = smtp)?');
$this->comment($MAIL_DRIVER ?? 'smtp');
$this->changeEnvironmentVariable('MAIL_DRIVER', $MAIL_DRIVER ?? 'smtp');
$MAIL_HOST = $this->ask('[KEY = "MAIL_HOST"] Enter MAIL_HOST (Optional, default = smtp.mailtrap.io)?');
$this->comment($MAIL_HOST ?? 'smtp.mailtrap.io');
$this->changeEnvironmentVariable('MAIL_HOST', $MAIL_HOST ?? 'smtp.mailtrap.io');
$MAIL_PORT = $this->ask('[KEY = "MAIL_PORT"] Enter MAIL_PORT (Optional, default = 2525)?');
$this->comment($MAIL_PORT ?? '2525');
$this->changeEnvironmentVariable('MAIL_PORT', $MAIL_PORT ?? '2525');
$MAIL_USERNAME = $this->ask('[KEY = "MAIL_USERNAME"] Enter MAIL_USERNAME?');
$this->comment($MAIL_USERNAME ?? null);
$this->changeEnvironmentVariable('MAIL_USERNAME', $MAIL_USERNAME ?? null);
$MAIL_PASSWORD = $this->ask('[KEY = "MAIL_PASSWORD"] Enter MAIL_PASSWORD?');
$this->comment($MAIL_PASSWORD ?? null);
$this->changeEnvironmentVariable('MAIL_PASSWORD', $MAIL_PASSWORD ?? null);
$MAIL_ENCRYPTION = $this->ask('[KEY = "MAIL_ENCRYPTION"] Enter MAIL_ENCRYPTION (default = tls)?');
$this->comment($MAIL_ENCRYPTION ?? 'tls');
$this->changeEnvironmentVariable('MAIL_ENCRYPTION', $MAIL_ENCRYPTION ?? 'tls');
$SHOP_MAIL_FROM = $this->ask('[KEY = "SHOP_MAIL_FROM"] Enter SHOP_MAIL_FROM?');
$this->comment($SHOP_MAIL_FROM ?? null);
$this->changeEnvironmentVariable('SHOP_MAIL_FROM', $SHOP_MAIL_FROM ?? null);
$ADMIN_MAIL_TO = $this->ask('[KEY = "ADMIN_MAIL_TO"] Enter ADMIN_MAIL_TO?');
$this->comment($ADMIN_MAIL_TO ?? null);
$this->changeEnvironmentVariable('ADMIN_MAIL_TO', $ADMIN_MAIL_TO ?? null);
$this->line('We are done setting all the configuration in the env file, now we will proceed by running the commands necessary for Bagisto');
$this->info('Running migrations...');
\Artisan::call('key:generate');
\Artisan::call('migrate');
$this->info('Migration completed.');
$this->info('Running seeders...');
\Artisan::call('db:seed', ['--force' => true]);
$this->info('Seeders finished.');
\Artisan::call('storage:link');
$this->info('Storage link created...');
\Artisan::call('vendor:publish', [0]);
$this->info('All provider tags are published...');
$this->info('Installation completed.');
$this->Line('Please write us: SUPPORT@BAGISTO.COM');
$this->Line('Thank you!!!');
}
public static function changeEnvironmentVariable($key, $value)
{
\Artisan::call('config:cache');
$path = base_path('.env');
if (file_exists($path)) {
file_put_contents($path, str_replace(
$key . '=' . env($key),
$key . '=' . $value,
file_get_contents($path)
));
}
\Artisan::call('config:cache');
}
}

View File

@ -31,8 +31,13 @@ return [
'route' => 'admin.sales.invoices.index',
'sort' => 3,
'icon-class' => ''
],
[
], [
'key' => 'sales.refunds',
'name' => 'admin::app.layouts.refunds',
'route' => 'admin.sales.refunds.index',
'sort' => 4,
'icon-class' => ''
], [
'key' => 'catalog',
'name' => 'admin::app.layouts.catalog',
'route' => 'admin.catalog.products.index',

View File

@ -0,0 +1,97 @@
<?php
namespace Webkul\Admin\DataGrids;
use Webkul\Ui\DataGrid\DataGrid;
use DB;
/**
* OrderRefundDataGrid Class
*
* @author Prashant Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class OrderRefundDataGrid extends DataGrid
{
protected $index = 'id';
protected $sortOrder = 'desc'; //asc or desc
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('refunds')
->select('refunds.id', 'refunds.order_id', 'refunds.state', 'refunds.base_grand_total', 'refunds.created_at')
->leftJoin('orders', 'refunds.order_id', '=', 'orders.id')
->leftJoin('order_address as order_address_billing', function($leftJoin) {
$leftJoin->on('order_address_billing.order_id', '=', 'orders.id')
->where('order_address_billing.address_type', 'billing');
})
->addSelect(DB::raw('CONCAT(order_address_billing.first_name, " ", order_address_billing.last_name) as billed_to'));
$this->addFilter('billed_to', DB::raw('CONCAT(order_address_billing.first_name, " ", order_address_billing.last_name)'));
$this->addFilter('id', 'refunds.id');
$this->addFilter('order_id', 'refunds.order_id');
$this->addFilter('state', 'refunds.state');
$this->addFilter('base_grand_total', 'refunds.base_grand_total');
$this->addFilter('created_at', 'refunds.created_at');
$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' => 'order_id',
'label' => trans('admin::app.datagrid.order-id'),
'type' => 'number',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'base_grand_total',
'label' => trans('admin::app.datagrid.refunded'),
'type' => 'price',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'billed_to',
'label' => trans('admin::app.datagrid.billed-to'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'created_at',
'label' => trans('admin::app.datagrid.refund-date'),
'type' => 'datetime',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
}
public function prepareActions() {
$this->addAction([
'title' => 'Order Refund View',
'method' => 'GET', // use GET request only for redirect purposes
'route' => 'admin.sales.refunds.view',
'icon' => 'icon eye-icon'
]);
}
}

View File

@ -286,7 +286,8 @@ class DashboardController extends Controller
private function getOrdersBetweenDate($start, $end)
{
return $this->order->scopeQuery(function ($query) use ($start, $end) {
return $query->where('orders.created_at', '>=', $start)->where('orders.created_at', '<=', $end);
return $query->where('orders.created_at', '>=', $start)->where('orders.created_at', '<=', $end)
->where('orders.status', '<>', 'canceled');
});
}

View File

@ -0,0 +1,163 @@
<?php
namespace Webkul\Admin\Http\Controllers\Sales;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Sales\Repositories\OrderItemRepository;
use Webkul\Sales\Repositories\RefundRepository;
/**
* Sales Refund controller
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class RefundController extends Controller
{
/**
* Display a listing of the resource.
*
* @var array
*/
protected $_config;
/**
* OrderRepository object
*
* @var Object
*/
protected $orderRepository;
/**
* OrderItemRepository object
*
* @var Object
*/
protected $orderItemRepository;
/**
* RefundRepository object
*
* @var Object
*/
protected $refundRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Sales\Repositories\OrderRepository $orderRepository
* @param \Webkul\Sales\Repositories\OrderItemRepository $orderItemRepository
* @param \Webkul\Sales\Repositories\RefundRepository $refundRepository
* @return void
*/
public function __construct(
OrderRepository $orderRepository,
OrderItemRepository $orderItemRepository,
RefundRepository $refundRepository
)
{
$this->middleware('admin');
$this->_config = request('_config');
$this->orderRepository = $orderRepository;
$this->orderItemRepository = $orderItemRepository;
$this->refundRepository = $refundRepository;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\View
*/
public function index()
{
return view($this->_config['view']);
}
/**
* Show the form for creating a new resource.
*
* @param int $orderId
* @return \Illuminate\Http\View
*/
public function create($orderId)
{
$order = $this->orderRepository->findOrFail($orderId);
return view($this->_config['view'], compact('order'));
}
/**
* Store a newly created resource in storage.
*
* @param int $orderId
* @return \Illuminate\Http\Response
*/
public function store($orderId)
{
$order = $this->orderRepository->findOrFail($orderId);
if (! $order->canRefund()) {
session()->flash('error', trans('admin::app.sales.refunds.creation-error'));
return redirect()->back();
}
$this->validate(request(), [
'refund.items.*' => 'required|numeric|min:0'
]);
$data = request()->all();
$totals = $this->refundRepository->getOrderItemsRefundSummary($data['refund']['items'], $orderId);
$maxRefundAmount = $totals['grand_total']['price'] - $order->refunds()->sum('base_adjustment_refund') + $order->refunds()->sum('base_adjustment_fee');
$refundAmount = $totals['grand_total']['price'] - $totals['shipping']['price'] + $data['refund']['shipping'] + $data['refund']['adjustment_refund'] - $data['refund']['adjustment_fee'];
if ($refundAmount > $maxRefundAmount) {
session()->flash('error', trans('admin::app.sales.refunds.refund-limit-error', ['amount' => core()->formatBasePrice($maxRefundAmount)]));
return redirect()->back();
}
$this->refundRepository->create(array_merge($data, ['order_id' => $orderId]));
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Refund']));
return redirect()->route($this->_config['redirect'], $orderId);
}
/**
* Store a newly created resource in storage.
*
* @param int $orderId
* @return \Illuminate\Http\JsonResponse
*/
public function updateQty($orderId)
{
$data = $this->refundRepository->getOrderItemsRefundSummary(request()->all(), $orderId);
if (! $data)
return response('');
return response()->json($data);
}
/**
* Show the view for the specified resource.
*
* @param int $id
* @return \Illuminate\Http\View
*/
public function view($id)
{
$refund = $this->refundRepository->findOrFail($id);
return view($this->_config['view'], compact('refund'));
}
}

View File

@ -196,6 +196,28 @@ Route::group(['middleware' => ['web']], function () {
Route::get('/shipments/view/{id}', 'Webkul\Admin\Http\Controllers\Sales\ShipmentController@view')->defaults('_config', [
'view' => 'admin::sales.shipments.view'
])->name('admin.sales.shipments.view');
// Sales Redunds Routes
Route::get('/refunds', 'Webkul\Admin\Http\Controllers\Sales\RefundController@index')->defaults('_config', [
'view' => 'admin::sales.refunds.index'
])->name('admin.sales.refunds.index');
Route::get('/refunds/create/{order_id}', 'Webkul\Admin\Http\Controllers\Sales\RefundController@create')->defaults('_config', [
'view' => 'admin::sales.refunds.create'
])->name('admin.sales.refunds.create');
Route::post('/refunds/create/{order_id}', 'Webkul\Admin\Http\Controllers\Sales\RefundController@store')->defaults('_config', [
'redirect' => 'admin.sales.orders.view'
])->name('admin.sales.refunds.store');
Route::post('/refunds/update-qty/{order_id}', 'Webkul\Admin\Http\Controllers\Sales\RefundController@updateQty')->defaults('_config', [
'redirect' => 'admin.sales.orders.view'
])->name('admin.sales.refunds.update_qty');
Route::get('/refunds/view/{id}', 'Webkul\Admin\Http\Controllers\Sales\RefundController@view')->defaults('_config', [
'view' => 'admin::sales.refunds.view'
])->name('admin.sales.refunds.view');
});
// Catalog Routes

View File

@ -51,7 +51,7 @@ class NewCustomerNotification extends Mailable
public function build()
{
return $this->to($this->customer->email)
->subject(trans('shop::app.mail.customer.subject'))
->subject(trans('shop::app.mail.customer.new.subject'))
->view('shop::emails.customer.new-customer')->with(['customer' => $this->customer, 'password' => $this->password]);
}
}

View File

@ -556,6 +556,7 @@ body {
tr {
td {
padding: 5px 8px;
vertical-align: text-bottom;
}
&.bold {

View File

@ -146,6 +146,7 @@ return [
'role' => 'الدور',
'sub-total' => 'المجموع الفرعي',
'no-of-products' => 'عدد المنتجات',
'refunded' => 'Refunded'
],
'account' => [
'title' => 'حسابي',
@ -262,6 +263,7 @@ return [
'item-invoice' => '3-الفواتير (:qty_invoiced)',
'item-shipped' => 'شحنت (:qty_shipped)',
'item-canceled' => 'ملغاة (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'Price',
'total' => 'المجموع',
'subtotal' => 'المجموع الفرعي',
@ -276,7 +278,9 @@ return [
'total-paid' => 'المجموع المدفوع',
'total-refunded' => 'مجموع المبالغ المستردة',
'total-due' => 'المجموع المستحق',
'cancel-confirm-msg' => 'هل أنت متأكد من أنك تريد إلغاء هذا الطلب ؟'
'cancel-confirm-msg' => 'هل أنت متأكد من أنك تريد إلغاء هذا الطلب ؟',
'refunds' => 'Refunds',
'refunded' => 'Refunded'
],
'invoices' => [
'title' => 'الفواتير',
@ -301,6 +305,7 @@ return [
'creation-error' => 'لا يسمح بإنشاء الفواتير.',
'product-error' => 'ولا يمكن إعداد الفاتورة بدون منتجات.'
],
'shipments' => [
'title' => 'الشحنات',
'id' => 'Id',
@ -325,6 +330,27 @@ return [
'creation-error' => 'لا يمكن إنشاء الشحنة لهذا الطلب.',
'order-error' => 'لا يسمح بإنشاء شحنة الطلب.',
'quantity-invalid' => 'الكمية المطلوبة غير صالحة أو غير متاحة.',
],
'refunds' => [
'title' => 'Refunds',
'id' => 'Id',
'add-title' => 'Create Refund',
'save-btn-title' => 'Refund',
'order-id' => 'Order Id',
'qty-ordered' => 'Qty Ordered',
'qty-to-refund' => 'Qty To Refund',
'refund-shipping' => 'Refund Shipping',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
'update-qty' => 'Update Quantities',
'invalid-qty' => 'Found invalid quantity for return items.',
'refund-limit-error' => 'The most money available to refund is :amount.',
'refunded' => 'Refunded',
'date' => 'Refund Date',
'customer-name' => 'Customer Name',
'status' => 'Status',
'action' => 'Action'
]
],
'catalog' => [

View File

@ -50,6 +50,7 @@ return [
'orders' => 'Orders',
'shipments' => 'Shipments',
'invoices' => 'Invoices',
'refunds' => 'Refunds',
'catalog' => 'Catalog',
'products' => 'Products',
'categories' => 'Categories',
@ -131,7 +132,7 @@ return [
'order-count' => ':count Orders',
'revenue' => 'Revenue :total',
'stock-threshold' => 'Stock Threshold',
'qty-left' => ':qty Left',
'qty-left' => ':qty Left'
],
'datagrid' => [
@ -198,7 +199,9 @@ return [
'per-cust' => 'Per Customer',
'usage-throttle' => 'Usage Times',
'for-guest' => 'For Guest',
'order_number' => 'Order Number'
'order_number' => 'Order Number',
'refund-date' => 'Refund Date',
'refunded' => 'Refunded'
],
'account' => [
@ -321,6 +324,7 @@ return [
'item-invoice' => 'Invoiced (:qty_invoiced)',
'item-shipped' => 'shipped (:qty_shipped)',
'item-canceled' => 'Canceled (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'Price',
'total' => 'Total',
'subtotal' => 'Subtotal',
@ -335,7 +339,9 @@ return [
'total-paid' => 'Total Paid',
'total-refunded' => 'Total Refunded',
'total-due' => 'Total Due',
'cancel-confirm-msg' => 'Are you sure you want to cancel this order ?'
'cancel-confirm-msg' => 'Are you sure you want to cancel this order ?',
'refund-btn-title' => 'Refund',
'refunds' => 'Refunds'
],
'invoices' => [
@ -386,6 +392,28 @@ return [
'creation-error' => 'Shipment can not be created for this order.',
'order-error' => 'Order shipment creation is not allowed.',
'quantity-invalid' => 'Requested quantity is invalid or not available.',
],
'refunds' => [
'title' => 'Refunds',
'id' => 'Id',
'add-title' => 'Create Refund',
'save-btn-title' => 'Refund',
'order-id' => 'Order Id',
'qty-ordered' => 'Qty Ordered',
'qty-to-refund' => 'Qty To Refund',
'refund-shipping' => 'Refund Shipping',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
'update-qty' => 'Update Quantities',
'invalid-qty' => 'Found invalid quantity for return items.',
'refund-limit-error' => 'The most money available to refund is :amount.',
'refunded' => 'Refunded',
'date' => 'Refund Date',
'customer-name' => 'Customer Name',
'status' => 'Status',
'action' => 'Action',
'view-title' => 'Refund #:refund_id',
]
],

View File

@ -166,7 +166,8 @@ return [
'action_type' => 'نوع عملیات',
'disc_quantity' => 'مقدار استفاده نشده',
'disc_threshold' => 'آستانه استفاده نشده',
'use_coupon' => 'استافده از کوپن'
'use_coupon' => 'استافده از کوپن',
'refunded' => 'Refunded'
],
'account' => [
@ -289,6 +290,7 @@ return [
'item-invoice' => 'صورت حساب (:qty_invoiced)',
'item-shipped' => 'حمل شده (:qty_shipped)',
'item-canceled' => 'لغو شده (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'قیمت',
'total' => 'کل',
'subtotal' => 'فرعی',
@ -302,7 +304,9 @@ return [
'total-paid' => 'کل پرداخت شده',
'total-refunded' => 'بازپرداخت کل',
'total-due' => 'بدهی کل',
'cancel-confirm-msg' => 'مطمئن هستید که می خواهید این سفارش را لغو کنید ؟'
'cancel-confirm-msg' => 'مطمئن هستید که می خواهید این سفارش را لغو کنید ؟',
'refunds' => 'Refunds',
'refunded' => 'Refunded'
],
'invoices' => [
@ -353,6 +357,27 @@ return [
'creation-error' => 'حمل و نقل برای این سفارش ایجاد نمی شود.',
'order-error' => 'ایجاد محموله سفارش مجاز نیست.',
'quantity-invalid' => 'مقدار درخواستی نامعتبر است یا در دسترس نیست.',
],
'refunds' => [
'title' => 'Refunds',
'id' => 'Id',
'add-title' => 'Create Refund',
'save-btn-title' => 'Refund',
'order-id' => 'Order Id',
'qty-ordered' => 'Qty Ordered',
'qty-to-refund' => 'Qty To Refund',
'refund-shipping' => 'Refund Shipping',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
'update-qty' => 'Update Quantities',
'invalid-qty' => 'Found invalid quantity for return items.',
'refund-limit-error' => 'The most money available to refund is :amount.',
'refunded' => 'Refunded',
'date' => 'Refund Date',
'customer-name' => 'Customer Name',
'status' => 'Status',
'action' => 'Action'
]
],

View File

@ -154,7 +154,8 @@ return [
'ends-till' => 'Termina Até',
'per-cust' => 'Por cliente',
'usage-throttle' => 'Tempos de uso',
'for-guest' => 'Para convidados'
'for-guest' => 'Para convidados',
'refunded' => 'Refunded'
],
'account' => [
'title' => 'Minha Conta',
@ -270,6 +271,7 @@ return [
'item-invoice' => 'Faturado(s) (:qty_invoiced)',
'item-shipped' => 'Enviado(s) (:qty_shipped)',
'item-canceled' => 'Cancelado(s) (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'Preço',
'total' => 'Total',
'subtotal' => 'Subtotal',
@ -284,7 +286,9 @@ return [
'total-paid' => 'Total Pago',
'total-refunded' => 'Total Estornado',
'total-due' => 'Total Devido',
'cancel-confirm-msg' => 'Tem certeza que deseja cancelar esse pedido ?'
'cancel-confirm-msg' => 'Tem certeza que deseja cancelar esse pedido ?',
'refunds' => 'Refunds',
'refunded' => 'Refunded'
],
'invoices' => [
'title' => 'Faturas',
@ -309,6 +313,7 @@ return [
'creation-error' => 'A criação de fatura de pedido não é permitida.',
'product-error' => 'A fatura não pode ser criada sem produtos.'
],
'shipments' => [
'title' => 'Entregas',
'id' => 'Id',
@ -333,6 +338,27 @@ return [
'creation-error' => 'A expedição não pode ser criada para este pedido.',
'order-error' => 'A criação de remessa de pedidos não é permitida.',
'quantity-invalid' => 'A quantidade solicitada é inválida ou não está disponível.'
],
'refunds' => [
'title' => 'Refunds',
'id' => 'Id',
'add-title' => 'Create Refund',
'save-btn-title' => 'Refund',
'order-id' => 'Order Id',
'qty-ordered' => 'Qty Ordered',
'qty-to-refund' => 'Qty To Refund',
'refund-shipping' => 'Refund Shipping',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
'update-qty' => 'Update Quantities',
'invalid-qty' => 'Found invalid quantity for return items.',
'refund-limit-error' => 'The most money available to refund is :amount.',
'refunded' => 'Refunded',
'date' => 'Refund Date',
'customer-name' => 'Customer Name',
'status' => 'Status',
'action' => 'Action'
]
],
'catalog' => [

View File

@ -31,6 +31,12 @@
</a>
@endif
@if ($order->canRefund())
<a href="{{ route('admin.sales.refunds.create', $order->id) }}" class="btn btn-lg btn-primary">
{{ __('admin::app.sales.orders.refund-btn-title') }}
</a>
@endif
@if ($order->canShip())
<a href="{{ route('admin.sales.shipments.create', $order->id) }}" class="btn btn-lg btn-primary">
{{ __('admin::app.sales.orders.shipment-btn-title') }}
@ -274,6 +280,10 @@
{{ $item->qty_shipped ? __('admin::app.sales.orders.item-shipped', ['qty_shipped' => $item->qty_shipped]) : '' }}
</span>
<span class="qty-row">
{{ $item->qty_refunded ? __('admin::app.sales.orders.item-refunded', ['qty_refunded' => $item->qty_refunded]) : '' }}
</span>
<span class="qty-row">
{{ $item->qty_canceled ? __('admin::app.sales.orders.item-canceled', ['qty_canceled' => $item->qty_canceled]) : '' }}
</span>
@ -440,6 +450,50 @@
</div>
</tab>
<tab name="{{ __('admin::app.sales.orders.refunds') }}">
<div class="table" style="padding: 20px 0">
<table>
<thead>
<tr>
<th>{{ __('admin::app.sales.refunds.id') }}</th>
<th>{{ __('admin::app.sales.refunds.date') }}</th>
<th>{{ __('admin::app.sales.refunds.order-id') }}</th>
<th>{{ __('admin::app.sales.refunds.customer-name') }}</th>
<th>{{ __('admin::app.sales.refunds.status') }}</th>
<th>{{ __('admin::app.sales.refunds.refunded') }}</th>
<th>{{ __('admin::app.sales.refunds.action') }}</th>
</tr>
</thead>
<tbody>
@foreach ($order->refunds as $refund)
<tr>
<td>#{{ $refund->id }}</td>
<td>{{ $refund->created_at }}</td>
<td>#{{ $refund->order->id }}</td>
<td>{{ $refund->order->customer_full_name }}</td>
<td>{{ __('admin::app.sales.refunds.refunded') }}</td>
<td>{{ core()->formatBasePrice($refund->base_grand_total) }}</td>
<td class="action">
<a href="{{ route('admin.sales.refunds.view', $refund->id) }}">
<i class="icon eye-icon"></i>
</a>
</td>
</tr>
@endforeach
@if (! $order->refunds->count())
<tr>
<td class="empty" colspan="7">{{ __('admin::app.common.no-result-found') }}</td>
<tr>
@endif
</table>
</div>
</tab>
</tabs>
</div>

View File

@ -0,0 +1,404 @@
@extends('admin::layouts.master')
@section('page_title')
{{ __('admin::app.sales.refunds.add-title') }}
@stop
@section('content-wrapper')
<div class="content full-page">
<form method="POST" action="{{ route('admin.sales.refunds.store', $order->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.sales.refunds.add-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.sales.refunds.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="sale-container">
<accordian :title="'{{ __('admin::app.sales.orders.order-and-account') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.order-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.refunds.order-id') }}
</span>
<span class="value">
<a href="{{ route('admin.sales.orders.view', $order->id) }}">#{{ $order->id }}</a>
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-date') }}
</span>
<span class="value">
{{ $order->created_at }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-status') }}
</span>
<span class="value">
{{ $order->status_label }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.channel') }}
</span>
<span class="value">
{{ $order->channel_name }}
</span>
</div>
</div>
</div>
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.account-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.customer-name') }}
</span>
<span class="value">
{{ $order->customer_full_name }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.email') }}
</span>
<span class="value">
{{ $order->customer_email }}
</span>
</div>
</div>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.payment-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.payment-method') }}
</span>
<span class="value">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.currency') }}
</span>
<span class="value">
{{ $order->order_currency_code }}
</span>
</div>
</div>
</div>
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>
</div>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.products-ordered') }}'" :active="true">
<div slot="body">
<refund-items></refund-items>
</div>
</accordian>
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script type="text/x-template" id="refund-items-template">
<div>
<div class="table">
<table>
<thead>
<tr>
<th>{{ __('admin::app.sales.orders.SKU') }}</th>
<th>{{ __('admin::app.sales.orders.product-name') }}</th>
<th>{{ __('admin::app.sales.orders.subtotal') }}</th>
<th>{{ __('admin::app.sales.orders.tax-amount') }}</th>
@if ($order->base_discount_amount > 0)
<th>{{ __('admin::app.sales.orders.discount-amount') }}</th>
@endif
<th>{{ __('admin::app.sales.orders.grand-total') }}</th>
<th>{{ __('admin::app.sales.refunds.qty-ordered') }}</th>
<th>{{ __('admin::app.sales.refunds.qty-to-refund') }}</th>
</tr>
</thead>
<tbody>
@foreach ($order->items as $item)
<tr>
<td>{{ $item->type == 'configurable' ? $item->child->sku : $item->sku }}</td>
<td>
{{ $item->name }}
@if ($html = $item->getOptionDetailHtml())
<p>{{ $html }}</p>
@endif
</td>
<td>{{ core()->formatBasePrice($item->base_price) }}</td>
<td>{{ core()->formatBasePrice($item->base_tax_amount) }}</td>
@if ($order->base_discount_amount > 0)
<td>{{ core()->formatBasePrice($item->base_discount_amount) }}</td>
@endif
<td>{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount - $item->base_discount_amount) }}</td>
<td>{{ $item->qty_ordered }}</td>
<td>
<div class="control-group" :class="[errors.has('refund[items][{{ $item->id }}]') ? 'has-error' : '']">
<input type="text" v-validate="'required|numeric|min:0'" class="control" id="refund[items][{{ $item->id }}]" name="refund[items][{{ $item->id }}]" v-model="refund.items[{{ $item->id }}]" data-vv-as="&quot;{{ __('admin::app.sales.refunds.qty-to-refund') }}&quot;"/>
<span class="control-error" v-if="errors.has('refund[items][{{ $item->id }}]')">
@verbatim
{{ errors.first('refund[items][<?php echo $item->id ?>]') }}
@endverbatim
</span>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div style="width: 100%; display: inline-block">
<button type="button" class="btn btn-lg btn-primary" style="float: right" @click="updateQty">
{{ __('admin::app.sales.refunds.update-qty') }}
</button>
</div>
<table v-if="refund.summary" class="sale-summary">
<tr>
<td>{{ __('admin::app.sales.orders.subtotal') }}</td>
<td>-</td>
<td>@{{ refund.summary.subtotal.formated_price }}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.orders.discount') }}</td>
<td>-</td>
<td>-@{{ refund.summary.discount.formated_price }}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.refunds.refund-shipping') }}</td>
<td>-</td>
<td>
<div class="control-group" :class="[errors.has('refund[shipping]') ? 'has-error' : '']" style="width: 100px; margin-bottom: 0;">
<input type="text" v-validate="'required|min_value:0|max_value:{{$order->base_shipping_invoiced - $order->base_shipping_refunded}}'" class="control" id="refund[shipping]" name="refund[shipping]" :value="refund.summary.shipping.price" data-vv-as="&quot;{{ __('admin::app.sales.refunds.refund-shipping') }}&quot;" style="width: 100%; margin: 0"/>
<span class="control-error" v-if="errors.has('refund[shipping]')">
@{{ errors.first('refund[shipping]') }}
</span>
</div>
</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.refunds.adjustment-refund') }}</td>
<td>-</td>
<td>
<div class="control-group" :class="[errors.has('refund[adjustment_refund]') ? 'has-error' : '']" style="width: 100px; margin-bottom: 0;">
<input type="text" v-validate="'required|min_value:0'" class="control" id="refund[adjustment_refund]" name="refund[adjustment_refund]" value="0" data-vv-as="&quot;{{ __('admin::app.sales.refunds.adjustment-refund') }}&quot;" style="width: 100%; margin: 0"/>
<span class="control-error" v-if="errors.has('refund[adjustment_refund]')">
@{{ errors.first('refund[adjustment_refund]') }}
</span>
</div>
</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.refunds.adjustment-fee') }}</td>
<td>-</td>
<td>
<div class="control-group" :class="[errors.has('refund[adjustment_fee]') ? 'has-error' : '']" style="width: 100px; margin-bottom: 0;">
<input type="text" v-validate="'required|min_value:0'" class="control" id="refund[adjustment_fee]" name="refund[adjustment_fee]" value="0" data-vv-as="&quot;{{ __('admin::app.sales.refunds.adjustment-fee') }}&quot;" style="width: 100%; margin: 0"/>
<span class="control-error" v-if="errors.has('refund[adjustment_fee]')">
@{{ errors.first('refund[adjustment_fee]') }}
</span>
</div>
</td>
</tr>
<tr class="border">
<td>{{ __('admin::app.sales.orders.tax') }}</td>
<td>-</td>
<td>@{{ refund.summary.tax.formated_price }}</td>
</tr>
<tr class="bold">
<td>{{ __('admin::app.sales.orders.grand-total') }}</td>
<td>-</td>
<td>@{{ refund.summary.grand_total.formated_price }}</td>
</tr>
</table>
</div>
</script>
<script>
Vue.component('refund-items', {
template: '#refund-items-template',
inject: ['$validator'],
data: function() {
return {
refund: {
items: {},
summary: null
}
}
},
mounted: function() {
@foreach ($order->items as $item)
this.refund.items[{{$item->id}}] = {{ $item->qty_to_refund }};
@endforeach
this.updateQty();
},
methods: {
updateQty: function() {
var this_this = this;
this.$http.post("{{ route('admin.sales.refunds.update_qty', $order->id) }}", this.refund.items)
.then(function(response) {
if (! response.data) {
window.flashMessages = [{
'type': 'alert-error',
'message': "{{ __('admin::app.sales.refunds.invalid-qty') }}"
}];
this_this.$root.addFlashMessages()
} else {
this_this.refund.summary = response.data;
}
})
.catch(function (error) {})
}
}
});
</script>
@endpush

View File

@ -0,0 +1,42 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.sales.refunds.title') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.sales.refunds.title') }}</h1>
</div>
<div class="page-action">
<div class="export-import" @click="showModal('downloadDataGrid')">
<i class="export-icon"></i>
<span>
{{ __('admin::app.export.export') }}
</span>
</div>
</div>
</div>
<div class="page-content">
@inject('refundGrid', 'Webkul\Admin\DataGrids\OrderRefundDataGrid')
{!! $refundGrid->render() !!}
</div>
</div>
<modal id="downloadDataGrid" :is-open="modalIds.downloadDataGrid">
<h3 slot="header">{{ __('admin::app.export.download') }}</h3>
<div slot="body">
<export-form></export-form>
</div>
</modal>
@stop
@push('scripts')
@include('admin::export.export', ['gridName' => $refundGrid])
@endpush

View File

@ -0,0 +1,314 @@
@extends('admin::layouts.master')
@section('page_title')
{{ __('admin::app.sales.refunds.view-title', ['refund_id' => $refund->id]) }}
@stop
@section('content-wrapper')
<?php $order = $refund->order; ?>
<div class="content full-page">
<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.sales.refunds.view-title', ['refund_id' => $refund->id]) }}
</h1>
</div>
<div class="page-action">
</div>
</div>
<div class="page-content">
<div class="sale-container">
<accordian :title="'{{ __('admin::app.sales.orders.order-and-account') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.order-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.refunds.order-id') }}
</span>
<span class="value">
<a href="{{ route('admin.sales.orders.view', $order->id) }}">#{{ $order->id }}</a>
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-date') }}
</span>
<span class="value">
{{ $order->created_at }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-status') }}
</span>
<span class="value">
{{ $order->status_label }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.channel') }}
</span>
<span class="value">
{{ $order->channel_name }}
</span>
</div>
</div>
</div>
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.account-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.customer-name') }}
</span>
<span class="value">
{{ $refund->order->customer_full_name }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.email') }}
</span>
<span class="value">
{{ $refund->order->customer_email }}
</span>
</div>
</div>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.payment-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.payment-method') }}
</span>
<span class="value">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.currency') }}
</span>
<span class="value">
{{ $order->order_currency_code }}
</span>
</div>
</div>
</div>
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>
</div>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.products-ordered') }}'" :active="true">
<div slot="body">
<div class="table">
<table>
<thead>
<tr>
<th>{{ __('admin::app.sales.orders.SKU') }}</th>
<th>{{ __('admin::app.sales.orders.product-name') }}</th>
<th>{{ __('admin::app.sales.orders.price') }}</th>
<th>{{ __('admin::app.sales.orders.qty') }}</th>
<th>{{ __('admin::app.sales.orders.subtotal') }}</th>
<th>{{ __('admin::app.sales.orders.tax-amount') }}</th>
@if ($refund->base_discount_amount > 0)
<th>{{ __('admin::app.sales.orders.discount-amount') }}</th>
@endif
<th>{{ __('admin::app.sales.orders.grand-total') }}</th>
</tr>
</thead>
<tbody>
@foreach ($refund->items as $item)
<tr>
<td>{{ $item->child ? $item->child->sku : $item->sku }}</td>
<td>
{{ $item->name }}
@if ($html = $item->getOptionDetailHtml())
<p>{{ $html }}</p>
@endif
</td>
<td>{{ core()->formatBasePrice($item->base_price) }}</td>
<td>{{ $item->qty }}</td>
<td>{{ core()->formatBasePrice($item->base_total) }}</td>
<td>{{ core()->formatBasePrice($item->base_tax_amount) }}</td>
@if ($refund->base_discount_amount > 0)
<td>{{ core()->formatBasePrice($item->base_discount_amount) }}</td>
@endif
<td>{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount - $item->base_discount_amount) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<table class="sale-summary">
<tr>
<td>{{ __('admin::app.sales.orders.subtotal') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_sub_total) }}</td>
</tr>
@if ($refund->base_shipping_amount > 0)
<tr>
<td>{{ __('admin::app.sales.orders.shipping-handling') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_shipping_amount) }}</td>
</tr>
@endif
@if ($refund->base_tax_amount > 0)
<tr>
<td>{{ __('admin::app.sales.orders.tax') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_tax_amount) }}</td>
</tr>
@endif
@if ($refund->base_discount_amount > 0)
<tr>
<td>{{ __('admin::app.sales.orders.discount') }}</td>
<td>-</td>
<td>-{{ core()->formatBasePrice($refund->base_discount_amount) }}</td>
</tr>
@endif
<tr>
<td>{{ __('admin::app.sales.refunds.adjustment-refund') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_adjustment_refund) }}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.refunds.adjustment-fee') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_adjustment_fee) }}</td>
</tr>
<tr class="bold">
<td>{{ __('admin::app.sales.orders.grand-total') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($refund->base_grand_total) }}</td>
</tr>
</table>
</div>
</accordian>
</div>
</div>
</div>
@stop

View File

@ -133,6 +133,32 @@ class CustomerController extends Controller
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$id = auth()->guard('customer')->user()->id;
$customer = $this->customer->findorFail($id);
try {
$this->customer->delete($id);
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Customer']));
return redirect()->route($this->_config['redirect']);
} catch(\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Customer']));
return redirect()->route($this->_config['redirect']);
}
}
/**
* Load the view for the customer account panel, showing approved reviews.
*

View File

@ -6,6 +6,7 @@ use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Webkul\Customer\Mail\RegistrationEmail;
use Webkul\Customer\Mail\VerificationEmail;
use Illuminate\Routing\Controller;
use Webkul\Customer\Repositories\CustomerRepository;
@ -97,6 +98,15 @@ class RegistrationController extends Controller
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
} else {
try {
Mail::queue(new RegistrationEmail(request()->all()));
session()->flash('success', trans('shop::app.customer.signup-form.success-verify')); //customer registered successfully
} catch (\Exception $e) {
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
session()->flash('success', trans('shop::app.customer.signup-form.success'));
}

View File

@ -0,0 +1,38 @@
<?php
namespace Webkul\Customer\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
/**
* Registration Mail class
*
* @author Prateek Srivastava
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class RegistrationEmail extends Mailable
{
use Queueable, SerializesModels;
public $data;
public function __construct($data) {
$this->data = $data;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->to($this->data['email'])
->from(env('SHOP_MAIL_FROM'))
->subject(trans('shop::app.mail.customer.registration.customer-registration'))
->view('shop::emails.customer.registration')->with('data', $this->data);
}
}

View File

@ -32,7 +32,7 @@ class VerificationEmail extends Mailable
{
return $this->to($this->verificationData['email'])
->from(env('SHOP_MAIL_FROM'))
->subject('Verification email')
->subject(trans('shop::app.mail.customer.verification.subject'))
->view('shop::emails.customer.verification-email')->with('data', ['email' => $this->verificationData['email'], 'token' => $this->verificationData['token']]);
}
}

View File

@ -182,7 +182,7 @@ class ConvertXToProductId
])->flatten()->all();
} else if ($testCondition == '=') {
$foundProducts = $this->product->findWhere([
['sku', '=', '%'.$testValue.'%'],
['sku', '=', $testValue],
['type', '!=', 'configurable']
])->flatten()->all();
}

View File

@ -171,7 +171,7 @@ class ConvertXToProductId
])->flatten()->all();
} else if ($testCondition == '=') {
$foundProducts = $this->product->findWhere([
['sku', '=', '%' . $testValue . '%'],
['sku', '=', $testValue],
['type', '!=', 'configurable']
])->flatten()->all();
}

View File

@ -7,7 +7,7 @@ return [
'class' => 'Webkul\Payment\Payment\CashOnDelivery',
'active' => true,
'sort' => 1,
'default' => 'no'
'default' => 'yes'
],
'moneytransfer' => [
@ -17,7 +17,7 @@ return [
'class' => 'Webkul\Payment\Payment\MoneyTransfer',
'active' => true,
'sort' => 2,
'default' => 'yes'
'default' => 'no'
],
'paypal_standard' => [

View File

@ -105,9 +105,9 @@ class Ipn
*/
protected function processOrder()
{
if ($this->post['payment_status'] == 'completed') {
if ($this->post['payment_status'] == 'Completed') {
if ($this->post['mc_gross'] != $this->order->grand_total) {
} else {
$this->orderRepository->update(['status' => 'processing'], $this->order->id);

View File

@ -8,9 +8,9 @@ Route::group(['middleware' => ['web']], function () {
Route::get('/success', 'Webkul\Paypal\Http\Controllers\StandardController@success')->name('paypal.standard.success');
Route::get('/cancel', 'Webkul\Paypal\Http\Controllers\StandardController@cancel')->name('paypal.standard.cancel');
Route::get('/ipn', 'Webkul\Paypal\Http\Controllers\StandardController@ipn')->name('paypal.standard.ipn');
Route::post('/ipn', 'Webkul\Paypal\Http\Controllers\StandardController@ipn')->name('paypal.standard.ipn');
});
});
Route::get('paypal/standard/ipn', 'Webkul\Paypal\Http\Controllers\StandardController@ipn')->name('paypal.standard.ipn');
Route::post('paypal/standard/ipn', 'Webkul\Paypal\Http\Controllers\StandardController@ipn')->name('paypal.standard.ipn');

View File

@ -129,7 +129,7 @@ class ProductController extends Controller
*/
public function store()
{
if (!request()->get('family') && request()->input('type') == 'configurable' && request()->input('sku') != '') {
if (! request()->get('family') && request()->input('type') == 'configurable' && request()->input('sku') != '') {
return redirect(url()->current() . '?family=' . request()->input('attribute_family_id') . '&sku=' . request()->input('sku'));
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Sales\Contracts;
interface Refund
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Sales\Contracts;
interface RefundItem
{
}

View File

@ -0,0 +1,65 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRefundsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('refunds', function (Blueprint $table) {
$table->increments('id');
$table->string('increment_id')->nullable();
$table->string('state')->nullable();
$table->boolean('email_sent')->default(0);
$table->integer('total_qty')->nullable();
$table->string('base_currency_code')->nullable();
$table->string('channel_currency_code')->nullable();
$table->string('order_currency_code')->nullable();
$table->decimal('adjustment_refund', 12, 4)->default(0)->nullable();
$table->decimal('base_adjustment_refund', 12, 4)->default(0)->nullable();
$table->decimal('adjustment_fee', 12, 4)->default(0)->nullable();
$table->decimal('base_adjustment_fee', 12, 4)->default(0)->nullable();
$table->decimal('sub_total', 12, 4)->default(0)->nullable();
$table->decimal('base_sub_total', 12, 4)->default(0)->nullable();
$table->decimal('grand_total', 12, 4)->default(0)->nullable();
$table->decimal('base_grand_total', 12, 4)->default(0)->nullable();
$table->decimal('shipping_amount', 12, 4)->default(0)->nullable();
$table->decimal('base_shipping_amount', 12, 4)->default(0)->nullable();
$table->decimal('tax_amount', 12, 4)->default(0)->nullable();
$table->decimal('base_tax_amount', 12, 4)->default(0)->nullable();
$table->decimal('discount_percent', 12, 4)->default(0)->nullable();
$table->decimal('discount_amount', 12, 4)->default(0)->nullable();
$table->decimal('base_discount_amount', 12, 4)->default(0)->nullable();
$table->integer('order_id')->unsigned()->nullable();
$table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('refunds');
}
}

View File

@ -0,0 +1,62 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRefundItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('refund_items', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->string('description')->nullable();
$table->string('sku')->nullable();
$table->integer('qty')->nullable();
$table->decimal('price', 12,4)->default(0);
$table->decimal('base_price', 12,4)->default(0);
$table->decimal('total', 12,4)->default(0);
$table->decimal('base_total', 12,4)->default(0);
$table->decimal('tax_amount', 12,4)->default(0)->nullable();
$table->decimal('base_tax_amount', 12,4)->default(0)->nullable();
$table->decimal('discount_percent', 12, 4)->default(0)->nullable();
$table->decimal('discount_amount', 12, 4)->default(0)->nullable();
$table->decimal('base_discount_amount', 12, 4)->default(0)->nullable();
$table->integer('product_id')->unsigned()->nullable();
$table->string('product_type')->nullable();
$table->integer('order_item_id')->unsigned()->nullable();
$table->foreign('order_item_id')->references('id')->on('order_items')->onDelete('cascade');
$table->integer('refund_id')->unsigned()->nullable();
$table->foreign('refund_id')->references('id')->on('refunds')->onDelete('cascade');
$table->integer('parent_id')->unsigned()->nullable();
$table->foreign('parent_id')->references('id')->on('refund_items')->onDelete('cascade');
$table->json('additional')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('refund_items');
}
}

View File

@ -74,6 +74,14 @@ class Order extends Model implements OrderContract
{
return $this->hasMany(InvoiceProxy::modelClass());
}
/**
* Get the order refunds record associated with the order.
*/
public function refunds()
{
return $this->hasMany(RefundProxy::modelClass());
}
/**
* Get the customer record associated with the order.
@ -148,9 +156,8 @@ class Order extends Model implements OrderContract
return false;
foreach ($this->items as $item) {
if ($item->qty_to_ship > 0) {
if ($item->qty_to_ship > 0)
return true;
}
}
return false;
@ -165,16 +172,15 @@ class Order extends Model implements OrderContract
return false;
foreach ($this->items as $item) {
if ($item->qty_to_invoice > 0) {
if ($item->qty_to_invoice > 0)
return true;
}
}
return false;
}
/**
* Checks if order could can canceled on not
* Checks if order can be canceled or not
*/
public function canCancel()
{
@ -182,11 +188,29 @@ class Order extends Model implements OrderContract
return false;
foreach ($this->items as $item) {
if ($item->qty_to_cancel > 0) {
if ($item->qty_to_cancel > 0)
return true;
}
}
return false;
}
/**
* Checks if order can be refunded or not
*/
public function canRefund()
{
if ($this->status == 'fraud')
return false;
foreach ($this->items as $item) {
if ($item->qty_to_refund > 0)
return true;
}
if ($this->base_grand_total_invoiced - $this->base_grand_total_refunded > 0)
return true;
return false;
}
}

View File

@ -38,6 +38,14 @@ class OrderItem extends Model implements OrderItemContract
return $this->qty_ordered - $this->qty_canceled - $this->qty_invoiced;
}
/**
* Get remaining qty for refund.
*/
public function getQtyToRefundAttribute()
{
return $this->qty_invoiced - $this->qty_refunded;
}
/**
* Get the order record associated with the order item.
*/
@ -78,6 +86,14 @@ class OrderItem extends Model implements OrderItemContract
return $this->hasMany(ShipmentItemProxy::modelClass());
}
/**
* Get the refund items record associated with the order item.
*/
public function refund_items()
{
return $this->hasMany(RefundItemProxy::modelClass());
}
/**
* Returns configurable option html
*/
@ -94,4 +110,22 @@ class OrderItem extends Model implements OrderItemContract
return implode(', ', $labels);
}
}
/**
* @return array
*/
public function toArray()
{
$array = parent::toArray();
$array['qty_to_ship'] = $this->qty_to_ship;
$array['qty_to_invoice'] = $this->qty_to_invoice;
$array['qty_to_cancel'] = $this->qty_to_cancel;
$array['qty_to_refund'] = $this->qty_to_refund;
return $array;
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Webkul\Sales\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Sales\Contracts\Refund as RefundContract;
class Refund extends Model implements RefundContract
{
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $statusLabel = [
];
/**
* Returns the status label from status code
*/
public function getStatusLabelAttribute()
{
return isset($this->statusLabel[$this->state]) ? $this->statusLabel[$this->state] : '';
}
/**
* Get the order that belongs to the Refund.
*/
public function order()
{
return $this->belongsTo(OrderProxy::modelClass());
}
/**
* Get the Refund items record associated with the Refund.
*/
public function items() {
return $this->hasMany(RefundItemProxy::modelClass())->whereNull('parent_id');
}
/**
* Get the customer record associated with the Refund.
*/
public function customer()
{
return $this->morphTo();
}
/**
* Get the channel record associated with the Refund.
*/
public function channel()
{
return $this->morphTo();
}
/**
* Get the addresses for the shipment.
*/
public function address()
{
return $this->belongsTo(OrderAddressProxy::modelClass(), 'order_address_id');
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace Webkul\Sales\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Sales\Contracts\RefundItem as RefundItemContract;
class RefundItem extends Model implements RefundItemContract
{
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $casts = [
'additional' => 'array',
];
/**
* Get the Refund record associated with the Refund item.
*/
public function refund()
{
return $this->belongsTo(RefundProxy::modelClass());
}
/**
* Get the order item record associated with the Refund item.
*/
public function order_item()
{
return $this->belongsTo(OrderItemProxy::modelClass());
}
/**
* Get the Refund record associated with the Refund item.
*/
public function product()
{
return $this->morphTo();
}
/**
* Get the child item record associated with the Refund item.
*/
public function child()
{
return $this->hasOne(RefundItemProxy::modelClass(), 'parent_id');
}
/**
* Returns configurable option html
*/
public function getOptionDetailHtml()
{
if ($this->type == 'configurable' && isset($this->additional['attributes'])) {
$labels = [];
foreach ($this->additional['attributes'] as $attribute) {
$labels[] = $attribute['attribute_name'] . ' : ' . $attribute['option_label'];
}
return implode(', ', $labels);
}
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Sales\Models;
use Konekt\Concord\Proxies\ModelProxy;
class RefundItemProxy extends ModelProxy
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Sales\Models;
use Konekt\Concord\Proxies\ModelProxy;
class RefundProxy extends ModelProxy
{
}

View File

@ -15,5 +15,7 @@ class ModuleServiceProvider extends BaseModuleServiceProvider
\Webkul\Sales\Models\InvoiceItem::class,
\Webkul\Sales\Models\Shipment::class,
\Webkul\Sales\Models\ShipmentItem::class,
\Webkul\Sales\Models\Refund::class,
\Webkul\Sales\Models\RefundItem::class,
];
}

View File

@ -201,10 +201,8 @@ class InvoiceRepository extends Repository
if ($invoice->order->shipping_amount) {
foreach ($invoice->order->invoices as $prevInvoice) {
if ((float) $prevInvoice->shipping_amount) {
$shippingAmount = 0;
$baseShippingAmount = 0;
}
if ((float) $prevInvoice->shipping_amount)
$shippingAmount = $baseShippingAmount = 0;
}
}

View File

@ -47,9 +47,13 @@ class OrderItemRepository extends Repository
*/
public function collectTotals($orderItem)
{
$qtyShipped = $qtyInvoiced = 0;
$qtyShipped = $qtyInvoiced = $qtyRefunded = 0;
$totalInvoiced = $baseTotalInvoiced = 0;
$taxInvoiced = $baseTaxInvoiced = 0;
$totalRefunded = $baseTotalRefunded = 0;
$taxRefunded = $baseTaxRefunded = 0;
foreach ($orderItem->invoice_items as $invoiceItem) {
$qtyInvoiced += $invoiceItem->qty;
@ -65,8 +69,19 @@ class OrderItemRepository extends Repository
$qtyShipped += $shipmentItem->qty;
}
foreach ($orderItem->refund_items as $refundItem) {
$qtyRefunded += $refundItem->qty;
$totalRefunded += $refundItem->total;
$baseTotalRefunded += $refundItem->base_total;
$taxRefunded += $refundItem->tax_amount;
$baseTaxRefunded += $refundItem->base_tax_amount;
}
$orderItem->qty_shipped = $qtyShipped;
$orderItem->qty_invoiced = $qtyInvoiced;
$orderItem->qty_refunded = $qtyRefunded;
$orderItem->total_invoiced = $totalInvoiced;
$orderItem->base_total_invoiced = $baseTotalInvoiced;
@ -74,6 +89,12 @@ class OrderItemRepository extends Repository
$orderItem->tax_amount_invoiced = $taxInvoiced;
$orderItem->base_tax_amount_invoiced = $baseTaxInvoiced;
$orderItem->amount_refunded = $totalRefunded;
$orderItem->base_amount_refunded = $baseTotalRefunded;
$orderItem->tax_amount_refunded = $taxRefunded;
$orderItem->base_tax_amount_refunded = $baseTaxRefunded;
$orderItem->save();
return $orderItem;

View File

@ -149,6 +149,7 @@ class OrderRepository extends Repository
public function generateIncrementId()
{
$config = new CoreConfig();
$invoiceNumberPrefix = $config->where('code','=',"sales.invoiceSettings.invoice_number.invoice_number_prefix")->first()
? $config->where('code','=',"sales.invoiceSettings.invoice_number.invoice_number_prefix")->first()->value : false;
$invoiceNumberLength = $config->where('code','=',"sales.invoiceSettings.invoice_number.invoice_number_length")->first()
@ -159,11 +160,9 @@ class OrderRepository extends Repository
$lastOrder = $this->model->orderBy('id', 'desc')->limit(1)->first();
$lastId = $lastOrder ? $lastOrder->id : 0;
if($invoiceNumberLength && ( $invoiceNumberPrefix || $invoiceNumberSuffix) ){
$invoiceNumber = $invoiceNumberPrefix . sprintf("%0{$invoiceNumberLength}d", $lastId + 1) . $invoiceNumberSuffix;
}
else{
if ($invoiceNumberLength && ( $invoiceNumberPrefix || $invoiceNumberSuffix) ) {
$invoiceNumber = $invoiceNumberPrefix . sprintf("%0{$invoiceNumberLength}d", 0) . ($lastId + 1) . $invoiceNumberSuffix;
} else {
$invoiceNumber = $lastId + 1;
}
@ -287,6 +286,32 @@ class OrderRepository extends Repository
$order->grand_total_invoiced = $order->sub_total_invoiced + $order->shipping_invoiced + $order->tax_amount_invoiced - $order->discount_invoiced;
$order->base_grand_total_invoiced = $order->base_sub_total_invoiced + $order->base_shipping_invoiced + $order->base_tax_amount_invoiced - $order->base_discount_invoiced;
$order->sub_total_refunded = $order->base_sub_total_refunded = 0;
$order->shipping_refunded = $order->base_shipping_refunded = 0;
$order->tax_amount_refunded = $order->base_tax_amount_refunded = 0;
$order->grand_total_refunded = $order->base_grand_total_refunded = 0;
foreach ($order->refunds as $refund) {
$order->sub_total_refunded += $refund->sub_total;
$order->base_sub_total_refunded += $refund->base_sub_total;
$order->shipping_refunded += $refund->shipping_amount;
$order->base_shipping_refunded += $refund->base_shipping_amount;
$order->tax_amount_refunded += $refund->tax_amount;
$order->base_tax_amount_refunded += $refund->base_tax_amount;
$order->discount_refunded += $refund->discount_amount;
$order->base_discount_refunded += $refund->base_discount_amount;
$order->grand_total_refunded += $refund->adjustment_refund - $refund->adjustment_fee;
$order->base_grand_total_refunded += $refund->base_adjustment_refund - $refund->base_adjustment_fee;
}
$order->grand_total_refunded += $order->sub_total_refunded + $order->shipping_refunded + $order->tax_amount_refunded - $order->discount_refunded;
$order->base_grand_total_refunded += $order->base_sub_total_refunded + $order->base_shipping_refunded + $order->base_tax_amount_refunded - $order->base_discount_refunded;
$order->save();
return $order;

View File

@ -0,0 +1,28 @@
<?php
namespace Webkul\Sales\Repositories;
use Illuminate\Container\Container as App;
use Webkul\Core\Eloquent\Repository;
use Webkul\Sales\Contracts\RefundItem;
/**
* Refund Item Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class RefundItemRepository extends Repository
{
/**
* Specify Model class name
*
* @return Mixed
*/
function model()
{
return RefundItem::class;
}
}

View File

@ -0,0 +1,261 @@
<?php
namespace Webkul\Sales\Repositories;
use Illuminate\Container\Container as App;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\DB;
use Webkul\Sales\Contracts\Refund;
use Webkul\Core\Eloquent\Repository;
/**
* Refund Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class RefundRepository extends Repository
{
/**
* OrderRepository object
*
* @var Object
*/
protected $orderRepository;
/**
* OrderItemRepository object
*
* @var Object
*/
protected $orderItemRepository;
/**
* RefundItemRepository object
*
* @var Object
*/
protected $refundItemRepository;
/**
* Create a new repository instance.
*
* @param \Webkul\Sales\Repositories\OrderRepository $orderRepository
* @param \Webkul\Sales\Repositories\OrderItemRepository $orderItemRepository
* @param \Webkul\Sales\Repositories\RefundItemRepository $refundItemRepository
* @param \Illuminate\Container\Container $app
*/
public function __construct(
OrderRepository $orderRepository,
OrderItemRepository $orderItemRepository,
RefundItemRepository $refundItemRepository,
App $app
)
{
$this->orderRepository = $orderRepository;
$this->orderItemRepository = $orderItemRepository;
$this->refundItemRepository = $refundItemRepository;
parent::__construct($app);
}
/**
* Specify Model class name
*
* @return Mixed
*/
function model()
{
return Refund::class;
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
DB::beginTransaction();
try {
Event::fire('sales.refund.save.before', $data);
$order = $this->orderRepository->find($data['order_id']);
$totalQty = array_sum($data['refund']['items']);
$refund = parent::create([
'order_id' => $order->id,
'total_qty' => $totalQty,
'state' => 'refunded',
'base_currency_code' => $order->base_currency_code,
'channel_currency_code' => $order->channel_currency_code,
'order_currency_code' => $order->order_currency_code,
'adjustment_refund' => core()->convertPrice($data['refund']['adjustment_refund'], $order->order_currency_code),
'base_adjustment_refund' => $data['refund']['adjustment_refund'],
'adjustment_fee' => core()->convertPrice($data['refund']['adjustment_fee'], $order->order_currency_code),
'base_adjustment_fee' => $data['refund']['adjustment_fee'],
'shipping_amount' => core()->convertPrice($data['refund']['shipping'], $order->order_currency_code),
'base_shipping_amount' => $data['refund']['shipping']
]);
foreach ($data['refund']['items'] as $itemId => $qty) {
if (! $qty)
continue;
$orderItem = $this->orderItemRepository->find($itemId);
if ($qty > $orderItem->qty_to_refund)
$qty = $orderItem->qty_to_refund;
$refundItem = $this->refundItemRepository->create([
'refund_id' => $refund->id,
'order_item_id' => $orderItem->id,
'name' => $orderItem->name,
'sku' => $orderItem->sku,
'qty' => $qty,
'price' => $orderItem->price,
'base_price' => $orderItem->base_price,
'total' => $orderItem->price * $qty,
'base_total' => $orderItem->base_price * $qty,
'tax_amount' => ( ($orderItem->tax_amount / $orderItem->qty_ordered) * $qty ),
'base_tax_amount' => ( ($orderItem->base_tax_amount / $orderItem->qty_ordered) * $qty ),
'discount_amount' => ( ($orderItem->discount_amount / $orderItem->qty_ordered) * $qty ),
'base_discount_amount' => ( ($orderItem->base_discount_amount / $orderItem->qty_ordered) * $qty ),
'product_id' => $orderItem->product_id,
'product_type' => $orderItem->product_type,
'additional' => $orderItem->additional
]);
if ($orderItem->type == 'configurable' && $orderItem->child) {
$childOrderItem = $orderItem->child;
$refundItem->child = $this->refundItemRepository->create([
'refund_id' => $refund->id,
'order_item_id' => $childOrderItem->id,
'parent_id' => $refundItem->id,
'name' => $childOrderItem->name,
'sku' => $childOrderItem->sku,
'qty' => $qty,
'price' => $childOrderItem->price,
'base_price' => $childOrderItem->base_price,
'total' => $childOrderItem->price * $qty,
'base_total' => $childOrderItem->base_price * $qty,
'tax_amount' => 0,
'base_tax_amount' => 0,
'discount_amount' => 0,
'base_discount_amount' => 0,
'product_id' => $childOrderItem->product_id,
'product_type' => $childOrderItem->product_type,
'additional' => $childOrderItem->additional
]);
}
$this->orderItemRepository->collectTotals($orderItem);
}
$this->collectTotals($refund);
$this->orderRepository->collectTotals($order);
$this->orderRepository->updateOrderStatus($order);
Event::fire('sales.refund.save.after', $refund);
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
DB::commit();
return $refund;
}
/**
* @param Refund $refund
* @return mixed
*/
public function collectTotals($refund)
{
$subTotal = $baseSubTotal = 0;
$taxAmount = $baseTaxAmount = 0;
$discountAmount = $baseDiscountAmount = 0;
foreach ($refund->items as $refundItem) {
$subTotal += $refundItem->total;
$baseSubTotal += $refundItem->base_total;
$taxAmount += $refundItem->tax_amount;
$baseTaxAmount += $refundItem->base_tax_amount;
$discountAmount += $refundItem->discount_amount;
$baseDiscountAmount += $refundItem->base_discount_amount;
}
$refund->sub_total = $subTotal;
$refund->base_sub_total = $baseSubTotal;
$refund->tax_amount = $taxAmount;
$refund->base_tax_amount = $baseTaxAmount;
$refund->grand_total = $subTotal + $taxAmount + $refund->shipping_amount + $refund->adjustment_refund - $refund->adjustment_fee - $discountAmount;
$refund->base_grand_total = $baseSubTotal + $baseTaxAmount + $refund->base_shipping_amount + $refund->base_adjustment_refund - $refund->adjustment_fee - $baseDiscountAmount;
$refund->save();
return $refund;
}
/**
* @param array $data
* @param integer $orderId
* @return array
*/
public function getOrderItemsRefundSummary($data, $orderId)
{
$order = $this->orderRepository->find($orderId);
$summary = [
'subtotal' => ['price' => 0],
'discount' => ['price' => 0],
'tax' => ['price' => 0],
'shipping' => ['price' => 0],
'grand_total' => ['price' => 0]
];
foreach ($data as $orderItemId => $qty) {
if (! $qty)
continue;
$orderItem = $this->orderItemRepository->find($orderItemId);
if ($qty > $orderItem->qty_to_refund)
return false;
$summary['subtotal']['price'] += $orderItem->base_price * $qty;
$summary['discount']['price'] += ($orderItem->base_discount_amount / $orderItem->qty_ordered) * $qty;
$summary['tax']['price'] += ($orderItem->tax_amount / $orderItem->qty_ordered) * $qty;
}
$summary['shipping']['price'] += $order->base_shipping_invoiced - $order->base_shipping_refunded;
$summary['grand_total']['price'] += $summary['subtotal']['price'] + $summary['tax']['price'] + $summary['shipping']['price'] - $summary['discount']['price'];
$summary['subtotal']['formated_price'] = core()->formatBasePrice($summary['subtotal']['price']);
$summary['discount']['formated_price'] = core()->formatBasePrice($summary['discount']['price']);
$summary['tax']['formated_price'] = core()->formatBasePrice($summary['tax']['price']);
$summary['shipping']['formated_price'] = core()->formatBasePrice($summary['shipping']['price']);
$summary['grand_total']['formated_price'] = core()->formatBasePrice($summary['grand_total']['price']);
return $summary;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/shop.js": "/js/shop.js?id=71f03d05d9690fe24784",
"/js/shop.js": "/js/shop.js?id=053b23126964b10d1ce6",
"/css/shop.css": "/css/shop.css?id=426d876808f107691dc6"
}

View File

@ -210,6 +210,12 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function
Route::post('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@update')->defaults('_config', [
'redirect' => 'customer.profile.index'
])->name('customer.profile.edit');
//Customer Profile Delete Form Store
Route::post('profile/destroy', 'Webkul\Customer\Http\Controllers\CustomerController@destroy')->defaults('_config', [
'redirect' => 'customer.profile.index'
])->name('customer.profile.destroy');
/* Profile Routes Ends Here */
/* Routes for Addresses */

View File

@ -32,7 +32,7 @@ class SubscriptionEmail extends Mailable
{
return $this->to($this->subscriptionData['email'])
->from(env('SHOP_MAIL_FROM'))
->subject('subscription email')
->subject(trans('shop::app.mail.customer.subscription.subject'))
->view('shop::emails.customer.subscription-email')->with('data', ['content' => 'You Are Subscribed', 'token' => $this->subscriptionData['token']]);
}
}

View File

@ -5,7 +5,19 @@ window.axios = require("axios");
require("./bootstrap");
require("ez-plus/src/jquery.ez-plus.js");
Vue.use(VeeValidate);
const dictionary = {
ar: {
required: (field) => 'حقل' + field + ' مطلوب',
email: (field) => + field + 'يجب ان يكون بريدا اليكتروني صحيح',
}
};
Vue.use(VeeValidate, {
dictionary: {
ar: { messages: dictionary.ar}
}
});
Vue.prototype.$http = axios
window.eventBus = new Vue();
@ -24,6 +36,8 @@ $(document).ready(function () {
mounted: function () {
this.addServerErrors();
this.addFlashMessages();
this.$validator.localize(document.documentElement.lang);
},
methods: {

View File

@ -0,0 +1,26 @@
[{
required : (field) => 'حقل' + field + ' مطلوب',
alpha : (field) => + field + ' يجب ان يحتوي على حروف فقط',
alpha_num : (field) => + field + ' قد يحتوي فقط على حروف وارقام',
min : (field) => 'الحقل ' + field + ' يجب ان يحتوي على {length} حروف على الأقل',
numeric : (field) => +field+ ' يمكن ان يحتوي فقط على ارقام',
oneOf : (field) => 'الحقل ' + field + 'يجب ان يكون قيمة صحيحة',
regex : (field) => 'الحقل' + field+ ' غير صحيح',
required_if : (field) => 'حقل' + field + ' مطلوب',
size : (field) => + field + ' يجب ان يكون اقل من {size} كيلوبايت',
min_value : (field) => 'قيمة الحقل' + field + ' يجب ان تكون اكبر من {min} او تساويها',
alpha_spaces : (field) => + field + ' قد يحتوي فقط على حروف ومسافات',
between : (field) => 'قيمة ' +field+ ' يجب ان تكون ما بين {min} و {max}',
confirmed : (field) => + field + ' لا يماثل التأكيد',
digits : (field) => + field + ' يجب ان تحتوي فقط على ارقام والا يزيد عددها عن {length} رقم',
dimensions : (field) => + field + ' يجب ان تكون بمقاس {width} بكسل في {height} بكسل',
email : (field) => + field + ' يجب ان يكون بريدا اليكتروني صحيح',
excluded : (field) => 'الحقل' + field +'غير صحيح',
ext : (field) =>'نوع مل'+ field + 'غير صحيح',
image : (field) => + field + ' يجب ان تكون صورة',
integer : (field) => 'الحقل ' +field + ' يجب ان يكون عدداً صحيحاً',
length : (field) => 'حقل'+ field + ' يجب الا يزيد عن {length}',
max_value : (field) => 'قيمة الحقل '+ field + ' يجب ان تكون اصغر من {min} او تساويها',
max : (field) => 'الحقل' + field + 'يجب ان يحتوي على {length} حروف على الأكثر',
mimes : (field) => 'نوع ملف' + field + 'غير صحيح'
}]

View File

@ -11,7 +11,8 @@ return [
],
'common' => [
'error' => 'حدث شيء خاطئ ، رجاء حاول ثانية لاحقا.'
'error' => 'حدث شيء خاطئ ، رجاء حاول ثانية لاحقا.',
'no-result-found' => 'We could not find any records.'
],
'home' => [
@ -249,6 +250,7 @@ return [
'item-invoice' => '3-الفواتير(:qty_invoiced)',
'item-shipped' => 'شحنت(:qty_shipped)',
'item-canceled' => 'ملغاة(:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'السعر',
'total' => 'المجموع',
'subtotal' => 'المجموع الفرعي',
@ -274,7 +276,11 @@ return [
'order-date' => 'تاريخ الطلب',
'bill-to' => 'بيل إلى',
'ship-to' => 'السفينة إلى',
'contact' => 'Contact'
'contact' => 'Contact',
'refunds' => 'Refunds',
'individual-refund' => 'Refund #:refund_id',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
]
],

View File

@ -14,7 +14,8 @@ return [
],
'common' => [
'error' => 'Something went wrong, please try again later.'
'error' => 'Something went wrong, please try again later.',
'no-result-found' => 'We could not find any records.'
],
'home' => [
@ -117,6 +118,7 @@ return [
'verified' => 'Your Account Has Been Verified, Try To Login Now',
'verify-failed' => 'We Cannot Verify Your Mail Account',
'dont-have-account' => 'You Do Not Have Account With Us',
'customer-registration' => 'Customer Registered Successfully'
],
'login-text' => [
@ -257,6 +259,7 @@ return [
'item-invoice' => 'Invoiced (:qty_invoiced)',
'item-shipped' => 'shipped (:qty_shipped)',
'item-canceled' => 'Canceled (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'Price',
'total' => 'Total',
'subtotal' => 'Subtotal',
@ -282,7 +285,11 @@ return [
'order-date' => 'Order Date',
'bill-to' => 'Bill to',
'ship-to' => 'Ship to',
'contact' => 'Contact'
'contact' => 'Contact',
'refunds' => 'Refunds',
'individual-refund' => 'Refund #:refund_id',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
]
],
@ -543,7 +550,40 @@ return [
'thanks' => 'Thanks!'
],
'customer' => [
'subject' => 'New Customer Registration'
'new' => [
'dear' => 'Dear :customer_name',
'username-email' => 'UserName/Email',
'subject' => 'New Customer Registration',
'password' => 'Password',
'summary' => 'Your account has been created in bagisto.
Your account details are below: ',
'thanks' => 'Thanks!',
],
'registration' => [
'subject' => 'New Customer Registration',
'customer-registration' => 'Customer Registered Successfully',
'dear' => 'Dear :customer_name',
'greeting' => 'Welcome and thank you for registering at Bagisto!',
'summary' => 'Your account has now been created successfully and you can login using your email address and password credentials. Upon logging in, you will be able to access other services including reviewing past orders, wishlists and editing your account information.',
'thanks' => 'Thanks!',
],
'verification' => [
'heading' => 'Bagisto - Email Verification',
'subject' => 'Verification Mail',
'verify' => 'Verify Your Account',
'summary' => 'This is the mail to verify that the email address you entered is yours.
Kindly click the Verify Your Account button below to verify your account.'
],
'subscription' => [
'subject' => 'Subscription Email',
'greeting' => ' Welcome to Bagisto - Email Subscription',
'unsubscribe' => 'Unsubscribe',
'summary' => 'Thanks for putting me into your inbox. Its been a while since youve read Bagisto email, and we dont want to overwhelm your inbox. If you still do not want to receive
the latest email marketing news then for sure click the button below.'
]
]
],

View File

@ -14,7 +14,8 @@ return [
],
'common' => [
'error' => 'مشکلی رخ داده است. لطفا بعدا دوباره امتحان کنید.'
'error' => 'مشکلی رخ داده است. لطفا بعدا دوباره امتحان کنید.',
'no-result-found' => 'We could not find any records.'
],
'home' => [
@ -256,6 +257,7 @@ return [
'item-invoice' => 'صورتحساب (:qty_invoiced)',
'item-shipped' => 'حمل شده (:qty_shipped)',
'item-canceled' => 'لغو شد (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'قیمت',
'total' => 'جمع',
'subtotal' => 'فرعی',
@ -281,7 +283,11 @@ return [
'order-date' => 'تاریخ سفارش',
'bill-to' => 'بیل به',
'ship-to' => 'حمل به',
'contact' => 'تماس'
'contact' => 'تماس',
'refunds' => 'Refunds',
'individual-refund' => 'Refund #:refund_id',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
]
],

View File

@ -11,7 +11,8 @@ return [
],
'common' => [
'error' => 'Algo deu errado, por favor, tente novamente mais tarde.'
'error' => 'Algo deu errado, por favor, tente novamente mais tarde.',
'no-result-found' => 'We could not find any records.'
],
'home' => [
@ -251,6 +252,7 @@ return [
'item-invoice' => 'Faturados (:qty_invoiced)',
'item-shipped' => 'enviados (:qty_shipped)',
'item-canceled' => 'Cancelados (:qty_canceled)',
'item-refunded' => 'Refunded (:qty_refunded)',
'price' => 'Preço',
'total' => 'Total',
'subtotal' => 'Subtotal',
@ -276,7 +278,11 @@ return [
'order-date' => 'Pedido Date',
'bill-to' => 'Cobrança de',
'ship-to' => 'Enviar para',
'contact' => 'Contato'
'contact' => 'Contato',
'refunds' => 'Refunds',
'individual-refund' => 'Refund #:refund_id',
'adjustment-refund' => 'Adjustment Refund',
'adjustment-fee' => 'Adjustment Fee',
]
],

View File

@ -71,9 +71,11 @@
@endguest
@auth('customer')
<a class="btn btn-lg btn-primary" @click = backToSavedBillingAddress()>
{{ __('shop::app.checkout.onepage.back') }}
</a>
@if(count(auth('customer')->user()->addresses))
<a class="btn btn-lg btn-primary" @click = backToSavedBillingAddress()>
{{ __('shop::app.checkout.onepage.back') }}
</a>
@endif
@endauth
</div>
@ -293,9 +295,11 @@
<h1>{{ __('shop::app.checkout.onepage.shipping-address') }}</h1>
@auth('customer')
<a class="btn btn-lg btn-primary" @click = backToSavedShippingAddress()>
{{ __('shop::app.checkout.onepage.back') }}
</a>
@if(count(auth('customer')->user()->addresses))
<a class="btn btn-lg btn-primary" @click = backToSavedShippingAddress()>
{{ __('shop::app.checkout.onepage.back') }}
</a>
@endif
@endauth
</div>

View File

@ -92,7 +92,7 @@
<div class="row">
<span class="label">{{ __('shop::app.customer.account.order.view.order-id') }} -</span>
<span class="value">#{{ $invoice->order_id }}</span>
<span class="value">#{{ $invoice->order->increment_id }}</span>
</div>
<div class="row">

View File

@ -90,6 +90,10 @@
{{ $item->qty_shipped ? __('shop::app.customer.account.order.view.item-shipped', ['qty_shipped' => $item->qty_shipped]) : '' }}
</span>
<span class="qty-row">
{{ $item->qty_refunded ? __('shop::app.customer.account.order.view.item-refunded', ['qty_refunded' => $item->qty_refunded]) : '' }}
</span>
<span class="qty-row">
{{ $item->qty_canceled ? __('shop::app.customer.account.order.view.item-canceled', ['qty_canceled' => $item->qty_canceled]) : '' }}
</span>
@ -297,6 +301,113 @@
</tab>
@endif
@if ($order->refunds->count())
<tab name="{{ __('shop::app.customer.account.order.view.refunds') }}">
@foreach ($order->refunds as $refund)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('shop::app.customer.account.order.view.individual-refund', ['refund_id' => $refund->id]) }}</span>
</div>
<div class="section-content">
<div class="table">
<table>
<thead>
<tr>
<th>{{ __('shop::app.customer.account.order.view.SKU') }}</th>
<th>{{ __('shop::app.customer.account.order.view.product-name') }}</th>
<th>{{ __('shop::app.customer.account.order.view.price') }}</th>
<th>{{ __('shop::app.customer.account.order.view.qty') }}</th>
<th>{{ __('shop::app.customer.account.order.view.subtotal') }}</th>
<th>{{ __('shop::app.customer.account.order.view.tax-amount') }}</th>
<th>{{ __('shop::app.customer.account.order.view.grand-total') }}</th>
</tr>
</thead>
<tbody>
@foreach ($refund->items as $item)
<tr>
<td data-value="{{ __('shop::app.customer.account.order.view.SKU') }}">{{ $item->child ? $item->child->sku : $item->sku }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.product-name') }}">{{ $item->name }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.price') }}">{{ core()->formatPrice($item->price, $order->order_currency_code) }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.qty') }}">{{ $item->qty }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.subtotal') }}">{{ core()->formatPrice($item->total, $order->order_currency_code) }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.tax-amount') }}">{{ core()->formatPrice($item->tax_amount, $order->order_currency_code) }}</td>
<td data-value="{{ __('shop::app.customer.account.order.view.grand-total') }}">{{ core()->formatPrice($item->total + $item->tax_amount, $order->order_currency_code) }}</td>
</tr>
@endforeach
@if (! $refund->items->count())
<tr>
<td class="empty" colspan="7">{{ __('admin::app.common.no-result-found') }}</td>
<tr>
@endif
</tbody>
</table>
</div>
<div class="totals">
<table class="sale-summary">
<tr>
<td>{{ __('shop::app.customer.account.order.view.subtotal') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->sub_total, $order->order_currency_code) }}</td>
</tr>
@if ($refund->shipping_amount > 0)
<tr>
<td>{{ __('shop::app.customer.account.order.view.shipping-handling') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->shipping_amount, $order->order_currency_code) }}</td>
</tr>
@endif
@if ($refund->discount_amount > 0)
<tr>
<td>{{ __('shop::app.customer.account.order.view.discount') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($order->discount_amount, $order->order_currency_code) }}</td>
</tr>
@endif
@if ($refund->tax_amount > 0)
<tr>
<td>{{ __('shop::app.customer.account.order.view.tax') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->tax_amount, $order->order_currency_code) }}</td>
</tr>
@endif
<tr>
<td>{{ __('shop::app.customer.account.order.view.adjustment-refund') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->adjustment_refund, $order->order_currency_code) }}</td>
</tr>
<tr>
<td>{{ __('shop::app.customer.account.order.view.adjustment-fee') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->adjustment_fee, $order->order_currency_code) }}</td>
</tr>
<tr class="bold">
<td>{{ __('shop::app.customer.account.order.view.grand-total') }}</td>
<td>-</td>
<td>{{ core()->formatPrice($refund->grand_total, $order->order_currency_code) }}</td>
</tr>
</table>
</div>
</div>
</div>
@endforeach
</tab>
@endif
</tabs>
<div class="sale-section">

View File

@ -67,6 +67,18 @@
</table>
</div>
<accordian :title="'{{ __('shop::app.customer.account.profile.index.title') }}'" :active="true">
<div slot="body">
<div class="page-action">
<form method="POST" action="{{ route('customer.profile.destroy') }}">
@csrf
<input type="submit" class="btn btn-lg btn-primary mt-10" value="Delete">
</form>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.shop.customers.account.profile.view.after', ['customer' => $customer]) !!}
</div>
</div>

View File

@ -8,15 +8,23 @@
</div>
<div style="font-size:16px; color:#242424; font-weight:600; margin-top: 60px; margin-bottom: 15px">
Hi {{ $customer['name'] }}, your new account has been created in bagisto.
Your account details are below
{{ __('shop::app.mail.customer.new.dear', ['customer_name' => $customer['name']]) }},
</div>
<div>
<b>UserName/Email</b> - {{ $customer['email'] }} <br>
<b>Password</b> - {{ $password}}
{!! __('shop::app.mail.customer.new.summary') !!}
</div>
<div>
<b> {!! __('shop::app.mail.customer.new.username-email') !!} </b> - {{ $customer['email'] }} <br>
<b> {!! __('shop::app.mail.customer.new.password') !!} </b> - {{ $password}}
</div>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.customer.new.thanks') }}
</p>
</div>
@endcomponent

View File

@ -0,0 +1,32 @@
@component('shop::emails.layouts.master')
<div>
<div style="text-align: center;">
<a href="{{ config('app.url') }}">
<img src="{{ bagisto_asset('images/logo.svg') }}">
</a>
</div>
<div style="padding: 30px;">
<div style="font-size: 20px;color: #242424;line-height: 30px;margin-bottom: 34px;">
<p style="font-weight: bold;font-size: 20px;color: #242424;line-height: 24px;">
{{ __('shop::app.mail.customer.registration.dear', ['customer_name' => $data['first_name']. ' ' .$data['last_name']]) }},
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{!! __('shop::app.mail.customer.registration.greeting') !!}
</p>
</div>
<div style="font-size: 16px;color: #5E5E5E;line-height: 30px;margin-bottom: 20px !important;">
{{ __('shop::app.mail.customer.registration.summary') }}
</div>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.customer.registration.thanks') }}
</p>
</div>
</div>
@endcomponent

View File

@ -8,18 +8,18 @@
</div>
<div style="font-size:16px; color:#242424; font-weight:600; margin-top: 60px; margin-bottom: 15px">
Welcome to Bagisto - Email Subscription
{!! __('shop::app.mail.customer.subscription.greeting') !!}
</div>
<div>
Thanks for putting me into your inbox. Its been a while since youve read Bagisto
email, and we dont want to overwhelm your inbox. If you still do not want to receive
the latest email marketing news then for sure click the button below.
{!! __('shop::app.mail.customer.subscription.summary') !!}
</div>
<div style="margin-top: 40px; text-align: center">
<a href="{{ route('shop.unsubscribe', $data['token']) }}" style="font-size: 16px;
color: #FFFFFF; text-align: center; background: #0031F0; padding: 10px 100px;text-decoration: none;">Unsubscribe</a>
color: #FFFFFF; text-align: center; background: #0031F0; padding: 10px 100px;text-decoration: none;">
{!! __('shop::app.mail.customer.subscription.unsubscribe') !!}
</a>
</div>
</div>

View File

@ -8,17 +8,18 @@
</div>
<div style="font-size:16px; color:#242424; font-weight:600; margin-top: 60px; margin-bottom: 15px">
Bagisto - Email Verification
{!! __('shop::app.mail.customer.verification.heading') !!}
</div>
<div>
This is the mail to verify that the email address you entered is yours.
Kindly click the 'Verify Your Account' button below to verify your account.
{!! __('shop::app.mail.customer.verification.summary') !!}
</div>
<div style="margin-top: 40px; text-align: center">
<a href="{{ route('customer.verify', $data['token']) }}" style="font-size: 16px;
color: #FFFFFF; text-align: center; background: #0031F0; padding: 10px 100px;text-decoration: none;">Verify Your Account</a>
color: #FFFFFF; text-align: center; background: #0031F0; padding: 10px 100px;text-decoration: none;">
{!! __('shop::app.mail.customer.verification.verify') !!}
</a>
</div>
</div>