842 lines
32 KiB
PHP
842 lines
32 KiB
PHP
@extends('admin.layouts.netgescon')
|
|
|
|
@php
|
|
$moduleTitle = 'Nuova Registrazione Contabile';
|
|
$moduleIcon = 'fas fa-plus-circle';
|
|
$moduleBreadcrumb = 'Moduli > Contabilità > Nuova Registrazione';
|
|
@endphp
|
|
|
|
@section('title', $moduleTitle)
|
|
|
|
@section('content')
|
|
@extends('admin.layouts.netgescon')
|
|
|
|
@section('title', 'Nuova Registrazione Contabile')
|
|
|
|
@section('content')
|
|
<div class="content-wrapper">
|
|
<div class="content-header">
|
|
<div class="container-fluid">
|
|
<div class="row mb-2">
|
|
<div class="col-sm-6">
|
|
<h1 class="m-0">Nuova Registrazione Contabile</h1>
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<ol class="breadcrumb float-sm-right">
|
|
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Home</a></li>
|
|
<li class="breadcrumb-item"><a href="{{ route('admin.contabilita.index') }}">Contabilità</a></li>
|
|
<li class="breadcrumb-item active">Nuova Registrazione</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sub-menu tabs come nella pagina stabili -->
|
|
<div class="content-header">
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card card-primary card-tabs">
|
|
<div class="card-header p-0 pt-1">
|
|
<ul class="nav nav-tabs" id="custom-tabs-one-tab" role="tablist">
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
href="{{ route('admin.contabilita.index') }}"
|
|
role="tab">
|
|
<i class="fas fa-list"></i> Registrazioni
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link active"
|
|
href="{{ route('admin.contabilita.create') }}"
|
|
role="tab">
|
|
<i class="fas fa-plus"></i> Nuova Registrazione
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
href="#bilanci"
|
|
role="tab"
|
|
onclick="alert('Funzione in sviluppo')">
|
|
<i class="fas fa-balance-scale"></i> Bilanci
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
href="#reports"
|
|
role="tab"
|
|
onclick="alert('Funzione in sviluppo')">
|
|
<i class="fas fa-chart-bar"></i> Reports
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
href="#piano-conti"
|
|
role="tab"
|
|
onclick="alert('Funzione in sviluppo')">
|
|
<i class="fas fa-list-alt"></i> Piano dei Conti
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
href="#config"
|
|
role="tab"
|
|
onclick="alert('Funzione in sviluppo')">
|
|
<i class="fas fa-cog"></i> Configurazione
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<form id="contabilita-form" method="POST" action="{{ route('admin.contabilita.store') }}">
|
|
@csrf
|
|
|
|
<!-- Dati Generali - Design System NetGescon -->
|
|
<div class="netgescon-card mb-4">
|
|
<div class="netgescon-card-header">
|
|
<div class="netgescon-card-title">
|
|
<i class="fas fa-file-invoice me-2"></i>Dati Generali della Registrazione
|
|
</div>
|
|
</div>
|
|
<div class="netgescon-card-body">
|
|
<div class="row g-4">
|
|
<div class="col-md-6">
|
|
<label for="entry_date" class="netgescon-form-label required">
|
|
<i class="fas fa-calendar me-1 text-primary"></i>
|
|
Data Registrazione
|
|
</label>
|
|
<input type="date"
|
|
class="netgescon-form-control @error('entry_date') is-invalid @enderror"
|
|
id="entry_date"
|
|
name="entry_date"
|
|
value="{{ old('entry_date', date('Y-m-d')) }}"
|
|
required>
|
|
@error('entry_date')
|
|
<div class="netgescon-invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label for="gestione_id" class="netgescon-form-label required">
|
|
<i class="fas fa-building me-1 text-primary"></i>
|
|
Gestione
|
|
</label>
|
|
<select class="netgescon-form-select @error('gestione_id') is-invalid @enderror"
|
|
id="gestione_id"
|
|
name="gestione_id"
|
|
required>
|
|
<option value="">Seleziona una gestione</option>
|
|
@foreach($gestioni as $gestione)
|
|
<option value="{{ $gestione->id_gestione }}"
|
|
{{ old('gestione_id') == $gestione->id_gestione ? 'selected' : '' }}>
|
|
{{ $gestione->anno_gestione }} - {{ $gestione->tipo_gestione }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error('gestione_id')
|
|
<div class="netgescon-invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label for="document_type" class="netgescon-form-label">
|
|
<i class="fas fa-tag me-1 text-primary"></i>
|
|
Tipo Documento
|
|
</label>
|
|
<select class="netgescon-form-select @error('document_type') is-invalid @enderror"
|
|
id="document_type"
|
|
name="document_type">
|
|
<option value="REG" {{ old('document_type', 'REG') == 'REG' ? 'selected' : '' }}>Registrazione Generale</option>
|
|
<option value="FAT" {{ old('document_type') == 'FAT' ? 'selected' : '' }}>Fattura</option>
|
|
<option value="RIC" {{ old('document_type') == 'RIC' ? 'selected' : '' }}>Ricevuta</option>
|
|
<option value="BON" {{ old('document_type') == 'BON' ? 'selected' : '' }}>Bonifico</option>
|
|
<option value="GIR" {{ old('document_type') == 'GIR' ? 'selected' : '' }}>Giroconto</option>
|
|
</select>
|
|
@error('document_type')
|
|
<div class="netgescon-invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label for="document_number" class="netgescon-form-label">
|
|
<i class="fas fa-hashtag me-1 text-primary"></i>
|
|
Numero Documento
|
|
</label>
|
|
<input type="text"
|
|
class="netgescon-form-control @error('document_number') is-invalid @enderror"
|
|
id="document_number"
|
|
name="document_number"
|
|
value="{{ old('document_number') }}"
|
|
placeholder="Numero del documento">
|
|
@error('document_number')
|
|
<div class="netgescon-invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<label for="description" class="netgescon-form-label required">
|
|
<i class="fas fa-comment me-1 text-primary"></i>
|
|
Descrizione
|
|
</label>
|
|
<textarea class="netgescon-form-control @error('description') is-invalid @enderror"
|
|
id="description"
|
|
name="description"
|
|
rows="3"
|
|
required
|
|
placeholder="Descrizione dettagliata della registrazione contabile">{{ old('description') }}</textarea>
|
|
@error('description')
|
|
<div class="netgescon-invalid-feedback">{{ $message }}</div>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Movimenti Contabili - Design System NetGescon -->
|
|
<div class="netgescon-card mb-4">
|
|
<div class="netgescon-card-header">
|
|
<div class="netgescon-card-title">
|
|
<i class="fas fa-exchange-alt me-2"></i>Movimenti Contabili (Partita Doppia)
|
|
</div>
|
|
<div class="netgescon-card-subtitle">
|
|
Il saldo DARE deve essere uguale al saldo AVERE
|
|
</div>
|
|
</div>
|
|
<div class="netgescon-card-body">
|
|
<!-- Riepilogo Saldi -->
|
|
<div class="netgescon-balance-summary mb-4">
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<div class="netgescon-balance-card netgescon-balance-dare">
|
|
<div class="netgescon-balance-label">
|
|
<i class="fas fa-arrow-up me-1"></i>
|
|
Totale DARE
|
|
</div>
|
|
<div class="netgescon-balance-amount" id="total-dare">€ 0,00</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="netgescon-balance-card netgescon-balance-avere">
|
|
<div class="netgescon-balance-label">
|
|
<i class="fas fa-arrow-down me-1"></i>
|
|
Totale AVERE
|
|
</div>
|
|
<div class="netgescon-balance-amount" id="total-avere">€ 0,00</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="netgescon-balance-card netgescon-balance-difference" id="balance-status">
|
|
<div class="netgescon-balance-label">
|
|
<i class="fas fa-balance-scale me-1"></i>
|
|
Differenza
|
|
</div>
|
|
<div class="netgescon-balance-amount" id="balance-difference">€ 0,00</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Movimenti -->
|
|
<div id="movements-container">
|
|
<!-- Movimento 1 -->
|
|
<div class="netgescon-movement-row" data-movement="1">
|
|
<div class="netgescon-movement-header">
|
|
<span class="netgescon-movement-number">Movimento #1</span>
|
|
<button type="button" class="netgescon-btn-remove" onclick="removeMovement(1)" style="display: none;">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="netgescon-form-label required">
|
|
<i class="fas fa-list me-1 text-primary"></i>
|
|
Conto
|
|
</label>
|
|
<select class="netgescon-form-select piano-conti-select"
|
|
name="movements[1][conto_id]"
|
|
required>
|
|
<option value="">Seleziona un conto</option>
|
|
@foreach($pianoConti as $conto)
|
|
<option value="{{ $conto->id }}">
|
|
{{ $conto->mastro }}.{{ $conto->conto }}.{{ $conto->sottoconto }} - {{ $conto->descrizione }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-up me-1 text-success"></i>
|
|
DARE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control dare-amount"
|
|
name="movements[1][dare]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-down me-1 text-danger"></i>
|
|
AVERE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control avere-amount"
|
|
name="movements[1][avere]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end">
|
|
<button type="button"
|
|
class="netgescon-btn netgescon-btn-outline w-100"
|
|
onclick="clearMovement(1)">
|
|
<i class="fas fa-eraser"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Movimento 2 -->
|
|
<div class="netgescon-movement-row" data-movement="2">
|
|
<div class="netgescon-movement-header">
|
|
<span class="netgescon-movement-number">Movimento #2</span>
|
|
<button type="button" class="netgescon-btn-remove" onclick="removeMovement(2)" style="display: none;">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="netgescon-form-label required">
|
|
<i class="fas fa-list me-1 text-primary"></i>
|
|
Conto
|
|
</label>
|
|
<select class="netgescon-form-select piano-conti-select"
|
|
name="movements[2][conto_id]"
|
|
required>
|
|
<option value="">Seleziona un conto</option>
|
|
@foreach($pianoConti as $conto)
|
|
<option value="{{ $conto->id }}">
|
|
{{ $conto->mastro }}.{{ $conto->conto }}.{{ $conto->sottoconto }} - {{ $conto->descrizione }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-up me-1 text-success"></i>
|
|
DARE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control dare-amount"
|
|
name="movements[2][dare]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-down me-1 text-danger"></i>
|
|
AVERE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control avere-amount"
|
|
name="movements[2][avere]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end">
|
|
<button type="button"
|
|
class="netgescon-btn netgescon-btn-outline w-100"
|
|
onclick="clearMovement(2)">
|
|
<i class="fas fa-eraser"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Aggiungi Movimento -->
|
|
<div class="text-center mt-4">
|
|
<button type="button"
|
|
class="netgescon-btn netgescon-btn-outline"
|
|
onclick="addMovement()">
|
|
<i class="fas fa-plus me-2"></i>
|
|
Aggiungi Movimento
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Azioni Form -->
|
|
<div class="netgescon-card">
|
|
<div class="netgescon-card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<div class="netgescon-form-check">
|
|
<input type="checkbox"
|
|
class="netgescon-form-check-input"
|
|
id="status_confirmed"
|
|
name="status"
|
|
value="confirmed"
|
|
{{ old('status') == 'confirmed' ? 'checked' : '' }}>
|
|
<label class="netgescon-form-check-label" for="status_confirmed">
|
|
<i class="fas fa-check-circle me-1 text-success"></i>
|
|
Conferma immediatamente la registrazione
|
|
</label>
|
|
</div>
|
|
<small class="netgescon-form-text">
|
|
Se non spuntato, la registrazione sarà salvata come bozza
|
|
</small>
|
|
</div>
|
|
<div class="col-md-6 text-end">
|
|
<div class="btn-group">
|
|
<button type="submit"
|
|
class="netgescon-btn netgescon-btn-success netgescon-btn-lg"
|
|
id="submit-btn"
|
|
disabled>
|
|
<i class="fas fa-save me-2"></i>
|
|
Salva Registrazione
|
|
</button>
|
|
<a href="{{ route('admin.contabilita.index') }}"
|
|
class="netgescon-btn netgescon-btn-outline">
|
|
<i class="fas fa-times me-1"></i>
|
|
Annulla
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
</div>
|
|
@endsection
|
|
|
|
@push('styles')
|
|
<style>
|
|
/* Design System NetGescon - Contabilità Create Form */
|
|
|
|
/* Required Field Indicator */
|
|
.required::after {
|
|
content: " *";
|
|
color: var(--bs-danger);
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* Balance Summary */
|
|
.netgescon-balance-summary {
|
|
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
border: 2px solid #e2e8f0;
|
|
}
|
|
|
|
.netgescon-balance-card {
|
|
background: white;
|
|
border-radius: 10px;
|
|
padding: 1.25rem;
|
|
text-align: center;
|
|
border: 2px solid;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.netgescon-balance-dare {
|
|
border-color: var(--bs-success);
|
|
}
|
|
|
|
.netgescon-balance-avere {
|
|
border-color: var(--bs-danger);
|
|
}
|
|
|
|
.netgescon-balance-difference {
|
|
border-color: var(--bs-warning);
|
|
}
|
|
|
|
.netgescon-balance-difference.balanced {
|
|
border-color: var(--bs-success);
|
|
background: rgba(22, 163, 74, 0.05);
|
|
}
|
|
|
|
.netgescon-balance-difference.unbalanced {
|
|
border-color: var(--bs-danger);
|
|
background: rgba(239, 68, 68, 0.05);
|
|
}
|
|
|
|
.netgescon-balance-label {
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
color: var(--bs-secondary);
|
|
margin-bottom: 0.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.netgescon-balance-amount {
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
color: var(--bs-dark);
|
|
}
|
|
|
|
/* Movement Rows */
|
|
.netgescon-movement-row {
|
|
background: white;
|
|
border: 2px solid #e2e8f0;
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
position: relative;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.netgescon-movement-row:hover {
|
|
border-color: var(--bs-primary);
|
|
box-shadow: 0 4px 16px rgba(37, 99, 235, 0.1);
|
|
}
|
|
|
|
.netgescon-movement-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
padding-bottom: 0.75rem;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
}
|
|
|
|
.netgescon-movement-number {
|
|
font-weight: 600;
|
|
color: var(--bs-primary);
|
|
font-size: 1.125rem;
|
|
}
|
|
|
|
.netgescon-btn-remove {
|
|
background: rgba(239, 68, 68, 0.1);
|
|
color: var(--bs-danger);
|
|
border: none;
|
|
border-radius: 8px;
|
|
width: 36px;
|
|
height: 36px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.netgescon-btn-remove:hover {
|
|
background: var(--bs-danger);
|
|
color: white;
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
/* Form Validation */
|
|
.netgescon-invalid-feedback {
|
|
display: block;
|
|
width: 100%;
|
|
margin-top: 0.25rem;
|
|
font-size: 0.875rem;
|
|
color: var(--bs-danger);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.is-invalid {
|
|
border-color: var(--bs-danger) !important;
|
|
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1) !important;
|
|
}
|
|
|
|
/* Form Check */
|
|
.netgescon-form-check {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
padding: 1rem;
|
|
background: #f8fafc;
|
|
border-radius: 8px;
|
|
border: 2px solid #e2e8f0;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.netgescon-form-check:hover {
|
|
border-color: var(--bs-primary);
|
|
}
|
|
|
|
.netgescon-form-check-input {
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 2px solid #e2e8f0;
|
|
border-radius: 4px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.netgescon-form-check-input:checked {
|
|
background-color: var(--bs-success);
|
|
border-color: var(--bs-success);
|
|
}
|
|
|
|
.netgescon-form-check-label {
|
|
margin: 0;
|
|
font-weight: 500;
|
|
color: var(--bs-dark);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.netgescon-form-text {
|
|
color: var(--bs-secondary);
|
|
font-style: italic;
|
|
margin-top: 0.25rem;
|
|
}
|
|
|
|
/* Success Button */
|
|
.netgescon-btn-success {
|
|
background: linear-gradient(135deg, var(--bs-success) 0%, #16a34a 100%);
|
|
color: white;
|
|
border: none;
|
|
}
|
|
|
|
.netgescon-btn-success:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 16px rgba(22, 163, 74, 0.3);
|
|
color: white;
|
|
}
|
|
|
|
.netgescon-btn-success:disabled {
|
|
background: #9ca3af;
|
|
color: white;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* Large Button */
|
|
.netgescon-btn-lg {
|
|
padding: 1rem 2rem;
|
|
font-size: 1.125rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Animations */
|
|
@keyframes balanceUpdate {
|
|
0% { transform: scale(1); }
|
|
50% { transform: scale(1.05); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
|
|
.balance-updated {
|
|
animation: balanceUpdate 0.3s ease;
|
|
}
|
|
|
|
/* Responsive Design */
|
|
@media (max-width: 768px) {
|
|
.netgescon-balance-summary .row {
|
|
gap: 1rem;
|
|
}
|
|
|
|
.netgescon-movement-row {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.netgescon-btn-lg {
|
|
padding: 0.75rem 1.5rem;
|
|
font-size: 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@push('scripts')
|
|
<script>
|
|
let movementCounter = 2;
|
|
|
|
function calculateBalance() {
|
|
let totalDare = 0;
|
|
let totalAvere = 0;
|
|
|
|
// Calcola tutti i movimenti DARE
|
|
document.querySelectorAll('.dare-amount').forEach(input => {
|
|
const value = parseFloat(input.value) || 0;
|
|
totalDare += value;
|
|
});
|
|
|
|
// Calcola tutti i movimenti AVERE
|
|
document.querySelectorAll('.avere-amount').forEach(input => {
|
|
const value = parseFloat(input.value) || 0;
|
|
totalAvere += value;
|
|
});
|
|
|
|
// Aggiorna i totali
|
|
document.getElementById('total-dare').textContent = '€ ' + totalDare.toLocaleString('it-IT', {minimumFractionDigits: 2});
|
|
document.getElementById('total-avere').textContent = '€ ' + totalAvere.toLocaleString('it-IT', {minimumFractionDigits: 2});
|
|
|
|
// Calcola la differenza
|
|
const difference = Math.abs(totalDare - totalAvere);
|
|
document.getElementById('balance-difference').textContent = '€ ' + difference.toLocaleString('it-IT', {minimumFractionDigits: 2});
|
|
|
|
// Aggiorna lo stato del bilanciamento
|
|
const balanceStatus = document.getElementById('balance-status');
|
|
const submitBtn = document.getElementById('submit-btn');
|
|
|
|
if (difference === 0 && totalDare > 0 && totalAvere > 0) {
|
|
balanceStatus.className = 'netgescon-balance-card netgescon-balance-difference balanced';
|
|
submitBtn.disabled = false;
|
|
} else {
|
|
balanceStatus.className = 'netgescon-balance-card netgescon-balance-difference unbalanced';
|
|
submitBtn.disabled = true;
|
|
}
|
|
|
|
// Animazione di aggiornamento
|
|
balanceStatus.classList.add('balance-updated');
|
|
setTimeout(() => {
|
|
balanceStatus.classList.remove('balance-updated');
|
|
}, 300);
|
|
}
|
|
|
|
function addMovement() {
|
|
movementCounter++;
|
|
|
|
const container = document.getElementById('movements-container');
|
|
const movementHtml = `
|
|
<div class="netgescon-movement-row" data-movement="${movementCounter}">
|
|
<div class="netgescon-movement-header">
|
|
<span class="netgescon-movement-number">Movimento #${movementCounter}</span>
|
|
<button type="button" class="netgescon-btn-remove" onclick="removeMovement(${movementCounter})">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="netgescon-form-label required">
|
|
<i class="fas fa-list me-1 text-primary"></i>
|
|
Conto
|
|
</label>
|
|
<select class="netgescon-form-select piano-conti-select"
|
|
name="movements[${movementCounter}][conto_id]"
|
|
required>
|
|
<option value="">Seleziona un conto</option>
|
|
@foreach($pianoConti as $conto)
|
|
<option value="{{ $conto->id }}">
|
|
{{ $conto->mastro }}.{{ $conto->conto }}.{{ $conto->sottoconto }} - {{ $conto->descrizione }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-up me-1 text-success"></i>
|
|
DARE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control dare-amount"
|
|
name="movements[${movementCounter}][dare]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="netgescon-form-label">
|
|
<i class="fas fa-arrow-down me-1 text-danger"></i>
|
|
AVERE
|
|
</label>
|
|
<input type="number"
|
|
class="netgescon-form-control avere-amount"
|
|
name="movements[${movementCounter}][avere]"
|
|
step="0.01"
|
|
min="0"
|
|
placeholder="0,00"
|
|
onchange="calculateBalance()">
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end">
|
|
<button type="button"
|
|
class="netgescon-btn netgescon-btn-outline w-100"
|
|
onclick="clearMovement(${movementCounter})">
|
|
<i class="fas fa-eraser"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
container.insertAdjacentHTML('beforeend', movementHtml);
|
|
updateRemoveButtons();
|
|
}
|
|
|
|
function removeMovement(movementId) {
|
|
const movement = document.querySelector(`[data-movement="${movementId}"]`);
|
|
if (movement) {
|
|
movement.remove();
|
|
calculateBalance();
|
|
updateRemoveButtons();
|
|
}
|
|
}
|
|
|
|
function clearMovement(movementId) {
|
|
const movement = document.querySelector(`[data-movement="${movementId}"]`);
|
|
if (movement) {
|
|
movement.querySelector('.piano-conti-select').selectedIndex = 0;
|
|
movement.querySelector('.dare-amount').value = '';
|
|
movement.querySelector('.avere-amount').value = '';
|
|
calculateBalance();
|
|
}
|
|
}
|
|
|
|
function updateRemoveButtons() {
|
|
const movements = document.querySelectorAll('.netgescon-movement-row');
|
|
movements.forEach((movement, index) => {
|
|
const removeBtn = movement.querySelector('.netgescon-btn-remove');
|
|
if (movements.length > 2) {
|
|
removeBtn.style.display = 'flex';
|
|
} else {
|
|
removeBtn.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
function clearForm() {
|
|
if (confirm('Sei sicuro di voler pulire tutti i campi del form?')) {
|
|
document.getElementById('contabilita-form').reset();
|
|
calculateBalance();
|
|
}
|
|
}
|
|
|
|
// Validazione DARE/AVERE - un solo campo per movimento può essere valorizzato
|
|
document.addEventListener('change', function(e) {
|
|
if (e.target.classList.contains('dare-amount')) {
|
|
const movementRow = e.target.closest('.netgescon-movement-row');
|
|
const avereInput = movementRow.querySelector('.avere-amount');
|
|
if (e.target.value && parseFloat(e.target.value) > 0) {
|
|
avereInput.value = '';
|
|
}
|
|
calculateBalance();
|
|
}
|
|
|
|
if (e.target.classList.contains('avere-amount')) {
|
|
const movementRow = e.target.closest('.netgescon-movement-row');
|
|
const dareInput = movementRow.querySelector('.dare-amount');
|
|
if (e.target.value && parseFloat(e.target.value) > 0) {
|
|
dareInput.value = '';
|
|
}
|
|
calculateBalance();
|
|
}
|
|
});
|
|
|
|
// Inizializza la pagina
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
calculateBalance();
|
|
updateRemoveButtons();
|
|
});
|
|
</script>
|
|
@endpush
|