parse($csvContent); expect($parsed['rows'])->toHaveCount(6) ->and($parsed['meta']['skipped_rows'])->toBe(0); // Row 0: Disposizione Gaia Consorzio $r0 = $parsed['rows'][0]; expect($r0['data']->toDateString())->toBe('2025-12-23') ->and($r0['importo'])->toBe(-1416.00) ->and($r0['causale'])->toBe('BONIFICO') ->and($r0['descrizione'])->toContain('GAIA CONSORZIO') ->and((string) $r0['descrizione_estesa'])->not->toContain('CONDOMINIO VIA OTTAVIANO') ->and($r0['match_data']['tipo'])->toBe('disposizione_bonifico') ->and($r0['match_data']['beneficiario'])->toBe('GAIA CONSORZIO') ->and($r0['match_data']['rif_fattura'])->toBe('FEP 1056') ->and($r0['match_data']['data_fattura'])->toBe('18/12/2025') ->and($r0['match_data']['cod_abi'])->toBe('05034') ->and($r0['match_data']['cod_cab'])->toBe('03214'); // Row 1: Bonifico entrata LAI LISU $r1 = $parsed['rows'][1]; expect($r1['data']->toDateString())->toBe('2025-12-11') ->and($r1['importo'])->toBe(501.00) ->and($r1['causale'])->toBe('BONIFICO') ->and($r1['match_data']['mittente'])->toBe('LAI LISU') ->and($r1['match_data']['dettaglio'])->toBe('Condominio'); // Row 2: CBILL ACEA ATO 2 $r2 = $parsed['rows'][2]; expect($r2['importo'])->toBe(-1351.68) ->and($r2['causale'])->toBe('CBILL') ->and($r2['match_data']['beneficiario'])->toBe('ACEA ATO 2 S.P.A.') ->and($r2['match_data']['codice_cbill'])->toBe('301059900049257704'); // Row 3: F24 Agenzia Entrate $r3 = $parsed['rows'][3]; expect($r3['importo'])->toBe(-995.00) ->and($r3['causale'])->toBe('F24') ->and($r3['match_data']['beneficiario'])->toBe('AGENZIA DELLE ENTRATE') ->and($r3['match_data']['data_incasso'])->toBe('16/12/2025'); // Row 4: Commissioni $r4 = $parsed['rows'][4]; expect($r4['importo'])->toBe(-0.70) ->and($r4['causale'])->toBe('COMMISSIONI') ->and($r4['match_data']['rif_disp'])->toBe('MB0B92378843'); // Row 5: Competenze $r5 = $parsed['rows'][5]; expect($r5['importo'])->toBe(-32.01) ->and($r5['causale'])->toBe('COMPETENZE'); }); test('importer creates clean movements and links supplier', function () { $user = User::first(); if (! $user) { $user = User::factory()->create(['email' => 'admin.test@netgescon.it']); } $adminId = DB::table('amministratori')->insertGetId([ 'user_id' => $user->id, 'nome' => 'Admin', 'cognome' => 'BpmTest', 'codice_amministratore' => 'ADMBPM01', 'created_at' => now(), 'updated_at' => now(), ]); $stabile = Stabile::query()->firstOrCreate( ['codice_stabile' => 'TEST_BPM_0013'], [ 'denominazione' => 'Condominio BPM Test', 'codice_fiscale' => '99999999991', 'amministratore_id' => $adminId, 'indirizzo' => 'Via Test 105', 'cap' => '00192', 'citta' => 'Roma', 'provincia' => 'RM', ] ); $fornitore = Fornitore::query()->firstOrCreate( ['ragione_sociale' => 'Gaia Consorzio'], [ 'amministratore_id' => $adminId, 'partita_iva' => '12345678901', 'codice_fiscale' => '12345678901', ] ); $conto = DatiBancari::query()->firstOrCreate( ['stabile_id' => $stabile->id, 'iban' => 'IT88A0503403214000000000707'], ['denominazione_banca' => 'BANCO BPM', 'numero_conto' => '010300000707'] ); $csvContent = <<importBpmCsvForConto($csvContent, (int) $stabile->id, (int) $conto->id, 'test_bpm.csv', null, true); expect($result['imported'])->toBe(1); $movement = MovimentoBanca::query() ->where('stabile_id', $stabile->id) ->where('conto_id', $conto->id) ->first(); expect($movement)->not->toBeNull() ->and((float) $movement->importo)->toBe(-1416.00) ->and($movement->causale)->toBe('BONIFICO') ->and((int) $movement->fornitore_id)->toBe((int) $fornitore->id) ->and((bool) $movement->da_confermare)->toBeFalse() ->and((string) $movement->beneficiario)->toContain('Gaia Consorzio') ->and((string) $movement->rif_documento)->toContain('FEP 1056') ->and((string) $movement->descrizione_estesa)->not->toContain('"CONDOMINIO TEST"') ->and((string) $movement->descrizione_estesa)->not->toContain('"-1416","EUR"'); });