purchases
This commit is contained in:
parent
6d3fe5ebba
commit
5d63a7058d
|
@ -89,4 +89,17 @@ class BranchController extends Controller
|
||||||
return redirect()->route('branch.index')
|
return redirect()->route('branch.index')
|
||||||
->with('success', 'Branch deleted successfully.');
|
->with('success', 'Branch deleted successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function switchBranch($branchId)
|
||||||
|
{
|
||||||
|
$branch = Branch::findOrFail($branchId);
|
||||||
|
|
||||||
|
// Update user's active branch
|
||||||
|
auth()->user()->update(['active_branch_id' => $branch->id]);
|
||||||
|
|
||||||
|
// Store in session
|
||||||
|
session(['active_branch_id' => $branch->id]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Branch switched successfully to ' . $branch->name);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -5,4 +5,5 @@ use Modules\Branch\Http\Controllers\BranchController;
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth'])->group(function () {
|
||||||
Route::resource('branch', BranchController::class);
|
Route::resource('branch', BranchController::class);
|
||||||
|
Route::get('/branch/switch/{branch}', [BranchController::class, 'switchBranch'])->name('branch.switch');
|
||||||
});
|
});
|
|
@ -15,12 +15,12 @@ class ProductDataTable extends DataTable
|
||||||
public function dataTable($query)
|
public function dataTable($query)
|
||||||
{
|
{
|
||||||
return datatables()
|
return datatables()
|
||||||
->eloquent($query)
|
->query($query)
|
||||||
->addColumn('action', function ($data) {
|
->addColumn('action', function ($data) {
|
||||||
return view('product::products.partials.actions', compact('data'));
|
return view('product::products.partials.actions', compact('data'));
|
||||||
})
|
})
|
||||||
->addColumn('product_image', function ($data) {
|
->addColumn('product_image', function ($data) {
|
||||||
$url = $data->getFirstMediaUrl('images');
|
$url = Product::find($data->id)->getFirstMediaUrl('images');
|
||||||
return '<img src="'.$url.'" class="product-img-thumb" alt="">';
|
return '<img src="'.$url.'" class="product-img-thumb" alt="">';
|
||||||
})
|
})
|
||||||
->addColumn('product_name', function ($data) {
|
->addColumn('product_name', function ($data) {
|
||||||
|
@ -34,10 +34,26 @@ class ProductDataTable extends DataTable
|
||||||
|
|
||||||
public function query(Product $model)
|
public function query(Product $model)
|
||||||
{
|
{
|
||||||
return $model->newQuery()
|
$products = DB::table('products')
|
||||||
->with('category')
|
->leftJoinSub(
|
||||||
->leftJoin(DB::raw('(SELECT product_id, SUM(quantity) as total_quantity FROM product_batches GROUP BY product_id) as pb'), 'products.id', '=', 'pb.product_id')
|
DB::table('product_batches')
|
||||||
->select('products.*', DB::raw('COALESCE(pb.total_quantity, 0) as product_quantity'));
|
->select('product_id', DB::raw('SUM(qty) as total_quantity'))
|
||||||
|
->groupBy('product_id'),
|
||||||
|
'pb',
|
||||||
|
'products.id',
|
||||||
|
'=',
|
||||||
|
'pb.product_id'
|
||||||
|
)
|
||||||
|
->select(
|
||||||
|
'products.id',
|
||||||
|
'products.product_name',
|
||||||
|
'products.product_code',
|
||||||
|
'products.product_unit',
|
||||||
|
'products.category_id',
|
||||||
|
DB::raw('COALESCE(pb.total_quantity, 0) as product_quantity')
|
||||||
|
);
|
||||||
|
|
||||||
|
return $products;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function html()
|
public function html()
|
||||||
|
@ -77,9 +93,9 @@ class ProductDataTable extends DataTable
|
||||||
->title('Code')
|
->title('Code')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
Column::make('category.category_name')
|
// Column::make('category.category_name')
|
||||||
->title('Category')
|
// ->title('Category')
|
||||||
->className('text-center align-middle'),
|
// ->className('text-center align-middle'),
|
||||||
|
|
||||||
Column::make('product_unit')
|
Column::make('product_unit')
|
||||||
->title('Unit')
|
->title('Unit')
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace Modules\Product\Entities;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Modules\Product\Notifications\NotifyQuantityAlert;
|
|
||||||
use Spatie\MediaLibrary\HasMedia;
|
use Spatie\MediaLibrary\HasMedia;
|
||||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
|
@ -12,27 +11,39 @@ use App\Models\ProductBatch;
|
||||||
|
|
||||||
class Product extends Model implements HasMedia
|
class Product extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
|
||||||
use HasFactory, InteractsWithMedia;
|
use HasFactory, InteractsWithMedia;
|
||||||
|
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
protected $with = ['media'];
|
protected $with = ['media'];
|
||||||
|
|
||||||
|
// Append product_quantity ke output model
|
||||||
protected $appends = ['product_quantity'];
|
protected $appends = ['product_quantity'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relasi ke kategori
|
||||||
|
*/
|
||||||
public function category() {
|
public function category() {
|
||||||
return $this->belongsTo(Category::class, 'category_id', 'id');
|
return $this->belongsTo(Category::class, 'category_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relasi ke batches (stok per cabang)
|
||||||
|
*/
|
||||||
public function batches() {
|
public function batches() {
|
||||||
return $this->hasMany(ProductBatch::class, 'product_id', 'id');
|
return $this->hasMany(ProductBatch::class, 'product_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter jumlah stok produk total dari semua batch
|
||||||
|
*/
|
||||||
public function getProductQuantityAttribute() {
|
public function getProductQuantityAttribute() {
|
||||||
return $this->batches()->sum('quantity');
|
return $this->batches()->sum('qty') ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Media fallback & koleksi media
|
||||||
|
*/
|
||||||
public function registerMediaCollections(): void {
|
public function registerMediaCollections(): void {
|
||||||
$this->addMediaCollection('images')
|
$this->addMediaCollection('images')
|
||||||
->useFallbackUrl('/images/fallback_product_image.png');
|
->useFallbackUrl('/images/fallback_product_image.png');
|
||||||
|
@ -44,22 +55,31 @@ class Product extends Model implements HasMedia
|
||||||
->height(50);
|
->height(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter & Getter harga modal (dikonversi ke cent jika ingin akurasi tinggi)
|
||||||
|
*/
|
||||||
public function setProductCostAttribute($value) {
|
public function setProductCostAttribute($value) {
|
||||||
$this->attributes['product_cost'] = ($value * 100);
|
$this->attributes['product_cost'] = $value !== null ? ($value * 100) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProductCostAttribute($value) {
|
public function getProductCostAttribute($value) {
|
||||||
return ($value / 100);
|
return $value !== null ? ($value / 100) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter & Getter harga jual
|
||||||
|
*/
|
||||||
public function setProductPriceAttribute($value) {
|
public function setProductPriceAttribute($value) {
|
||||||
$this->attributes['product_price'] = ($value * 100);
|
$this->attributes['product_price'] = $value !== null ? ($value * 100) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProductPriceAttribute($value) {
|
public function getProductPriceAttribute($value) {
|
||||||
return ($value / 100);
|
return $value !== null ? ($value / 100) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hitung harga grosir jika kuantitas mencukupi
|
||||||
|
*/
|
||||||
public function getWholesalePrice($quantity) {
|
public function getWholesalePrice($quantity) {
|
||||||
if ($this->min_quantity_for_wholesale && $quantity >= $this->min_quantity_for_wholesale) {
|
if ($this->min_quantity_for_wholesale && $quantity >= $this->min_quantity_for_wholesale) {
|
||||||
$discount = $this->wholesale_discount_percentage / 100;
|
$discount = $this->wholesale_discount_percentage / 100;
|
||||||
|
@ -68,6 +88,9 @@ class Product extends Model implements HasMedia
|
||||||
return $this->product_price;
|
return $this->product_price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cek apakah kuantitas memenuhi harga grosir
|
||||||
|
*/
|
||||||
public function isWholesalePrice($quantity) {
|
public function isWholesalePrice($quantity) {
|
||||||
return $this->min_quantity_for_wholesale && $quantity >= $this->min_quantity_for_wholesale;
|
return $this->min_quantity_for_wholesale && $quantity >= $this->min_quantity_for_wholesale;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,42 +8,87 @@ use Yajra\DataTables\Html\Column;
|
||||||
use Yajra\DataTables\Html\Editor\Editor;
|
use Yajra\DataTables\Html\Editor\Editor;
|
||||||
use Yajra\DataTables\Html\Editor\Fields;
|
use Yajra\DataTables\Html\Editor\Fields;
|
||||||
use Yajra\DataTables\Services\DataTable;
|
use Yajra\DataTables\Services\DataTable;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class PurchaseDataTable extends DataTable
|
class PurchaseDataTable extends DataTable
|
||||||
{
|
{
|
||||||
public function dataTable($query)
|
public function dataTable($query)
|
||||||
{
|
{
|
||||||
|
Log::info('PurchaseDataTable::dataTable called', [
|
||||||
|
'query_type' => get_class($query)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Gunakan query builder DB langsung untuk memastikan data diambil
|
||||||
|
$purchases = DB::table('purchases')
|
||||||
|
->select([
|
||||||
|
'purchases.id',
|
||||||
|
'purchases.date',
|
||||||
|
'purchases.reference_no',
|
||||||
|
'purchases.supplier_id',
|
||||||
|
'purchases.total',
|
||||||
|
'purchases.paid_amount',
|
||||||
|
'purchases.due_amount',
|
||||||
|
'purchases.payment_status',
|
||||||
|
'suppliers.name as supplier_name'
|
||||||
|
])
|
||||||
|
->leftJoin('suppliers', 'purchases.supplier_id', '=', 'suppliers.id')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
Log::info('Direct DB Query Results', [
|
||||||
|
'count' => $purchases->count(),
|
||||||
|
'data' => $purchases->take(3)->toArray()
|
||||||
|
]);
|
||||||
|
|
||||||
return datatables()
|
return datatables()
|
||||||
->eloquent($query)
|
->of($purchases)
|
||||||
->addColumn('action', function ($data) {
|
->addColumn('action', function ($data) {
|
||||||
return view('purchase::partials.actions', [
|
return view('purchase::partials.actions', [
|
||||||
'id' => $data->id
|
'id' => $data->id
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
->editColumn('total_amount', function ($data) {
|
->editColumn('total', function ($data) {
|
||||||
return format_currency($data->total_amount);
|
return format_currency($data->total / 100);
|
||||||
})
|
})
|
||||||
->editColumn('paid_amount', function ($data) {
|
->editColumn('paid_amount', function ($data) {
|
||||||
return format_currency($data->paid_amount);
|
return format_currency($data->paid_amount / 100);
|
||||||
})
|
})
|
||||||
->editColumn('due_amount', function ($data) {
|
->editColumn('due_amount', function ($data) {
|
||||||
return format_currency($data->due_amount);
|
return format_currency($data->due_amount / 100);
|
||||||
})
|
|
||||||
->editColumn('status', function ($data) {
|
|
||||||
return view('purchase::partials.status', [
|
|
||||||
'status' => $data->status
|
|
||||||
]);
|
|
||||||
})
|
})
|
||||||
->editColumn('payment_status', function ($data) {
|
->editColumn('payment_status', function ($data) {
|
||||||
return view('purchase::partials.payment-status', [
|
return view('purchase::partials.payment-status', [
|
||||||
'payment_status' => $data->payment_status
|
'payment_status' => $data->payment_status
|
||||||
]);
|
]);
|
||||||
});
|
})
|
||||||
|
->rawColumns(['action', 'payment_status']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function query(Purchase $model)
|
public function query(Purchase $model)
|
||||||
{
|
{
|
||||||
return $model->newQuery();
|
// Cek semua data purchase yang ada
|
||||||
|
$allPurchases = DB::table('purchases')->get();
|
||||||
|
Log::info('All Purchases from DB', [
|
||||||
|
'count' => $allPurchases->count(),
|
||||||
|
'data' => $allPurchases->take(3)->toArray()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Periksa struktur tabel
|
||||||
|
$columns = DB::getSchemaBuilder()->getColumnListing('purchases');
|
||||||
|
Log::info('Purchases Table Columns', [
|
||||||
|
'columns' => $columns
|
||||||
|
]);
|
||||||
|
|
||||||
|
$activeBranch = session('active_branch');
|
||||||
|
|
||||||
|
Log::info('Active Branch', [
|
||||||
|
'branch_id' => $activeBranch
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Kita tidak menggunakan query ini karena menggunakan DB query langsung di dataTable()
|
||||||
|
$query = $model->newQuery();
|
||||||
|
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function html()
|
public function html()
|
||||||
|
@ -79,7 +124,7 @@ class PurchaseDataTable extends DataTable
|
||||||
->title('Date')
|
->title('Date')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
Column::make('reference')
|
Column::make('reference_no')
|
||||||
->title('Reference')
|
->title('Reference')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
|
@ -87,15 +132,11 @@ class PurchaseDataTable extends DataTable
|
||||||
->title('Supplier')
|
->title('Supplier')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
Column::make('status')
|
|
||||||
->title('Status')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::make('payment_status')
|
Column::make('payment_status')
|
||||||
->title('Payment Status')
|
->title('Payment Status')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
Column::make('total_amount')
|
Column::make('total')
|
||||||
->title('Total')
|
->title('Total')
|
||||||
->className('text-center align-middle'),
|
->className('text-center align-middle'),
|
||||||
|
|
||||||
|
|
|
@ -6,33 +6,35 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class Purchase extends Model
|
class Purchase extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'branch_id',
|
||||||
|
'user_id',
|
||||||
|
'date',
|
||||||
'reference_no',
|
'reference_no',
|
||||||
'supplier_id',
|
'supplier_id',
|
||||||
'date',
|
'discount_percentage',
|
||||||
'discount_amount',
|
'discount',
|
||||||
'payment_method',
|
'total',
|
||||||
'paid_amount',
|
'paid_amount',
|
||||||
'total_amount',
|
|
||||||
'due_amount',
|
'due_amount',
|
||||||
'payment_status',
|
'payment_status',
|
||||||
'user_id',
|
'payment_method',
|
||||||
'branch_id',
|
'note',
|
||||||
'created_by',
|
|
||||||
'updated_by'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'date' => 'date',
|
'date' => 'date',
|
||||||
|
'discount_percentage' => 'float',
|
||||||
|
'discount' => 'decimal:2',
|
||||||
|
'total' => 'decimal:2',
|
||||||
'paid_amount' => 'decimal:2',
|
'paid_amount' => 'decimal:2',
|
||||||
'total_amount' => 'decimal:2',
|
'due_amount' => 'decimal:2'
|
||||||
'due_amount' => 'decimal:2',
|
|
||||||
'discount_amount' => 'decimal:2'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function purchaseDetails(): HasMany
|
public function purchaseDetails(): HasMany
|
||||||
|
@ -42,7 +44,7 @@ class Purchase extends Model
|
||||||
|
|
||||||
public function supplier(): BelongsTo
|
public function supplier(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo('Modules\People\Entities\Supplier');
|
return $this->belongsTo('Modules\People\Entities\Supplier', 'supplier_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user(): BelongsTo
|
public function user(): BelongsTo
|
||||||
|
@ -66,17 +68,31 @@ class Purchase extends Model
|
||||||
$number = Purchase::max('id') + 1;
|
$number = Purchase::max('id') + 1;
|
||||||
$model->reference_no = make_reference_id('PR', $number);
|
$model->reference_no = make_reference_id('PR', $number);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Log when model is retrieved
|
||||||
|
static::retrieved(function ($model) {
|
||||||
|
Log::info('Purchase Model Retrieved', [
|
||||||
|
'id' => $model->id,
|
||||||
|
'reference_no' => $model->reference_no,
|
||||||
|
'supplier_id' => $model->supplier_id,
|
||||||
|
'payment_status' => $model->payment_status
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeCompleted($query) {
|
public function scopeCompleted($query) {
|
||||||
return $query->where('payment_status', 'Paid');
|
return $query->where('payment_status', 'Paid');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaidAmountAttribute($value) {
|
public function getDiscountAttribute($value) {
|
||||||
return $value / 100;
|
return $value / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotalAmountAttribute($value) {
|
public function getTotalAttribute($value) {
|
||||||
|
return $value / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaidAmountAttribute($value) {
|
||||||
return $value / 100;
|
return $value / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +100,19 @@ class Purchase extends Model
|
||||||
return $value / 100;
|
return $value / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDiscountAmountAttribute($value) {
|
public function setDiscountAttribute($value) {
|
||||||
return $value / 100;
|
$this->attributes['discount'] = $value * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTotalAttribute($value) {
|
||||||
|
$this->attributes['total'] = $value * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPaidAmountAttribute($value) {
|
||||||
|
$this->attributes['paid_amount'] = $value * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDueAmountAttribute($value) {
|
||||||
|
$this->attributes['due_amount'] = $value * 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,12 @@ use Modules\People\Entities\Supplier;
|
||||||
use Modules\Product\Entities\Product;
|
use Modules\Product\Entities\Product;
|
||||||
use Modules\Purchase\Entities\Purchase;
|
use Modules\Purchase\Entities\Purchase;
|
||||||
use Modules\Purchase\Entities\PurchaseDetail;
|
use Modules\Purchase\Entities\PurchaseDetail;
|
||||||
use Modules\Purchase\Entities\PurchasePayment;
|
|
||||||
use Modules\Purchase\Http\Requests\StorePurchaseRequest;
|
use Modules\Purchase\Http\Requests\StorePurchaseRequest;
|
||||||
use Modules\Purchase\Http\Requests\UpdatePurchaseRequest;
|
use Modules\Purchase\Http\Requests\UpdatePurchaseRequest;
|
||||||
use App\Models\ProductBatch;
|
use App\Models\ProductBatch;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class PurchaseController extends Controller
|
class PurchaseController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -25,6 +24,51 @@ class PurchaseController extends Controller
|
||||||
public function index(PurchaseDataTable $dataTable) {
|
public function index(PurchaseDataTable $dataTable) {
|
||||||
abort_if(Gate::denies('access_purchases'), 403);
|
abort_if(Gate::denies('access_purchases'), 403);
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
Log::info('PurchaseController@index called', [
|
||||||
|
'active_branch' => session('active_branch'),
|
||||||
|
'user' => auth()->user()->name ?? 'Unknown'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Periksa data purchases secara langsung
|
||||||
|
$purchases = DB::table('purchases')->get();
|
||||||
|
Log::info('Direct Purchase Query', [
|
||||||
|
'count' => $purchases->count(),
|
||||||
|
'data' => $purchases->take(3)->toArray()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Jika tidak ada data di DataTable, tampilkan data langsung dari DB
|
||||||
|
if ($purchases->count() > 0 && request()->ajax()) {
|
||||||
|
Log::info('Returning direct data for AJAX request');
|
||||||
|
return datatables()
|
||||||
|
->of($purchases)
|
||||||
|
->addColumn('action', function ($data) {
|
||||||
|
return view('purchase::partials.actions', [
|
||||||
|
'id' => $data->id
|
||||||
|
])->render();
|
||||||
|
})
|
||||||
|
->addColumn('supplier_name', function ($data) {
|
||||||
|
$supplier = DB::table('suppliers')->where('id', $data->supplier_id)->first();
|
||||||
|
return $supplier ? $supplier->name : 'N/A';
|
||||||
|
})
|
||||||
|
->editColumn('total', function ($data) {
|
||||||
|
return format_currency($data->total / 100);
|
||||||
|
})
|
||||||
|
->editColumn('paid_amount', function ($data) {
|
||||||
|
return format_currency($data->paid_amount / 100);
|
||||||
|
})
|
||||||
|
->editColumn('due_amount', function ($data) {
|
||||||
|
return format_currency($data->due_amount / 100);
|
||||||
|
})
|
||||||
|
->editColumn('payment_status', function ($data) {
|
||||||
|
return view('purchase::partials.payment-status', [
|
||||||
|
'payment_status' => $data->payment_status
|
||||||
|
])->render();
|
||||||
|
})
|
||||||
|
->rawColumns(['action', 'payment_status'])
|
||||||
|
->make(true);
|
||||||
|
}
|
||||||
|
|
||||||
return $dataTable->render('purchase::index');
|
return $dataTable->render('purchase::index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +89,7 @@ class PurchaseController extends Controller
|
||||||
'paid_amount' => 'required|numeric|min:0',
|
'paid_amount' => 'required|numeric|min:0',
|
||||||
'products' => 'required|array|min:1',
|
'products' => 'required|array|min:1',
|
||||||
'products.*.product_id' => 'required|exists:products,id',
|
'products.*.product_id' => 'required|exists:products,id',
|
||||||
'products.*.quantity' => 'required|integer|min:1',
|
'products.*.qty' => 'required|integer|min:1',
|
||||||
'products.*.purchase_price' => 'required|numeric|min:0',
|
'products.*.purchase_price' => 'required|numeric|min:0',
|
||||||
'products.*.expired_date' => 'nullable|date|after:today',
|
'products.*.expired_date' => 'nullable|date|after:today',
|
||||||
'discount_percentage' => 'nullable|numeric|min:0',
|
'discount_percentage' => 'nullable|numeric|min:0',
|
||||||
|
@ -61,11 +105,13 @@ class PurchaseController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Log request data
|
||||||
|
Log::info("Request Data", $request->all());
|
||||||
|
|
||||||
// Calculate total amount
|
// Calculate total amount
|
||||||
$totalAmount = collect($request->products)->sum(function ($product) {
|
$totalAmount = collect($request->products)->sum(function ($product) {
|
||||||
return $product['quantity'] * $product['purchase_price'];
|
return $product['qty'] * $product['purchase_price'];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate due amount
|
// Calculate due amount
|
||||||
|
@ -75,27 +121,33 @@ class PurchaseController extends Controller
|
||||||
$paymentStatus = $request->paid_amount == 0 ? 'Unpaid' :
|
$paymentStatus = $request->paid_amount == 0 ? 'Unpaid' :
|
||||||
($dueAmount == 0 ? 'Paid' : 'Partial');
|
($dueAmount == 0 ? 'Paid' : 'Partial');
|
||||||
|
|
||||||
|
// Check active branch
|
||||||
|
if (!session('active_branch')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Branch not selected'
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Simpan ke purchases
|
// 1. Simpan ke purchases
|
||||||
$purchase = Purchase::create([
|
$purchase = Purchase::create([
|
||||||
'reference_no' => $request->reference_no,
|
'reference_no' => $request->reference_no,
|
||||||
'supplier_id' => $request->supplier_id,
|
'supplier_id' => $request->supplier_id,
|
||||||
'supplier_name' => Supplier::findOrFail($request->supplier_id)->name,
|
|
||||||
'date' => $request->date,
|
'date' => $request->date,
|
||||||
'discount_percentage' => $request->discount_percentage ?? 0,
|
'discount_percentage' => $request->discount_percentage ?? 0,
|
||||||
//'discount_amount' => $request->discount_amount ?? 0,
|
'discount' => round($request->discount_amount * 100),
|
||||||
'payment_method' => $request->payment_method,
|
'payment_method' => $request->payment_method,
|
||||||
'paid_amount' => round($request->paid_amount * 100),
|
'paid_amount' => round($request->paid_amount * 100),
|
||||||
'total_amount' => round($totalAmount * 100),
|
'total' => round($totalAmount * 100),
|
||||||
'discount_amount' => round($request->discount_amount * 100),
|
'due_amount' => round($dueAmount * 100),
|
||||||
'due_amount' => $dueAmount,
|
|
||||||
'payment_status' => $paymentStatus,
|
'payment_status' => $paymentStatus,
|
||||||
'note' => $request->note,
|
'note' => $request->note,
|
||||||
'user_id' => auth()->id(),
|
'user_id' => auth()->id(),
|
||||||
'branch_id' => session(['active_branch' => 1]),// contoh ID cabang default
|
'branch_id' => session('active_branch')
|
||||||
'created_by' => auth()->user()->name,
|
|
||||||
'updated_by' => auth()->user()->name
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Log purchase created
|
||||||
|
Log::info("Purchase Created", ['purchase' => $purchase->toArray()]);
|
||||||
|
|
||||||
// 2. Simpan detail produk & batch
|
// 2. Simpan detail produk & batch
|
||||||
foreach ($request->products as $product) {
|
foreach ($request->products as $product) {
|
||||||
// Detail
|
// Detail
|
||||||
|
@ -104,43 +156,49 @@ class PurchaseController extends Controller
|
||||||
'product_id' => $product['product_id'],
|
'product_id' => $product['product_id'],
|
||||||
'product_name' => Product::findOrFail($product['product_id'])->product_name,
|
'product_name' => Product::findOrFail($product['product_id'])->product_name,
|
||||||
'product_code' => Product::findOrFail($product['product_id'])->product_code,
|
'product_code' => Product::findOrFail($product['product_id'])->product_code,
|
||||||
'quantity' => $product['quantity'],
|
'qty' => $product['qty'],
|
||||||
'price' => $product['purchase_price'],
|
// 'price' => $product['purchase_price'],
|
||||||
'unit_price' => $product['purchase_price'],
|
'unit_price' => $product['purchase_price'],
|
||||||
'sub_total' => $product['quantity'] * $product['purchase_price'],
|
'subtotal' => $product['qty'] * $product['purchase_price'],
|
||||||
'product_discount_amount' => 0,
|
'product_discount_amount' => 0,
|
||||||
'product_discount_type' => 'fixed',
|
'product_discount_type' => 'fixed',
|
||||||
'product_tax_amount' => 0,
|
'product_tax_amount' => 0
|
||||||
'created_by' => auth()->user()->name,
|
|
||||||
'updated_by' => auth()->user()->name
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Batch
|
// Batch
|
||||||
ProductBatch::addStock([
|
ProductBatch::addStock([
|
||||||
'product_id' => $product['product_id'],
|
'product_id' => $product['product_id'],
|
||||||
'branch_id' => session(['active_branch' => 1]), // contoh ID cabang default,
|
'branch_id' => session('active_branch'),
|
||||||
'quantity' => $product['quantity'],
|
'qty' => $product['qty'],
|
||||||
'purchase_price' => $product['purchase_price'],
|
'purchase_price' => $product['purchase_price'],
|
||||||
'expired_date' => $product['expired_date'],
|
'exp_date' => $product['expired_date'],
|
||||||
'purchase_id' => $purchase->id,
|
'purchase_id' => $purchase->id,
|
||||||
'batch_code' => $purchase->reference_no . '-' . $product['product_id'],
|
'batch_code' => $purchase->reference_no . '-' . $product['product_id'],
|
||||||
'created_by' => auth()->user()->name,
|
'created_by' => auth()->user()->name ?? 'system',
|
||||||
'updated_by' => auth()->user()->name
|
'updated_by' => auth()->user()->name ?? 'system'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Simpan pembayaran (jika ada)
|
// 3. Simpan pembayaran (jika ada)
|
||||||
if ($purchase->paid_amount > 0) {
|
if ($purchase->paid_amount > 0) {
|
||||||
|
// Kode ini dinonaktifkan karena tabel purchase_payments sudah dihapus
|
||||||
|
/*
|
||||||
PurchasePayment::create([
|
PurchasePayment::create([
|
||||||
'purchase_id' => $purchase->id,
|
'purchase_id' => $purchase->id,
|
||||||
'branch_id' => session(['active_branch' => 1]), // contoh ID cabang default,
|
'branch_id' => session('active_branch'),
|
||||||
'amount' => $purchase->paid_amount,
|
'amount' => $purchase->paid_amount,
|
||||||
'date' => $purchase->date,
|
'date' => $purchase->date,
|
||||||
'reference' => 'PAY-' . $purchase->reference_no,
|
'reference' => 'PAY-' . $purchase->reference_no,
|
||||||
'payment_method' => $purchase->payment_method,
|
'payment_method' => $purchase->payment_method,
|
||||||
'note' => 'Initial payment for purchase ' . $purchase->reference_no,
|
'note' => 'Initial payment for purchase ' . $purchase->reference_no
|
||||||
'created_by' => auth()->user()->name,
|
]);
|
||||||
'updated_by' => auth()->user()->name
|
*/
|
||||||
|
|
||||||
|
// Hanya catat di log
|
||||||
|
Log::info("Purchase Payment Info (not saved to DB)", [
|
||||||
|
'purchase_id' => $purchase->id,
|
||||||
|
'amount' => $purchase->paid_amount,
|
||||||
|
'payment_method' => $purchase->payment_method
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,9 +208,14 @@ class PurchaseController extends Controller
|
||||||
'message' => 'Purchase created successfully',
|
'message' => 'Purchase created successfully',
|
||||||
'data' => $purchase
|
'data' => $purchase
|
||||||
], 201);
|
], 201);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
Log::error("Error Creating Purchase", [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'file' => $e->getFile()
|
||||||
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Failed to create purchase',
|
'message' => 'Failed to create purchase',
|
||||||
'error' => $e->getMessage()
|
'error' => $e->getMessage()
|
||||||
|
@ -197,7 +260,7 @@ class PurchaseController extends Controller
|
||||||
'options' => [
|
'options' => [
|
||||||
'product_discount' => $purchase_detail->product_discount_amount,
|
'product_discount' => $purchase_detail->product_discount_amount,
|
||||||
'product_discount_type' => $purchase_detail->product_discount_type,
|
'product_discount_type' => $purchase_detail->product_discount_type,
|
||||||
'sub_total' => $purchase_detail->sub_total,
|
'subtotal' => $purchase_detail->subtotal,
|
||||||
'code' => $purchase_detail->product_code,
|
'code' => $purchase_detail->product_code,
|
||||||
'stock' => Product::findOrFail($purchase_detail->product_id)->product_quantity,
|
'stock' => Product::findOrFail($purchase_detail->product_id)->product_quantity,
|
||||||
'product_tax' => $purchase_detail->product_tax_amount,
|
'product_tax' => $purchase_detail->product_tax_amount,
|
||||||
|
@ -225,7 +288,7 @@ class PurchaseController extends Controller
|
||||||
if ($purchase->status == 'Completed') {
|
if ($purchase->status == 'Completed') {
|
||||||
$product = Product::findOrFail($purchase_detail->product_id);
|
$product = Product::findOrFail($purchase_detail->product_id);
|
||||||
$product->update([
|
$product->update([
|
||||||
'product_quantity' => $product->product_quantity - $purchase_detail->quantity
|
'product_quantity' => $product->product_quantity - $purchase_detail->qty
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$purchase_detail->delete();
|
$purchase_detail->delete();
|
||||||
|
@ -233,21 +296,16 @@ class PurchaseController extends Controller
|
||||||
|
|
||||||
$purchase->update([
|
$purchase->update([
|
||||||
'date' => $request->date,
|
'date' => $request->date,
|
||||||
'reference' => $request->reference,
|
'reference_no' => $request->reference,
|
||||||
'supplier_id' => $request->supplier_id,
|
'supplier_id' => $request->supplier_id,
|
||||||
'supplier_name' => Supplier::findOrFail($request->supplier_id)->supplier_name,
|
|
||||||
'tax_percentage' => $request->tax_percentage,
|
|
||||||
'discount_percentage' => $request->discount_percentage,
|
'discount_percentage' => $request->discount_percentage,
|
||||||
'shipping_amount' => $request->shipping_amount * 100,
|
'discount' => $request->shipping_amount * 100,
|
||||||
'paid_amount' => $request->paid_amount * 100,
|
'paid_amount' => $request->paid_amount * 100,
|
||||||
'total_amount' => $request->total_amount * 100,
|
'total' => $request->total_amount * 100,
|
||||||
'due_amount' => $due_amount * 100,
|
'due_amount' => $due_amount * 100,
|
||||||
'status' => $request->status,
|
|
||||||
'payment_status' => $payment_status,
|
'payment_status' => $payment_status,
|
||||||
'payment_method' => $request->payment_method,
|
'payment_method' => $request->payment_method,
|
||||||
'note' => $request->note,
|
'note' => $request->note
|
||||||
'tax_amount' => Cart::instance('purchase')->tax() * 100,
|
|
||||||
'discount_amount' => Cart::instance('purchase')->discount() * 100,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach (Cart::instance('purchase')->content() as $cart_item) {
|
foreach (Cart::instance('purchase')->content() as $cart_item) {
|
||||||
|
@ -256,10 +314,10 @@ class PurchaseController extends Controller
|
||||||
'product_id' => $cart_item->id,
|
'product_id' => $cart_item->id,
|
||||||
'product_name' => $cart_item->name,
|
'product_name' => $cart_item->name,
|
||||||
'product_code' => $cart_item->options->code,
|
'product_code' => $cart_item->options->code,
|
||||||
'quantity' => $cart_item->qty,
|
'qty' => $cart_item->qty,
|
||||||
'price' => $cart_item->price * 100,
|
'price' => $cart_item->price * 100,
|
||||||
'unit_price' => $cart_item->options->unit_price * 100,
|
'unit_price' => $cart_item->price * 100,
|
||||||
'sub_total' => $cart_item->options->sub_total * 100,
|
'subtotal' => $cart_item->options->subtotal * 100,
|
||||||
'product_discount_amount' => $cart_item->options->product_discount * 100,
|
'product_discount_amount' => $cart_item->options->product_discount * 100,
|
||||||
'product_discount_type' => $cart_item->options->product_discount_type,
|
'product_discount_type' => $cart_item->options->product_discount_type,
|
||||||
'product_tax_amount' => $cart_item->options->product_tax * 100,
|
'product_tax_amount' => $cart_item->options->product_tax * 100,
|
||||||
|
@ -297,11 +355,14 @@ class PurchaseController extends Controller
|
||||||
$purchase = Purchase::findOrFail($id);
|
$purchase = Purchase::findOrFail($id);
|
||||||
$supplier = Supplier::findOrFail($purchase->supplier_id);
|
$supplier = Supplier::findOrFail($purchase->supplier_id);
|
||||||
|
|
||||||
$pdf = PDF::loadView('purchase::print', [
|
// Menggunakan cara alternatif untuk membuat PDF
|
||||||
|
$pdf = app('dompdf.wrapper')
|
||||||
|
->loadView('purchase::print', [
|
||||||
'purchase' => $purchase,
|
'purchase' => $purchase,
|
||||||
'supplier' => $supplier,
|
'supplier' => $supplier,
|
||||||
])->setPaper('a4');
|
])
|
||||||
|
->setPaper('a4');
|
||||||
|
|
||||||
return $pdf->stream('purchase-'. $purchase->reference .'.pdf');
|
return $pdf->stream('purchase-'. $purchase->reference_no .'.pdf');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ use Modules\People\Entities\Supplier;
|
||||||
use Modules\Product\Entities\Product;
|
use Modules\Product\Entities\Product;
|
||||||
use Modules\Purchase\Entities\Purchase;
|
use Modules\Purchase\Entities\Purchase;
|
||||||
use Modules\Purchase\Entities\PurchaseDetail;
|
use Modules\Purchase\Entities\PurchaseDetail;
|
||||||
use Modules\Purchase\Entities\PurchasePayment;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class CreatePurchase extends Component
|
class CreatePurchase extends Component
|
||||||
|
@ -127,42 +127,61 @@ class CreatePurchase extends Component
|
||||||
|
|
||||||
public function save()
|
public function save()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
try {
|
// Log session variables
|
||||||
|
Log::info("CreatePurchase: Session variables", [
|
||||||
|
'branch_id' => session('branch_id'),
|
||||||
|
'active_branch' => session('active_branch'),
|
||||||
|
'all_session' => session()->all()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Log bahwa validasi berhasil
|
||||||
|
Log::info("CreatePurchase: Validation successful", [
|
||||||
|
'supplier_id' => $this->supplier_id,
|
||||||
|
'reference_no' => $this->reference_no,
|
||||||
|
'items_count' => count($this->items)
|
||||||
|
]);
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
$supplier = Supplier::findOrFail($this->supplier_id);
|
$supplier = Supplier::findOrFail($this->supplier_id);
|
||||||
|
Log::info("CreatePurchase: Supplier found", ['supplier' => $supplier->toArray()]);
|
||||||
|
|
||||||
$purchase = Purchase::create([
|
$purchase = Purchase::create([
|
||||||
'branch_id' => session('branch_id'),
|
'branch_id' => session('branch_id') ?? session('active_branch') ?? 1,
|
||||||
'user_id' => auth()->id(),
|
'user_id' => auth()->id(),
|
||||||
'date' => $this->date,
|
'date' => $this->date,
|
||||||
'reference_no' => $this->reference_no,
|
'reference_no' => $this->reference_no,
|
||||||
'supplier_id' => $this->supplier_id,
|
'supplier_id' => $this->supplier_id,
|
||||||
'supplier_name' => $supplier->supplier_name,
|
'discount_percentage' => $this->discount_percentage ?? 0,
|
||||||
'discount_percentage' => $this->discount_percentage,
|
'discount' => $this->discount ?? 0,
|
||||||
'discount' => $this->discount,
|
'total' => $this->total_amount ?? 0,
|
||||||
'total' => $this->total_amount,
|
'paid_amount' => $this->paid_amount ?? 0,
|
||||||
'paid_amount' => $this->paid_amount,
|
'due_amount' => $this->due_amount ?? 0,
|
||||||
'due_amount' => $this->due_amount,
|
|
||||||
'payment_status' => ($this->paid_amount >= $this->total_after_discount) ? 'paid' : 'due',
|
'payment_status' => ($this->paid_amount >= $this->total_after_discount) ? 'paid' : 'due',
|
||||||
'payment_method' => $this->payment_method,
|
'payment_method' => $this->payment_method,
|
||||||
'note' => $this->note,
|
'note' => $this->note,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Log::info("CreatePurchase: Purchase created", ['purchase' => $purchase->toArray()]);
|
||||||
|
|
||||||
// Save purchase items and update product quantities
|
// Save purchase items and update product quantities
|
||||||
foreach ($this->items as $item) {
|
foreach ($this->items as $index => $item) {
|
||||||
|
Log::info("CreatePurchase: Processing item", ['index' => $index, 'item' => $item]);
|
||||||
|
|
||||||
$product = Product::findOrFail($item['product_id']);
|
$product = Product::findOrFail($item['product_id']);
|
||||||
|
Log::info("CreatePurchase: Product found", ['product' => $product->toArray()]);
|
||||||
|
|
||||||
// Create purchase detail
|
// Create purchase detail
|
||||||
PurchaseDetail::create([
|
$purchaseDetail = PurchaseDetail::create([
|
||||||
'purchase_id' => $purchase->id,
|
'purchase_id' => $purchase->id,
|
||||||
'product_id' => $item['product_id'],
|
'product_id' => $item['product_id'],
|
||||||
'product_name' => $product->product_name,
|
'product_name' => $product->product_name,
|
||||||
'product_code' => $product->product_code,
|
// 'product_code' => $product->product_code,
|
||||||
'qty' => $item['qty'],
|
'qty' => $item['qty'],
|
||||||
'purchase_price' => $item['purchase_price'],
|
// 'price' => $item['purchase_price'],
|
||||||
'unit_price' => $item['unit_price'],
|
'unit_price' => $item['unit_price'],
|
||||||
'subtotal' => $item['qty'] * $item['unit_price'],
|
'subtotal' => $item['qty'] * $item['unit_price'],
|
||||||
'product_discount_amount' => $item['discount'] ?? 0,
|
'product_discount_amount' => $item['discount'] ?? 0,
|
||||||
|
@ -170,42 +189,48 @@ class CreatePurchase extends Component
|
||||||
'product_tax_amount' => $item['tax'] ?? 0,
|
'product_tax_amount' => $item['tax'] ?? 0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update product quantity
|
Log::info("CreatePurchase: Purchase detail created", ['purchaseDetail' => $purchaseDetail->toArray()]);
|
||||||
$product->update([
|
|
||||||
'product_quantity' => $product->product_quantity + $item['qty']
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Create or update product batch
|
// Create or update product batch
|
||||||
|
$batchData = [
|
||||||
|
'product_id' => $item['product_id'],
|
||||||
|
'branch_id' => session('branch_id') ?? session('active_branch') ?? 1,
|
||||||
|
'batch_code' => $this->reference_no . '-' . $item['product_id'],
|
||||||
|
'qty' => $item['qty'],
|
||||||
|
'unit_price' => $item['purchase_price'],
|
||||||
|
'exp_date' => null,
|
||||||
|
'purchase_id' => $purchase->id,
|
||||||
|
'created_by' => auth()->user()->name ?? 'system',
|
||||||
|
'updated_by' => auth()->user()->name ?? 'system',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
];
|
||||||
|
|
||||||
|
Log::info("CreatePurchase: Inserting batch", ['batchData' => $batchData]);
|
||||||
|
|
||||||
DB::table('product_batches')->updateOrInsert(
|
DB::table('product_batches')->updateOrInsert(
|
||||||
[
|
[
|
||||||
'product_id' => $item['product_id'],
|
'product_id' => $item['product_id'],
|
||||||
'batch_number' => $this->reference_no,
|
'batch_code' => $this->reference_no . '-' . $item['product_id'],
|
||||||
],
|
],
|
||||||
[
|
$batchData
|
||||||
'product_id' => $item['product_id'],
|
|
||||||
'batch_number' => $this->reference_no,
|
|
||||||
'qty' => $item['qty'],
|
|
||||||
'expiry_date' => null,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Log::info("CreatePurchase: Batch inserted/updated successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create purchase payment if there's a paid amount
|
// Create purchase payment if there's a paid amount
|
||||||
if ($this->paid_amount > 0) {
|
if ($this->paid_amount > 0) {
|
||||||
PurchasePayment::create([
|
// Hanya catat informasi pembayaran di log
|
||||||
'branch_id' => session('branch_id'),
|
Log::info("CreatePurchase: Payment info (not saved to DB)", [
|
||||||
'purchase_id' => $purchase->id,
|
'purchase_id' => $purchase->id,
|
||||||
'amount' => $this->paid_amount,
|
'amount' => $this->paid_amount,
|
||||||
'date' => now(),
|
'payment_method' => $this->payment_method
|
||||||
'reference' => 'PAY-' . strtoupper(Str::random(6)),
|
|
||||||
'payment_method' => $this->payment_method,
|
|
||||||
'note' => $this->note,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
Log::info("CreatePurchase: Transaction committed successfully");
|
||||||
|
|
||||||
$this->dispatch('showSuccessMessage', [
|
$this->dispatch('showSuccessMessage', [
|
||||||
'message' => 'Purchase created successfully!',
|
'message' => 'Purchase created successfully!',
|
||||||
|
@ -214,10 +239,20 @@ class CreatePurchase extends Component
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
Log::error("CreatePurchase: Error creating purchase", [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
$this->dispatch('showErrorMessage', [
|
$this->dispatch('showErrorMessage', [
|
||||||
'message' => 'Error creating purchase: ' . $e->getMessage()
|
'message' => 'Error creating purchase: ' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dispatch debug event untuk front-end
|
||||||
|
$this->dispatch('debug', [
|
||||||
|
'message' => 'Purchase process completed, check console logs'
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
|
|
|
@ -24,11 +24,145 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{{ $dataTable->table() }}
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Reference</th>
|
||||||
|
<th>Supplier ID</th>
|
||||||
|
<th>Total</th>
|
||||||
|
<th>Paid</th>
|
||||||
|
<th>Due</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@php
|
||||||
|
$purchases = DB::table('purchases')->get();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
@forelse($purchases as $purchase)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $purchase->id }}</td>
|
||||||
|
<td>{{ $purchase->date }}</td>
|
||||||
|
<td>{{ $purchase->reference_no }}</td>
|
||||||
|
<td>{{ $purchase->supplier_id }}</td>
|
||||||
|
<td>{{ $purchase->total / 100 }}</td>
|
||||||
|
<td>{{ $purchase->paid_amount / 100 }}</td>
|
||||||
|
<td>{{ $purchase->due_amount / 100 }}</td>
|
||||||
|
<td>{{ $purchase->payment_status }}</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="8" class="text-center">No purchases found in database.</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Debug Info -->
|
||||||
|
{{-- <div class="card mt-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Debug Info</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>Active Branch: {{ session('active_branch') ?? 'Not set' }}</p>
|
||||||
|
<p>Database Connection: {{ config('database.default') }}</p>
|
||||||
|
<p>Purchases Table Exists: {{ Schema::hasTable('purchases') ? 'Yes' : 'No' }}</p>
|
||||||
|
<p>Purchases Count: {{ DB::table('purchases')->count() }}</p>
|
||||||
|
<div id="ajax-response-debug"></div>
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
{{ $dataTable->scripts() }}
|
{{ $dataTable->scripts() }}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
console.log('DataTable scripts loaded');
|
||||||
|
|
||||||
|
// Log any DataTable errors
|
||||||
|
$.fn.dataTable.ext.errMode = function(settings, helpPage, message) {
|
||||||
|
console.error('DataTable Error:', message);
|
||||||
|
$('#ajax-response-debug').html('<div class="alert alert-danger">DataTable Error: ' + message + '</div>');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if DataTable is initialized
|
||||||
|
if ($.fn.dataTable.isDataTable('#purchases-table')) {
|
||||||
|
console.log('DataTable initialized successfully');
|
||||||
|
} else {
|
||||||
|
console.log('DataTable not initialized');
|
||||||
|
$('#ajax-response-debug').html('<div class="alert alert-warning">DataTable not initialized</div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intercept AJAX requests
|
||||||
|
$(document).ajaxSend(function(event, jqxhr, settings) {
|
||||||
|
console.log('AJAX Request:', settings.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Monitor AJAX responses
|
||||||
|
$(document).ajaxComplete(function(event, jqxhr, settings) {
|
||||||
|
console.log('AJAX Response:', jqxhr.status, jqxhr.responseJSON);
|
||||||
|
|
||||||
|
// Display the response in the debug area
|
||||||
|
if (settings.url.includes('purchases-table')) {
|
||||||
|
var responseData = jqxhr.responseJSON;
|
||||||
|
var debugInfo = '<h5>AJAX Response:</h5>';
|
||||||
|
debugInfo += '<p>Status: ' + jqxhr.status + '</p>';
|
||||||
|
|
||||||
|
if (responseData) {
|
||||||
|
debugInfo += '<p>Records Total: ' + responseData.recordsTotal + '</p>';
|
||||||
|
debugInfo += '<p>Records Filtered: ' + responseData.recordsFiltered + '</p>';
|
||||||
|
debugInfo += '<p>Data Count: ' + (responseData.data ? responseData.data.length : 0) + '</p>';
|
||||||
|
} else {
|
||||||
|
debugInfo += '<p class="text-danger">No response data</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#ajax-response-debug').html(debugInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Monitor AJAX errors
|
||||||
|
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
|
||||||
|
console.error('AJAX Error:', thrownError, jqxhr.responseText);
|
||||||
|
$('#ajax-response-debug').html('<div class="alert alert-danger">AJAX Error: ' + thrownError + '</div><pre>' + jqxhr.responseText + '</pre>');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Manual check for purchases data
|
||||||
|
$.ajax({
|
||||||
|
url: '/purchases?draw=1&columns[0][data]=date&columns[0][name]=date&columns[0][searchable]=true&columns[0][orderable]=true&columns[0][search][value]=&columns[0][search][regex]=false&columns[1][data]=reference_no&columns[1][name]=reference_no&columns[1][searchable]=true&columns[1][orderable]=true&columns[1][search][value]=&columns[1][search][regex]=false&columns[2][data]=supplier_name&columns[2][name]=supplier_name&columns[2][searchable]=true&columns[2][orderable]=true&columns[2][search][value]=&columns[2][search][regex]=false&columns[3][data]=payment_status&columns[3][name]=payment_status&columns[3][searchable]=true&columns[3][orderable]=true&columns[3][search][value]=&columns[3][search][regex]=false&columns[4][data]=total&columns[4][name]=total&columns[4][searchable]=true&columns[4][orderable]=true&columns[4][search][value]=&columns[4][search][regex]=false&columns[5][data]=paid_amount&columns[5][name]=paid_amount&columns[5][searchable]=true&columns[5][orderable]=true&columns[5][search][value]=&columns[5][search][regex]=false&columns[6][data]=due_amount&columns[6][name]=due_amount&columns[6][searchable]=true&columns[6][orderable]=true&columns[6][search][value]=&columns[6][search][regex]=false&columns[7][data]=action&columns[7][name]=action&columns[7][searchable]=false&columns[7][orderable]=false&columns[7][search][value]=&columns[7][search][regex]=false&order[0][column]=0&order[0][dir]=asc&start=0&length=10&search[value]=&search[regex]=false&_=1716306781000',
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Manual AJAX check:', response);
|
||||||
|
|
||||||
|
var manualCheckInfo = '<h5>Manual AJAX Check:</h5>';
|
||||||
|
if (response) {
|
||||||
|
manualCheckInfo += '<p>Records Total: ' + response.recordsTotal + '</p>';
|
||||||
|
manualCheckInfo += '<p>Records Filtered: ' + response.recordsFiltered + '</p>';
|
||||||
|
manualCheckInfo += '<p>Data Count: ' + (response.data ? response.data.length : 0) + '</p>';
|
||||||
|
|
||||||
|
if (response.data && response.data.length > 0) {
|
||||||
|
manualCheckInfo += '<p>First Record: ' + JSON.stringify(response.data[0]) + '</p>';
|
||||||
|
} else {
|
||||||
|
manualCheckInfo += '<p class="text-warning">No records found</p>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
manualCheckInfo += '<p class="text-danger">No response data</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#ajax-response-debug').append(manualCheckInfo);
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
|
console.error('Manual AJAX check error:', textStatus, errorThrown);
|
||||||
|
$('#ajax-response-debug').append('<div class="alert alert-danger">Manual AJAX Error: ' + errorThrown + '</div>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
document.addEventListener('livewire:init', function () {
|
document.addEventListener('livewire:init', function () {
|
||||||
// Success Message
|
// Success Message
|
||||||
Livewire.on('showSuccessMessage', function(data) {
|
Livewire.on('showSuccessMessage', function(data) {
|
||||||
|
console.log('Success message received:', data);
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Success!',
|
title: 'Success!',
|
||||||
text: data.message,
|
text: data.message,
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
|
|
||||||
// Error Message
|
// Error Message
|
||||||
Livewire.on('showErrorMessage', function(data) {
|
Livewire.on('showErrorMessage', function(data) {
|
||||||
|
console.log('Error message received:', data);
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Error!',
|
title: 'Error!',
|
||||||
text: data.message,
|
text: data.message,
|
||||||
|
@ -27,6 +29,7 @@
|
||||||
|
|
||||||
// Confirmation Dialog
|
// Confirmation Dialog
|
||||||
Livewire.on('showConfirmDialog', function(data) {
|
Livewire.on('showConfirmDialog', function(data) {
|
||||||
|
console.log('Confirmation dialog received:', data);
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: data.title,
|
title: data.title,
|
||||||
text: data.text,
|
text: data.text,
|
||||||
|
@ -42,6 +45,24 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Debug Event
|
||||||
|
Livewire.on('debug', function(data) {
|
||||||
|
console.log('DEBUG EVENT:', data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debug form submission
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const form = document.querySelector('form[wire\\:submit\\.prevent="save"]');
|
||||||
|
if (form) {
|
||||||
|
console.log('Form found, adding submit event listener');
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
console.log('Form submit event triggered');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Form not found!');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
|
@ -59,11 +59,10 @@
|
||||||
<th>Reference</th>
|
<th>Reference</th>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Supplier</th>
|
<th>Supplier</th>
|
||||||
<th>Total Amount</th>
|
<th>Total</th>
|
||||||
<th>Paid Amount</th>
|
<th>Paid Amount</th>
|
||||||
<th>Due Amount</th>
|
<th>Due Amount</th>
|
||||||
<th>Payment Status</th>
|
<th>Payment Status</th>
|
||||||
<th>Created By</th>
|
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -73,15 +72,14 @@
|
||||||
<td>{{ $purchase->reference_no }}</td>
|
<td>{{ $purchase->reference_no }}</td>
|
||||||
<td>{{ $purchase->date->format('d/m/Y') }}</td>
|
<td>{{ $purchase->date->format('d/m/Y') }}</td>
|
||||||
<td>{{ $purchase->supplier->name }}</td>
|
<td>{{ $purchase->supplier->name }}</td>
|
||||||
<td>{{ number_format($purchase->total_amount, 2) }}</td>
|
<td>{{ number_format($purchase->total, 2) }}</td>
|
||||||
<td>{{ number_format($purchase->paid_amount, 2) }}</td>
|
<td>{{ number_format($purchase->paid_amount, 2) }}</td>
|
||||||
<td>{{ $purchase->due_amount ? number_format($purchase->due_amount, 2) : '0.00' }}</td>
|
<td>{{ number_format($purchase->due_amount, 2) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-{{ $purchase->payment_status === 'Paid' ? 'success' : ($purchase->payment_status === 'Partial' ? 'warning' : 'danger') }}">
|
<span class="badge badge-{{ $purchase->payment_status === 'Paid' ? 'success' : ($purchase->payment_status === 'Partial' ? 'warning' : 'danger') }}">
|
||||||
{{ $purchase->payment_status }}
|
{{ $purchase->payment_status }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ $purchase->created_by }}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="{{ route('purchases.show', $purchase->id) }}" class="btn btn-info btn-sm">
|
<a href="{{ route('purchases.show', $purchase->id) }}" class="btn btn-info btn-sm">
|
||||||
|
@ -100,7 +98,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="9" class="text-center">No purchases found.</td>
|
<td colspan="8" class="text-center">No purchases found.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
|
||||||
<script>
|
<script>
|
||||||
function deletePurchase(id) {
|
function deletePurchase(id) {
|
||||||
if (confirm('Are you sure you want to delete this purchase?')) {
|
if (confirm('Are you sure you want to delete this purchase?')) {
|
||||||
|
@ -38,4 +37,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
@if ($data->payment_status == 'Partial')
|
@if (strtolower($payment_status) == 'partial')
|
||||||
<span class="badge badge-warning">
|
<span class="badge badge-warning">
|
||||||
{{ $data->payment_status }}
|
Partial
|
||||||
</span>
|
</span>
|
||||||
@elseif ($data->payment_status == 'Paid')
|
@elseif (strtolower($payment_status) == 'paid')
|
||||||
<span class="badge badge-success">
|
<span class="badge badge-success">
|
||||||
{{ $data->payment_status }}
|
Paid
|
||||||
</span>
|
</span>
|
||||||
@else
|
@else
|
||||||
<span class="badge badge-danger">
|
<span class="badge badge-danger">
|
||||||
{{ $data->payment_status }}
|
{{ $payment_status ?? 'Unpaid' }}
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
@ -29,7 +29,8 @@ Route::middleware(['web', 'auth'])->group(function () {
|
||||||
Route::get('/stock/{productId}/{branchId}', [PurchaseController::class, 'getStock'])->name('purchases.stock');
|
Route::get('/stock/{productId}/{branchId}', [PurchaseController::class, 'getStock'])->name('purchases.stock');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Purchase Payments
|
// Purchase Payments - dinonaktifkan karena tabel sudah dihapus
|
||||||
|
/*
|
||||||
Route::prefix('purchase-payments')->group(function () {
|
Route::prefix('purchase-payments')->group(function () {
|
||||||
Route::get('/{purchase_id}', 'PurchasePaymentsController@index')->name('purchase-payments.index');
|
Route::get('/{purchase_id}', 'PurchasePaymentsController@index')->name('purchase-payments.index');
|
||||||
Route::get('/{purchase_id}/create', 'PurchasePaymentsController@create')->name('purchase-payments.create');
|
Route::get('/{purchase_id}/create', 'PurchasePaymentsController@create')->name('purchase-payments.create');
|
||||||
|
@ -38,6 +39,7 @@ Route::middleware(['web', 'auth'])->group(function () {
|
||||||
Route::patch('/update/{purchasePayment}', 'PurchasePaymentsController@update')->name('purchase-payments.update');
|
Route::patch('/update/{purchasePayment}', 'PurchasePaymentsController@update')->name('purchase-payments.update');
|
||||||
Route::delete('/destroy/{purchasePayment}', 'PurchasePaymentsController@destroy')->name('purchase-payments.destroy');
|
Route::delete('/destroy/{purchasePayment}', 'PurchasePaymentsController@destroy')->name('purchase-payments.destroy');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
// Livewire Routes
|
// Livewire Routes
|
||||||
Route::get('/purchases/create', function () {
|
Route::get('/purchases/create', function () {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
'name' => 'PurchasesReturn'
|
|
||||||
];
|
|
|
@ -1,78 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\DataTables;
|
|
||||||
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturnPayment;
|
|
||||||
use Yajra\DataTables\Html\Button;
|
|
||||||
use Yajra\DataTables\Html\Column;
|
|
||||||
use Yajra\DataTables\Html\Editor\Editor;
|
|
||||||
use Yajra\DataTables\Html\Editor\Fields;
|
|
||||||
use Yajra\DataTables\Services\DataTable;
|
|
||||||
|
|
||||||
class PurchaseReturnPaymentsDataTable extends DataTable
|
|
||||||
{
|
|
||||||
|
|
||||||
public function dataTable($query) {
|
|
||||||
return datatables()
|
|
||||||
->eloquent($query)
|
|
||||||
->addColumn('amount', function ($data) {
|
|
||||||
return format_currency($data->amount);
|
|
||||||
})
|
|
||||||
->addColumn('action', function ($data) {
|
|
||||||
return view('purchasesreturn::payments.partials.actions', compact('data'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function query(PurchaseReturnPayment $model) {
|
|
||||||
return $model->newQuery()->byPurchaseReturn()->with('purchaseReturn');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function html() {
|
|
||||||
return $this->builder()
|
|
||||||
->setTableId('purchase-payments-table')
|
|
||||||
->columns($this->getColumns())
|
|
||||||
->minifiedAjax()
|
|
||||||
->dom("<'row'<'col-md-3'l><'col-md-5 mb-2'B><'col-md-4'f>> .
|
|
||||||
'tr' .
|
|
||||||
<'row'<'col-md-5'i><'col-md-7 mt-2'p>>")
|
|
||||||
->orderBy(5)
|
|
||||||
->buttons(
|
|
||||||
Button::make('excel')
|
|
||||||
->text('<i class="bi bi-file-earmark-excel-fill"></i> Excel'),
|
|
||||||
Button::make('print')
|
|
||||||
->text('<i class="bi bi-printer-fill"></i> Print'),
|
|
||||||
Button::make('reset')
|
|
||||||
->text('<i class="bi bi-x-circle"></i> Reset'),
|
|
||||||
Button::make('reload')
|
|
||||||
->text('<i class="bi bi-arrow-repeat"></i> Reload')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getColumns() {
|
|
||||||
return [
|
|
||||||
Column::make('date')
|
|
||||||
->className('align-middle text-center'),
|
|
||||||
|
|
||||||
Column::make('reference')
|
|
||||||
->className('align-middle text-center'),
|
|
||||||
|
|
||||||
Column::computed('amount')
|
|
||||||
->className('align-middle text-center'),
|
|
||||||
|
|
||||||
Column::make('payment_method')
|
|
||||||
->className('align-middle text-center'),
|
|
||||||
|
|
||||||
Column::computed('action')
|
|
||||||
->exportable(false)
|
|
||||||
->printable(false)
|
|
||||||
->className('align-middle text-center'),
|
|
||||||
|
|
||||||
Column::make('created_at')
|
|
||||||
->visible(false),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function filename(): string {
|
|
||||||
return 'PurchaseReturnPayments_' . date('YmdHis');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\DataTables;
|
|
||||||
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturn;
|
|
||||||
use Yajra\DataTables\Html\Button;
|
|
||||||
use Yajra\DataTables\Html\Column;
|
|
||||||
use Yajra\DataTables\Html\Editor\Editor;
|
|
||||||
use Yajra\DataTables\Html\Editor\Fields;
|
|
||||||
use Yajra\DataTables\Services\DataTable;
|
|
||||||
|
|
||||||
class PurchaseReturnsDataTable extends DataTable
|
|
||||||
{
|
|
||||||
|
|
||||||
public function dataTable($query) {
|
|
||||||
return datatables()
|
|
||||||
->eloquent($query)
|
|
||||||
->addColumn('total_amount', function ($data) {
|
|
||||||
return format_currency($data->total_amount);
|
|
||||||
})
|
|
||||||
->addColumn('paid_amount', function ($data) {
|
|
||||||
return format_currency($data->paid_amount);
|
|
||||||
})
|
|
||||||
->addColumn('due_amount', function ($data) {
|
|
||||||
return format_currency($data->due_amount);
|
|
||||||
})
|
|
||||||
->addColumn('status', function ($data) {
|
|
||||||
return view('purchasesreturn::partials.status', compact('data'));
|
|
||||||
})
|
|
||||||
->addColumn('payment_status', function ($data) {
|
|
||||||
return view('purchasesreturn::partials.payment-status', compact('data'));
|
|
||||||
})
|
|
||||||
->addColumn('action', function ($data) {
|
|
||||||
return view('purchasesreturn::partials.actions', compact('data'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function query(PurchaseReturn $model) {
|
|
||||||
return $model->newQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function html() {
|
|
||||||
return $this->builder()
|
|
||||||
->setTableId('purchase-returns-table')
|
|
||||||
->columns($this->getColumns())
|
|
||||||
->minifiedAjax()
|
|
||||||
->dom("<'row'<'col-md-3'l><'col-md-5 mb-2'B><'col-md-4'f>> .
|
|
||||||
'tr' .
|
|
||||||
<'row'<'col-md-5'i><'col-md-7 mt-2'p>>")
|
|
||||||
->orderBy(8)
|
|
||||||
->buttons(
|
|
||||||
Button::make('excel')
|
|
||||||
->text('<i class="bi bi-file-earmark-excel-fill"></i> Excel'),
|
|
||||||
Button::make('print')
|
|
||||||
->text('<i class="bi bi-printer-fill"></i> Print'),
|
|
||||||
Button::make('reset')
|
|
||||||
->text('<i class="bi bi-x-circle"></i> Reset'),
|
|
||||||
Button::make('reload')
|
|
||||||
->text('<i class="bi bi-arrow-repeat"></i> Reload')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getColumns() {
|
|
||||||
return [
|
|
||||||
Column::make('reference')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::make('supplier_name')
|
|
||||||
->title('Supplier')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('status')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('total_amount')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('paid_amount')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('due_amount')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('payment_status')
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::computed('action')
|
|
||||||
->exportable(false)
|
|
||||||
->printable(false)
|
|
||||||
->className('text-center align-middle'),
|
|
||||||
|
|
||||||
Column::make('created_at')
|
|
||||||
->visible(false)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function filename(): string {
|
|
||||||
return 'PurchaseReturns_' . date('YmdHis');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
|
|
||||||
class CreatePurchaseReturnsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('purchase_returns', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->date('date');
|
|
||||||
$table->string('reference');
|
|
||||||
$table->unsignedBigInteger('supplier_id')->nullable();
|
|
||||||
$table->string('supplier_name');
|
|
||||||
$table->integer('tax_percentage')->default(0);
|
|
||||||
$table->integer('tax_amount')->default(0);
|
|
||||||
$table->integer('discount_percentage')->default(0);
|
|
||||||
$table->integer('discount_amount')->default(0);
|
|
||||||
$table->integer('shipping_amount')->default(0);
|
|
||||||
$table->integer('total_amount');
|
|
||||||
$table->integer('paid_amount');
|
|
||||||
$table->integer('due_amount');
|
|
||||||
$table->string('status');
|
|
||||||
$table->string('payment_status');
|
|
||||||
$table->string('payment_method');
|
|
||||||
$table->text('note')->nullable();
|
|
||||||
$table->foreign('supplier_id')->references('id')->on('suppliers')->nullOnDelete();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('purchase_returns');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
|
|
||||||
class CreatePurchaseReturnDetailsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('purchase_return_details', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->unsignedBigInteger('purchase_return_id');
|
|
||||||
$table->unsignedBigInteger('product_id')->nullable();
|
|
||||||
$table->string('product_name');
|
|
||||||
$table->string('product_code');
|
|
||||||
$table->integer('quantity');
|
|
||||||
$table->integer('price');
|
|
||||||
$table->integer('unit_price');
|
|
||||||
$table->integer('sub_total');
|
|
||||||
$table->integer('product_discount_amount');
|
|
||||||
$table->string('product_discount_type')->default('fixed');
|
|
||||||
$table->integer('product_tax_amount');
|
|
||||||
$table->foreign('purchase_return_id')->references('id')
|
|
||||||
->on('purchase_returns')->cascadeOnDelete();
|
|
||||||
$table->foreign('product_id')->references('id')
|
|
||||||
->on('products')->nullOnDelete();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('purchase_return_details');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
|
|
||||||
class CreatePurchaseReturnPaymentsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('purchase_return_payments', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->unsignedBigInteger('purchase_return_id');
|
|
||||||
$table->integer('amount');
|
|
||||||
$table->date('date');
|
|
||||||
$table->string('reference');
|
|
||||||
$table->string('payment_method');
|
|
||||||
$table->text('note')->nullable();
|
|
||||||
$table->foreign('purchase_return_id')->references('id')->on('purchase_returns')->cascadeOnDelete();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('purchase_return_payments');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Database\Seeders;
|
|
||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class PurchasesReturnDatabaseSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
Model::unguard();
|
|
||||||
|
|
||||||
// $this->call("OthersTableSeeder");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Entities;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
|
|
||||||
class PurchaseReturn extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
protected $guarded = [];
|
|
||||||
|
|
||||||
public function purchaseReturnDetails() {
|
|
||||||
return $this->hasMany(PurchaseReturnDetail::class, 'purchase_return_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function purchaseReturnPayments() {
|
|
||||||
return $this->hasMany(PurchaseReturnPayment::class, 'purchase_return_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function boot() {
|
|
||||||
parent::boot();
|
|
||||||
|
|
||||||
static::creating(function ($model) {
|
|
||||||
$number = PurchaseReturn::max('id') + 1;
|
|
||||||
$model->reference = make_reference_id('PRRN', $number);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeCompleted($query) {
|
|
||||||
return $query->where('status', 'Completed');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getShippingAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPaidAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDueAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTaxAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDiscountAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Entities;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Modules\Product\Entities\Product;
|
|
||||||
|
|
||||||
class PurchaseReturnDetail extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
protected $guarded = [];
|
|
||||||
|
|
||||||
protected $with = ['product'];
|
|
||||||
|
|
||||||
public function product() {
|
|
||||||
return $this->belongsTo(Product::class, 'product_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function purchaseReturn() {
|
|
||||||
return $this->belongsTo(PurchaseReturn::class, 'purchase_return_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPriceAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUnitPriceAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSubTotalAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getProductDiscountAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getProductTaxAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Entities;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
|
|
||||||
class PurchaseReturnPayment extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
protected $guarded = [];
|
|
||||||
|
|
||||||
public function purchaseReturn() {
|
|
||||||
return $this->belongsTo(PurchaseReturn::class, 'purchase_return_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setAmountAttribute($value) {
|
|
||||||
$this->attributes['amount'] = $value * 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAmountAttribute($value) {
|
|
||||||
return $value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDateAttribute($value) {
|
|
||||||
return Carbon::parse($value)->format('d M, Y');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeByPurchaseReturn($query) {
|
|
||||||
return $query->where('purchase_return_id', request()->route('purchase_return_id'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Http\Controllers;
|
|
||||||
|
|
||||||
use Modules\PurchasesReturn\DataTables\PurchaseReturnPaymentsDataTable;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Routing\Controller;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturn;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturnPayment;
|
|
||||||
|
|
||||||
class PurchaseReturnPaymentsController extends Controller
|
|
||||||
{
|
|
||||||
|
|
||||||
public function index($purchase_return_id, PurchaseReturnPaymentsDataTable $dataTable) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::findOrFail($purchase_return_id);
|
|
||||||
|
|
||||||
return $dataTable->render('purchasesreturn::payments.index', compact('purchase_return'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function create($purchase_return_id) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::findOrFail($purchase_return_id);
|
|
||||||
|
|
||||||
return view('purchasesreturn::payments.create', compact('purchase_return'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function store(Request $request) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$request->validate([
|
|
||||||
'date' => 'required|date',
|
|
||||||
'reference' => 'required|string|max:255',
|
|
||||||
'amount' => 'required|numeric',
|
|
||||||
'note' => 'nullable|string|max:1000',
|
|
||||||
'purchase_return_id' => 'required',
|
|
||||||
'payment_method' => 'required|string|max:255'
|
|
||||||
]);
|
|
||||||
|
|
||||||
DB::transaction(function () use ($request) {
|
|
||||||
PurchaseReturnPayment::create([
|
|
||||||
'date' => $request->date,
|
|
||||||
'reference' => $request->reference,
|
|
||||||
'amount' => $request->amount,
|
|
||||||
'note' => $request->note,
|
|
||||||
'purchase_return_id' => $request->purchase_return_id,
|
|
||||||
'payment_method' => $request->payment_method
|
|
||||||
]);
|
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::findOrFail($request->purchase_return_id);
|
|
||||||
|
|
||||||
$due_amount = $purchase_return->due_amount - $request->amount;
|
|
||||||
|
|
||||||
if ($due_amount == $purchase_return->total_amount) {
|
|
||||||
$payment_status = 'Unpaid';
|
|
||||||
} elseif ($due_amount > 0) {
|
|
||||||
$payment_status = 'Partial';
|
|
||||||
} else {
|
|
||||||
$payment_status = 'Paid';
|
|
||||||
}
|
|
||||||
|
|
||||||
$purchase_return->update([
|
|
||||||
'paid_amount' => ($purchase_return->paid_amount + $request->amount) * 100,
|
|
||||||
'due_amount' => $due_amount * 100,
|
|
||||||
'payment_status' => $payment_status
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
toast('Purchase Return Payment Created!', 'success');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function edit($purchase_return_id, PurchaseReturnPayment $purchaseReturnPayment) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::findOrFail($purchase_return_id);
|
|
||||||
|
|
||||||
return view('purchasesreturn::payments.edit', compact('purchaseReturnPayment', 'purchase_return'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function update(Request $request, PurchaseReturnPayment $purchaseReturnPayment) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$request->validate([
|
|
||||||
'date' => 'required|date',
|
|
||||||
'reference' => 'required|string|max:255',
|
|
||||||
'amount' => 'required|numeric',
|
|
||||||
'note' => 'nullable|string|max:1000',
|
|
||||||
'purchase_return_id' => 'required',
|
|
||||||
'payment_method' => 'required|string|max:255'
|
|
||||||
]);
|
|
||||||
|
|
||||||
DB::transaction(function () use ($request, $purchaseReturnPayment) {
|
|
||||||
$purchase_return = $purchaseReturnPayment->purchaseReturn;
|
|
||||||
|
|
||||||
$due_amount = ($purchase_return->due_amount + $purchaseReturnPayment->amount) - $request->amount;
|
|
||||||
|
|
||||||
if ($due_amount == $purchase_return->total_amount) {
|
|
||||||
$payment_status = 'Unpaid';
|
|
||||||
} elseif ($due_amount > 0) {
|
|
||||||
$payment_status = 'Partial';
|
|
||||||
} else {
|
|
||||||
$payment_status = 'Paid';
|
|
||||||
}
|
|
||||||
|
|
||||||
$purchase_return->update([
|
|
||||||
'paid_amount' => (($purchase_return->paid_amount - $purchaseReturnPayment->amount) + $request->amount) * 100,
|
|
||||||
'due_amount' => $due_amount * 100,
|
|
||||||
'payment_status' => $payment_status
|
|
||||||
]);
|
|
||||||
|
|
||||||
$purchaseReturnPayment->update([
|
|
||||||
'date' => $request->date,
|
|
||||||
'reference' => $request->reference,
|
|
||||||
'amount' => $request->amount,
|
|
||||||
'note' => $request->note,
|
|
||||||
'purchase_return_id' => $request->purchase_return_id,
|
|
||||||
'payment_method' => $request->payment_method
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
toast('Purchase Return Payment Updated!', 'info');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function destroy(PurchaseReturnPayment $purchaseReturnPayment) {
|
|
||||||
abort_if(Gate::denies('access_purchase_return_payments'), 403);
|
|
||||||
|
|
||||||
$purchaseReturnPayment->delete();
|
|
||||||
|
|
||||||
toast('Purchase Return Payment Deleted!', 'warning');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,232 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Http\Controllers;
|
|
||||||
|
|
||||||
use Modules\PurchasesReturn\DataTables\PurchaseReturnsDataTable;
|
|
||||||
use Gloudemans\Shoppingcart\Facades\Cart;
|
|
||||||
use Illuminate\Routing\Controller;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
use Modules\People\Entities\Supplier;
|
|
||||||
use Modules\Product\Entities\Product;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturn;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturnDetail;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturnPayment;
|
|
||||||
use Modules\PurchasesReturn\Http\Requests\StorePurchaseReturnRequest;
|
|
||||||
use Modules\PurchasesReturn\Http\Requests\UpdatePurchaseReturnRequest;
|
|
||||||
|
|
||||||
class PurchasesReturnController extends Controller
|
|
||||||
{
|
|
||||||
|
|
||||||
public function index(PurchaseReturnsDataTable $dataTable) {
|
|
||||||
abort_if(Gate::denies('access_purchase_returns'), 403);
|
|
||||||
|
|
||||||
return $dataTable->render('purchasesreturn::index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function create() {
|
|
||||||
abort_if(Gate::denies('create_purchase_returns'), 403);
|
|
||||||
|
|
||||||
Cart::instance('purchase_return')->destroy();
|
|
||||||
|
|
||||||
return view('purchasesreturn::create');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function store(StorePurchaseReturnRequest $request) {
|
|
||||||
DB::transaction(function () use ($request) {
|
|
||||||
$due_amount = $request->total_amount - $request->paid_amount;
|
|
||||||
|
|
||||||
if ($due_amount == $request->total_amount) {
|
|
||||||
$payment_status = 'Unpaid';
|
|
||||||
} elseif ($due_amount > 0) {
|
|
||||||
$payment_status = 'Partial';
|
|
||||||
} else {
|
|
||||||
$payment_status = 'Paid';
|
|
||||||
}
|
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::create([
|
|
||||||
'date' => $request->date,
|
|
||||||
'supplier_id' => $request->supplier_id,
|
|
||||||
'supplier_name' => Supplier::findOrFail($request->supplier_id)->supplier_name,
|
|
||||||
'tax_percentage' => $request->tax_percentage,
|
|
||||||
'discount_percentage' => $request->discount_percentage,
|
|
||||||
'shipping_amount' => $request->shipping_amount * 100,
|
|
||||||
'paid_amount' => $request->paid_amount * 100,
|
|
||||||
'total_amount' => $request->total_amount * 100,
|
|
||||||
'due_amount' => $due_amount * 100,
|
|
||||||
'status' => $request->status,
|
|
||||||
'payment_status' => $payment_status,
|
|
||||||
'payment_method' => $request->payment_method,
|
|
||||||
'note' => $request->note,
|
|
||||||
'tax_amount' => Cart::instance('purchase_return')->tax() * 100,
|
|
||||||
'discount_amount' => Cart::instance('purchase_return')->discount() * 100,
|
|
||||||
]);
|
|
||||||
|
|
||||||
foreach (Cart::instance('purchase_return')->content() as $cart_item) {
|
|
||||||
PurchaseReturnDetail::create([
|
|
||||||
'purchase_return_id' => $purchase_return->id,
|
|
||||||
'product_id' => $cart_item->id,
|
|
||||||
'product_name' => $cart_item->name,
|
|
||||||
'product_code' => $cart_item->options->code,
|
|
||||||
'quantity' => $cart_item->qty,
|
|
||||||
'price' => $cart_item->price * 100,
|
|
||||||
'unit_price' => $cart_item->options->unit_price * 100,
|
|
||||||
'sub_total' => $cart_item->options->sub_total * 100,
|
|
||||||
'product_discount_amount' => $cart_item->options->product_discount * 100,
|
|
||||||
'product_discount_type' => $cart_item->options->product_discount_type,
|
|
||||||
'product_tax_amount' => $cart_item->options->product_tax * 100,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($request->status == 'Shipped' || $request->status == 'Completed') {
|
|
||||||
$product = Product::findOrFail($cart_item->id);
|
|
||||||
$product->update([
|
|
||||||
'product_quantity' => $product->product_quantity - $cart_item->qty
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cart::instance('purchase_return')->destroy();
|
|
||||||
|
|
||||||
if ($purchase_return->paid_amount > 0) {
|
|
||||||
PurchaseReturnPayment::create([
|
|
||||||
'date' => $request->date,
|
|
||||||
'reference' => 'INV/' . $purchase_return->reference,
|
|
||||||
'amount' => $purchase_return->paid_amount,
|
|
||||||
'purchase_return_id' => $purchase_return->id,
|
|
||||||
'payment_method' => $request->payment_method
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
toast('Purchase Return Created!', 'success');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function show(PurchaseReturn $purchase_return) {
|
|
||||||
abort_if(Gate::denies('show_purchase_returns'), 403);
|
|
||||||
|
|
||||||
$supplier = Supplier::findOrFail($purchase_return->supplier_id);
|
|
||||||
|
|
||||||
return view('purchasesreturn::show', compact('purchase_return', 'supplier'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function edit(PurchaseReturn $purchase_return) {
|
|
||||||
abort_if(Gate::denies('edit_purchase_returns'), 403);
|
|
||||||
|
|
||||||
$purchase_return_details = $purchase_return->purchaseReturnDetails;
|
|
||||||
|
|
||||||
Cart::instance('purchase_return')->destroy();
|
|
||||||
|
|
||||||
$cart = Cart::instance('purchase_return');
|
|
||||||
|
|
||||||
foreach ($purchase_return_details as $purchase_return_detail) {
|
|
||||||
$cart->add([
|
|
||||||
'id' => $purchase_return_detail->product_id,
|
|
||||||
'name' => $purchase_return_detail->product_name,
|
|
||||||
'qty' => $purchase_return_detail->quantity,
|
|
||||||
'price' => $purchase_return_detail->price,
|
|
||||||
'weight' => 1,
|
|
||||||
'options' => [
|
|
||||||
'product_discount' => $purchase_return_detail->product_discount_amount,
|
|
||||||
'product_discount_type' => $purchase_return_detail->product_discount_type,
|
|
||||||
'sub_total' => $purchase_return_detail->sub_total,
|
|
||||||
'code' => $purchase_return_detail->product_code,
|
|
||||||
'stock' => Product::findOrFail($purchase_return_detail->product_id)->product_quantity,
|
|
||||||
'product_tax' => $purchase_return_detail->product_tax_amount,
|
|
||||||
'unit_price' => $purchase_return_detail->unit_price
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('purchasesreturn::edit', compact('purchase_return'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function update(UpdatePurchaseReturnRequest $request, PurchaseReturn $purchase_return) {
|
|
||||||
DB::transaction(function () use ($request, $purchase_return) {
|
|
||||||
$due_amount = $request->total_amount - $request->paid_amount;
|
|
||||||
|
|
||||||
if ($due_amount == $request->total_amount) {
|
|
||||||
$payment_status = 'Unpaid';
|
|
||||||
} elseif ($due_amount > 0) {
|
|
||||||
$payment_status = 'Partial';
|
|
||||||
} else {
|
|
||||||
$payment_status = 'Paid';
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($purchase_return->purchaseReturnDetails as $purchase_return_detail) {
|
|
||||||
if ($purchase_return->status == 'Shipped' || $purchase_return->status == 'Completed') {
|
|
||||||
$product = Product::findOrFail($purchase_return_detail->product_id);
|
|
||||||
$product->update([
|
|
||||||
'product_quantity' => $product->product_quantity + $purchase_return_detail->quantity
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$purchase_return_detail->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
$purchase_return->update([
|
|
||||||
'date' => $request->date,
|
|
||||||
'reference' => $request->reference,
|
|
||||||
'supplier_id' => $request->supplier_id,
|
|
||||||
'supplier_name' => Supplier::findOrFail($request->supplier_id)->supplier_name,
|
|
||||||
'tax_percentage' => $request->tax_percentage,
|
|
||||||
'discount_percentage' => $request->discount_percentage,
|
|
||||||
'shipping_amount' => $request->shipping_amount * 100,
|
|
||||||
'paid_amount' => $request->paid_amount * 100,
|
|
||||||
'total_amount' => $request->total_amount * 100,
|
|
||||||
'due_amount' => $due_amount * 100,
|
|
||||||
'status' => $request->status,
|
|
||||||
'payment_status' => $payment_status,
|
|
||||||
'payment_method' => $request->payment_method,
|
|
||||||
'note' => $request->note,
|
|
||||||
'tax_amount' => Cart::instance('purchase_return')->tax() * 100,
|
|
||||||
'discount_amount' => Cart::instance('purchase_return')->discount() * 100,
|
|
||||||
]);
|
|
||||||
|
|
||||||
foreach (Cart::instance('purchase_return')->content() as $cart_item) {
|
|
||||||
PurchaseReturnDetail::create([
|
|
||||||
'purchase_return_id' => $purchase_return->id,
|
|
||||||
'product_id' => $cart_item->id,
|
|
||||||
'product_name' => $cart_item->name,
|
|
||||||
'product_code' => $cart_item->options->code,
|
|
||||||
'quantity' => $cart_item->qty,
|
|
||||||
'price' => $cart_item->price * 100,
|
|
||||||
'unit_price' => $cart_item->options->unit_price * 100,
|
|
||||||
'sub_total' => $cart_item->options->sub_total * 100,
|
|
||||||
'product_discount_amount' => $cart_item->options->product_discount * 100,
|
|
||||||
'product_discount_type' => $cart_item->options->product_discount_type,
|
|
||||||
'product_tax_amount' => $cart_item->options->product_tax * 100,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($request->status == 'Shipped' || $request->status == 'Completed') {
|
|
||||||
$product = Product::findOrFail($cart_item->id);
|
|
||||||
$product->update([
|
|
||||||
'product_quantity' => $product->product_quantity - $cart_item->qty
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cart::instance('purchase_return')->destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
toast('Purchase Return Updated!', 'info');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function destroy(PurchaseReturn $purchase_return) {
|
|
||||||
abort_if(Gate::denies('delete_purchase_returns'), 403);
|
|
||||||
|
|
||||||
$purchase_return->delete();
|
|
||||||
|
|
||||||
toast('Purchase Return Deleted!', 'warning');
|
|
||||||
|
|
||||||
return redirect()->route('purchase-returns.index');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
|
|
||||||
class StorePurchaseReturnRequest extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'supplier_id' => 'required|numeric',
|
|
||||||
'reference' => 'required|string|max:255',
|
|
||||||
'tax_percentage' => 'required|integer|min:0|max:100',
|
|
||||||
'discount_percentage' => 'required|integer|min:0|max:100',
|
|
||||||
'shipping_amount' => 'required|numeric',
|
|
||||||
'total_amount' => 'required|numeric',
|
|
||||||
'paid_amount' => 'required|numeric',
|
|
||||||
'status' => 'required|string|max:255',
|
|
||||||
'payment_method' => 'required|string|max:255',
|
|
||||||
'note' => 'nullable|string|max:1000'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the user is authorized to make this request.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function authorize()
|
|
||||||
{
|
|
||||||
return Gate::allows('create_purchase_returns');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
|
|
||||||
class UpdatePurchaseReturnRequest extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'supplier_id' => 'required|numeric',
|
|
||||||
'reference' => 'required|string|max:255',
|
|
||||||
'tax_percentage' => 'required|integer|min:0|max:100',
|
|
||||||
'discount_percentage' => 'required|integer|min:0|max:100',
|
|
||||||
'shipping_amount' => 'required|numeric',
|
|
||||||
'total_amount' => 'required|numeric',
|
|
||||||
'paid_amount' => 'required|numeric|max:' . $this->purchase_return->total_amount,
|
|
||||||
'status' => 'required|string|max:255',
|
|
||||||
'payment_method' => 'required|string|max:255',
|
|
||||||
'note' => 'nullable|string|max:1000'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the user is authorized to make this request.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function authorize()
|
|
||||||
{
|
|
||||||
return Gate::allows('edit_purchase_returns');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Providers;
|
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
|
||||||
use Illuminate\Database\Eloquent\Factory;
|
|
||||||
|
|
||||||
class PurchasesReturnServiceProvider extends ServiceProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string $moduleName
|
|
||||||
*/
|
|
||||||
protected $moduleName = 'PurchasesReturn';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string $moduleNameLower
|
|
||||||
*/
|
|
||||||
protected $moduleNameLower = 'purchasesreturn';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boot the application events.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function boot()
|
|
||||||
{
|
|
||||||
$this->registerTranslations();
|
|
||||||
$this->registerConfig();
|
|
||||||
$this->registerViews();
|
|
||||||
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the service provider.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function register()
|
|
||||||
{
|
|
||||||
$this->app->register(RouteServiceProvider::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register config.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function registerConfig()
|
|
||||||
{
|
|
||||||
$this->publishes([
|
|
||||||
module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
|
|
||||||
], 'config');
|
|
||||||
$this->mergeConfigFrom(
|
|
||||||
module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register views.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function registerViews()
|
|
||||||
{
|
|
||||||
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
|
|
||||||
|
|
||||||
$sourcePath = module_path($this->moduleName, 'Resources/views');
|
|
||||||
|
|
||||||
$this->publishes([
|
|
||||||
$sourcePath => $viewPath
|
|
||||||
], ['views', $this->moduleNameLower . '-module-views']);
|
|
||||||
|
|
||||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register translations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function registerTranslations()
|
|
||||||
{
|
|
||||||
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
|
|
||||||
|
|
||||||
if (is_dir($langPath)) {
|
|
||||||
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
|
|
||||||
} else {
|
|
||||||
$this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the services provided by the provider.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function provides()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getPublishableViewPaths(): array
|
|
||||||
{
|
|
||||||
$paths = [];
|
|
||||||
foreach (\Config::get('view.paths') as $path) {
|
|
||||||
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
|
|
||||||
$paths[] = $path . '/modules/' . $this->moduleNameLower;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $paths;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Modules\PurchasesReturn\Providers;
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
|
||||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
|
||||||
|
|
||||||
class RouteServiceProvider extends ServiceProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The module namespace to assume when generating URLs to actions.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $moduleNamespace = 'Modules\PurchasesReturn\Http\Controllers';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before routes are registered.
|
|
||||||
*
|
|
||||||
* Register any model bindings or pattern based filters.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function boot()
|
|
||||||
{
|
|
||||||
parent::boot();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the routes for the application.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function map()
|
|
||||||
{
|
|
||||||
$this->mapApiRoutes();
|
|
||||||
|
|
||||||
$this->mapWebRoutes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the "web" routes for the application.
|
|
||||||
*
|
|
||||||
* These routes all receive session state, CSRF protection, etc.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function mapWebRoutes()
|
|
||||||
{
|
|
||||||
Route::middleware('web')
|
|
||||||
->namespace($this->moduleNamespace)
|
|
||||||
->group(module_path('PurchasesReturn', '/Routes/web.php'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the "api" routes for the application.
|
|
||||||
*
|
|
||||||
* These routes are typically stateless.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function mapApiRoutes()
|
|
||||||
{
|
|
||||||
Route::prefix('api')
|
|
||||||
->middleware('api')
|
|
||||||
->namespace($this->moduleNamespace)
|
|
||||||
->group(module_path('PurchasesReturn', '/Routes/api.php'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,138 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Create Purchase Return')
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purchase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item active">Add</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid mb-4">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<livewire:search-product/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
@include('utils.alerts')
|
|
||||||
<form id="purchase-return-form" action="{{ route('purchase-returns.store') }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="reference">Reference <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="reference" required readonly value="PRRN">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="supplier_id">Supplier <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="supplier_id" id="supplier_id" required>
|
|
||||||
@foreach(\Modules\People\Entities\Supplier::all() as $supplier)
|
|
||||||
<option value="{{ $supplier->id }}">{{ $supplier->supplier_name }}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="date">Date <span class="text-danger">*</span></label>
|
|
||||||
<input type="date" class="form-control" name="date" required value="{{ now()->format('Y-m-d') }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<livewire:product-cart :cartInstance="'purchase_return'"/>
|
|
||||||
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="status">Status <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="status" id="status" required>
|
|
||||||
<option value="Pending">Pending</option>
|
|
||||||
<option value="Shipped">Shipped</option>
|
|
||||||
<option value="Completed">Completed</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="payment_method">Payment Method <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="payment_method" id="payment_method" required>
|
|
||||||
<option value="Cash">Cash</option>
|
|
||||||
<option value="Credit Card">Credit Card</option>
|
|
||||||
<option value="Bank Transfer">Bank Transfer</option>
|
|
||||||
<option value="Cheque">Cheque</option>
|
|
||||||
<option value="Other">Other</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="paid_amount">Amount Received <span class="text-danger">*</span></label>
|
|
||||||
<div class="input-group">
|
|
||||||
<input id="paid_amount" type="text" class="form-control" name="paid_amount" required>
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button id="getTotalAmount" class="btn btn-primary" type="button">
|
|
||||||
<i class="bi bi-check-square"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="note">Note (If Needed)</label>
|
|
||||||
<textarea name="note" id="note" rows="5" class="form-control"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-3">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
Create Purchase Return <i class="bi bi-check"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
<script src="{{ asset('js/jquery-mask-money.js') }}"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#paid_amount').maskMoney({
|
|
||||||
prefix:'{{ settings()->currency->symbol }}',
|
|
||||||
thousands:'{{ settings()->currency->thousand_separator }}',
|
|
||||||
decimal:'{{ settings()->currency->decimal_separator }}',
|
|
||||||
allowZero: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#getTotalAmount').click(function () {
|
|
||||||
$('#paid_amount').maskMoney('mask', {{ Cart::instance('purchase_return')->total() }});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#purchase-return-form').submit(function () {
|
|
||||||
var paid_amount = $('#paid_amount').maskMoney('unmasked')[0];
|
|
||||||
$('#paid_amount').val(paid_amount);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endpush
|
|
|
@ -1,124 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Edit Purchase Return')
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purchase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item active">Edit</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid mb-4">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<livewire:search-product/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
@include('utils.alerts')
|
|
||||||
<form id="purchase-return-form" action="{{ route('purchase-returns.update', $purchase_return) }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('patch')
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="reference">Reference <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="reference" required value="{{ $purchase_return->reference }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="supplier_id">Supplier <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="supplier_id" id="supplier_id" required>
|
|
||||||
@foreach(\Modules\People\Entities\Supplier::all() as $supplier)
|
|
||||||
<option {{ $purchase_return->supplier_id == $supplier->id ? 'selected' : '' }} value="{{ $supplier->id }}">{{ $supplier->supplier_name }}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="date">Date <span class="text-danger">*</span></label>
|
|
||||||
<input type="date" class="form-control" name="date" required value="{{ $purchase_return->date }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<livewire:product-cart :cartInstance="'purchase_return'" :data="$purchase_return"/>
|
|
||||||
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="status">Status <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="status" id="status" required>
|
|
||||||
<option {{ $purchase_return->status == 'Pending' ? 'selected' : '' }} value="Pending">Pending</option>
|
|
||||||
<option {{ $purchase_return->status == 'Shipped' ? 'selected' : '' }} value="Shipped">Shipped</option>
|
|
||||||
<option {{ $purchase_return->status == 'Completed' ? 'selected' : '' }} value="Completed">Completed</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="payment_method">Payment Method <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="payment_method" required value="{{ $purchase_return->payment_method }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="paid_amount">Amount Paid <span class="text-danger">*</span></label>
|
|
||||||
<input id="paid_amount" type="text" class="form-control" name="paid_amount" required value="{{ $purchase_return->paid_amount }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="note">Note (If Needed)</label>
|
|
||||||
<textarea name="note" id="note" rows="5" class="form-control">{{ $purchase_return->note }}</textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-3">
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
Update Purchase Return <i class="bi bi-check"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
<script src="{{ asset('js/jquery-mask-money.js') }}"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#paid_amount').maskMoney({
|
|
||||||
prefix:'{{ settings()->currency->symbol }}',
|
|
||||||
thousands:'{{ settings()->currency->thousand_separator }}',
|
|
||||||
decimal:'{{ settings()->currency->decimal_separator }}',
|
|
||||||
allowZero: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#paid_amount').maskMoney('mask');
|
|
||||||
|
|
||||||
$('#purchase-return-form').submit(function () {
|
|
||||||
var paid_amount = $('#paid_amount').maskMoney('unmasked')[0];
|
|
||||||
$('#paid_amount').val(paid_amount);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endpush
|
|
|
@ -1,40 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Purchase Returns')
|
|
||||||
|
|
||||||
@section('third_party_stylesheets')
|
|
||||||
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap4.min.css">
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item active">Purchase Returns</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<a href="{{ route('purchase-returns.create') }}" class="btn btn-primary">
|
|
||||||
Add Purchase Return <i class="bi bi-plus"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
|
||||||
{!! $dataTable->table() !!}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
{!! $dataTable->scripts() !!}
|
|
||||||
@endpush
|
|
|
@ -1,42 +0,0 @@
|
||||||
<div class="btn-group dropleft">
|
|
||||||
<button type="button" class="btn btn-ghost-primary dropdown rounded" data-toggle="dropdown" aria-expanded="false">
|
|
||||||
<i class="bi bi-three-dots-vertical"></i>
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu">
|
|
||||||
@can('access_purchase_return_payments')
|
|
||||||
<a href="{{ route('purchase-return-payments.index', $data->id) }}" class="dropdown-item">
|
|
||||||
<i class="bi bi-cash-coin mr-2 text-warning" style="line-height: 1;"></i> Show Payments
|
|
||||||
</a>
|
|
||||||
@endcan
|
|
||||||
@can('access_purchase_return_payments')
|
|
||||||
@if($data->due_amount > 0)
|
|
||||||
<a href="{{ route('purchase-return-payments.create', $data->id) }}" class="dropdown-item">
|
|
||||||
<i class="bi bi-plus-circle-dotted mr-2 text-success" style="line-height: 1;"></i> Add Payment
|
|
||||||
</a>
|
|
||||||
@endif
|
|
||||||
@endcan
|
|
||||||
@can('edit_purchase_returns')
|
|
||||||
<a href="{{ route('purchase-returns.edit', $data->id) }}" class="dropdown-item">
|
|
||||||
<i class="bi bi-pencil mr-2 text-primary" style="line-height: 1;"></i> Edit
|
|
||||||
</a>
|
|
||||||
@endcan
|
|
||||||
@can('show_purchase_returns')
|
|
||||||
<a href="{{ route('purchase-returns.show', $data->id) }}" class="dropdown-item">
|
|
||||||
<i class="bi bi-eye mr-2 text-info" style="line-height: 1;"></i> Details
|
|
||||||
</a>
|
|
||||||
@endcan
|
|
||||||
@can('delete_purchase_return')
|
|
||||||
<button id="delete" class="dropdown-item" onclick="
|
|
||||||
event.preventDefault();
|
|
||||||
if (confirm('Are you sure? It will delete the data permanently!')) {
|
|
||||||
document.getElementById('destroy{{ $data->id }}').submit()
|
|
||||||
}">
|
|
||||||
<i class="bi bi-trash mr-2 text-danger" style="line-height: 1;"></i> Delete
|
|
||||||
<form id="destroy{{ $data->id }}" class="d-none" action="{{ route('purchase-returns.destroy', $data->id) }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('delete')
|
|
||||||
</form>
|
|
||||||
</button>
|
|
||||||
@endcan
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,13 +0,0 @@
|
||||||
@if ($data->payment_status == 'Partial')
|
|
||||||
<span class="badge badge-warning">
|
|
||||||
{{ $data->payment_status }}
|
|
||||||
</span>
|
|
||||||
@elseif ($data->payment_status == 'Paid')
|
|
||||||
<span class="badge badge-success">
|
|
||||||
{{ $data->payment_status }}
|
|
||||||
</span>
|
|
||||||
@else
|
|
||||||
<span class="badge badge-danger">
|
|
||||||
{{ $data->payment_status }}
|
|
||||||
</span>
|
|
||||||
@endif
|
|
|
@ -1,13 +0,0 @@
|
||||||
@if ($data->status == 'Pending')
|
|
||||||
<span class="badge badge-info">
|
|
||||||
{{ $data->status }}
|
|
||||||
</span>
|
|
||||||
@elseif ($data->status == 'Shipped')
|
|
||||||
<span class="badge badge-primary">
|
|
||||||
{{ $data->status }}
|
|
||||||
</span>
|
|
||||||
@else
|
|
||||||
<span class="badge badge-success">
|
|
||||||
{{ $data->status }}
|
|
||||||
</span>
|
|
||||||
@endif
|
|
|
@ -1,114 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Create Payment')
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purchase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.show', $purchase_return) }}">{{ $purchase_return->reference }}</a></li>
|
|
||||||
<li class="breadcrumb-item active">Add Payment</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid">
|
|
||||||
<form id="payment-form" action="{{ route('purchase-return-payments.store') }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
@include('utils.alerts')
|
|
||||||
<div class="form-group">
|
|
||||||
<button class="btn btn-primary">Create Payment <i class="bi bi-check"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="reference">Reference <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="reference" required readonly value="INV/{{ $purchase_return->reference }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="date">Date <span class="text-danger">*</span></label>
|
|
||||||
<input type="date" class="form-control" name="date" required value="{{ now()->format('Y-m-d') }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="due_amount">Due Amount <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="due_amount" required value="{{ format_currency($purchase_return->due_amount) }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="amount">Amount <span class="text-danger">*</span></label>
|
|
||||||
<div class="input-group">
|
|
||||||
<input id="amount" type="text" class="form-control" name="amount" required value="{{ old('amount') }}">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button id="getTotalAmount" class="btn btn-primary" type="button">
|
|
||||||
<i class="bi bi-check-square"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="payment_method">Payment Method <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="payment_method" id="payment_method" required>
|
|
||||||
<option value="Cash">Cash</option>
|
|
||||||
<option value="Credit Card">Credit Card</option>
|
|
||||||
<option value="Bank Transfer">Bank Transfer</option>
|
|
||||||
<option value="Cheque">Cheque</option>
|
|
||||||
<option value="Other">Other</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="note">Note</label>
|
|
||||||
<textarea class="form-control" rows="4" name="note">{{ old('note') }}</textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input type="hidden" value="{{ $purchase_return->id }}" name="purchase_return_id">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
<script src="{{ asset('js/jquery-mask-money.js') }}"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#amount').maskMoney({
|
|
||||||
prefix:'{{ settings()->currency->symbol }}',
|
|
||||||
thousands:'{{ settings()->currency->thousand_separator }}',
|
|
||||||
decimal:'{{ settings()->currency->decimal_separator }}',
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#getTotalAmount').click(function () {
|
|
||||||
$('#amount').maskMoney('mask', {{ $purchase_return->due_amount }});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#payment-form').submit(function () {
|
|
||||||
var amount = $('#amount').maskMoney('unmasked')[0];
|
|
||||||
$('#amount').val(amount);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endpush
|
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Edit Payment')
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purchase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.show', $purchase_return) }}">{{ $purchase_return->reference }}</a></li>
|
|
||||||
<li class="breadcrumb-item active">Edit Payment</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid">
|
|
||||||
<form id="payment-form" action="{{ route('purchase-return-payments.update', $purchaseReturnPayment) }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('patch')
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
@include('utils.alerts')
|
|
||||||
<div class="form-group">
|
|
||||||
<button class="btn btn-primary">Update Payment <i class="bi bi-check"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="reference">Reference <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="reference" required readonly value="{{ $purchaseReturnPayment->reference }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="date">Date <span class="text-danger">*</span></label>
|
|
||||||
<input type="date" class="form-control" name="date" required value="{{ $purchaseReturnPayment->getAttributes()['date'] }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="due_amount">Due Amount <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" name="due_amount" required value="{{ format_currency($purchase_return->due_amount) }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="amount">Amount <span class="text-danger">*</span></label>
|
|
||||||
<div class="input-group">
|
|
||||||
<input id="amount" type="text" class="form-control" name="amount" required value="{{ old('amount') ?? $purchaseReturnPayment->amount }}">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button id="getTotalAmount" class="btn btn-primary" type="button">
|
|
||||||
<i class="bi bi-check-square"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<div class="from-group">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="payment_method">Payment Method <span class="text-danger">*</span></label>
|
|
||||||
<select class="form-control" name="payment_method" id="payment_method" required>
|
|
||||||
<option {{ $purchaseReturnPayment->payment_method == 'Cash' ? 'selected' : '' }} value="Cash">Cash</option>
|
|
||||||
<option {{ $purchaseReturnPayment->payment_method == 'Credit Card' ? 'selected' : '' }} value="Credit Card">Credit Card</option>
|
|
||||||
<option {{ $purchaseReturnPayment->payment_method == 'Bank Transfer' ? 'selected' : '' }} value="Bank Transfer">Bank Transfer</option>
|
|
||||||
<option {{ $purchaseReturnPayment->payment_method == 'Cheque' ? 'selected' : '' }} value="Cheque">Cheque</option>
|
|
||||||
<option {{ $purchaseReturnPayment->payment_method == 'Other' ? 'selected' : '' }} value="Other">Other</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="note">Note</label>
|
|
||||||
<textarea class="form-control" rows="4" name="note">{{ old('note') ?? $purchaseReturnPayment->note }}</textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input type="hidden" value="{{ $purchase_return->id }}" name="purchase_return_id">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
<script src="{{ asset('js/jquery-mask-money.js') }}"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#amount').maskMoney({
|
|
||||||
prefix:'{{ settings()->currency->symbol }}',
|
|
||||||
thousands:'{{ settings()->currency->thousand_separator }}',
|
|
||||||
decimal:'{{ settings()->currency->decimal_separator }}',
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#amount').maskMoney('mask');
|
|
||||||
|
|
||||||
$('#getTotalAmount').click(function () {
|
|
||||||
$('#amount').maskMoney('mask', {{ $purchase_return->due_amount }});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#payment-form').submit(function () {
|
|
||||||
var amount = $('#amount').maskMoney('unmasked')[0];
|
|
||||||
$('#amount').val(amount);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endpush
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Sale Payments')
|
|
||||||
|
|
||||||
@section('third_party_stylesheets')
|
|
||||||
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap4.min.css">
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purcase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchases.show', $purchase_return) }}">{{ $purchase_return->reference }}</a></li>
|
|
||||||
<li class="breadcrumb-item active">Payments</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
@include('utils.alerts')
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
{!! $dataTable->table() !!}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@push('page_scripts')
|
|
||||||
{!! $dataTable->scripts() !!}
|
|
||||||
@endpush
|
|
|
@ -1,19 +0,0 @@
|
||||||
@can('access_purchase_return_payments')
|
|
||||||
<a href="{{ route('purchase-return-payments.edit', [$data->purchaseReturn->id, $data->id]) }}" class="btn btn-info btn-sm">
|
|
||||||
<i class="bi bi-pencil"></i>
|
|
||||||
</a>
|
|
||||||
@endcan
|
|
||||||
@can('access_purchase_return_payments')
|
|
||||||
<button id="delete" class="btn btn-danger btn-sm" onclick="
|
|
||||||
event.preventDefault();
|
|
||||||
if (confirm('Are you sure? It will delete the data permanently!')) {
|
|
||||||
document.getElementById('destroy{{ $data->id }}').submit()
|
|
||||||
}
|
|
||||||
">
|
|
||||||
<i class="bi bi-trash"></i>
|
|
||||||
<form id="destroy{{ $data->id }}" class="d-none" action="{{ route('purchase-return-payments.destroy', $data->id) }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('delete')
|
|
||||||
</form>
|
|
||||||
</button>
|
|
||||||
@endcan
|
|
|
@ -1,133 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<title>Purchase Return Details</title>
|
|
||||||
<link rel="stylesheet" href="{{ public_path('b3/bootstrap.min.css') }}">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<div style="text-align: center;margin-bottom: 25px;">
|
|
||||||
<img width="180" src="{{ public_path('images/logo-dark.png') }}" alt="Logo">
|
|
||||||
<h4 style="margin-bottom: 20px;">
|
|
||||||
<span>Reference::</span> <strong>{{ $purchase_return->reference }}</strong>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row mb-4">
|
|
||||||
<div class="col-xs-4 mb-3 mb-md-0">
|
|
||||||
<h4 class="mb-2" style="border-bottom: 1px solid #dddddd;padding-bottom: 10px;">Company Info:</h4>
|
|
||||||
<div><strong>{{ settings()->company_name }}</strong></div>
|
|
||||||
<div>{{ settings()->company_address }}</div>
|
|
||||||
<div>Email: {{ settings()->company_email }}</div>
|
|
||||||
<div>Phone: {{ settings()->company_phone }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xs-4 mb-3 mb-md-0">
|
|
||||||
<h4 class="mb-2" style="border-bottom: 1px solid #dddddd;padding-bottom: 10px;">Supplier Info:</h4>
|
|
||||||
<div><strong>{{ $supplier->supplier_name }}</strong></div>
|
|
||||||
<div>{{ $supplier->address }}</div>
|
|
||||||
<div>Email: {{ $supplier->supplier_email }}</div>
|
|
||||||
<div>Phone: {{ $supplier->supplier_phone }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xs-4 mb-3 mb-md-0">
|
|
||||||
<h4 class="mb-2" style="border-bottom: 1px solid #dddddd;padding-bottom: 10px;">Invoice Info:</h4>
|
|
||||||
<div>Invoice: <strong>INV/{{ $purchase_return->reference }}</strong></div>
|
|
||||||
<div>Date: {{ \Carbon\Carbon::parse($purchase_return->date)->format('d M, Y') }}</div>
|
|
||||||
<div>
|
|
||||||
Status: <strong>{{ $purchase_return->status }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Payment Status: <strong>{{ $purchase_return->payment_status }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-responsive-sm" style="margin-top: 30px;">
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="align-middle">Product</th>
|
|
||||||
<th class="align-middle">Net Unit Price</th>
|
|
||||||
<th class="align-middle">Quantity</th>
|
|
||||||
<th class="align-middle">Discount</th>
|
|
||||||
<th class="align-middle">Tax</th>
|
|
||||||
<th class="align-middle">Sub Total</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($purchase_return->purchaseReturnDetails as $item)
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ $item->product_name }} <br>
|
|
||||||
<span class="badge badge-success">
|
|
||||||
{{ $item->product_code }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">{{ format_currency($item->unit_price) }}</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ $item->quantity }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->product_discount_amount) }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->product_tax_amount) }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->sub_total) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-4 col-xs-offset-8">
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Discount ({{ $purchase_return->discount_percentage }}%)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->discount_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Tax ({{ $purchase_return->tax_percentage }}%)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->tax_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Shipping)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->shipping_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Grand Total</strong></td>
|
|
||||||
<td class="right"><strong>{{ format_currency($purchase_return->total_amount) }}</strong></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="margin-top: 25px;">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<p style="font-style: italic;text-align: center">{{ settings()->company_name }} © {{ date('Y') }}.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,135 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('title', 'Purchase Details')
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
|
||||||
<ol class="breadcrumb border-0 m-0">
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
|
||||||
<li class="breadcrumb-item"><a href="{{ route('purchase-returns.index') }}">Purchase Returns</a></li>
|
|
||||||
<li class="breadcrumb-item active">Details</li>
|
|
||||||
</ol>
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header d-flex flex-wrap align-items-center">
|
|
||||||
<div>
|
|
||||||
Reference: <strong>{{ $purchase_return->reference }}</strong>
|
|
||||||
</div>
|
|
||||||
<a target="_blank" class="btn btn-sm btn-secondary mfs-auto mfe-1 d-print-none" href="{{ route('purchase-returns.pdf', $purchase_return->id) }}">
|
|
||||||
<i class="bi bi-printer"></i> Print
|
|
||||||
</a>
|
|
||||||
<a target="_blank" class="btn btn-sm btn-info mfe-1 d-print-none" href="{{ route('purchase-returns.pdf', $purchase_return->id) }}">
|
|
||||||
<i class="bi bi-save"></i> Save
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row mb-4">
|
|
||||||
<div class="col-sm-4 mb-3 mb-md-0">
|
|
||||||
<h5 class="mb-2 border-bottom pb-2">Company Info:</h5>
|
|
||||||
<div><strong>{{ settings()->company_name }}</strong></div>
|
|
||||||
<div>{{ settings()->company_address }}</div>
|
|
||||||
<div>Email: {{ settings()->company_email }}</div>
|
|
||||||
<div>Phone: {{ settings()->company_phone }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-4 mb-3 mb-md-0">
|
|
||||||
<h5 class="mb-2 border-bottom pb-2">Supplier Info:</h5>
|
|
||||||
<div><strong>{{ $supplier->supplier_name }}</strong></div>
|
|
||||||
<div>{{ $supplier->address }}</div>
|
|
||||||
<div>Email: {{ $supplier->supplier_email }}</div>
|
|
||||||
<div>Phone: {{ $supplier->supplier_phone }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-4 mb-3 mb-md-0">
|
|
||||||
<h5 class="mb-2 border-bottom pb-2">Invoice Info:</h5>
|
|
||||||
<div>Invoice: <strong>INV/{{ $purchase_return->reference }}</strong></div>
|
|
||||||
<div>Date: {{ \Carbon\Carbon::parse($purchase_return->date)->format('d M, Y') }}</div>
|
|
||||||
<div>
|
|
||||||
Status: <strong>{{ $purchase_return->status }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Payment Status: <strong>{{ $purchase_return->payment_status }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-responsive-sm">
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="align-middle">Product</th>
|
|
||||||
<th class="align-middle">Net Unit Price</th>
|
|
||||||
<th class="align-middle">Quantity</th>
|
|
||||||
<th class="align-middle">Discount</th>
|
|
||||||
<th class="align-middle">Tax</th>
|
|
||||||
<th class="align-middle">Sub Total</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($purchase_return->purchaseReturnDetails as $item)
|
|
||||||
<tr>
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ $item->product_name }} <br>
|
|
||||||
<span class="badge badge-success">
|
|
||||||
{{ $item->product_code }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">{{ format_currency($item->unit_price) }}</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ $item->quantity }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->product_discount_amount) }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->product_tax_amount) }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="align-middle">
|
|
||||||
{{ format_currency($item->sub_total) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4 col-sm-5 ml-md-auto">
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Discount ({{ $purchase_return->discount_percentage }}%)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->discount_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Tax ({{ $purchase_return->tax_percentage }}%)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->tax_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Shipping)</strong></td>
|
|
||||||
<td class="right">{{ format_currency($purchase_return->shipping_amount) }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><strong>Grand Total</strong></td>
|
|
||||||
<td class="right"><strong>{{ format_currency($purchase_return->total_amount) }}</strong></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Web Routes
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here is where you can register web routes for your application. These
|
|
||||||
| routes are loaded by the RouteServiceProvider within a group which
|
|
||||||
| contains the "web" middleware group. Now create something great!
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
Route::group(['middleware' => 'auth'], function() {
|
|
||||||
|
|
||||||
//Generate PDF
|
|
||||||
Route::get('/purchase-returns/pdf/{id}', function ($id) {
|
|
||||||
$purchaseReturn = \Modules\PurchasesReturn\Entities\PurchaseReturn::findOrFail($id);
|
|
||||||
$supplier = \Modules\People\Entities\Supplier::findOrFail($purchaseReturn->supplier_id);
|
|
||||||
|
|
||||||
$pdf = \PDF::loadView('purchasesreturn::print', [
|
|
||||||
'purchase_return' => $purchaseReturn,
|
|
||||||
'supplier' => $supplier,
|
|
||||||
])->setPaper('a4');
|
|
||||||
|
|
||||||
return $pdf->stream('purchase-return-'. $purchaseReturn->reference .'.pdf');
|
|
||||||
})->name('purchase-returns.pdf');
|
|
||||||
|
|
||||||
//Purchase Returns
|
|
||||||
Route::resource('purchase-returns', 'PurchasesReturnController');
|
|
||||||
|
|
||||||
//Payments
|
|
||||||
Route::get('/purchase-return-payments/{purchase_return_id}', 'PurchaseReturnPaymentsController@index')
|
|
||||||
->name('purchase-return-payments.index');
|
|
||||||
Route::get('/purchase-return-payments/{purchase_return_id}/create', 'PurchaseReturnPaymentsController@create')
|
|
||||||
->name('purchase-return-payments.create');
|
|
||||||
Route::post('/purchase-return-payments/store', 'PurchaseReturnPaymentsController@store')
|
|
||||||
->name('purchase-return-payments.store');
|
|
||||||
Route::get('/purchase-return-payments/{purchase_return_id}/edit/{purchaseReturnPayment}', 'PurchaseReturnPaymentsController@edit')
|
|
||||||
->name('purchase-return-payments.edit');
|
|
||||||
Route::patch('/purchase-return-payments/update/{purchaseReturnPayment}', 'PurchaseReturnPaymentsController@update')
|
|
||||||
->name('purchase-return-payments.update');
|
|
||||||
Route::delete('/purchase-return-payments/destroy/{purchaseReturnPayment}', 'PurchaseReturnPaymentsController@destroy')
|
|
||||||
->name('purchase-return-payments.destroy');
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"name": "PurchasesReturn",
|
|
||||||
"alias": "purchasesreturn",
|
|
||||||
"description": "",
|
|
||||||
"keywords": [],
|
|
||||||
"priority": 0,
|
|
||||||
"providers": [
|
|
||||||
"Modules\\PurchasesReturn\\Providers\\PurchasesReturnServiceProvider"
|
|
||||||
],
|
|
||||||
"aliases": {},
|
|
||||||
"files": [],
|
|
||||||
"requires": []
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "npm run development",
|
|
||||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
|
||||||
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
|
||||||
"watch-poll": "npm run watch -- --watch-poll",
|
|
||||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
|
||||||
"prod": "npm run production",
|
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"cross-env": "^7.0",
|
|
||||||
"laravel-mix": "^5.0.1",
|
|
||||||
"laravel-mix-merge-manifest": "^0.1.2"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
const dotenvExpand = require('dotenv-expand');
|
|
||||||
dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/}));
|
|
||||||
|
|
||||||
const mix = require('laravel-mix');
|
|
||||||
require('laravel-mix-merge-manifest');
|
|
||||||
|
|
||||||
mix.setPublicPath('../../public').mergeManifest();
|
|
||||||
|
|
||||||
mix.js(__dirname + '/Resources/assets/js/app.js', 'js/purchasesreturn.js')
|
|
||||||
.sass( __dirname + '/Resources/assets/sass/app.scss', 'css/purchasesreturn.css');
|
|
||||||
|
|
||||||
if (mix.inProduction()) {
|
|
||||||
mix.version();
|
|
||||||
}
|
|
|
@ -15,12 +15,6 @@ class ReportsController extends Controller
|
||||||
return view('reports::profit-loss.index');
|
return view('reports::profit-loss.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function paymentsReport() {
|
|
||||||
abort_if(Gate::denies('access_reports'), 403);
|
|
||||||
|
|
||||||
return view('reports::payments.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function salesReport() {
|
public function salesReport() {
|
||||||
abort_if(Gate::denies('access_reports'), 403);
|
abort_if(Gate::denies('access_reports'), 403);
|
||||||
|
|
||||||
|
@ -32,16 +26,4 @@ class ReportsController extends Controller
|
||||||
|
|
||||||
return view('reports::purchases.index');
|
return view('reports::purchases.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function salesReturnReport() {
|
|
||||||
abort_if(Gate::denies('access_reports'), 403);
|
|
||||||
|
|
||||||
return view('reports::sales-return.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function purchasesReturnReport() {
|
|
||||||
abort_if(Gate::denies('access_reports'), 403);
|
|
||||||
|
|
||||||
return view('reports::purchases-return.index');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,19 +15,10 @@ Route::group(['middleware' => 'auth'], function () {
|
||||||
//Profit Loss Report
|
//Profit Loss Report
|
||||||
Route::get('/profit-loss-report', 'ReportsController@profitLossReport')
|
Route::get('/profit-loss-report', 'ReportsController@profitLossReport')
|
||||||
->name('profit-loss-report.index');
|
->name('profit-loss-report.index');
|
||||||
//Payments Report
|
|
||||||
Route::get('/payments-report', 'ReportsController@paymentsReport')
|
|
||||||
->name('payments-report.index');
|
|
||||||
//Sales Report
|
//Sales Report
|
||||||
Route::get('/sales-report', 'ReportsController@salesReport')
|
Route::get('/sales-report', 'ReportsController@salesReport')
|
||||||
->name('sales-report.index');
|
->name('sales-report.index');
|
||||||
//Purchases Report
|
//Purchases Report
|
||||||
Route::get('/purchases-report', 'ReportsController@purchasesReport')
|
Route::get('/purchases-report', 'ReportsController@purchasesReport')
|
||||||
->name('purchases-report.index');
|
->name('purchases-report.index');
|
||||||
//Sales Return Report
|
|
||||||
Route::get('/sales-return-report', 'ReportsController@salesReturnReport')
|
|
||||||
->name('sales-return-report.index');
|
|
||||||
//Purchases Return Report
|
|
||||||
Route::get('/purchases-return-report', 'ReportsController@purchasesReturnReport')
|
|
||||||
->name('purchases-return-report.index');
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => 'StockTransfer'
|
||||||
|
];
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('stock_transfers', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('reference_no')->unique();
|
||||||
|
$table->foreignId('source_branch_id')->constrained('branches')->onDelete('restrict');
|
||||||
|
$table->foreignId('destination_branch_id')->constrained('branches')->onDelete('restrict');
|
||||||
|
$table->date('transfer_date');
|
||||||
|
$table->text('note')->nullable();
|
||||||
|
$table->string('status')->default('pending'); // pending, completed, cancelled
|
||||||
|
$table->string('created_by');
|
||||||
|
$table->string('updated_by')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('stock_transfers');
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('stock_transfer_items', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('stock_transfer_id')->constrained('stock_transfers')->onDelete('cascade');
|
||||||
|
$table->foreignId('product_id')->constrained('products')->onDelete('restrict');
|
||||||
|
$table->foreignId('product_batch_id')->constrained('product_batches')->onDelete('restrict');
|
||||||
|
$table->integer('quantity');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('stock_transfer_items');
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\StockTransfer\Entities;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Models\Branch;
|
||||||
|
use App\Models\ProductBatch;
|
||||||
|
|
||||||
|
class StockTransfer extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'reference_no',
|
||||||
|
'source_branch_id',
|
||||||
|
'destination_branch_id',
|
||||||
|
'transfer_date',
|
||||||
|
'note',
|
||||||
|
'status',
|
||||||
|
'created_by',
|
||||||
|
'updated_by'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'transfer_date' => 'date'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function sourceBranch()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Branch::class, 'source_branch_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destinationBranch()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Branch::class, 'destination_branch_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function items()
|
||||||
|
{
|
||||||
|
return $this->hasMany(StockTransferItem::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransferDateAttribute($value)
|
||||||
|
{
|
||||||
|
return Carbon::parse($value)->format('d M, Y');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::creating(function ($model) {
|
||||||
|
$number = StockTransfer::max('id') + 1;
|
||||||
|
$model->reference_no = 'TRF-' . date('Ymd') . '-' . str_pad($number, 4, '0', STR_PAD_LEFT);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\StockTransfer\Entities;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Modules\Product\Entities\Product;
|
||||||
|
use App\Models\ProductBatch;
|
||||||
|
|
||||||
|
class StockTransferItem extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'stock_transfer_id',
|
||||||
|
'product_id',
|
||||||
|
'product_batch_id',
|
||||||
|
'quantity'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'quantity' => 'integer'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function stockTransfer()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(StockTransfer::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function product()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Product::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function productBatch()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ProductBatch::class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\StockTransfer\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Modules\StockTransfer\Entities\StockTransfer;
|
||||||
|
use Modules\StockTransfer\Entities\StockTransferItem;
|
||||||
|
use Modules\StockTransfer\Http\Requests\StockTransferRequest;
|
||||||
|
use App\Models\ProductBatch;
|
||||||
|
use Modules\Branch\Entities\Branch;
|
||||||
|
use Modules\Product\Entities\Product;
|
||||||
|
|
||||||
|
class StockTransferController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$stockTransfers = StockTransfer::with(['sourceBranch', 'destinationBranch'])
|
||||||
|
->latest()
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
return view('stocktransfer::index', compact('stockTransfers'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$branches = Branch::all();
|
||||||
|
$products = Product::all();
|
||||||
|
|
||||||
|
return view('stocktransfer::create', compact('branches', 'products'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StockTransferRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Create stock transfer record
|
||||||
|
$transfer = StockTransfer::create([
|
||||||
|
'source_branch_id' => $request->source_branch_id,
|
||||||
|
'destination_branch_id' => $request->destination_branch_id,
|
||||||
|
'transfer_date' => $request->transfer_date,
|
||||||
|
'note' => $request->note,
|
||||||
|
'status' => 'pending',
|
||||||
|
'created_by' => auth()->id(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Process each transfer item
|
||||||
|
foreach ($request->items as $item) {
|
||||||
|
// Get source batch
|
||||||
|
$sourceBatch = ProductBatch::findOrFail($item['product_batch_id']);
|
||||||
|
|
||||||
|
// Step 1: Deduct quantity from source branch
|
||||||
|
$sourceBatch->quantity -= $item['quantity'];
|
||||||
|
$sourceBatch->save();
|
||||||
|
|
||||||
|
// Step 2: Create new batch in destination branch
|
||||||
|
ProductBatch::create([
|
||||||
|
'product_id' => $sourceBatch->product_id,
|
||||||
|
'branch_id' => $request->destination_branch_id,
|
||||||
|
'batch_code' => $sourceBatch->batch_code,
|
||||||
|
'quantity' => $item['quantity'],
|
||||||
|
'purchase_price' => $sourceBatch->purchase_price,
|
||||||
|
'expired_date' => $sourceBatch->expired_date,
|
||||||
|
'created_by' => auth()->id(),
|
||||||
|
'updated_by' => auth()->id()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Step 3: Create transfer item record
|
||||||
|
StockTransferItem::create([
|
||||||
|
'stock_transfer_id' => $transfer->id,
|
||||||
|
'product_id' => $sourceBatch->product_id,
|
||||||
|
'product_batch_id' => $sourceBatch->id,
|
||||||
|
'quantity' => $item['quantity']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update transfer status to completed
|
||||||
|
$transfer->update([
|
||||||
|
'status' => 'completed',
|
||||||
|
'updated_by' => auth()->id()
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('stock-transfers.show', $transfer)
|
||||||
|
->with('success', 'Stock transfer created successfully.');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', 'Error creating stock transfer: ' . $e->getMessage())
|
||||||
|
->withInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(StockTransfer $stockTransfer)
|
||||||
|
{
|
||||||
|
$stockTransfer->load(['sourceBranch', 'destinationBranch', 'items.product', 'items.productBatch']);
|
||||||
|
return view('stocktransfer::show', compact('stockTransfer'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBatches($productId, $branchId)
|
||||||
|
{
|
||||||
|
$batches = ProductBatch::where('product_id', $productId)
|
||||||
|
->where('branch_id', $branchId)
|
||||||
|
->where('quantity', '>', 0)
|
||||||
|
->get(['id', 'batch_code', 'quantity']);
|
||||||
|
|
||||||
|
return response()->json($batches);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\StockTransfer\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use App\Models\ProductBatch;
|
||||||
|
|
||||||
|
class StockTransferRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'source_branch_id' => [
|
||||||
|
'required',
|
||||||
|
'exists:branches,id',
|
||||||
|
'different:destination_branch_id'
|
||||||
|
],
|
||||||
|
'destination_branch_id' => [
|
||||||
|
'required',
|
||||||
|
'exists:branches,id',
|
||||||
|
'different:source_branch_id'
|
||||||
|
],
|
||||||
|
'transfer_date' => 'required|date',
|
||||||
|
'note' => 'nullable|string|max:1000',
|
||||||
|
'items' => 'required|array|min:1',
|
||||||
|
'items.*.product_id' => 'required|exists:products,id',
|
||||||
|
'items.*.product_batch_id' => [
|
||||||
|
'required',
|
||||||
|
'exists:product_batches,id',
|
||||||
|
function ($attribute, $value, $fail) {
|
||||||
|
$index = explode('.', $attribute)[1];
|
||||||
|
$sourceBranchId = $this->input('source_branch_id');
|
||||||
|
$productId = $this->input("items.{$index}.product_id");
|
||||||
|
$quantity = $this->input("items.{$index}.quantity");
|
||||||
|
|
||||||
|
// Check if batch belongs to source branch
|
||||||
|
$batch = ProductBatch::where('id', $value)
|
||||||
|
->where('product_id', $productId)
|
||||||
|
->where('branch_id', $sourceBranchId)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$batch) {
|
||||||
|
$fail('Selected batch does not belong to source branch.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if quantity is available
|
||||||
|
if ($batch->quantity < $quantity) {
|
||||||
|
$fail("Insufficient quantity in batch. Available: {$batch->quantity}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'items.*.quantity' => 'required|integer|min:1'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'source_branch_id.required' => 'Source branch is required',
|
||||||
|
'source_branch_id.exists' => 'Selected source branch is invalid',
|
||||||
|
'source_branch_id.different' => 'Source branch must be different from destination branch',
|
||||||
|
'destination_branch_id.required' => 'Destination branch is required',
|
||||||
|
'destination_branch_id.exists' => 'Selected destination branch is invalid',
|
||||||
|
'destination_branch_id.different' => 'Destination branch must be different from source branch',
|
||||||
|
'transfer_date.required' => 'Transfer date is required',
|
||||||
|
'transfer_date.date' => 'Invalid transfer date format',
|
||||||
|
'items.required' => 'At least one product is required',
|
||||||
|
'items.min' => 'At least one product is required',
|
||||||
|
'items.*.product_id.required' => 'Product is required',
|
||||||
|
'items.*.product_id.exists' => 'Selected product is invalid',
|
||||||
|
'items.*.product_batch_id.required' => 'Product batch is required',
|
||||||
|
'items.*.product_batch_id.exists' => 'Selected product batch is invalid',
|
||||||
|
'items.*.quantity.required' => 'Quantity is required',
|
||||||
|
'items.*.quantity.integer' => 'Quantity must be a whole number',
|
||||||
|
'items.*.quantity.min' => 'Quantity must be at least 1'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\StockTransfer\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Database\Eloquent\Factory;
|
||||||
|
|
||||||
|
class StockTransferServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bootstrap the application events.
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->loadTranslationsFrom(module_path('StockTransfer', 'Resources/lang'), 'stocktransfer');
|
||||||
|
$this->loadViewsFrom(module_path('StockTransfer', 'Resources/views'), 'stocktransfer');
|
||||||
|
$this->loadMigrationsFrom(module_path('StockTransfer', 'Database/Migrations'));
|
||||||
|
$this->loadRoutesFrom(module_path('StockTransfer', 'Routes/web.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the service provider.
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Create Stock Transfer')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Create Stock Transfer</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{ route('stock-transfers.store') }}" method="POST" id="stock-transfer-form">
|
||||||
|
@csrf
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="source_branch_id">Source Branch <span class="text-danger">*</span></label>
|
||||||
|
<select name="source_branch_id" id="source_branch_id" class="form-control select2" required>
|
||||||
|
<option value="">Select Source Branch</option>
|
||||||
|
@foreach($branches as $branch)
|
||||||
|
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="destination_branch_id">Destination Branch <span class="text-danger">*</span></label>
|
||||||
|
<select name="destination_branch_id" id="destination_branch_id" class="form-control select2" required>
|
||||||
|
<option value="">Select Destination Branch</option>
|
||||||
|
@foreach($branches as $branch)
|
||||||
|
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="transfer_date">Transfer Date <span class="text-danger">*</span></label>
|
||||||
|
<input type="date" name="transfer_date" id="transfer_date" class="form-control" value="{{ date('Y-m-d') }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="note">Note</label>
|
||||||
|
<textarea name="note" id="note" class="form-control" rows="1"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered" id="transfer-items-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Product <span class="text-danger">*</span></th>
|
||||||
|
<th>Batch <span class="text-danger">*</span></th>
|
||||||
|
<th>Available Quantity</th>
|
||||||
|
<th>Transfer Quantity <span class="text-danger">*</span></th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<select name="items[0][product_id]" class="form-control select2 product-select" required>
|
||||||
|
<option value="">Select Product</option>
|
||||||
|
@foreach($products as $product)
|
||||||
|
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="items[0][product_batch_id]" class="form-control select2 batch-select" required disabled>
|
||||||
|
<option value="">Select Batch</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="available-quantity">0</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="items[0][quantity]" class="form-control transfer-quantity" min="1" required disabled>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-danger btn-sm remove-row">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-success" id="add-row">
|
||||||
|
<i class="bi bi-plus"></i> Add Item
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<button type="submit" class="btn btn-primary">Create Transfer</button>
|
||||||
|
<a href="{{ route('stock-transfers.index') }}" class="btn btn-secondary">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
let rowCount = 1;
|
||||||
|
|
||||||
|
// Initialize Select2
|
||||||
|
$('.select2').select2();
|
||||||
|
|
||||||
|
// Add new row
|
||||||
|
$('#add-row').click(function() {
|
||||||
|
const newRow = `
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<select name="items[${rowCount}][product_id]" class="form-control select2 product-select" required>
|
||||||
|
<option value="">Select Product</option>
|
||||||
|
@foreach($products as $product)
|
||||||
|
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="items[${rowCount}][product_batch_id]" class="form-control select2 batch-select" required disabled>
|
||||||
|
<option value="">Select Batch</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="available-quantity">0</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="items[${rowCount}][quantity]" class="form-control transfer-quantity" min="1" required disabled>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-danger btn-sm remove-row">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
$('#transfer-items-table tbody').append(newRow);
|
||||||
|
initializeRow(rowCount);
|
||||||
|
rowCount++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove row
|
||||||
|
$(document).on('click', '.remove-row', function() {
|
||||||
|
$(this).closest('tr').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize row elements
|
||||||
|
function initializeRow(index) {
|
||||||
|
$(`select[name="items[${index}][product_id]"]`).select2();
|
||||||
|
$(`select[name="items[${index}][product_batch_id]"]`).select2();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle product selection
|
||||||
|
$(document).on('change', '.product-select', function() {
|
||||||
|
const row = $(this).closest('tr');
|
||||||
|
const productId = $(this).val();
|
||||||
|
const batchSelect = row.find('.batch-select');
|
||||||
|
const quantityInput = row.find('.transfer-quantity');
|
||||||
|
const availableQuantity = row.find('.available-quantity');
|
||||||
|
|
||||||
|
if (productId) {
|
||||||
|
const sourceBranchId = $('#source_branch_id').val();
|
||||||
|
if (!sourceBranchId) {
|
||||||
|
toastr.error('Please select source branch first');
|
||||||
|
$(this).val('').trigger('change');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch batches for the selected product and branch
|
||||||
|
$.get(`/stock-transfers/batches/${productId}/${sourceBranchId}`, function(data) {
|
||||||
|
batchSelect.empty().append('<option value="">Select Batch</option>');
|
||||||
|
data.forEach(batch => {
|
||||||
|
batchSelect.append(`<option value="${batch.id}" data-quantity="${batch.quantity}">${batch.batch_number}</option>`);
|
||||||
|
});
|
||||||
|
batchSelect.prop('disabled', false).trigger('change');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
batchSelect.empty().prop('disabled', true).trigger('change');
|
||||||
|
quantityInput.prop('disabled', true).val('');
|
||||||
|
availableQuantity.text('0');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle batch selection
|
||||||
|
$(document).on('change', '.batch-select', function() {
|
||||||
|
const row = $(this).closest('tr');
|
||||||
|
const quantityInput = row.find('.transfer-quantity');
|
||||||
|
const availableQuantity = row.find('.available-quantity');
|
||||||
|
const selectedOption = $(this).find('option:selected');
|
||||||
|
|
||||||
|
if (selectedOption.val()) {
|
||||||
|
const quantity = selectedOption.data('quantity');
|
||||||
|
availableQuantity.text(quantity);
|
||||||
|
quantityInput.prop('disabled', false).attr('max', quantity);
|
||||||
|
} else {
|
||||||
|
quantityInput.prop('disabled', true).val('');
|
||||||
|
availableQuantity.text('0');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form submission
|
||||||
|
$('#stock-transfer-form').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Validate source and destination branches are different
|
||||||
|
const sourceBranch = $('#source_branch_id').val();
|
||||||
|
const destinationBranch = $('#destination_branch_id').val();
|
||||||
|
|
||||||
|
if (sourceBranch === destinationBranch) {
|
||||||
|
toastr.error('Source and destination branches cannot be the same');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate quantities
|
||||||
|
let isValid = true;
|
||||||
|
$('.transfer-quantity').each(function() {
|
||||||
|
const quantity = parseInt($(this).val());
|
||||||
|
const max = parseInt($(this).attr('max'));
|
||||||
|
if (quantity > max) {
|
||||||
|
toastr.error('Transfer quantity cannot exceed available quantity');
|
||||||
|
isValid = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
this.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
|
@ -0,0 +1,68 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Stock Transfers')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Stock Transfers</h3>
|
||||||
|
<div class="card-tools">
|
||||||
|
@can('create_stock_transfers')
|
||||||
|
<a href="{{ route('stock-transfers.create') }}" class="btn btn-primary">
|
||||||
|
<i class="bi bi-plus"></i> Create Transfer
|
||||||
|
</a>
|
||||||
|
@endcan
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Reference No</th>
|
||||||
|
<th>Source Branch</th>
|
||||||
|
<th>Destination Branch</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($stockTransfers as $transfer)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $transfer->reference_no }}</td>
|
||||||
|
<td>{{ $transfer->sourceBranch->name }}</td>
|
||||||
|
<td>{{ $transfer->destinationBranch->name }}</td>
|
||||||
|
<td>{{ $transfer->transfer_date->format('d M Y') }}</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge badge-{{ $transfer->status === 'completed' ? 'success' : ($transfer->status === 'pending' ? 'warning' : 'danger') }}">
|
||||||
|
{{ ucfirst($transfer->status) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('stock-transfers.show', $transfer) }}" class="btn btn-info btn-sm">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center">No stock transfers found</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
{{ $stockTransfers->links() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Module StockTransfer</title>
|
||||||
|
|
||||||
|
{{-- Laravel Vite - CSS File --}}
|
||||||
|
{{-- {{ module_vite('build-stocktransfer', 'Resources/assets/sass/app.scss') }} --}}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
@yield('content')
|
||||||
|
|
||||||
|
{{-- Laravel Vite - JS File --}}
|
||||||
|
{{-- {{ module_vite('build-stocktransfer', 'Resources/assets/js/app.js') }} --}}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,84 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Stock Transfer Details')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Stock Transfer Details</h3>
|
||||||
|
<div class="card-tools">
|
||||||
|
<a href="{{ route('stock-transfers.index') }}" class="btn btn-secondary">
|
||||||
|
<i class="bi bi-arrow-left"></i> Back to List
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tr>
|
||||||
|
<th style="width: 200px;">Reference No</th>
|
||||||
|
<td>{{ $stockTransfer->reference_no }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Source Branch</th>
|
||||||
|
<td>{{ $stockTransfer->sourceBranch->name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Destination Branch</th>
|
||||||
|
<td>{{ $stockTransfer->destinationBranch->name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Transfer Date</th>
|
||||||
|
<td>{{ $stockTransfer->transfer_date->format('d M Y') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Status</th>
|
||||||
|
<td>
|
||||||
|
<span class="badge badge-{{ $stockTransfer->status === 'completed' ? 'success' : ($stockTransfer->status === 'pending' ? 'warning' : 'danger') }}">
|
||||||
|
{{ ucfirst($stockTransfer->status) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Note</th>
|
||||||
|
<td>{{ $stockTransfer->note ?? '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4>Transfer Items</h4>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Product</th>
|
||||||
|
<th>Batch</th>
|
||||||
|
<th>Quantity</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($stockTransfer->items as $item)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $item->product->name }}</td>
|
||||||
|
<td>{{ $item->productBatch->batch_number }}</td>
|
||||||
|
<td>{{ $item->quantity }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -13,6 +13,6 @@ use Illuminate\Http\Request;
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::middleware('auth:api')->get('/purchasesreturn', function (Request $request) {
|
Route::middleware('auth:api')->get('/stocktransfer', function (Request $request) {
|
||||||
return $request->user();
|
return $request->user();
|
||||||
});
|
});
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Web Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register web routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| contains the "web" middleware group. Now create something great!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Modules\StockTransfer\Http\Controllers\StockTransferController;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::middleware(['web', 'auth'])->group(function () {
|
||||||
|
Route::prefix('stock-transfers')->group(function () {
|
||||||
|
Route::get('/', [StockTransferController::class, 'index'])->name('stock-transfers.index');
|
||||||
|
Route::get('/create', [StockTransferController::class, 'create'])->name('stock-transfers.create');
|
||||||
|
Route::post('/', [StockTransferController::class, 'store'])->name('stock-transfers.store');
|
||||||
|
Route::get('/{stockTransfer}', [StockTransferController::class, 'show'])->name('stock-transfers.show');
|
||||||
|
Route::get('/batches/{productId}/{branchId}', [StockTransferController::class, 'getBatches'])->name('stock-transfers.batches');
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "nwidart/purchasesreturn",
|
"name": "nwidart/stocktransfer",
|
||||||
"description": "",
|
"description": "",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Modules\\PurchasesReturn\\": ""
|
"Modules\\StockTransfer\\": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "StockTransfer",
|
||||||
|
"alias": "stocktransfer",
|
||||||
|
"description": "Stock Transfer Module",
|
||||||
|
"keywords": [],
|
||||||
|
"priority": 0,
|
||||||
|
"providers": [
|
||||||
|
"Modules\\StockTransfer\\Providers\\StockTransferServiceProvider"
|
||||||
|
],
|
||||||
|
"files": []
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Modules\Setting\Entities\Setting;
|
use Modules\Setting\Entities\Setting;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
if (!function_exists('settings')) {
|
if (!function_exists('settings')) {
|
||||||
function settings()
|
function settings()
|
||||||
|
@ -12,8 +13,25 @@ if (!function_exists('settings')) {
|
||||||
if (!function_exists('format_currency')) {
|
if (!function_exists('format_currency')) {
|
||||||
function format_currency($price)
|
function format_currency($price)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$settings = settings();
|
$settings = settings();
|
||||||
|
Log::info('Format Currency', [
|
||||||
|
'price' => $price,
|
||||||
|
'currency_symbol' => $settings->currency->symbol ?? 'Rp'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!isset($settings->currency)) {
|
||||||
|
return 'Rp ' . number_format($price, 0, ',', '.') . ',-';
|
||||||
|
}
|
||||||
|
|
||||||
return $settings->currency->symbol . ' ' . number_format($price, 0, $settings->currency->decimal_separator, $settings->currency->thousand_separator) . ',-';
|
return $settings->currency->symbol . ' ' . number_format($price, 0, $settings->currency->decimal_separator, $settings->currency->thousand_separator) . ',-';
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error in format_currency', [
|
||||||
|
'price' => $price,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
return 'Rp ' . number_format($price, 0, ',', '.') . ',-';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@ use Illuminate\Support\Facades\DB;
|
||||||
use Modules\Expense\Entities\Expense;
|
use Modules\Expense\Entities\Expense;
|
||||||
use Modules\Purchase\Entities\Purchase;
|
use Modules\Purchase\Entities\Purchase;
|
||||||
use Modules\Purchase\Entities\PurchasePayment;
|
use Modules\Purchase\Entities\PurchasePayment;
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturn;
|
|
||||||
use Modules\PurchasesReturn\Entities\PurchaseReturnPayment;
|
|
||||||
use Modules\Sale\Entities\Sale;
|
use Modules\Sale\Entities\Sale;
|
||||||
use Modules\Sale\Entities\SalePayment;
|
use Modules\Sale\Entities\SalePayment;
|
||||||
|
|
||||||
|
@ -35,10 +33,6 @@ class HomeController extends Controller
|
||||||
->where('branch_id', $activeBranchId)
|
->where('branch_id', $activeBranchId)
|
||||||
->sum('total_amount');
|
->sum('total_amount');
|
||||||
|
|
||||||
$purchase_returns = PurchaseReturn::where('payment_status', 'Completed')
|
|
||||||
->where('branch_id', $activeBranchId)
|
|
||||||
->sum('total_amount');
|
|
||||||
|
|
||||||
$product_costs = 0;
|
$product_costs = 0;
|
||||||
|
|
||||||
foreach (Sale::where('payment_status', 'Completed')
|
foreach (Sale::where('payment_status', 'Completed')
|
||||||
|
@ -56,12 +50,10 @@ class HomeController extends Controller
|
||||||
|
|
||||||
return view('home', [
|
return view('home', [
|
||||||
'revenue' => $revenue,
|
'revenue' => $revenue,
|
||||||
'purchase_returns' => $purchase_returns / 100,
|
|
||||||
'profit' => $profit
|
'profit' => $profit
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function currentMonthChart() {
|
public function currentMonthChart() {
|
||||||
abort_if(!request()->ajax(), 404);
|
abort_if(!request()->ajax(), 404);
|
||||||
|
|
||||||
|
@ -91,7 +83,6 @@ class HomeController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function salesPurchasesChart() {
|
public function salesPurchasesChart() {
|
||||||
abort_if(!request()->ajax(), 404);
|
abort_if(!request()->ajax(), 404);
|
||||||
|
|
||||||
|
@ -103,7 +94,6 @@ class HomeController extends Controller
|
||||||
return response()->json(['sales' => $sales, 'purchases' => $purchases]);
|
return response()->json(['sales' => $sales, 'purchases' => $purchases]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function paymentChart() {
|
public function paymentChart() {
|
||||||
abort_if(!request()->ajax(), 404);
|
abort_if(!request()->ajax(), 404);
|
||||||
|
|
||||||
|
@ -135,15 +125,6 @@ class HomeController extends Controller
|
||||||
->groupBy('month')->orderBy('month')
|
->groupBy('month')->orderBy('month')
|
||||||
->get()->pluck('amount', 'month');
|
->get()->pluck('amount', 'month');
|
||||||
|
|
||||||
$purchase_return_payments = PurchaseReturnPayment::where('date', '>=', $date_range)
|
|
||||||
->where('branch_id', $activeBranchId)
|
|
||||||
->select([
|
|
||||||
DB::raw("DATE_FORMAT(date, '%m-%Y') as month"),
|
|
||||||
DB::raw("SUM(amount) as amount")
|
|
||||||
])
|
|
||||||
->groupBy('month')->orderBy('month')
|
|
||||||
->get()->pluck('amount', 'month');
|
|
||||||
|
|
||||||
$expenses = Expense::where('date', '>=', $date_range)
|
$expenses = Expense::where('date', '>=', $date_range)
|
||||||
->where('branch_id', $activeBranchId)
|
->where('branch_id', $activeBranchId)
|
||||||
->select([
|
->select([
|
||||||
|
@ -198,22 +179,24 @@ class HomeController extends Controller
|
||||||
->get([
|
->get([
|
||||||
DB::raw(DB::raw("DATE_FORMAT(date,'%d-%m-%y') as date")),
|
DB::raw(DB::raw("DATE_FORMAT(date,'%d-%m-%y') as date")),
|
||||||
DB::raw('SUM(total_amount) AS count'),
|
DB::raw('SUM(total_amount) AS count'),
|
||||||
])
|
])->pluck('count', 'date');
|
||||||
->pluck('count', 'date');
|
|
||||||
|
|
||||||
$dates = $dates->merge($sales);
|
$dates = $dates->merge($sales);
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
$days = [];
|
$labels = [];
|
||||||
|
|
||||||
foreach ($dates as $key => $value) {
|
foreach ($dates as $key => $value) {
|
||||||
$data[] = $value / 100;
|
$data[] = $value / 100;
|
||||||
$days[] = $key;
|
$labels[] = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(['data' => $data, 'days' => $days]);
|
return [
|
||||||
|
'data' => $data,
|
||||||
|
'labels' => $labels,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function purchasesChartData() {
|
public function purchasesChartData() {
|
||||||
$activeBranchId = session('active_branch_id') ?? 1;
|
$activeBranchId = session('active_branch_id') ?? 1;
|
||||||
|
|
||||||
|
@ -233,19 +216,21 @@ class HomeController extends Controller
|
||||||
->get([
|
->get([
|
||||||
DB::raw(DB::raw("DATE_FORMAT(date,'%d-%m-%y') as date")),
|
DB::raw(DB::raw("DATE_FORMAT(date,'%d-%m-%y') as date")),
|
||||||
DB::raw('SUM(total_amount) AS count'),
|
DB::raw('SUM(total_amount) AS count'),
|
||||||
])
|
])->pluck('count', 'date');
|
||||||
->pluck('count', 'date');
|
|
||||||
|
|
||||||
$dates = $dates->merge($purchases);
|
$dates = $dates->merge($purchases);
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
$days = [];
|
$labels = [];
|
||||||
|
|
||||||
foreach ($dates as $key => $value) {
|
foreach ($dates as $key => $value) {
|
||||||
$data[] = $value / 100;
|
$data[] = $value / 100;
|
||||||
$days[] = $key;
|
$labels[] = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(['data' => $data, 'days' => $days]);
|
return [
|
||||||
|
'data' => $data,
|
||||||
|
'labels' => $labels,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Product\Entities\Product;
|
||||||
|
|
||||||
class ProductBatch extends Model
|
class ProductBatch extends Model
|
||||||
{
|
{
|
||||||
|
@ -12,14 +13,17 @@ class ProductBatch extends Model
|
||||||
'product_id',
|
'product_id',
|
||||||
'branch_id',
|
'branch_id',
|
||||||
'batch_code',
|
'batch_code',
|
||||||
'quantity',
|
'qty',
|
||||||
'purchase_price',
|
'unit_price',
|
||||||
'expired_date',
|
'exp_date',
|
||||||
|
'purchase_id',
|
||||||
|
'created_by',
|
||||||
|
'updated_by'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'expired_date' => 'date',
|
'exp_date' => 'date',
|
||||||
'purchase_price' => 'decimal:2',
|
'unit_price' => 'decimal:2',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function product(): BelongsTo
|
public function product(): BelongsTo
|
||||||
|
@ -47,8 +51,8 @@ class ProductBatch extends Model
|
||||||
{
|
{
|
||||||
return self::where('product_id', $productId)
|
return self::where('product_id', $productId)
|
||||||
->where('branch_id', $branchId)
|
->where('branch_id', $branchId)
|
||||||
->where('quantity', '>', 0)
|
->where('qty', '>', 0)
|
||||||
->orderBy('expired_date', 'asc')
|
->orderBy('exp_date', 'asc')
|
||||||
->orderBy('created_at', 'asc')
|
->orderBy('created_at', 'asc')
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
@ -65,15 +69,15 @@ class ProductBatch extends Model
|
||||||
foreach ($batches as $batch) {
|
foreach ($batches as $batch) {
|
||||||
if ($remainingQuantity <= 0) break;
|
if ($remainingQuantity <= 0) break;
|
||||||
|
|
||||||
$deductAmount = min($remainingQuantity, $batch->quantity);
|
$deductAmount = min($remainingQuantity, $batch->qty);
|
||||||
$batch->quantity -= $deductAmount;
|
$batch->qty -= $deductAmount;
|
||||||
$batch->save();
|
$batch->save();
|
||||||
|
|
||||||
$usedBatches[] = [
|
$usedBatches[] = [
|
||||||
'batch_id' => $batch->id,
|
'batch_id' => $batch->id,
|
||||||
'quantity' => $deductAmount,
|
'qty' => $deductAmount,
|
||||||
'purchase_price' => $batch->purchase_price,
|
'unit_price' => $batch->unit_price,
|
||||||
'expired_date' => $batch->expired_date
|
'exp_date' => $batch->exp_date
|
||||||
];
|
];
|
||||||
|
|
||||||
$remainingQuantity -= $deductAmount;
|
$remainingQuantity -= $deductAmount;
|
||||||
|
@ -91,6 +95,18 @@ class ProductBatch extends Model
|
||||||
*/
|
*/
|
||||||
public static function addStock(array $data)
|
public static function addStock(array $data)
|
||||||
{
|
{
|
||||||
|
// Rename expired_date to exp_date if it exists
|
||||||
|
if (isset($data['expired_date'])) {
|
||||||
|
$data['exp_date'] = $data['expired_date'];
|
||||||
|
unset($data['expired_date']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename purchase_price to unit_price if it exists
|
||||||
|
if (isset($data['purchase_price'])) {
|
||||||
|
$data['unit_price'] = $data['purchase_price'];
|
||||||
|
unset($data['purchase_price']);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate batch code if not provided
|
// Generate batch code if not provided
|
||||||
if (!isset($data['batch_code'])) {
|
if (!isset($data['batch_code'])) {
|
||||||
$data['batch_code'] = self::generateBatchCode();
|
$data['batch_code'] = self::generateBatchCode();
|
||||||
|
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
||||||
$table->foreignId('branch_id')->constrained('branches')->onDelete('cascade');
|
$table->foreignId('branch_id')->constrained('branches')->onDelete('cascade');
|
||||||
$table->string('batch_code')->nullable();
|
$table->string('batch_code')->nullable();
|
||||||
$table->integer('quantity');
|
$table->integer('quantity');
|
||||||
$table->decimal('purchase_price', 10, 2);
|
$table->decimal('unit_price', 10, 2);
|
||||||
$table->date('expired_date')->nullable();
|
$table->date('expired_date')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchase_details', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('purchase_price');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchase_details', function (Blueprint $table) {
|
||||||
|
$table->decimal('purchase_price', 10, 2)->after('product_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchases', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('supplier_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchases', function (Blueprint $table) {
|
||||||
|
$table->string('supplier_name')->after('supplier_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchases', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('purchases', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -14,5 +14,6 @@
|
||||||
"PurchasesReturn": true,
|
"PurchasesReturn": true,
|
||||||
"Quotation": true,
|
"Quotation": true,
|
||||||
"Reports": true,
|
"Reports": true,
|
||||||
"Branch": true
|
"Branch": true,
|
||||||
|
"StockTransfer": true
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
@can('show_total_stats')
|
@can('show_total_stats')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 col-lg-3">
|
<div class="col-md-6 col-lg-6">
|
||||||
<div class="card border-0">
|
<div class="card border-0">
|
||||||
<div class="card-body p-0 d-flex align-items-center shadow-sm">
|
<div class="card-body p-0 d-flex align-items-center shadow-sm">
|
||||||
<div class="bg-gradient-primary p-4 mfe-3 rounded-left">
|
<div class="bg-gradient-primary p-4 mfe-3 rounded-left">
|
||||||
|
@ -26,21 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6 col-lg-3">
|
<div class="col-md-6 col-lg-6">
|
||||||
<div class="card border-0">
|
|
||||||
<div class="card-body p-0 d-flex align-items-center shadow-sm">
|
|
||||||
<div class="bg-gradient-success p-4 mfe-3 rounded-left">
|
|
||||||
<i class="bi bi-arrow-return-right font-2xl"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-value text-success">{{ format_currency($purchase_returns) }}</div>
|
|
||||||
<div class="text-muted text-uppercase font-weight-bold small">Purchases Return</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6 col-lg-3">
|
|
||||||
<div class="card border-0">
|
<div class="card border-0">
|
||||||
<div class="card-body p-0 d-flex align-items-center shadow-sm">
|
<div class="card-body p-0 d-flex align-items-center shadow-sm">
|
||||||
<div class="bg-gradient-info p-4 mfe-3 rounded-left">
|
<div class="bg-gradient-info p-4 mfe-3 rounded-left">
|
||||||
|
|
|
@ -10,6 +10,24 @@
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="c-header-nav ml-auto mr-4">
|
<ul class="c-header-nav ml-auto mr-4">
|
||||||
|
@can('access_branches')
|
||||||
|
<li class="c-header-nav-item mr-3">
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-outline-primary btn-pill dropdown-toggle" type="button" id="branchDropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="bi bi-building mr-1"></i> {{ auth()->user()->active_branch ? auth()->user()->active_branch->name : 'Pilih Cabang' }}
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="branchDropdown">
|
||||||
|
@foreach(\Modules\Branch\Entities\Branch::all() as $branch)
|
||||||
|
<a class="dropdown-item {{ auth()->user()->active_branch && auth()->user()->active_branch->id === $branch->id ? 'active' : '' }}"
|
||||||
|
href="{{ route('branch.switch', $branch->id) }}">
|
||||||
|
{{ $branch->name }}
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
|
|
||||||
@can('create_pos_sales')
|
@can('create_pos_sales')
|
||||||
<li class="c-header-nav-item mr-3">
|
<li class="c-header-nav-item mr-3">
|
||||||
<a class="btn btn-primary btn-pill {{ request()->routeIs('app.pos.index') ? 'disabled' : '' }}" href="{{ route('app.pos.index') }}">
|
<a class="btn btn-primary btn-pill {{ request()->routeIs('app.pos.index') ? 'disabled' : '' }}" href="{{ route('app.pos.index') }}">
|
||||||
|
|
|
@ -84,6 +84,28 @@
|
||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
|
@can('access_stock_transfers')
|
||||||
|
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('stock-transfers.*') ? 'c-show' : '' }}">
|
||||||
|
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||||
|
<i class="c-sidebar-nav-icon bi bi-arrow-left-right" style="line-height: 1;"></i> Stock Transfers
|
||||||
|
</a>
|
||||||
|
<ul class="c-sidebar-nav-dropdown-items">
|
||||||
|
@can('create_stock_transfers')
|
||||||
|
<li class="c-sidebar-nav-item">
|
||||||
|
<a class="c-sidebar-nav-link {{ request()->routeIs('stock-transfers.create') ? 'c-active' : '' }}" href="{{ route('stock-transfers.create') }}">
|
||||||
|
<i class="c-sidebar-nav-icon bi bi-journal-plus" style="line-height: 1;"></i> Create Transfer
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
|
<li class="c-sidebar-nav-item">
|
||||||
|
<a class="c-sidebar-nav-link {{ request()->routeIs('stock-transfers.index') ? 'c-active' : '' }}" href="{{ route('stock-transfers.index') }}">
|
||||||
|
<i class="c-sidebar-nav-icon bi bi-journals" style="line-height: 1;"></i> All Transfers
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
|
|
||||||
@can('access_quotations')
|
@can('access_quotations')
|
||||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('quotations.*') ? 'c-show' : '' }}">
|
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('quotations.*') ? 'c-show' : '' }}">
|
||||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||||
|
@ -130,30 +152,6 @@
|
||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('access_purchase_returns')
|
|
||||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('purchase-returns.*') || request()->routeIs('purchase-return-payments.*') ? 'c-show' : '' }}">
|
|
||||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-arrow-return-right" style="line-height: 1;"></i> Purchase Returns
|
|
||||||
</a>
|
|
||||||
@can('create_purchase_returns')
|
|
||||||
<ul class="c-sidebar-nav-dropdown-items">
|
|
||||||
<li class="c-sidebar-nav-item">
|
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('purchase-returns.create') ? 'c-active' : '' }}" href="{{ route('purchase-returns.create') }}">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-journal-plus" style="line-height: 1;"></i> Create Purchase Return
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
@endcan
|
|
||||||
<ul class="c-sidebar-nav-dropdown-items">
|
|
||||||
<li class="c-sidebar-nav-item">
|
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('purchase-returns.index') ? 'c-active' : '' }}" href="{{ route('purchase-returns.index') }}">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-journals" style="line-height: 1;"></i> All Purchase Returns
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
@endcan
|
|
||||||
|
|
||||||
@can('access_sales')
|
@can('access_sales')
|
||||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('sales.*') || request()->routeIs('sale-payments*') ? 'c-show' : '' }}">
|
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('sales.*') || request()->routeIs('sale-payments*') ? 'c-show' : '' }}">
|
||||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||||
|
@ -242,11 +240,6 @@
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Profit / Loss Report
|
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Profit / Loss Report
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-sidebar-nav-item">
|
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('payments-report.index') ? 'c-active' : '' }}" href="{{ route('payments-report.index') }}">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Payments Report
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="c-sidebar-nav-item">
|
<li class="c-sidebar-nav-item">
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('sales-report.index') ? 'c-active' : '' }}" href="{{ route('sales-report.index') }}">
|
<a class="c-sidebar-nav-link {{ request()->routeIs('sales-report.index') ? 'c-active' : '' }}" href="{{ route('sales-report.index') }}">
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Sales Report
|
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Sales Report
|
||||||
|
@ -257,16 +250,6 @@
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Purchases Report
|
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Purchases Report
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="c-sidebar-nav-item">
|
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('sales-return-report.index') ? 'c-active' : '' }}" href="{{ route('sales-return-report.index') }}">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Sales Return Report
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="c-sidebar-nav-item">
|
|
||||||
<a class="c-sidebar-nav-link {{ request()->routeIs('purchases-return-report.index') ? 'c-active' : '' }}" href="{{ route('purchases-return-report.index') }}">
|
|
||||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Purchases Return Report
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
Loading…
Reference in New Issue