Importar Facturas desde CSV
Importar Facturas desde CSV
app/Http/Controllers/Admin/[Link]
... ... @@ -3,12 +3,49 @@
3 3 namespace App\Http\Controllers\Admin;
4 4
5 5 use App\Http\Controllers\Controller;
6 + use App\Imports\InvoiceDetailImport;
7 + use App\Imports\InvoiceImport;
8 + use App\Service;
6 9 use Illuminate\Http\Request;
10 + use Maatwebsite\Excel\Facades\Excel;
7 11
8 12 class InvoiceController extends Controller
9 13 {
10 14 public function index()
11 15 {
12 - return view('[Link]');
16 + $services = Service::whereGetInstances('idBranch', '=', \State::get('[Link]'));
17 + return view('[Link]', compact('services'));
18 + }
19 +
20 +
21 + public function uploadInvoices(Request $request)
22 + {
23 + $request->validate([
24 + 'idService' => 'required',
25 + 'invoicesFile' => 'required|file'
26 + ]);
27 +
28 + $import = new InvoiceImport($request->get('idService'));
29 + Excel::import($import, request()->file('invoicesFile'));
30 +
31 + feedback('success', 'Se importaron *'.$import->getRowCount().'* facturas');
32 +
33 + return redirect()->route('[Link]');
34 + }
35 +
36 +
37 + public function uploadDetails(Request $request)
38 + {
39 + $request->validate([
40 + 'idService' => 'required',
41 + 'detailsFile' => 'required|file'
42 + ]);
43 +
44 + $import = new InvoiceDetailImport($request->get('idService'));
45 + Excel::import($import, request()->file('detailsFile'));
46 +
47 + feedback('success', 'Se importaron *'.$import->getRowCount().'* conceptos');
48 +
49 + return redirect()->route('[Link]');
13 50 }
14 51 }
app/Imports/[Link] 0 → 100644
[Link] 1/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
1 + <?php
2 +
3 + namespace App\Imports;
4 +
5 + use App\InvoiceDetail;
6 + use Illuminate\Support\Collection;
7 + use Maatwebsite\Excel\Concerns\ToCollection;
8 + use Maatwebsite\Excel\Concerns\WithBatchInserts;
9 + use Maatwebsite\Excel\Concerns\WithChunkReading;
10 + use Maatwebsite\Excel\Concerns\WithHeadingRow;
11 +
12 + class InvoiceDetailImport implements ToCollection, WithHeadingRow, WithChunkReading, WithBatchInserts
13 +{
14 + private $serviceId;
15 + private $rows = 0;
16 +
17 + public function __construct(string $serviceId)
18 + {
19 + $this->serviceId = $serviceId;
20 + }
21 +
22 + public function collection(Collection $collection)
23 + {
24 + $batch = InvoiceDetail::batch();
25 + $invoicesIds = $collection->map(fn($r) => (string)$r['numero_factura'])->unique()->toArray();
26 + $clients = Client::whereGetInstances('identification', 'in', $clientsIds);
27 + foreach ($collection as $row) {
28 + ++$this->rows;
29 + $client = $clients->first(function ($client) use ($row) {
30 + return $client->field('identification') == $row['numero_identificacion'];
31 + });
32 + $batch->create(InvoiceDetail::newDocument(), [
33 + 'companyAddress' => $row['direccion'],
34 + 'companyIdClient' => $row['numero_identificacion'],
35 + 'companyIdInvoice' => $row['numero_factura'],
36 + 'companyName' => $row['nombre'],
37 + 'companyPhone' => $row['telefono'],
38 + 'month' => $row['mes'],
39 + 'year' => $row['ano'],
40 + 'valor' => $row['valor'],
41 + 'idBranch' => \State::get('[Link]'),
42 + 'idCompany' => \State::get('[Link]'),
43 + 'idClient' => $client ? $client->id() : null,
44 + 'idService' => $this->serviceId,
45 + 'state' => 'Activo',
46 + 'createAt' => date_create(),
47 + 'creteBy' => \State::get('[Link]'),
48 + ]);
49 + }
50 + $batch->commit();
51 + }
52 +
53 + public function chunkSize(): int
54 + {
55 + return 3;
56 + }
57 +
58 + public function batchSize(): int
59 + {
60 + return 3;
61 + }
62 +
63 + public function getRowCount(): int
64 + {
65 + return $this->rows;
66 + }
67 +}
app/Imports/[Link] 0 → 100644
1 + <?php
2 +
3 + namespace App\Imports;
4 +
5 + use App\Client;
[Link] 2/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
6 + use App\Invoice;
7 + use Illuminate\Support\Collection;
8 + use Maatwebsite\Excel\Concerns\ToCollection;
9 + use Maatwebsite\Excel\Concerns\WithBatchInserts;
10 + use Maatwebsite\Excel\Concerns\WithChunkReading;
11 + use Maatwebsite\Excel\Concerns\WithHeadingRow;
12 +
13 + class InvoiceImport implements ToCollection, WithHeadingRow, WithChunkReading, WithBatchInserts
14 +{
15 + private $serviceId;
16 + private $rows = 0;
17 +
18 + public function __construct(string $serviceId)
19 + {
20 + $this->serviceId = $serviceId;
21 + }
22 +
23 + public function collection(Collection $collection)
24 + {
25 + $batch = Invoice::batch();
26 + $clientsIds = $collection->map(fn($r) => (string)$r['numero_identificacion'])->toArray();
27 + $clients = Client::whereGetInstances('identification', 'in', $clientsIds);
28 + foreach ($collection as $row) {
29 + ++$this->rows;
30 + $client = $clients->first(function ($client) use ($row) {
31 + return $client->field('identification') == $row['numero_identificacion'];
32 + });
33 + $batch->create(Invoice::newDocument(), [
34 + 'companyAddress' => $row['direccion'],
35 + 'companyIdClient' => $row['numero_identificacion'],
36 + 'companyIdInvoice' => $row['numero_factura'],
37 + 'companyName' => $row['nombre'],
38 + 'companyPhone' => $row['telefono'],
39 + 'month' => $row['mes'],
40 + 'year' => $row['ano'],
41 + 'valor' => $row['valor'],
42 + 'idBranch' => \State::get('[Link]'),
43 + 'idCompany' => \State::get('[Link]'),
44 + 'idClient' => $client ? $client->id() : null,
45 + 'idService' => $this->serviceId,
46 + 'state' => 'Activo',
47 + 'createAt' => date_create(),
48 + 'creteBy' => \State::get('[Link]'),
49 + ]);
50 + }
51 + $batch->commit();
52 + }
53 +
54 + public function chunkSize(): int
55 + {
56 + return 2;
57 + }
58 +
59 + public function batchSize(): int
60 + {
61 + return 2;
62 + }
63 +
64 + public function getRowCount(): int
65 + {
66 + return $this->rows;
67 + }
68 +}
app/[Link] 0 → 100644
1 + <?php
2 +
3 + namespace App;
4 +
5 + use App\Support\LarafireModel;
6 +
7 + class Invoice extends LarafireModel
8 +{
9 + protected $collectionName = 'invoices';
[Link] 3/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
10 +}
app/[Link] 0 → 100644
1 + <?php
2 +
3 + namespace App;
4 +
5 + use App\Support\LarafireModel;
6 +
7 + class InvoiceDetail extends LarafireModel
8 +{
9 + protected $collectionName = 'invoicesDetails';
10 +}
app/Support/Larafi[Link]
... ... @@ -181,6 +181,21 @@ class LarafireModel implements JsonSerializable
181 181 }
182 182
183 183
184 + public static function newDocument()
185 + {
186 + $instance = self::getNewInstance();
187 + return $instance->collection->newDocument();
188 + }
189 +
190 + public static function batch()
191 + {
192 + $instance = self::getNewInstance();
193 + return $instance->firestore->database()->batch();
194 + }
195 +
196 +
197 +
198 +
184 199 // INSTANCE METHODS
185 200
186 201 private function checkFirebaseObjectSet()
... ... @@ -275,6 +290,8 @@ class LarafireModel implements JsonSerializable
275 290 }
276 291
277 292
293 +
294 +
278 295 // MUTATION
279 296
280 297 public static function create($data)
... ...
bootstrap/cache/confi[Link]
bootstrap/cache/[Link]
... ... @@ -69,6 +69,17 @@
69 69 0 => 'Laraveles\\Spanish\\SpanishServiceProvider',
70 70 ),
71 71 ),
72 + 'maatwebsite/excel' =>
73 + array (
74 + 'providers' =>
75 + array (
76 + 0 => 'Maatwebsite\\Excel\\ExcelServiceProvider',
77 + ),
78 + 'aliases' =>
79 + array (
80 + 'Excel' => 'Maatwebsite\\Excel\\Facades\\Excel',
81 + ),
82 + ),
72 83 'nesbot/carbon' =>
73 84 array (
74 85 'providers' =>
... ...
bootstrap/cache/[Link]
[Link] 5/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
[Link]
... ... @@ -19,6 +19,7 @@
19 19 "laravel/tinker": "^2.0",
20 20 "laravel/ui": "^2.0",
21 21 "laraveles/spanish": "^1.4",
22 + "maatwebsite/excel": "^3.1",
22 23 "pusher/pusher-php-server": "~4.0",
23 24 "yoeunes/notify": "^1.0"
24 25 },
... ...
[Link]
config/[Link] 0 → 100644
1 + <?php
2 +
[Link] 6/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
3 + use Maatwebsite\Excel\Excel;
4 +
5 + return [
6 +
7 + 'exports' => [
8 +
9 + /*
10 + |--------------------------------------------------------------------------
11 + | Chunk size
12 + |--------------------------------------------------------------------------
13 + |
14 + | When using FromQuery, the query is automatically chunked.
15 + | Here you can specify how big the chunk should be.
16 + |
17 + */
18 + 'chunk_size' => 1000,
19 +
20 + /*
21 + |--------------------------------------------------------------------------
22 + | Pre-calculate formulas during export
23 + |--------------------------------------------------------------------------
24 + */
25 + 'pre_calculate_formulas' => false,
26 +
27 + /*
28 + |--------------------------------------------------------------------------
29 + | CSV Settings
30 + |--------------------------------------------------------------------------
31 + |
32 + | Configure e.g. delimiter, enclosure and line ending for CSV exports.
33 + |
34 + */
35 + 'csv' => [
36 + 'delimiter' => ';',
37 + 'enclosure' => '"',
38 + 'line_ending' => PHP_EOL,
39 + 'use_bom' => false,
40 + 'include_separator_line' => false,
41 + 'excel_compatibility' => false,
42 + ],
43 + ],
44 +
45 + 'imports' => [
46 +
47 + 'read_only' => true,
48 +
49 + 'heading_row' => [
50 +
51 + /*
52 + |--------------------------------------------------------------------------
53 + | Heading Row Formatter
54 + |--------------------------------------------------------------------------
55 + |
56 + | Configure the heading row formatter.
57 + | Available options: none|slug|custom
58 + |
59 + */
60 + 'formatter' => 'slug',
61 + ],
62 +
63 + /*
64 + |--------------------------------------------------------------------------
65 + | CSV Settings
66 + |--------------------------------------------------------------------------
67 + |
68 + | Configure e.g. delimiter, enclosure and line ending for CSV imports.
69 + |
70 + */
71 + 'csv' => [
72 + 'delimiter' => ';',
73 + 'enclosure' => '"',
74 + 'escape_character' => '\\',
75 + 'contiguous' => false,
76 + 'input_encoding' => 'UTF-8',
77 + ],
[Link] 7/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
78 + ],
79 +
80 + /*
81 + |--------------------------------------------------------------------------
82 + | Extension detector
83 + |--------------------------------------------------------------------------
84 + |
85 + | Configure here which writer type should be used when
86 + | the package needs to guess the correct type
87 + | based on the extension alone.
88 + |
89 + */
90 + 'extension_detector' => [
91 + 'xlsx' => Excel::XLSX,
92 + 'xlsm' => Excel::XLSX,
93 + 'xltx' => Excel::XLSX,
94 + 'xltm' => Excel::XLSX,
95 + 'xls' => Excel::XLS,
96 + 'xlt' => Excel::XLS,
97 + 'ods' => Excel::ODS,
98 + 'ots' => Excel::ODS,
99 + 'slk' => Excel::SLK,
100 + 'xml' => Excel::XML,
101 + 'gnumeric' => Excel::GNUMERIC,
102 + 'htm' => Excel::HTML,
103 + 'html' => Excel::HTML,
104 + 'csv' => Excel::CSV,
105 + 'tsv' => Excel::TSV,
106 +
107 + /*
108 + |--------------------------------------------------------------------------
109 + | PDF Extension
110 + |--------------------------------------------------------------------------
111 + |
112 + | Configure here which Pdf driver should be used by default.
113 + | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF
114 + |
115 + */
116 + 'pdf' => Excel::DOMPDF,
117 + ],
118 +
119 + 'value_binder' => [
120 +
121 + /*
122 + |--------------------------------------------------------------------------
123 + | Default Value Binder
124 + |--------------------------------------------------------------------------
125 + |
126 + | PhpSpreadsheet offers a way to hook into the process of a value being
127 + | written to a cell. In there some assumptions are made on how the
128 + | value should be formatted. If you want to change those defaults,
129 + | you can implement your own default value binder.
130 + |
131 + */
132 + 'default' => Maatwebsite\Excel\DefaultValueBinder::class,
133 + ],
134 +
135 + 'transactions' => [
136 +
137 + /*
138 + |--------------------------------------------------------------------------
139 + | Transaction Handler
140 + |--------------------------------------------------------------------------
141 + |
142 + | By default the import is wrapped in a transaction. This is useful
143 + | for when an import may fail and you want to retry it. With the
144 + | transactions, the previous import gets rolled-back.
145 + |
146 + | You can disable the transaction handler by setting this to null.
147 + | Or you can choose a custom made transaction handler here.
148 + |
149 + | Supported handlers: null|db
150 + |
151 + */
152 + 'handler' => 'null',
[Link] 8/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
153 + ],
154 +
155 + 'temporary_files' => [
156 +
157 + /*
158 + |--------------------------------------------------------------------------
159 + | Local Temporary Path
160 + |--------------------------------------------------------------------------
161 + |
162 + | When exporting and importing files, we use a temporary file, before
163 + | storing reading or downloading. Here you can customize that path.
164 + |
165 + */
166 + 'local_path' => sys_get_temp_dir(),
167 +
168 + /*
169 + |--------------------------------------------------------------------------
170 + | Remote Temporary Disk
171 + |--------------------------------------------------------------------------
172 + |
173 + | When dealing with a multi server setup with queues in which you
174 + | cannot rely on having a shared local temporary path, you might
175 + | want to store the temporary file on a shared disk. During the
176 + | queue executing, we'll retrieve the temporary file from that
177 + | location instead. When left to null, it will always use
178 + | the local path. This setting only has effect when using
179 + | in conjunction with queued imports and exports.
180 + |
181 + */
182 + 'remote_disk' => null,
183 + 'remote_prefix' => null,
184 +
185 + ],
186 + ];
public/js/[Link] 0 → 100644
resources/views/admin/invoices/[Link]
1 1 @extends('[Link]', ['title' => 'Administrar Facturas'])
2 2 @section('content')
3 3 <div class="container" id="invoices">
4 - <div class="mb-3 d-flex justify-content-end">
5 - <button class="btn btn-primary" @click="create">Carga Masiva de Facturas</button>
6 - </div>
7 - <div class="w-100" style="overflow-x: scroll">
8 - @{{msg}}
4 +
5 +
6 + <!-- CARGUE MASIVO DE FACTURAS -->
7 + <div class="border rounded p-3">
8 + <h2>Cargue masivo de Facturas</h2>
9 + <form action="{{route('[Link]-invoices')}}"
10 + method="post"
11 + enctype="multipart/form-data">
12 + @csrf
13 +
14 + <div class="row">
15 + <div class="col-md-4">
16 + <select id="" name="idService" class="form-control" v-model="invoiceIdService">
17 + <option value="" selected>Seleccione el trámite</option>
18 + @forelse($services as $service)
19 + <option value="{{$service->id()}}">{{$service->field('name')}}</option>
20 + @empty
21 + <option value="" disabled>No hay trámites para mostrar</option>
22 + @endforelse
23 + </select>
24 + </div>
25 + <div class="col-mg-4">
26 + <div class="custom-file">
27 + <input type="file"
28 + class="custom-file-input"
[Link] 9/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
29 + name="invoicesFile"
30 + accept=".csv"
31 + @change="invoiceFileChanged">
32 + <label class="custom-file-label" for="customFile">@{{invoiceFileText}}</label>
33 + </div>
34 + </div>
35 + </div>
36 +
37 + <div class="w-100 my-3" style="overflow-x: scroll" v-show="[Link]">
38 + <table class="table">
39 + <thead>
40 + <th class="text-center">#Factura</th>
41 + <th>Mes</th>
42 + <th>Año</th>
43 + <th>Valor</th>
44 + <th>#Identificación</th>
45 + <th>Nombre</th>
46 + <th>Dirección</th>
47 + <th>Teléfono</th>
48 + </thead>
49 + <tbody>
50 + <tr v-for="row in previewInvoiceRows">
51 + <td class="text-center">@{{row.numero_factura}}</td>
52 + <td>@{{[Link]}}</td>
53 + <td>@{{[Link]}}</td>
54 + <td>@{{[Link]}}</td>
55 + <td>@{{row.numero_identificacion}}</td>
56 + <td>@{{[Link]}}</td>
57 + <td>@{{[Link]}}</td>
58 + <td>@{{[Link]}}</td>
59 + </tr>
60 + </tbody>
61 + </table>
62 + <p class="text-center text-muted"><small>-- primeros 3 registros del lote --</small>
</p>
63 + </div>
64 + <div class="d-flex justify-content-end">
65 + <button class="btn btn-primary"
66 + v-show="invoiceFileSelected && invoiceIdService"
67 + @click="submitInvoice">
68 + Cargar este lote de Facturas
69 + </button>
70 + </div>
71 + </form>
9 72 </div>
10 73
74 +
75 + <!-- CARGUE MASIVO DE CONCEPTOS -->
76 + <div class="border rounded p-3 mt-5">
77 + <h2>Cargue masivo de Conceptos</h2>
78 + <form action="{{route('[Link]-details')}}"
79 + method="post"
80 + enctype="multipart/form-data">
81 + @csrf
82 +
83 + <div class="row">
84 + <div class="col-md-4">
85 + <select id="" name="idService" class="form-control" v-model="detailsIdService">
86 + <option value="" selected>Seleccione el trámite</option>
87 + @forelse($services as $service)
88 + <option value="{{$service->id()}}">{{$service->field('name')}}</option>
89 + @empty
90 + <option value="" disabled>No hay trámites para mostrar</option>
91 + @endforelse
92 + </select>
93 + </div>
94 + <div class="col-mg-4">
95 + <div class="custom-file">
96 + <input type="file"
97 + class="custom-file-input"
98 + name="detailsFile"
99 + accept=".csv"
100 + @change="detailsFileChanged">
101 + <label class="custom-file-label" for="customFile">@{{detailsFileText}}</label>
102 + </div>
[Link] 10/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
103 + </div>
104 + </div>
105 +
106 + <div class="w-100 my-3" style="overflow-x: scroll" v-show="[Link]">
107 + <table class="table">
108 + <thead>
109 + <th class="text-center">#Factura</th>
110 + <th>Concepto</th>
111 + <th>Valor</th>
112 + </thead>
113 + <tbody>
114 + <tr v-for="row in previewDetailsRows">
115 + <td class="text-center">@{{row.numero_factura}}</td>
116 + <td>@{{[Link]}}</td>
117 + <td>@{{[Link]}}</td>
118 + </tr>
119 + </tbody>
120 + </table>
121 + <p class="text-center text-muted"><small>-- primeros 3 registros del lote --</small>
</p>
122 + </div>
123 + <div class="d-flex justify-content-end">
124 + <button class="btn btn-primary"
125 + v-show="detailsFileSelected && detailsIdService"
126 + @click="submitDetails">
127 + Cargar este lote de Conceptos
128 + </button>
129 + </div>
130 + </form>
131 + </div>
11 132 </div>
12 133 @endsection
13 134 @push('js')
135 + <script src="{{asset('js/[Link]')}}"></script>
14 136 <script>
15 137 const invoices = new Vue({
16 138 el: '#invoices',
17 139 data() {
18 140 return {
19 - msg: 'bla'
141 + invoiceFileSelected: false,
142 + invoiceFileText: 'Seleccione archivo .csv',
143 + invoiceIdService: '',
144 + previewInvoiceRows: [],
145 + detailsFileSelected: false,
146 + detailsFileText: 'Seleccione archivo .csv',
147 + detailsIdService: '',
148 + previewDetailsRows: [],
20 149 }
21 150 },
151 + methods: {
152 + submitInvoice(ev) {
153 + if (![Link] || ![Link]) {
154 + [Link]()
155 + return [Link]('Por favor, seleccione un trámite y un archivo .csv')
156 + }
157 + },
158 + invoiceFileChanged(ev) {
159 + const value = [Link]
160 + [Link] = value ? [Link](12) : 'Seleccione archivo .csv'
161 + [Link] = value ? true : false
162 +
163 + const handleParsedRows = (results) => [Link] = [Link]
164 +
165 + [Link]([Link][0], {
166 + delimiter: ';',
167 + header: true,
168 + skipEmptyLines: true,
169 + preview: 3,
170 + complete: handleParsedRows
171 + })
172 + },
173 + submitDetails() {
174 + if (![Link] || ![Link]) {
175 + [Link]()
[Link] 11/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
resources/views/admin/services/[Link]
... ... @@ -127,9 +127,8 @@
127 127 x-data="{
128 128 text: 'Seleccionar Imagen',
129 129 onChange(ev) {
130 - [Link] = [Link]
131 - ? [Link](12)
132 - : 'Seleccionar Imagen'
130 + [Link] = [Link] ? [Link](12)
131 + : 'Seleccionar Imagen'
133 132 }
134 133 }">
135 134 <label for="">Imagen</label>
... ... @@ -185,9 +184,6 @@
185 184 </div>
186 185 </div>
187 186 @endsection
188 - @push('head')
189 - <style> .custom-file-label::after { content: 'Elegir'; } </style>
190 - @endpush
191 187 @push('js')
192 188 <script>
193 189 const services = new Vue({
... ...
resources/views/layouts/includes/[Link]
... ... @@ -2,4 +2,7 @@
2 2 .navbar-brand-img {
3 3 max-height: 4rem !important;
4 4 }
5 + .custom-file-label::after {
6 + content: 'Elegir';
7 +}
5 8 </style>
routes/[Link]
... ... @@ -97,6 +97,8 @@ Route::group([
97 97 'as' => 'invoices.'
98 98 ], function() {
99 99 Route::get('', 'InvoiceController@index')->name('index');
100 + Route::post('upload-invoices', 'InvoiceController@uploadInvoices')->name('upload-invoices');
101 + Route::post('upload-details', 'InvoiceController@uploadDetails')->name('upload-details');
100 102 });
101 103 });
102 104
... ...
[Link] 12/13
1/8/2020 Puede importar facturas desde un csv (d10782f6) · Commits · Guillermo Agudelo / transito-frontend · GitLab
[Link] 13/13