From 978e8631aa94bf866adf1ce89bd7412a2502ab66 Mon Sep 17 00:00:00 2001 From: denisdulici Date: Sat, 23 Jun 2018 15:59:13 +0300 Subject: [PATCH] import validation --- app/Http/Controllers/Common/Items.php | 18 +--- app/Http/Controllers/Expenses/Bills.php | 47 +++------- app/Http/Controllers/Expenses/Payments.php | 18 +--- app/Http/Controllers/Expenses/Vendors.php | 35 +------- app/Http/Controllers/Incomes/Customers.php | 35 +------- app/Http/Controllers/Incomes/Invoices.php | 47 +++------- app/Http/Controllers/Incomes/Revenues.php | 18 +--- app/Http/Requests/Expense/Bill.php | 6 +- app/Http/Requests/Expense/BillHistory.php | 32 +++++++ app/Http/Requests/Expense/BillItem.php | 37 ++++++++ app/Http/Requests/Expense/BillTotal.php | 33 +++++++ app/Http/Requests/Income/Invoice.php | 6 +- app/Http/Requests/Income/InvoiceHistory.php | 32 +++++++ app/Http/Requests/Income/InvoiceItem.php | 37 ++++++++ app/Http/Requests/Income/InvoiceTotal.php | 33 +++++++ app/Listeners/Updates/Version128.php | 30 +++++++ app/Providers/EventServiceProvider.php | 1 + app/Utilities/Import.php | 84 ++++++++++++++++++ .../2018_06_23_000000_modify_email_column.php | 41 +++++++++ public/files/import/bills.xlsx | Bin 13361 -> 13368 bytes public/files/import/invoices.xlsx | Bin 13370 -> 13426 bytes resources/lang/en-GB/messages.php | 1 + 22 files changed, 417 insertions(+), 174 deletions(-) create mode 100644 app/Http/Requests/Expense/BillHistory.php create mode 100644 app/Http/Requests/Expense/BillItem.php create mode 100644 app/Http/Requests/Expense/BillTotal.php create mode 100644 app/Http/Requests/Income/InvoiceHistory.php create mode 100644 app/Http/Requests/Income/InvoiceItem.php create mode 100644 app/Http/Requests/Income/InvoiceTotal.php create mode 100644 app/Listeners/Updates/Version128.php create mode 100644 app/Utilities/Import.php create mode 100644 database/migrations/2018_06_23_000000_modify_email_column.php diff --git a/app/Http/Controllers/Common/Items.php b/app/Http/Controllers/Common/Items.php index d38c43efd..144f31019 100644 --- a/app/Http/Controllers/Common/Items.php +++ b/app/Http/Controllers/Common/Items.php @@ -9,6 +9,7 @@ use App\Models\Setting\Category; use App\Models\Setting\Currency; use App\Models\Setting\Tax; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; class Items extends Controller @@ -106,20 +107,9 @@ class Items extends Controller */ public function import(ImportFile $import) { - // Loop through all sheets - $import->each(function ($sheet) { - if ($sheet->getTitle() != 'items') { - return; - } - - // Loop through all rows - $sheet->each(function ($row) { - $data = $row->toArray(); - $data['company_id'] = session('company_id'); - - Item::create($data); - }); - }); + if (!Import::createFromFile($import, 'Common\Item')) { + return redirect('common/import/common/items'); + } $message = trans('messages.success.imported', ['type' => trans_choice('general.items', 2)]); diff --git a/app/Http/Controllers/Expenses/Bills.php b/app/Http/Controllers/Expenses/Bills.php index 0e3c2d452..fab91f2af 100644 --- a/app/Http/Controllers/Expenses/Bills.php +++ b/app/Http/Controllers/Expenses/Bills.php @@ -24,6 +24,7 @@ use App\Models\Common\Media; use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; use App\Utilities\Modules; use Date; @@ -291,45 +292,23 @@ class Bills extends Controller */ public function import(ImportFile $import) { + $success = true; + // Loop through all sheets - $import->each(function ($sheet) { - $class = '\App\Models\Expense\\' . str_singular(studly_case($sheet->getTitle())); + $import->each(function ($sheet) use (&$success) { + $slug = 'Expense\\' . str_singular(studly_case($sheet->getTitle())); - if (!class_exists($class)) { - return; + $success = Import::createFromSheet($sheet, $slug); + + if (!$success) { + return false; } - - $sheet->each(function ($row) use ($sheet, $class) { - $data = $row->toArray(); - $data['company_id'] = session('company_id'); - - switch ($sheet->getTitle()) { - case 'bills': - if (empty($data['vendor_email'])) { - $data['vendor_email'] = ''; - } - break; - case 'bill_items': - if (empty($data['tax_id'])) { - $data['tax_id'] = '0'; - } - break; - case 'bill_histories': - if (empty($data['notify'])) { - $data['notify'] = '0'; - } - break; - case 'bill_totals': - if (empty($data['amount'])) { - $data['amount'] = '0'; - } - break; - } - - $class::create($data); - }); }); + if (!$success) { + return redirect('common/import/expenses/bills'); + } + $message = trans('messages.success.imported', ['type' => trans_choice('general.bills', 2)]); flash($message)->success(); diff --git a/app/Http/Controllers/Expenses/Payments.php b/app/Http/Controllers/Expenses/Payments.php index 4e64ed7c3..028de238c 100644 --- a/app/Http/Controllers/Expenses/Payments.php +++ b/app/Http/Controllers/Expenses/Payments.php @@ -10,6 +10,7 @@ use App\Models\Expense\Vendor; use App\Models\Setting\Category; use App\Models\Setting\Currency; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; use App\Utilities\Modules; @@ -133,20 +134,9 @@ class Payments extends Controller */ public function import(ImportFile $import) { - // Loop through all sheets - $import->each(function ($sheet) { - if ($sheet->getTitle() != 'payments') { - return; - } - - // Loop through all rows - $sheet->each(function ($row) { - $data = $row->toArray(); - $data['company_id'] = session('company_id'); - - Payment::create($data); - }); - }); + if (!Import::createFromFile($import, 'Expense\Payment')) { + return redirect('common/import/expenses/payments'); + } $message = trans('messages.success.imported', ['type' => trans_choice('general.payments', 2)]); diff --git a/app/Http/Controllers/Expenses/Vendors.php b/app/Http/Controllers/Expenses/Vendors.php index e8ccb3162..142b68720 100644 --- a/app/Http/Controllers/Expenses/Vendors.php +++ b/app/Http/Controllers/Expenses/Vendors.php @@ -9,6 +9,7 @@ use App\Models\Expense\Payment; use App\Models\Expense\Vendor; use App\Models\Setting\Currency; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; use Date; use Illuminate\Pagination\Paginator; @@ -124,10 +125,6 @@ class Vendors extends Controller */ public function store(Request $request) { - if (empty($request['email'])) { - $request['email'] = ''; - } - $vendor = Vendor::create($request->all()); // Upload logo @@ -171,25 +168,9 @@ class Vendors extends Controller */ public function import(ImportFile $import) { - // Loop through all sheets - $import->each(function ($sheet) { - if ($sheet->getTitle() != 'vendors') { - return; - } - - // Loop through all rows - $sheet->each(function ($row) { - $data = $row->toArray(); - - if (empty($data['email'])) { - $data['email'] = ''; - } - - $data['company_id'] = session('company_id'); - - Vendor::create($data); - }); - }); + if (!Import::createFromFile($import, 'Expense\Vendor')) { + return redirect('common/import/expenses/vendors'); + } $message = trans('messages.success.imported', ['type' => trans_choice('general.vendors', 2)]); @@ -222,10 +203,6 @@ class Vendors extends Controller */ public function update(Vendor $vendor, Request $request) { - if (empty($request['email'])) { - $request['email'] = ''; - } - $vendor->update($request->all()); // Upload logo @@ -336,10 +313,6 @@ class Vendors extends Controller public function vendor(Request $request) { - if (empty($request['email'])) { - $request['email'] = ''; - } - $vendor = Vendor::create($request->all()); return response()->json($vendor); diff --git a/app/Http/Controllers/Incomes/Customers.php b/app/Http/Controllers/Incomes/Customers.php index 3b72eb5f4..699ea5603 100644 --- a/app/Http/Controllers/Incomes/Customers.php +++ b/app/Http/Controllers/Incomes/Customers.php @@ -9,6 +9,7 @@ use App\Models\Income\Customer; use App\Models\Income\Invoice; use App\Models\Income\Revenue; use App\Models\Setting\Currency; +use App\Utilities\Import; use App\Utilities\ImportFile; use Date; use Illuminate\Http\Request as FRequest; @@ -125,10 +126,6 @@ class Customers extends Controller public function store(Request $request) { if (empty($request->input('create_user'))) { - if (empty($request['email'])) { - $request['email'] = ''; - } - Customer::create($request->all()); } else { // Check if user exist @@ -191,25 +188,9 @@ class Customers extends Controller */ public function import(ImportFile $import) { - // Loop through all sheets - $import->each(function ($sheet) { - if ($sheet->getTitle() != 'customers') { - return; - } - - // Loop through all rows - $sheet->each(function ($row) { - $data = $row->toArray(); - - if (empty($data['email'])) { - $data['email'] = ''; - } - - $data['company_id'] = session('company_id'); - - Customer::create($data); - }); - }); + if (!Import::createFromFile($import, 'Income\Customer')) { + return redirect('common/import/incomes/customers'); + } $message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 2)]); @@ -243,10 +224,6 @@ class Customers extends Controller public function update(Customer $customer, Request $request) { if (empty($request->input('create_user'))) { - if (empty($request['email'])) { - $request['email'] = ''; - } - $customer->update($request->all()); } else { // Check if user exist @@ -372,10 +349,6 @@ class Customers extends Controller public function customer(Request $request) { - if (empty($request['email'])) { - $request['email'] = ''; - } - $customer = Customer::create($request->all()); return response()->json($customer); diff --git a/app/Http/Controllers/Incomes/Invoices.php b/app/Http/Controllers/Incomes/Invoices.php index 5e96cd0cf..d8c5f995b 100644 --- a/app/Http/Controllers/Incomes/Invoices.php +++ b/app/Http/Controllers/Incomes/Invoices.php @@ -27,6 +27,7 @@ use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Incomes; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; use App\Utilities\Modules; use Date; @@ -312,45 +313,23 @@ class Invoices extends Controller */ public function import(ImportFile $import) { + $success = true; + // Loop through all sheets - $import->each(function ($sheet) { - $class = '\App\Models\Income\\' . str_singular(studly_case($sheet->getTitle())); + $import->each(function ($sheet) use (&$success) { + $slug = 'Income\\' . str_singular(studly_case($sheet->getTitle())); - if (!class_exists($class)) { - return; + $success = Import::createFromSheet($sheet, $slug); + + if (!$success) { + return false; } - - $sheet->each(function ($row) use ($sheet, $class) { - $data = $row->toArray(); - $data['company_id'] = session('company_id'); - - switch ($sheet->getTitle()) { - case 'invoices': - if (empty($data['customer_email'])) { - $data['customer_email'] = ''; - } - break; - case 'invoice_items': - if (empty($data['tax_id'])) { - $data['tax_id'] = '0'; - } - break; - case 'invoice_histories': - if (empty($data['notify'])) { - $data['notify'] = '0'; - } - break; - case 'invoice_totals': - if (empty($data['amount'])) { - $data['amount'] = '0'; - } - break; - } - - $class::create($data); - }); }); + if (!$success) { + return redirect('common/import/incomes/invoices'); + } + $message = trans('messages.success.imported', ['type' => trans_choice('general.invoices', 2)]); flash($message)->success(); diff --git a/app/Http/Controllers/Incomes/Revenues.php b/app/Http/Controllers/Incomes/Revenues.php index 093ac327e..7526ec4f4 100644 --- a/app/Http/Controllers/Incomes/Revenues.php +++ b/app/Http/Controllers/Incomes/Revenues.php @@ -12,6 +12,7 @@ use App\Models\Setting\Currency; use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Uploads; +use App\Utilities\Import; use App\Utilities\ImportFile; use App\Utilities\Modules; @@ -135,20 +136,9 @@ class Revenues extends Controller */ public function import(ImportFile $import) { - // Loop through all sheets - $import->each(function ($sheet) { - if ($sheet->getTitle() != 'revenues') { - return; - } - - // Loop through all rows - $sheet->each(function ($row) { - $data = $row->toArray(); - $data['company_id'] = session('company_id'); - - Revenue::create($data); - }); - }); + if (!Import::createFromFile($import, 'Income\Revenue')) { + return redirect('common/import/incomes/revenues'); + } $message = trans('messages.success.imported', ['type' => trans_choice('general.revenues', 2)]); diff --git a/app/Http/Requests/Expense/Bill.php b/app/Http/Requests/Expense/Bill.php index 8bd84e01c..75484218e 100644 --- a/app/Http/Requests/Expense/Bill.php +++ b/app/Http/Requests/Expense/Bill.php @@ -34,11 +34,15 @@ class Bill extends Request $company_id = $this->request->get('company_id'); return [ - 'vendor_id' => 'required|integer', 'bill_number' => 'required|string|unique:bills,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL', + 'bill_status_code' => 'required|string', 'billed_at' => 'required|date', 'due_at' => 'required|date', + 'amount' => 'required', 'currency_code' => 'required|string', + 'currency_rate' => 'required', + 'vendor_id' => 'required|integer', + 'vendor_name' => 'required|string', 'category_id' => 'required|integer', 'attachment' => 'mimes:' . setting('general.file_types') . '|between:0,' . setting('general.file_size') * 1024, ]; diff --git a/app/Http/Requests/Expense/BillHistory.php b/app/Http/Requests/Expense/BillHistory.php new file mode 100644 index 000000000..6c58f3d22 --- /dev/null +++ b/app/Http/Requests/Expense/BillHistory.php @@ -0,0 +1,32 @@ + 'required|integer', + 'status_code' => 'required|string', + 'notify' => 'required|integer', + ]; + } +} diff --git a/app/Http/Requests/Expense/BillItem.php b/app/Http/Requests/Expense/BillItem.php new file mode 100644 index 000000000..316b3b7e0 --- /dev/null +++ b/app/Http/Requests/Expense/BillItem.php @@ -0,0 +1,37 @@ + 'required|integer', + 'name' => 'required|string', + 'quantity' => 'required|integer', + 'price' => 'required', + 'price' => 'required', + 'total' => 'required', + 'tax' => 'required', + 'tax_id' => 'required', + ]; + } +} diff --git a/app/Http/Requests/Expense/BillTotal.php b/app/Http/Requests/Expense/BillTotal.php new file mode 100644 index 000000000..f303ef3f9 --- /dev/null +++ b/app/Http/Requests/Expense/BillTotal.php @@ -0,0 +1,33 @@ + 'required|integer', + 'name' => 'required|string', + 'amount' => 'required', + 'sort_order' => 'required|integer', + ]; + } +} diff --git a/app/Http/Requests/Income/Invoice.php b/app/Http/Requests/Income/Invoice.php index ed35db28c..ee25a3927 100644 --- a/app/Http/Requests/Income/Invoice.php +++ b/app/Http/Requests/Income/Invoice.php @@ -34,11 +34,15 @@ class Invoice extends Request $company_id = $this->request->get('company_id'); return [ - 'customer_id' => 'required|integer', 'invoice_number' => 'required|string|unique:invoices,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL', + 'invoice_status_code' => 'required|string', 'invoiced_at' => 'required|date', 'due_at' => 'required|date', + 'amount' => 'required', 'currency_code' => 'required|string', + 'currency_rate' => 'required', + 'customer_id' => 'required|integer', + 'customer_name' => 'required|string', 'category_id' => 'required|integer', 'attachment' => 'mimes:' . setting('general.file_types') . '|between:0,' . setting('general.file_size') * 1024, ]; diff --git a/app/Http/Requests/Income/InvoiceHistory.php b/app/Http/Requests/Income/InvoiceHistory.php new file mode 100644 index 000000000..638105518 --- /dev/null +++ b/app/Http/Requests/Income/InvoiceHistory.php @@ -0,0 +1,32 @@ + 'required|integer', + 'status_code' => 'required|string', + 'notify' => 'required|integer', + ]; + } +} diff --git a/app/Http/Requests/Income/InvoiceItem.php b/app/Http/Requests/Income/InvoiceItem.php new file mode 100644 index 000000000..87f3e7661 --- /dev/null +++ b/app/Http/Requests/Income/InvoiceItem.php @@ -0,0 +1,37 @@ + 'required|integer', + 'name' => 'required|string', + 'quantity' => 'required|integer', + 'price' => 'required', + 'price' => 'required', + 'total' => 'required', + 'tax' => 'required', + 'tax_id' => 'required', + ]; + } +} diff --git a/app/Http/Requests/Income/InvoiceTotal.php b/app/Http/Requests/Income/InvoiceTotal.php new file mode 100644 index 000000000..9bdf603d6 --- /dev/null +++ b/app/Http/Requests/Income/InvoiceTotal.php @@ -0,0 +1,33 @@ + 'required|integer', + 'name' => 'required|string', + 'amount' => 'required', + 'sort_order' => 'required|integer', + ]; + } +} diff --git a/app/Listeners/Updates/Version128.php b/app/Listeners/Updates/Version128.php new file mode 100644 index 000000000..590c8f73c --- /dev/null +++ b/app/Listeners/Updates/Version128.php @@ -0,0 +1,30 @@ +check($event)) { + return; + } + + // Update database + Artisan::call('migrate', ['--force' => true]); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 23962f7db..2ef72f7b5 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -25,6 +25,7 @@ class EventServiceProvider extends ServiceProvider 'App\Listeners\Updates\Version120', 'App\Listeners\Updates\Version126', 'App\Listeners\Updates\Version127', + 'App\Listeners\Updates\Version128', ], 'Illuminate\Auth\Events\Login' => [ 'App\Listeners\Auth\Login', diff --git a/app/Utilities/Import.php b/app/Utilities/Import.php new file mode 100644 index 000000000..1c035f72d --- /dev/null +++ b/app/Utilities/Import.php @@ -0,0 +1,84 @@ +each(function ($sheet) use (&$success, $slug) { + $model = '\App\Models\\' . $slug; + $request = '\App\Http\Requests\\' . $slug; + + if (!class_exists($model) || !class_exists($request)) { + return false; + } + + $tmp = explode('\\', $slug); + $file_name = str_plural(strtolower($tmp[1])); + + if ($sheet->getTitle() != $file_name) { + return false; + } + + $success = static::createFromSheet($sheet, $slug); + }); + + return $success; + } + + public static function createFromSheet($sheet, $slug) + { + $success = true; + + $model = '\App\Models\\' . $slug; + $request = '\App\Http\Requests\\' . $slug; + + if (!class_exists($model) || !class_exists($request)) { + return false; + } + + // Loop through all rows + $sheet->each(function ($row, $index) use ($sheet, &$success, $model, $request) { + $data = $row->toArray(); + + // Set the line values so that request class could validate + request()->merge($data); + + try { + app($request); + + $data['company_id'] = session('company_id'); + + $model::create($data); + } catch (ValidationException $e) { + $message = trans('messages.error.import_failed', [ + 'message' => $e->validator->errors()->first(), + 'sheet' => $sheet->getTitle(), + 'line' => $index + 2, + ]); + + flash($message)->error()->important(); + + $success = false; + + // Break the import process + return false; + } + + // Unset added line values + foreach ($data as $key => $value) { + request()->offsetUnset($key); + } + }); + + return $success; + } + +} \ No newline at end of file diff --git a/database/migrations/2018_06_23_000000_modify_email_column.php b/database/migrations/2018_06_23_000000_modify_email_column.php new file mode 100644 index 000000000..7fefdb8c2 --- /dev/null +++ b/database/migrations/2018_06_23_000000_modify_email_column.php @@ -0,0 +1,41 @@ +string('email')->nullable()->change(); + }); + + Schema::table('invoices', function (Blueprint $table) { + $table->string('customer_email')->nullable()->change(); + }); + + Schema::table('vendors', function (Blueprint $table) { + $table->string('email')->nullable()->change(); + }); + + Schema::table('bills', function (Blueprint $table) { + $table->string('vendor_email')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +} diff --git a/public/files/import/bills.xlsx b/public/files/import/bills.xlsx index 6338606658b76cda7f77f8d0f5935fd916fa37ba..078074190add659c9e8988a9cf7959977ab33069 100644 GIT binary patch delta 7239 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 UUmgKK@E<9a01?Vxu77s(Uv+j~-v9sr diff --git a/public/files/import/invoices.xlsx b/public/files/import/invoices.xlsx index bc8c084de13d91337135c9a01c939b5c198d7e3e..b6c2f6fb5305361b67c52ee588a0f2d11dda26d2 100644 GIT binary patch delta 6241 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 H{~G-dnDcw{ diff --git a/resources/lang/en-GB/messages.php b/resources/lang/en-GB/messages.php index ce5ea6127..59336a662 100644 --- a/resources/lang/en-GB/messages.php +++ b/resources/lang/en-GB/messages.php @@ -18,6 +18,7 @@ return [ 'no_file' => 'Error: No file selected!', 'last_category' => 'Error: Can not delete the last :type category!', 'invalid_token' => 'Error: The token entered is invalid!', + 'import_failed' => 'Error: :message Sheet name: :sheet. Line number: :line.', ], 'warning' => [ 'deleted' => 'Warning: You are not allowed to delete :name because it has :text related.',