318 lines
13 KiB
PHP
318 lines
13 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Wave\Http\Controllers\CMS;
|
||
|
|
|
||
|
|
use App\Http\Controllers\Controller;
|
||
|
|
use App\Models\BookkeepingDocument;
|
||
|
|
use App\Models\BookkeepingDocumentCategory;
|
||
|
|
use App\Models\Company;
|
||
|
|
use App\Models\DocumentActionLogs;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\Support\Facades\Validator;
|
||
|
|
use Illuminate\Validation\Rule;
|
||
|
|
use Yajra\DataTables\Facades\DataTables;
|
||
|
|
|
||
|
|
class BookkeepingController extends Controller
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* Create a new controller instance.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function __construct()
|
||
|
|
{
|
||
|
|
$this->middleware('auth');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function index()
|
||
|
|
{
|
||
|
|
return view('theme::cms.bookkeepings.index');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getCompanies()
|
||
|
|
{
|
||
|
|
$nameColumn = strtolower(app()->getLocale()) == 'zh_hk' ? 'name_chinese' : 'name_english';
|
||
|
|
$companies = Company::where($nameColumn, '!=', null)
|
||
|
|
->orderBy($nameColumn)
|
||
|
|
->get()
|
||
|
|
->map(function ($company) use ($nameColumn) {
|
||
|
|
$company->name = $company->{$nameColumn};
|
||
|
|
|
||
|
|
return $company;
|
||
|
|
});
|
||
|
|
|
||
|
|
return response()->json([
|
||
|
|
'success' => true,
|
||
|
|
'companies' => $companies,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getCategories()
|
||
|
|
{
|
||
|
|
$categories = BookkeepingDocumentCategory::where('status', 'active')
|
||
|
|
->orderBy('name')
|
||
|
|
->get();
|
||
|
|
|
||
|
|
return response()->json([
|
||
|
|
'success' => true,
|
||
|
|
'categories' => $categories,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function table($isCompleted = false)
|
||
|
|
{
|
||
|
|
$documents = BookkeepingDocument::query()
|
||
|
|
->select(
|
||
|
|
'bookkeeping_documents.id',
|
||
|
|
'companies.name_english',
|
||
|
|
'companies.name_chinese',
|
||
|
|
'bookkeeping_documents.file_name',
|
||
|
|
'bookkeeping_document_categories.name as category_name',
|
||
|
|
'users.first_name',
|
||
|
|
'users.last_name',
|
||
|
|
'bookkeeping_documents.batch_name',
|
||
|
|
'bookkeeping_documents.remark',
|
||
|
|
'bookkeeping_documents.created_at',
|
||
|
|
'bookkeeping_documents.status',
|
||
|
|
'bookkeeping_documents.xero_status',
|
||
|
|
'bookkeeping_documents.xero_amount',
|
||
|
|
)
|
||
|
|
->leftJoin('companies', 'bookkeeping_documents.company_id', '=', 'companies.id')
|
||
|
|
->leftJoin('users', 'bookkeeping_documents.user_id', '=', 'users.id')
|
||
|
|
->leftJoin('bookkeeping_document_categories', 'bookkeeping_documents.bookkeeping_document_category_id', '=', 'bookkeeping_document_categories.id');
|
||
|
|
|
||
|
|
if ($isCompleted) {
|
||
|
|
$documents = $documents->where('bookkeeping_documents.status', 'completed');
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$documents = $documents->where('bookkeeping_documents.status', '!=', 'completed');
|
||
|
|
}
|
||
|
|
|
||
|
|
$processCount = $documents->clone()->where('bookkeeping_documents.status', 'in_progress')->count();
|
||
|
|
$queueCount = $documents->clone()->where('bookkeeping_documents.status', 'uploaded')->count();
|
||
|
|
|
||
|
|
return Datatables::of($documents)
|
||
|
|
->escapeColumns(['id'])
|
||
|
|
->addColumn('file_name', function ($document) {
|
||
|
|
$ext = pathinfo($document->file_name, PATHINFO_EXTENSION);
|
||
|
|
|
||
|
|
return '
|
||
|
|
<div class="flex justify-start">
|
||
|
|
<img class="max-25" src="' . ( $ext == 'pdf' ? asset('themes/tailwind/images/pdf.svg') : asset('themes/tailwind/images/jpg.svg')) . '">
|
||
|
|
<span class="fix-text">' . $document->file_name . '</span>
|
||
|
|
</div>
|
||
|
|
';
|
||
|
|
})
|
||
|
|
->addColumn('user_name', function ($document) {
|
||
|
|
if ($document->status == 'uploaded') {
|
||
|
|
return '<span class="grey-text">processing...</span>';
|
||
|
|
}
|
||
|
|
else if ($document->status == 'failed') {
|
||
|
|
return '<span class="grey-text" style="color: #6D7581;">Failed</span>';
|
||
|
|
}
|
||
|
|
|
||
|
|
return $document->first_name . ($document->last_name ? ' ' : '') . $document->last_name;
|
||
|
|
})
|
||
|
|
->addColumn('created_at', function ($document) {
|
||
|
|
return date('Ymd-H:i', strtotime($document->created_at));
|
||
|
|
})
|
||
|
|
->addColumn('status_select', function ($document) {
|
||
|
|
$html = '
|
||
|
|
<select class="change-status" data-id="' . $document->id . '">
|
||
|
|
<option value="uploaded" ' . ($document->status == 'uploaded' ? 'selected' : '') . '>' . __("Uploaded") . '</option>
|
||
|
|
<option value="in_progress" ' . ($document->status == 'in_progress' ? 'selected' : '') . '>' . __("In Progress") . '</option>
|
||
|
|
<option value="ocr_complete" ' . ($document->status == 'ocr_complete' ? 'selected' : '') . '>' . __("OCR Completed") . '</option>
|
||
|
|
<option value="failed" ' . ($document->status == 'failed' ? 'selected' : '') . '>' . __("Failed") . '</option>
|
||
|
|
<option value="completed" ' . ($document->status == 'completed' ? 'selected' : '') . '>' . __("Completed") . '</option>
|
||
|
|
</select>
|
||
|
|
';
|
||
|
|
|
||
|
|
if ($document->status == 'failed') {
|
||
|
|
$html .= '
|
||
|
|
<div>
|
||
|
|
<input type="file" data-id="' . $document->id . '" class="d-none re-upload-file" accept="image/png, image/jpeg, application/pdf, application/msword" multiple>
|
||
|
|
<button type="button" class="failed item-list-note flex btn-link reupload-button" style="text-wrap: nowrap;">
|
||
|
|
<img class="max-25" src="' . asset('themes/tailwind/images/flag-2.svg') . '"> ' . __("Reupload") . '
|
||
|
|
</button>
|
||
|
|
</div>';
|
||
|
|
}
|
||
|
|
else if ($document->status == 'ocr_complete') {
|
||
|
|
$html .= '<button type="button" class="failed item-list-note flex btn-link" style="text-wrap: nowrap;"><img class="max-25" src="' . asset('themes/tailwind/images/flag-2.svg') . '"> ' . __("Require Datamolino") . '?</button>';
|
||
|
|
}
|
||
|
|
|
||
|
|
return $html;
|
||
|
|
})
|
||
|
|
->addColumn('xero_status', function ($document) {
|
||
|
|
if ($document->status != 'ocr_complete') {
|
||
|
|
if ($document->xero_status) {
|
||
|
|
return '<img class="max-25" src="' . asset("themes/tailwind/images/success.svg") . '">';
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return '<img class="max-25" src="' . asset("themes/tailwind/images/error.svg") . '">';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return '';
|
||
|
|
})
|
||
|
|
->addColumn('xero_amount', function ($document) {
|
||
|
|
if ($document->xero_amount > 0 && $document->status != 'ocr_complete') {
|
||
|
|
return '$' . $document->xero_amount;
|
||
|
|
}
|
||
|
|
|
||
|
|
return '';
|
||
|
|
})
|
||
|
|
->addColumn('actions', function ($document) {
|
||
|
|
$actions = '
|
||
|
|
<div class="dropdown non-custom">
|
||
|
|
<button type="button" data-bs-toggle="dropdown" aria-expanded="false"><img class="max-25" src="' . asset('themes/tailwind/images/more.svg') . '"></button>
|
||
|
|
<div class="dropdown-menu">
|
||
|
|
<a class="dropdown-item" href="#">' . __("Cancel Request") . '</a>
|
||
|
|
<a class="dropdown-item" href="#">' . __("Message on file") . '</a>
|
||
|
|
<a class="dropdown-item" href="#">' . __("Stop processing") . '</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
';
|
||
|
|
return $actions;
|
||
|
|
})
|
||
|
|
->with([
|
||
|
|
'processCount' => $processCount,
|
||
|
|
'queueCount' => $queueCount,
|
||
|
|
])
|
||
|
|
->make(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function updateStatus(Request $request)
|
||
|
|
{
|
||
|
|
$validator = Validator::make($request->all(), [
|
||
|
|
'id' => 'required',
|
||
|
|
'status' => 'required',
|
||
|
|
'xero_status' => [
|
||
|
|
'nullable',
|
||
|
|
Rule::requiredIf($request->status == 'completed'),
|
||
|
|
],
|
||
|
|
'xero_amount' => [
|
||
|
|
'nullable',
|
||
|
|
Rule::requiredIf($request->status == 'completed'),
|
||
|
|
'numeric',
|
||
|
|
],
|
||
|
|
]);
|
||
|
|
if ($validator->fails()) {
|
||
|
|
return response()->json([
|
||
|
|
'success' => false,
|
||
|
|
'errors' => $validator->errors()
|
||
|
|
], 422);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$bookkeepingDocument = BookkeepingDocument::find($request->id);
|
||
|
|
if (! $bookkeepingDocument) {
|
||
|
|
return response()->json([
|
||
|
|
'success' => false,
|
||
|
|
'message' => __("Document not exists!"),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
$bookkeepingDocument->status = $request->status;
|
||
|
|
if ($request->status == 'completed') {
|
||
|
|
$bookkeepingDocument->xero_status = $request->xero_status == '1' ? true : false;
|
||
|
|
$bookkeepingDocument->xero_amount = $request->xero_amount;
|
||
|
|
}
|
||
|
|
$bookkeepingDocument->save();
|
||
|
|
|
||
|
|
DocumentActionLogs::create([
|
||
|
|
'user_id' => $request->user()->id,
|
||
|
|
'event' => 'Change status',
|
||
|
|
'description' => 'Change [' . $bookkeepingDocument->file_name . '] status to ' . $request->status . '.',
|
||
|
|
'status' => 'success',
|
||
|
|
]);
|
||
|
|
|
||
|
|
if ($request->status == 'completed') {
|
||
|
|
storeUserNotification(null, 'Bookkeeping Queue', $bookkeepingDocument->file_name, 'Bookkeeping Queue', true, $bookkeepingDocument->id, 'bookkeeping_queue', 'completed');
|
||
|
|
}
|
||
|
|
else if ($request->status == 'failed') {
|
||
|
|
storeUserNotification(null, 'Bookkeeping Queue', $bookkeepingDocument->file_name, 'Bookkeeping Queue', true, $bookkeepingDocument->id, 'bookkeeping_queue', 'failed');
|
||
|
|
}
|
||
|
|
|
||
|
|
return response()->json([
|
||
|
|
'success' => true,
|
||
|
|
'message' => __("Document has successfully updated!"),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public function actionLogsTable()
|
||
|
|
{
|
||
|
|
$logs = DocumentActionLogs::query()
|
||
|
|
->select(
|
||
|
|
'users.email',
|
||
|
|
'users.name',
|
||
|
|
'document_action_logs.created_at',
|
||
|
|
'document_action_logs.event',
|
||
|
|
'document_action_logs.description',
|
||
|
|
'document_action_logs.status',
|
||
|
|
)
|
||
|
|
->leftJoin('users', 'document_action_logs.user_id', '=', 'users.id');
|
||
|
|
|
||
|
|
return Datatables::of($logs)
|
||
|
|
->escapeColumns(['id'])
|
||
|
|
->addColumn('date', function ($log) {
|
||
|
|
return date('Ymd', strtotime($log->created_at));
|
||
|
|
})
|
||
|
|
->addColumn('time', function ($log) {
|
||
|
|
return date('H:i', strtotime($log->created_at));
|
||
|
|
})
|
||
|
|
->addColumn('status', function ($log) {
|
||
|
|
return '<span class="' . $log->status . ' item-list-note">' . ucwords($log->status) . '</span>';
|
||
|
|
})
|
||
|
|
->make(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function reUploadFile(Request $request)
|
||
|
|
{
|
||
|
|
$validator = Validator::make($request->all(), [
|
||
|
|
'id' => 'required',
|
||
|
|
'uploaded_file' => 'required',
|
||
|
|
]);
|
||
|
|
if ($validator->fails()) {
|
||
|
|
return response()->json([
|
||
|
|
'success' => false,
|
||
|
|
'errors' => $validator->errors()
|
||
|
|
], 422);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$bookkeepingDocument = BookkeepingDocument::find($request->id);
|
||
|
|
if (! $bookkeepingDocument) {
|
||
|
|
return response()->json([
|
||
|
|
'success' => true,
|
||
|
|
'message' => __("Document not exists!"),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
$fileName = '';
|
||
|
|
if ($request->hasFile('uploaded_file')) {
|
||
|
|
if (\Storage::exists($bookkeepingDocument->file_path)) {
|
||
|
|
\Storage::delete($bookkeepingDocument->file_path);
|
||
|
|
}
|
||
|
|
|
||
|
|
$file = $request->file('uploaded_file');
|
||
|
|
$fileName = $request->file('uploaded_file')->getClientOriginalName();
|
||
|
|
$file->storePubliclyAs($bookkeepingDocument->folder_path, $fileName);
|
||
|
|
|
||
|
|
$bookkeepingDocument->file_name = $fileName;
|
||
|
|
$bookkeepingDocument->status = 'uploaded';
|
||
|
|
$bookkeepingDocument->save();
|
||
|
|
}
|
||
|
|
|
||
|
|
DocumentActionLogs::create([
|
||
|
|
'user_id' => $request->user()->id,
|
||
|
|
'event' => 'Upload',
|
||
|
|
'description' => 'Upload [' . $fileName . '] from local file.',
|
||
|
|
'status' => 'success',
|
||
|
|
]);
|
||
|
|
|
||
|
|
return response()->json([
|
||
|
|
'success' => true,
|
||
|
|
'message' => __("Document has successfully uploaded!"),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|