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 633860665..078074190 100644 Binary files a/public/files/import/bills.xlsx and b/public/files/import/bills.xlsx differ diff --git a/public/files/import/invoices.xlsx b/public/files/import/invoices.xlsx index bc8c084de..b6c2f6fb5 100644 Binary files a/public/files/import/invoices.xlsx and b/public/files/import/invoices.xlsx differ 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.',