diff --git a/app/Http/Controllers/Common/Import.php b/app/Http/Controllers/Common/Import.php new file mode 100644 index 000000000..3ea718b8d --- /dev/null +++ b/app/Http/Controllers/Common/Import.php @@ -0,0 +1,22 @@ +middleware('permission:create-' . $controller)->only(['create', 'store', 'duplicate']); + $this->middleware('permission:create-' . $controller)->only(['create', 'store', 'duplicate', 'import']); $this->middleware('permission:read-' . $controller)->only(['index', 'show', 'edit']); $this->middleware('permission:update-' . $controller)->only(['update']); $this->middleware('permission:delete-' . $controller)->only('destroy'); diff --git a/app/Http/Controllers/Expenses/Bills.php b/app/Http/Controllers/Expenses/Bills.php index dbaea590d..fd87dbff2 100644 --- a/app/Http/Controllers/Expenses/Bills.php +++ b/app/Http/Controllers/Expenses/Bills.php @@ -22,6 +22,7 @@ use App\Models\Setting\Tax; use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Uploads; +use App\Utilities\ImportFile; use App\Utilities\Modules; use Date; @@ -284,6 +285,31 @@ class Bills extends Controller return redirect('expenses/bills/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Bill::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.bills', 2)]); + + flash($message)->success(); + + return redirect('expenses/bills'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Expenses/Payments.php b/app/Http/Controllers/Expenses/Payments.php index 89822f8df..e8d3f97da 100644 --- a/app/Http/Controllers/Expenses/Payments.php +++ b/app/Http/Controllers/Expenses/Payments.php @@ -10,7 +10,7 @@ use App\Models\Expense\Vendor; use App\Models\Setting\Category; use App\Models\Setting\Currency; use App\Traits\Uploads; - +use App\Utilities\ImportFile; use App\Utilities\Modules; class Payments extends Controller @@ -108,6 +108,31 @@ class Payments extends Controller return redirect('expenses/payments/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Payment::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.payments', 2)]); + + flash($message)->success(); + + return redirect('expenses/payments'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Expenses/Vendors.php b/app/Http/Controllers/Expenses/Vendors.php index f7eab2142..6b06d28be 100644 --- a/app/Http/Controllers/Expenses/Vendors.php +++ b/app/Http/Controllers/Expenses/Vendors.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Expense\Vendor as Request; use App\Models\Expense\Vendor; use App\Models\Setting\Currency; +use App\Utilities\ImportFile; class Vendors extends Controller { @@ -70,6 +71,31 @@ class Vendors extends Controller return redirect('expenses/vendors/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Vendor::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.vendors', 2)]); + + flash($message)->success(); + + return redirect('expenses/vendors'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Incomes/Customers.php b/app/Http/Controllers/Incomes/Customers.php index 7080a184f..8ed42c8aa 100644 --- a/app/Http/Controllers/Incomes/Customers.php +++ b/app/Http/Controllers/Incomes/Customers.php @@ -7,6 +7,7 @@ use App\Http\Requests\Income\Customer as Request; use App\Models\Auth\User; use App\Models\Income\Customer; use App\Models\Setting\Currency; +use App\Utilities\ImportFile; class Customers extends Controller { @@ -94,6 +95,31 @@ class Customers extends Controller return redirect('incomes/customers/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Customer::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 2)]); + + flash($message)->success(); + + return redirect('incomes/customers'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Incomes/Invoices.php b/app/Http/Controllers/Incomes/Invoices.php index 2ad496be1..460913897 100644 --- a/app/Http/Controllers/Incomes/Invoices.php +++ b/app/Http/Controllers/Incomes/Invoices.php @@ -26,6 +26,7 @@ use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Incomes; use App\Traits\Uploads; +use App\Utilities\ImportFile; use App\Utilities\Modules; use Date; use File; @@ -276,6 +277,31 @@ class Invoices extends Controller return redirect('incomes/invoices/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Invoice::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.invoices', 2)]); + + flash($message)->success(); + + return redirect('incomes/invoices'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Incomes/Revenues.php b/app/Http/Controllers/Incomes/Revenues.php index 44e8a443f..9bad9163e 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\ImportFile; use App\Utilities\Modules; class Revenues extends Controller @@ -109,6 +110,31 @@ class Revenues extends Controller return redirect('incomes/revenues/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Revenue::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.revenues', 2)]); + + flash($message)->success(); + + return redirect('incomes/revenues'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Http/Controllers/Items/Items.php b/app/Http/Controllers/Items/Items.php index b0fd510d6..b3477aadf 100644 --- a/app/Http/Controllers/Items/Items.php +++ b/app/Http/Controllers/Items/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\ImportFile; class Items extends Controller { @@ -85,6 +86,31 @@ class Items extends Controller return redirect('items/items/' . $clone->id . '/edit'); } + /** + * Import the specified resource. + * + * @param ImportFile $import + * + * @return Response + */ + public function import(ImportFile $import) + { + $rows = $import->all(); + + foreach ($rows as $row) { + $data = $row->toArray(); + $data['company_id'] = session('company_id'); + + Item::create($data); + } + + $message = trans('messages.success.imported', ['type' => trans_choice('general.items', 2)]); + + flash($message)->success(); + + return redirect('items/items'); + } + /** * Show the form for editing the specified resource. * diff --git a/app/Listeners/Updates/Version110.php b/app/Listeners/Updates/Version110.php new file mode 100644 index 000000000..e8ebe934f --- /dev/null +++ b/app/Listeners/Updates/Version110.php @@ -0,0 +1,48 @@ +check($event)) { + return; + } + + // Create permission + $permission = Permission::firstOrCreate([ + 'name' => 'create-common-import', + 'display_name' => 'Create Common Import', + 'description' => 'Create Common Import', + ]); + + // Attach permission to roles + $roles = Role::all(); + + foreach ($roles as $role) { + $allowed = ['admin', 'manager']; + + if (!in_array($role->name, $allowed)) { + continue; + } + + $role->attachPermission($permission); + } + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index de24146b8..d40ac00eb 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -18,6 +18,7 @@ class EventServiceProvider extends ServiceProvider 'App\Listeners\Updates\Version107', 'App\Listeners\Updates\Version108', 'App\Listeners\Updates\Version109', + 'App\Listeners\Updates\Version110', ], 'Illuminate\Auth\Events\Login' => [ 'App\Listeners\Auth\Login', diff --git a/app/Utilities/ImportFile.php b/app/Utilities/ImportFile.php new file mode 100644 index 000000000..fa43216aa --- /dev/null +++ b/app/Utilities/ImportFile.php @@ -0,0 +1,36 @@ +hasFile('import')) { + flash(trans('messages.error.no_file'))->error(); + + redirect()->back()->send(); + } + + $folder = session('company_id') . '/imports'; + + // Upload file + $path = Storage::path($request->import->store($folder)); + + return $path; + } + + public function getFilters() + { + return [ + 'chunk' + ]; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json index 4fe4b6b1d..408c87be8 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "laravel/framework": "5.4.*", "laravel/tinker": "~1.0", "LaravelCollective/html": "5.4.*", + "maatwebsite/excel": "2.1.*", "nwidart/laravel-menus": "0.5.*", "nwidart/laravel-modules": "1.*", "santigarcor/laratrust": "4.0.*", diff --git a/config/app.php b/config/app.php index bebb54ee9..803a21955 100644 --- a/config/app.php +++ b/config/app.php @@ -198,6 +198,7 @@ return [ Kyslik\ColumnSortable\ColumnSortableServiceProvider::class, Laracasts\Flash\FlashServiceProvider::class, Laratrust\LaratrustServiceProvider::class, + Maatwebsite\Excel\ExcelServiceProvider::class, Nwidart\Menus\MenusServiceProvider::class, Nwidart\Modules\LaravelModulesServiceProvider::class, Sofa\Eloquence\ServiceProvider::class, @@ -258,6 +259,7 @@ return [ 'Debugbar' => Barryvdh\Debugbar\Facade::class, 'Date' => Jenssegers\Date\Date::class, 'DotenvEditor' => Jackiedo\DotenvEditor\Facades\DotenvEditor::class, + 'Excel' => Maatwebsite\Excel\Facades\Excel::class, 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class, 'Image' => Intervention\Image\Facades\Image::class, diff --git a/config/excel.php b/config/excel.php new file mode 100644 index 000000000..3e682141b --- /dev/null +++ b/config/excel.php @@ -0,0 +1,704 @@ + [ + + /* + |-------------------------------------------------------------------------- + | Enable/Disable cell caching + |-------------------------------------------------------------------------- + */ + 'enable' => true, + + /* + |-------------------------------------------------------------------------- + | Caching driver + |-------------------------------------------------------------------------- + | + | Set the caching driver + | + | Available methods: + | memory|gzip|serialized|igbinary|discISAM|apc|memcache|temp|wincache|sqlite|sqlite3 + | + */ + 'driver' => 'memory', + + /* + |-------------------------------------------------------------------------- + | Cache settings + |-------------------------------------------------------------------------- + */ + 'settings' => [ + + 'memoryCacheSize' => '32MB', + 'cacheTime' => 600 + + ], + + /* + |-------------------------------------------------------------------------- + | Memcache settings + |-------------------------------------------------------------------------- + */ + 'memcache' => [ + + 'host' => 'localhost', + 'port' => 11211, + + ], + + /* + |-------------------------------------------------------------------------- + | Cache dir (for discISAM) + |-------------------------------------------------------------------------- + */ + + 'dir' => storage_path('cache') + ], + + 'properties' => [ + 'creator' => 'Akaunting', + 'lastModifiedBy' => 'Akaunting', + 'title' => 'Spreadsheet', + 'description' => 'Default spreadsheet export', + 'subject' => 'Spreadsheet export', + 'keywords' => 'akaunting, excel, export', + 'category' => 'Excel', + 'manager' => 'Akaunting', + 'company' => 'Akaunting', + ], + + /* + |-------------------------------------------------------------------------- + | Sheets settings + |-------------------------------------------------------------------------- + */ + 'sheets' => [ + + /* + |-------------------------------------------------------------------------- + | Default page setup + |-------------------------------------------------------------------------- + */ + 'pageSetup' => [ + 'orientation' => 'portrait', + 'paperSize' => '9', + 'scale' => '100', + 'fitToPage' => false, + 'fitToHeight' => true, + 'fitToWidth' => true, + 'columnsToRepeatAtLeft' => ['', ''], + 'rowsToRepeatAtTop' => [0, 0], + 'horizontalCentered' => false, + 'verticalCentered' => false, + 'printArea' => null, + 'firstPageNumber' => null, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Creator + |-------------------------------------------------------------------------- + | + | The default creator of a new Excel file + | + */ + + 'creator' => 'Akaunting', + + 'csv' => [ + /* + |-------------------------------------------------------------------------- + | Delimiter + |-------------------------------------------------------------------------- + | + | The default delimiter which will be used to read out a CSV file + | + */ + + 'delimiter' => ',', + + /* + |-------------------------------------------------------------------------- + | Enclosure + |-------------------------------------------------------------------------- + */ + + 'enclosure' => '"', + + /* + |-------------------------------------------------------------------------- + | Line endings + |-------------------------------------------------------------------------- + */ + + 'line_ending' => "\r\n", + + /* + |-------------------------------------------------------------------------- + | setUseBom + |-------------------------------------------------------------------------- + */ + + 'use_bom' => false + ], + + 'export' => [ + + /* + |-------------------------------------------------------------------------- + | Autosize columns + |-------------------------------------------------------------------------- + | + | Disable/enable column autosize or set the autosizing for + | an array of columns ( array('A', 'B') ) + | + */ + 'autosize' => true, + + /* + |-------------------------------------------------------------------------- + | Autosize method + |-------------------------------------------------------------------------- + | + | --> PHPExcel_Shared_Font::AUTOSIZE_METHOD_APPROX + | The default is based on an estimate, which does its calculation based + | on the number of characters in the cell value (applying any calculation + | and format mask, and allowing for wordwrap and rotation) and with an + | "arbitrary" adjustment based on the font (Arial, Calibri or Verdana, + | defaulting to Calibri if any other font is used) and a proportional + | adjustment for the font size. + | + | --> PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT + | The second method is more accurate, based on actual style formatting as + | well (bold, italic, etc), and is calculated by generating a gd2 imagettf + | bounding box and using its dimensions to determine the size; but this + | method is significantly slower, and its accuracy is still dependent on + | having the appropriate fonts installed. + | + */ + 'autosize-method' => PHPExcel_Shared_Font::AUTOSIZE_METHOD_APPROX, + + /* + |-------------------------------------------------------------------------- + | Auto generate table heading + |-------------------------------------------------------------------------- + | + | If set to true, the array indices (or model attribute names) + | will automatically be used as first row (table heading) + | + */ + 'generate_heading_by_indices' => true, + + /* + |-------------------------------------------------------------------------- + | Auto set alignment on merged cells + |-------------------------------------------------------------------------- + */ + 'merged_cell_alignment' => 'left', + + /* + |-------------------------------------------------------------------------- + | Pre-calculate formulas during export + |-------------------------------------------------------------------------- + */ + 'calculate' => false, + + /* + |-------------------------------------------------------------------------- + | Include Charts during export + |-------------------------------------------------------------------------- + */ + 'includeCharts' => false, + + /* + |-------------------------------------------------------------------------- + | Default sheet settings + |-------------------------------------------------------------------------- + */ + 'sheets' => [ + + /* + |-------------------------------------------------------------------------- + | Default page margin + |-------------------------------------------------------------------------- + | + | 1) When set to false, default margins will be used + | 2) It's possible to enter a single margin which will + | be used for all margins. + | 3) Alternatively you can pass an array with 4 margins + | Default order: array(top, right, bottom, left) + | + */ + 'page_margin' => false, + + /* + |-------------------------------------------------------------------------- + | Value in source array that stands for blank cell + |-------------------------------------------------------------------------- + */ + 'nullValue' => null, + + /* + |-------------------------------------------------------------------------- + | Insert array starting from this cell address as the top left coordinate + |-------------------------------------------------------------------------- + */ + 'startCell' => 'A1', + + /* + |-------------------------------------------------------------------------- + | Apply strict comparison when testing for null values in the array + |-------------------------------------------------------------------------- + */ + 'strictNullComparison' => false + ], + + /* + |-------------------------------------------------------------------------- + | Store settings + |-------------------------------------------------------------------------- + */ + + 'store' => [ + + /* + |-------------------------------------------------------------------------- + | Path + |-------------------------------------------------------------------------- + | + | The path we want to save excel file to + | + */ + 'path' => storage_path('app/exports'), + + /* + |-------------------------------------------------------------------------- + | Return info + |-------------------------------------------------------------------------- + | + | Whether we want to return information about the stored file or not + | + */ + 'returnInfo' => false + + ], + + /* + |-------------------------------------------------------------------------- + | PDF Settings + |-------------------------------------------------------------------------- + */ + 'pdf' => [ + + /* + |-------------------------------------------------------------------------- + | PDF Drivers + |-------------------------------------------------------------------------- + | Supported: DomPDF, tcPDF, mPDF + */ + 'driver' => 'DomPDF', + + /* + |-------------------------------------------------------------------------- + | PDF Driver settings + |-------------------------------------------------------------------------- + */ + 'drivers' => [ + + /* + |-------------------------------------------------------------------------- + | DomPDF settings + |-------------------------------------------------------------------------- + */ + 'DomPDF' => [ + 'path' => base_path('vendor/dompdf/dompdf/') + ], + + /* + |-------------------------------------------------------------------------- + | tcPDF settings + |-------------------------------------------------------------------------- + */ + 'tcPDF' => [ + 'path' => base_path('vendor/tecnick.com/tcpdf/') + ], + + /* + |-------------------------------------------------------------------------- + | mPDF settings + |-------------------------------------------------------------------------- + */ + 'mPDF' => [ + 'path' => base_path('vendor/mpdf/mpdf/') + ], + ] + ] + ], + + 'filters' => [ + /* + |-------------------------------------------------------------------------- + | Register read filters + |-------------------------------------------------------------------------- + */ + + 'registered' => [ + 'chunk' => 'Maatwebsite\Excel\Filters\ChunkReadFilter' + ], + + /* + |-------------------------------------------------------------------------- + | Enable certain filters for every file read + |-------------------------------------------------------------------------- + */ + + 'enabled' => [] + ], + + 'import' => [ + + /* + |-------------------------------------------------------------------------- + | Has heading + |-------------------------------------------------------------------------- + | + | The sheet has a heading (first) row which we can use as attribute names + | + | Options: true|false|slugged|slugged_with_count|ascii|numeric|hashed|trans|original + | + */ + + 'heading' => 'slugged', + + /* + |-------------------------------------------------------------------------- + | First Row with data or heading of data + |-------------------------------------------------------------------------- + | + | If the heading row is not the first row, or the data doesn't start + | on the first row, here you can change the start row. + | + */ + + 'startRow' => 1, + + /* + |-------------------------------------------------------------------------- + | Cell name word separator + |-------------------------------------------------------------------------- + | + | The default separator which is used for the cell names + | Note: only applies to 'heading' settings 'true' && 'slugged' + | + */ + + 'separator' => '_', + + /* + |-------------------------------------------------------------------------- + | Slug whitelisting + |-------------------------------------------------------------------------- + | + | Here you can whitelist certain characters in the slug. + | E.g. user.last_name will not remove . and _ + | Note: only applies to 'heading' settings 'true' && 'slugged' + | + */ + + 'slug_whitelist' => '._', + + /* + |-------------------------------------------------------------------------- + | Include Charts during import + |-------------------------------------------------------------------------- + */ + + 'includeCharts' => false, + + /* + |-------------------------------------------------------------------------- + | Sheet heading conversion + |-------------------------------------------------------------------------- + | + | Convert headings to ASCII + | Note: only applies to 'heading' settings 'true' && 'slugged' + | + */ + + 'to_ascii' => true, + + /* + |-------------------------------------------------------------------------- + | Import encoding + |-------------------------------------------------------------------------- + */ + + 'encoding' => [ + + 'input' => 'UTF-8', + 'output' => 'UTF-8' + + ], + + /* + |-------------------------------------------------------------------------- + | Calculate + |-------------------------------------------------------------------------- + | + | By default cells with formulas will be calculated. + | + */ + + 'calculate' => true, + + /* + |-------------------------------------------------------------------------- + | Ignore empty cells + |-------------------------------------------------------------------------- + | + | By default empty cells are not ignored + | + */ + + 'ignoreEmpty' => true, + + /* + |-------------------------------------------------------------------------- + | Force sheet collection + |-------------------------------------------------------------------------- + | + | For a sheet collection even when there is only 1 sheets. + | When set to false and only 1 sheet found, the parsed file will return + | a row collection instead of a sheet collection. + | When set to true, it will return a sheet collection instead. + | + */ + 'force_sheets_collection' => false, + + /* + |-------------------------------------------------------------------------- + | Date format + |-------------------------------------------------------------------------- + | + | The format dates will be parsed to + | + */ + + 'dates' => [ + + /* + |-------------------------------------------------------------------------- + | Enable/disable date formatting + |-------------------------------------------------------------------------- + */ + 'enabled' => true, + + /* + |-------------------------------------------------------------------------- + | Default date format + |-------------------------------------------------------------------------- + | + | If set to false, a carbon object will return + | + */ + 'format' => false, + + /* + |-------------------------------------------------------------------------- + | Date columns + |-------------------------------------------------------------------------- + */ + 'columns' => [] + ], + + /* + |-------------------------------------------------------------------------- + | Import sheets by config + |-------------------------------------------------------------------------- + */ + 'sheets' => [ + + /* + |-------------------------------------------------------------------------- + | Example sheet + |-------------------------------------------------------------------------- + | + | Example sheet "test" will grab the firstname at cell A2 + | + */ + + 'test' => [ + + 'firstname' => 'A2' + + ] + + ] + ], + + 'views' => [ + + /* + |-------------------------------------------------------------------------- + | Styles + |-------------------------------------------------------------------------- + | + | The default styles which will be used when parsing a view + | + */ + + 'styles' => [ + + /* + |-------------------------------------------------------------------------- + | Table headings + |-------------------------------------------------------------------------- + */ + 'th' => [ + 'font' => [ + 'bold' => true, + 'size' => 12, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Strong tags + |-------------------------------------------------------------------------- + */ + 'strong' => [ + 'font' => [ + 'bold' => true, + 'size' => 12, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Bold tags + |-------------------------------------------------------------------------- + */ + 'b' => [ + 'font' => [ + 'bold' => true, + 'size' => 12, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Italic tags + |-------------------------------------------------------------------------- + */ + 'i' => [ + 'font' => [ + 'italic' => true, + 'size' => 12, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 1 + |-------------------------------------------------------------------------- + */ + 'h1' => [ + 'font' => [ + 'bold' => true, + 'size' => 24, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 2 + |-------------------------------------------------------------------------- + */ + 'h2' => [ + 'font' => [ + 'bold' => true, + 'size' => 18, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 3 + |-------------------------------------------------------------------------- + */ + 'h3' => [ + 'font' => [ + 'bold' => true, + 'size' => 13.5, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 4 + |-------------------------------------------------------------------------- + */ + 'h4' => [ + 'font' => [ + 'bold' => true, + 'size' => 12, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 5 + |-------------------------------------------------------------------------- + */ + 'h5' => [ + 'font' => [ + 'bold' => true, + 'size' => 10, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Heading 6 + |-------------------------------------------------------------------------- + */ + 'h6' => [ + 'font' => [ + 'bold' => true, + 'size' => 7.5, + ] + ], + + /* + |-------------------------------------------------------------------------- + | Hyperlinks + |-------------------------------------------------------------------------- + */ + 'a' => [ + 'font' => [ + 'underline' => true, + 'color' => ['argb' => 'FF0000FF'], + ] + ], + + /* + |-------------------------------------------------------------------------- + | Horizontal rules + |-------------------------------------------------------------------------- + */ + 'hr' => [ + 'borders' => [ + 'bottom' => [ + 'style' => 'thin', + 'color' => ['FF000000'] + ], + ] + ] + ] + + ] + +); diff --git a/database/seeds/Roles.php b/database/seeds/Roles.php index fc3005018..db424e010 100644 --- a/database/seeds/Roles.php +++ b/database/seeds/Roles.php @@ -35,6 +35,7 @@ class Roles extends Seeder 'auth-permissions' => 'c,r,u,d', 'auth-profile' => 'r,u', 'companies-companies' => 'c,r,u,d', + 'common-import' => 'c', 'items-items' => 'c,r,u,d', 'incomes-invoices' => 'c,r,u,d', 'incomes-revenues' => 'c,r,u,d', @@ -64,6 +65,7 @@ class Roles extends Seeder 'admin-panel' => 'r', 'auth-profile' => 'r,u', 'companies-companies' => 'c,r,u,d', + 'common-import' => 'c', 'items-items' => 'c,r,u,d', 'incomes-invoices' => 'c,r,u,d', 'incomes-revenues' => 'c,r,u,d', diff --git a/public/files/import/bills.csv b/public/files/import/bills.csv new file mode 100644 index 000000000..60839ef4f --- /dev/null +++ b/public/files/import/bills.csv @@ -0,0 +1,2 @@ +"bill_number","order_number","bill_status_code","billed_at","due_at","amount","currency_code","currency_rate","vendor_id","vendor_name","vendor_email","vendor_tax_number","vendor_phone","vendor_address","notes","attachment","created_at","updated_at","deleted_at" +"987654","","received","2017-11-30","2017-12-07","10.0000","USD","1.00000000","1","Test Vendor","test@vendor.com","","","","","","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/customers.csv b/public/files/import/customers.csv new file mode 100644 index 000000000..b24d6c976 --- /dev/null +++ b/public/files/import/customers.csv @@ -0,0 +1,2 @@ +"user_id","name","email","tax_number","phone","address","website","currency_code","enabled","created_at","updated_at","deleted_at" +"","Test Customer","test@customer.com","","","","","USD","1","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/invoices.csv b/public/files/import/invoices.csv new file mode 100644 index 000000000..bfd0e99af --- /dev/null +++ b/public/files/import/invoices.csv @@ -0,0 +1,2 @@ +"invoice_number","order_number","invoice_status_code","invoiced_at","due_at","amount","currency_code","currency_rate","customer_id","customer_name","customer_email","customer_tax_number","customer_phone","customer_address","notes","attachment","created_at","updated_at","deleted_at" +"INV-00001","","sent","2017-11-30","2017-12-07","10.0000","USD","1.00000000","1","Test Customer","test@customer.com","","","","","","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/items.csv b/public/files/import/items.csv new file mode 100644 index 000000000..5aea19d2f --- /dev/null +++ b/public/files/import/items.csv @@ -0,0 +1,2 @@ +"name","sku","description","sale_price","purchase_price","quantity","category_id","tax_id","picture","enabled","created_at","updated_at","deleted_at" +"Test Item","test-item","","10.0000","5.0000","1","5","2","items/test-item.png","1","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/payments.csv b/public/files/import/payments.csv new file mode 100644 index 000000000..363dc2b9b --- /dev/null +++ b/public/files/import/payments.csv @@ -0,0 +1,2 @@ +"account_id","paid_at","amount","currency_code","currency_rate","vendor_id","description","category_id","payment_method","reference","attachment","created_at","updated_at","deleted_at" +"1","2017-11-30","10.0000","USD","1.00000000","1","","4","offlinepayment.cash.1","","","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/revenues.csv b/public/files/import/revenues.csv new file mode 100644 index 000000000..bd110fc1f --- /dev/null +++ b/public/files/import/revenues.csv @@ -0,0 +1,2 @@ +"account_id","paid_at","amount","currency_code","currency_rate","customer_id","description","category_id","payment_method","reference","attachment","created_at","updated_at","deleted_at" +"1","2017-11-30","10.0000","USD","1.00000000","","","3","offlinepayment.cash.1","","revenues/test-revenue.pdf","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/public/files/import/vendors.csv b/public/files/import/vendors.csv new file mode 100644 index 000000000..83b680232 --- /dev/null +++ b/public/files/import/vendors.csv @@ -0,0 +1,2 @@ +"user_id","name","email","tax_number","phone","address","website","currency_code","enabled","created_at","updated_at","deleted_at" +"","Test Vendor","test@vendor.com","","","","","USD","1","2017-11-30 00:00:00","2017-11-30 00:00:00",NULL diff --git a/resources/lang/en-GB/import.php b/resources/lang/en-GB/import.php new file mode 100644 index 000000000..fe5acbbc0 --- /dev/null +++ b/resources/lang/en-GB/import.php @@ -0,0 +1,9 @@ + 'Import', + 'title' => 'Import :type', + 'message' => 'Allowed file types: CSV, XLS. Please, download the sample file.', + +]; diff --git a/resources/lang/en-GB/messages.php b/resources/lang/en-GB/messages.php index d6e23dd67..62334f8bd 100644 --- a/resources/lang/en-GB/messages.php +++ b/resources/lang/en-GB/messages.php @@ -7,10 +7,12 @@ return [ 'updated' => ':type updated!', 'deleted' => ':type deleted!', 'duplicated' => ':type duplicated!', + 'imported' => ':type imported!', ], 'error' => [ 'not_user_company' => 'Error: You are not allowed to manage this company!', 'customer' => 'Error: You can not created user! :name use this email address.', + 'no_file' => 'Error: No file selected!', ], 'warning' => [ 'deleted' => 'Warning: You are not allowed to delete :name because it has :text related.', diff --git a/resources/views/common/import/create.blade.php b/resources/views/common/import/create.blade.php new file mode 100644 index 000000000..07cb70c93 --- /dev/null +++ b/resources/views/common/import/create.blade.php @@ -0,0 +1,54 @@ +@extends('layouts.admin') + +@section('title', trans('import.title', ['type' => trans_choice('general.' . $type, 2)])) + +@section('content') +
+ {!! Form::open(['url' => $path . '/import', 'files' => true, 'role' => 'form']) !!} + +
+
+
+ {!! trans('import.message', ['link' => url('public/files/import/' . $type . '.csv')]) !!} +
+
+
+ {!! Form::label('import', trans('general.form.select.file'), ['class' => 'control-label']) !!} + {!! Form::file('import', null, ['class' => 'form-control']) !!} + {!! $errors->first('import', '

:message

') !!} +
+
+ + + + + {!! Form::close() !!} +
+@endsection + +@push('js') + +@endpush + +@push('css') + +@endpush + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/expenses/bills/index.blade.php b/resources/views/expenses/bills/index.blade.php index 456f931bf..751b73f03 100644 --- a/resources/views/expenses/bills/index.blade.php +++ b/resources/views/expenses/bills/index.blade.php @@ -5,6 +5,7 @@ @permission('create-expenses-bills') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/expenses/payments/index.blade.php b/resources/views/expenses/payments/index.blade.php index 86445632a..645461b2b 100644 --- a/resources/views/expenses/payments/index.blade.php +++ b/resources/views/expenses/payments/index.blade.php @@ -5,6 +5,7 @@ @permission('create-expenses-payments') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/expenses/vendors/index.blade.php b/resources/views/expenses/vendors/index.blade.php index 0a4b898b5..ffb3bc589 100644 --- a/resources/views/expenses/vendors/index.blade.php +++ b/resources/views/expenses/vendors/index.blade.php @@ -5,6 +5,7 @@ @permission('create-expenses-vendors') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/incomes/customers/index.blade.php b/resources/views/incomes/customers/index.blade.php index 80826bcd9..2edd47f10 100644 --- a/resources/views/incomes/customers/index.blade.php +++ b/resources/views/incomes/customers/index.blade.php @@ -5,6 +5,7 @@ @permission('create-incomes-customers') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/incomes/invoices/index.blade.php b/resources/views/incomes/invoices/index.blade.php index 3d6b0ea0c..7d230246e 100644 --- a/resources/views/incomes/invoices/index.blade.php +++ b/resources/views/incomes/invoices/index.blade.php @@ -5,6 +5,7 @@ @permission('create-incomes-invoices') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/incomes/revenues/index.blade.php b/resources/views/incomes/revenues/index.blade.php index 1f7e4fae1..f11009575 100644 --- a/resources/views/incomes/revenues/index.blade.php +++ b/resources/views/incomes/revenues/index.blade.php @@ -5,6 +5,7 @@ @permission('create-incomes-revenues') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/resources/views/items/items/index.blade.php b/resources/views/items/items/index.blade.php index b04de3d8d..74271f61e 100644 --- a/resources/views/items/items/index.blade.php +++ b/resources/views/items/items/index.blade.php @@ -5,6 +5,7 @@ @permission('create-items-items') @section('new_button')  {{ trans('general.add_new') }} +  {{ trans('import.import') }} @endsection @endpermission diff --git a/routes/web.php b/routes/web.php index bd6435044..a78f4e130 100644 --- a/routes/web.php +++ b/routes/web.php @@ -21,10 +21,15 @@ Route::group(['middleware' => 'language'], function () { Route::resource('search', 'Search\Search'); }); + Route::group(['prefix' => 'common'], function () { + Route::get('import/{group}/{type}', 'Common\Import@create'); + }); + Route::group(['prefix' => 'items'], function () { Route::get('items/autocomplete', 'Items\Items@autocomplete'); Route::post('items/totalItem', 'Items\Items@totalItem'); Route::get('items/{item}/duplicate', 'Items\Items@duplicate'); + Route::post('items/import', 'Items\Items@import'); Route::resource('items', 'Items\Items'); }); @@ -53,12 +58,15 @@ Route::group(['middleware' => 'language'], function () { Route::get('invoices/{invoice}/duplicate', 'Incomes\Invoices@duplicate'); Route::post('invoices/payment', 'Incomes\Invoices@payment'); Route::delete('invoices/payment/{payment}', 'Incomes\Invoices@paymentDestroy'); + Route::post('invoices/import', 'Incomes\Invoices@import'); Route::resource('invoices', 'Incomes\Invoices'); Route::get('revenues/{revenue}/duplicate', 'Incomes\Revenues@duplicate'); + Route::post('revenues/import', 'Incomes\Revenues@import'); Route::resource('revenues', 'Incomes\Revenues'); Route::get('customers/currency', 'Incomes\Customers@currency'); Route::get('customers/{customer}/duplicate', 'Incomes\Customers@duplicate'); Route::post('customers/customer', 'Incomes\Customers@customer'); + Route::post('customers/import', 'Incomes\Customers@import'); Route::resource('customers', 'Incomes\Customers'); }); @@ -69,12 +77,15 @@ Route::group(['middleware' => 'language'], function () { Route::get('bills/{bill}/duplicate', 'Expenses\Bills@duplicate'); Route::post('bills/payment', 'Expenses\Bills@payment'); Route::delete('bills/payment/{payment}', 'Expenses\Bills@paymentDestroy'); + Route::post('bills/import', 'Expenses\Bills@import'); Route::resource('bills', 'Expenses\Bills'); Route::get('payments/{payment}/duplicate', 'Expenses\Payments@duplicate'); + Route::post('payments/import', 'Expenses\Payments@import'); Route::resource('payments', 'Expenses\Payments'); Route::get('vendors/currency', 'Expenses\Vendors@currency'); Route::get('vendors/{vendor}/duplicate', 'Expenses\Vendors@duplicate'); Route::post('vendors/vendor', 'Expenses\Vendors@vendor'); + Route::post('vendors/import', 'Expenses\Vendors@import'); Route::resource('vendors', 'Expenses\Vendors'); });