merge sync

This commit is contained in:
Prashant Singh 2019-09-24 11:59:02 +05:30
commit a9bb0ca129
41 changed files with 2175 additions and 97 deletions

View File

@ -4,8 +4,6 @@
## **v0.1.7 (17th of September, 2019)** - *Release*
* [feature] - New product types added - Virtual, Downloadable and Group.
* [feature] - Fiterable attributes according to category.
* [feature] - New module CMS added for adding static pages.

View File

@ -8,30 +8,30 @@
"license": "MIT",
"type": "project",
"require": {
"php": "^7.1.3",
"ext-curl": "*",
"ext-intl": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-tokenizer": "*",
"barryvdh/laravel-dompdf": "0.8.3",
"dimsav/laravel-translatable": "^9.0",
"doctrine/dbal": "2.9.2",
"fideloper/proxy": "^4.0",
"flynsarmy/db-blade-compiler": "*",
"guzzlehttp/guzzle": "~6.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
"konekt/concord": "^1.2",
"laravel/framework": "5.6.*",
"laravel/tinker": "^1.0",
"maatwebsite/excel": "3.1.11",
"nwidart/laravel-modules": "^3.2",
"prettus/l5-repository": "2.6.32",
"tymon/jwt-auth": "1.0.0-rc.4"
"php": "^7.1.3",
"ext-curl": "*",
"ext-intl": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-tokenizer": "*",
"astrotomic/laravel-translatable": "^11.0.0",
"barryvdh/laravel-dompdf": "0.8.3",
"doctrine/dbal": "2.9.2",
"fideloper/proxy": "^4.0",
"flynsarmy/db-blade-compiler": "*",
"guzzlehttp/guzzle": "~6.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
"konekt/concord": "^1.2",
"laravel/framework": "5.6.*",
"laravel/tinker": "^1.0",
"maatwebsite/excel": "3.1.11",
"nwidart/laravel-modules": "^3.2",
"prettus/l5-repository": "2.6.32",
"tymon/jwt-auth": "1.0.0-rc.4"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.1",
@ -123,4 +123,4 @@
"optimize-autoloader": true
},
"minimum-stability": "dev"
}
}

View File

@ -202,7 +202,7 @@ return [
* Package Service Providers...
*/
Dimsav\Translatable\TranslatableServiceProvider::class,
Astrotomic\Translatable\TranslatableServiceProvider::class,
/*
* Application Service Providers...

View File

@ -44,7 +44,7 @@ class WishlistController extends Controller
auth()->setDefaultDriver($this->guard);
$this->middleware('auth:' . $this->guard);
$this->wishlistRepository = $wishlistRepository;
$this->productRepository = $productRepository;

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

@ -0,0 +1,169 @@
<?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');
$refundAmount = $totals['grand_total']['price'] - $totals['shipping']['price'] + $data['refund']['shipping'] + $data['refund']['adjustment_refund'] - $data['refund']['adjustment_fee'];
if (! $refundAmount) {
session()->flash('error', trans('admin::app.sales.refunds.invalid-refund-amount-error'));
return redirect()->back();
}
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

@ -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,29 @@ 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-title' => 'Refund #:refund_id',
'invalid-refund-amount-error' => 'Refund amount should be non zero.'
]
],
'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,30 @@ 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',
'invalid-refund-amount-error' => 'Refund amount should be non zero.'
]
],

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,29 @@ 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-title' => 'Refund #:refund_id',
'invalid-refund-amount-error' => 'Refund amount should be non zero.'
]
],

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,29 @@ 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',
'view-title' => 'Refund #:refund_id',
'invalid-refund-amount-error' => 'Refund amount should be non zero.'
]
],
'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->increment_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]" v-model="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,316 @@
@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->increment_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>
<th>{{ __('admin::app.sales.orders.discount-amount') }}</th>
<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>
<td>{{ core()->formatBasePrice($item->base_discount_amount) }}</td>
<td>{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount - $item->base_discount_amount) }}</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>
<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

@ -3,7 +3,7 @@
namespace Webkul\Core\Eloquent;
use Illuminate\Database\Eloquent\Model;
use Dimsav\Translatable\Translatable;
use Astrotomic\Translatable\Translatable;
use Webkul\Core\Models\Locale;
class TranslatableModel extends Model

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

@ -49,7 +49,7 @@ class ProductFlatRepository extends Repository
// ->where('product_categories.category_id', $categoryId)
// ->max('price');
return $this->model->max('price');
return $this->model->max('product_flat.price');
}
/**
@ -59,7 +59,7 @@ class ProductFlatRepository extends Repository
*/
public function getProductMaximumPrice()
{
return $this->model->max('price');
return $this->model->max('product_flat.price');
}
/**

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 - $this->refunds()->sum('base_adjustment_fee') > 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

@ -98,9 +98,7 @@ class InvoiceRepository extends Repository
'base_currency_code' => $order->base_currency_code,
'channel_currency_code' => $order->channel_currency_code,
'order_currency_code' => $order->order_currency_code,
'order_address_id' => $order->billing_address->id,
"discount_amount" => $order->discount_amount,
"base_discount_amount" => $order->base_discount_amount,
'order_address_id' => $order->billing_address->id
]);
foreach ($data['invoice']['items'] as $itemId => $qty) {
@ -174,51 +172,40 @@ class InvoiceRepository extends Repository
return $invoice;
}
/**
* @param mixed $invoice
* @return mixed
*/
public function collectTotals($invoice)
{
$subTotal = $baseSubTotal = 0;
$taxAmount = $baseTaxAmount = 0;
$discountAmount = $baseDiscountAmount = 0;
$invoice->sub_total = $invoice->base_sub_total = 0;
$invoice->tax_amount = $invoice->base_tax_amount = 0;
$invoice->discount_amount = $invoice->base_discount_amount = 0;
foreach ($invoice->items as $invoiceItem) {
$subTotal += $invoiceItem->total;
$baseSubTotal += $invoiceItem->base_total;
$invoice->sub_total += $invoiceItem->total;
$invoice->base_sub_total += $invoiceItem->base_total;
$taxAmount += $invoiceItem->tax_amount;
$baseTaxAmount += $invoiceItem->base_tax_amount;
$invoice->tax_amount += $invoiceItem->tax_amount;
$invoice->base_tax_amount += $invoiceItem->base_tax_amount;
$discountAmount += $invoiceItem->discount_amount;
$baseDiscountAmount += $invoiceItem->base_discount_amount;
$invoice->discount_amount += $invoiceItem->discount_amount;
$invoice->base_discount_amount += $invoiceItem->base_discount_amount;
}
$shippingAmount = $invoice->order->shipping_amount;
$baseShippingAmount = $invoice->order->base_shipping_amount;
$invoice->shipping_amount = $invoice->order->shipping_amount;
$invoice->base_shipping_amount = $invoice->order->base_shipping_amount;
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)
$invoice->shipping_amount = $invoice->base_shipping_amount = 0;
}
}
$invoice->sub_total = $subTotal;
$invoice->base_sub_total = $baseSubTotal;
$invoice->shipping_amount = $shippingAmount;
$invoice->base_shipping_amount = $baseShippingAmount;
$invoice->tax_amount = $taxAmount;
$invoice->base_tax_amount = $baseTaxAmount;
$invoice->grand_total = $subTotal + $taxAmount + $shippingAmount - $discountAmount;
$invoice->base_grand_total = $baseSubTotal + $baseTaxAmount + $baseShippingAmount - $baseDiscountAmount;
$invoice->grand_total = $invoice->sub_total + $invoice->tax_amount + $invoice->shipping_amount - $invoice->discount_amount;
$invoice->base_grand_total = $invoice->base_sub_total + $invoice->base_tax_amount + $invoice->base_shipping_amount - $invoice->base_discount_amount;
$invoice->save();

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;
@ -114,7 +135,7 @@ class OrderItemRepository extends Repository
/**
* Returns qty to product inventory after order cancelation
*
* @param mixed $orderItem
* @param OrderItem $orderItem
* @return void
*/
public function returnQtyToProductInventory($orderItem)
@ -129,9 +150,8 @@ class OrderItemRepository extends Repository
if (! $orderedInventory)
return ;
if (($qty = $orderedInventory->qty - $orderItem->qty_to_cancel) < 0) {
if (($qty = $orderedInventory->qty - $quantity) < 0)
$qty = 0;
}
$orderedInventory->update([
'qty' => $qty

View File

@ -265,9 +265,11 @@ class OrderRepository extends Repository
*/
public function collectTotals($order)
{
//Order invoice total
$order->sub_total_invoiced = $order->base_sub_total_invoiced = 0;
$order->shipping_invoiced = $order->base_shipping_invoiced = 0;
$order->tax_amount_invoiced = $order->base_tax_amount_invoiced = 0;
$order->discount_invoiced = $order->base_discount_invoiced = 0;
foreach ($order->invoices as $invoice) {
$order->sub_total_invoiced += $invoice->sub_total;
@ -286,6 +288,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 refund total
$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,65 @@
<?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;
}
/**
* Returns qty to product inventory after order refund
*
* @param RefundItem $refundItem
* @param integer $quantity
* @return void
*/
public function returnQtyToProductInventory($refundItem, $quantity)
{
return;
if (! $product = $refundItem->product)
return;
if ($qtyShipped = $refundItem->order_item->qty_shipped) {
} else {
}
$orderedInventory = $product->ordered_inventories()
->where('channel_id', $refundItem->order->channel->id)
->first();
if ($orderedInventory) {
} else {
}
if (($qty = $orderedInventory->qty - $quantity) < 0)
$qty = 0;
$orderedInventory->update([
'qty' => $qty
]);
}
}

View File

@ -0,0 +1,259 @@
<?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->refundItemRepository->returnQtyToProductInventory($childOrderItem, $qty);
} else {
$this->refundItemRepository->returnQtyToProductInventory($orderItem, $qty);
}
$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)
{
$refund->sub_total = $refund->base_sub_total = 0;
$refund->tax_amount = $refund->base_tax_amount = 0;
$refund->discount_amount = $refund->base_discount_amount = 0;
foreach ($refund->items as $refundItem) {
$refund->sub_total += $refundItem->total;
$refund->base_sub_total += $refundItem->base_total;
$refund->tax_amount += $refundItem->tax_amount;
$refund->base_tax_amount += $refundItem->base_tax_amount;
$refund->discount_amount += $refundItem->discount_amount;
$refund->base_discount_amount += $refundItem->base_discount_amount;
}
$refund->grand_total = $refund->sub_total + $refund->tax_amount + $refund->shipping_amount + $refund->adjustment_refund - $refund->adjustment_fee - $refund->discount_amount;
$refund->base_grand_total = $refund->base_sub_total + $refund->base_tax_amount + $refund->base_shipping_amount + $refund->base_adjustment_refund - $refund->adjustment_fee - $refund->base_discount_amount;
$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;
}
}

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' => [
@ -258,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',
@ -283,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',
]
],

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

@ -68,6 +68,7 @@
<td data-value="{{ __('shop::app.customer.account.order.view.SKU') }}">
{{ $item->type == 'configurable' ? $item->child->sku : $item->sku }}
</td>
<td data-value="{{ __('shop::app.customer.account.order.view.product-name') }}">
{{ $item->name }} <br>
@if (isset($item['additional']['attributes']))
@ -76,7 +77,11 @@
@endforeach
@endif
</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.price') }}">
{{ core()->formatPrice($item->price, $order->order_currency_code) }}
</td>
<td data-value="{{ __('shop::app.customer.account.order.view.item-status') }}">
<span class="qty-row">
{{ __('shop::app.customer.account.order.view.item-ordered', ['qty_ordered' => $item->qty_ordered]) }}
@ -90,14 +95,30 @@
{{ $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>
</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-percent') }}">{{ number_format($item->tax_percent, 2) }}%</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>
<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-percent') }}">
{{ number_format($item->tax_percent, 2) }}%
</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 - $item->discount_amount, $order->order_currency_code) }}
</td>
</tr>
@endforeach
</tbody>
@ -297,6 +318,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">