|
@@ -31,6 +31,7 @@ export default function LeaseDetail() {
|
|
|
const { id } = useParams()
|
|
const { id } = useParams()
|
|
|
const [lease, setLease] = useState(null)
|
|
const [lease, setLease] = useState(null)
|
|
|
const [payments, setPayments] = useState([])
|
|
const [payments, setPayments] = useState([])
|
|
|
|
|
+ const [charges, setCharges] = useState([])
|
|
|
const [revisions, setRevisions] = useState([])
|
|
const [revisions, setRevisions] = useState([])
|
|
|
const [pendingReg, setPendingReg] = useState({ pending: [], total: 0 })
|
|
const [pendingReg, setPendingReg] = useState({ pending: [], total: 0 })
|
|
|
const [showModal, setShowModal] = useState(false)
|
|
const [showModal, setShowModal] = useState(false)
|
|
@@ -85,6 +86,11 @@ export default function LeaseDetail() {
|
|
|
setTenants(ten.data)
|
|
setTenants(ten.data)
|
|
|
setOwners(own.data)
|
|
setOwners(own.data)
|
|
|
setForm(f => ({ ...f, rent_paid: l.data.rent_amount, charges_paid: l.data.charges_amount }))
|
|
setForm(f => ({ ...f, rent_paid: l.data.rent_amount, charges_paid: l.data.charges_amount }))
|
|
|
|
|
+ // Charger les charges récupérables du bien associé au bail
|
|
|
|
|
+ if (l.data.property_id) {
|
|
|
|
|
+ const ch = await api.get(`/charges?property_id=${l.data.property_id}`)
|
|
|
|
|
+ setCharges(ch.data.filter(c => c.recoverable_type === 'recoverable'))
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => { load() }, [id])
|
|
useEffect(() => { load() }, [id])
|
|
@@ -343,6 +349,13 @@ export default function LeaseDetail() {
|
|
|
|
|
|
|
|
{/* Récapitulatif annuel */}
|
|
{/* Récapitulatif annuel */}
|
|
|
{payments.length > 0 && (() => {
|
|
{payments.length > 0 && (() => {
|
|
|
|
|
+ // Charges récupérables réelles par année (depuis la table charges)
|
|
|
|
|
+ const chargesByYear = {}
|
|
|
|
|
+ charges.forEach(c => {
|
|
|
|
|
+ const y = String(c.year)
|
|
|
|
|
+ chargesByYear[y] = (chargesByYear[y] || 0) + Number(c.amount)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
const byYear = {}
|
|
const byYear = {}
|
|
|
payments.forEach(p => {
|
|
payments.forEach(p => {
|
|
|
const y = p.period_year
|
|
const y = p.period_year
|
|
@@ -364,6 +377,7 @@ export default function LeaseDetail() {
|
|
|
<th className="pb-2 pr-6 font-medium">Année</th>
|
|
<th className="pb-2 pr-6 font-medium">Année</th>
|
|
|
<th className="pb-2 pr-6 font-medium text-right">Loyers encaissés</th>
|
|
<th className="pb-2 pr-6 font-medium text-right">Loyers encaissés</th>
|
|
|
<th className="pb-2 pr-6 font-medium text-right">Charges encaissées</th>
|
|
<th className="pb-2 pr-6 font-medium text-right">Charges encaissées</th>
|
|
|
|
|
+ <th className="pb-2 pr-6 font-medium text-right">Charges récupérables réelles</th>
|
|
|
<th className="pb-2 pr-6 font-medium text-right">Régularisations</th>
|
|
<th className="pb-2 pr-6 font-medium text-right">Régularisations</th>
|
|
|
<th className="pb-2 font-medium text-right">Total net</th>
|
|
<th className="pb-2 font-medium text-right">Total net</th>
|
|
|
</tr>
|
|
</tr>
|
|
@@ -371,12 +385,18 @@ export default function LeaseDetail() {
|
|
|
<tbody className="divide-y divide-gray-50">
|
|
<tbody className="divide-y divide-gray-50">
|
|
|
{years.map(y => {
|
|
{years.map(y => {
|
|
|
const d = byYear[y]
|
|
const d = byYear[y]
|
|
|
|
|
+ const recov = chargesByYear[y] || 0
|
|
|
const net = d.rent + d.charges - d.reg
|
|
const net = d.rent + d.charges - d.reg
|
|
|
return (
|
|
return (
|
|
|
<tr key={y} className="hover:bg-gray-50">
|
|
<tr key={y} className="hover:bg-gray-50">
|
|
|
<td className="py-2 pr-6 font-semibold text-gray-800">{y}</td>
|
|
<td className="py-2 pr-6 font-semibold text-gray-800">{y}</td>
|
|
|
<td className="py-2 pr-6 text-right text-gray-700">{fmt(d.rent)}</td>
|
|
<td className="py-2 pr-6 text-right text-gray-700">{fmt(d.rent)}</td>
|
|
|
<td className="py-2 pr-6 text-right text-gray-500">{fmt(d.charges)}</td>
|
|
<td className="py-2 pr-6 text-right text-gray-500">{fmt(d.charges)}</td>
|
|
|
|
|
+ <td className="py-2 pr-6 text-right">
|
|
|
|
|
+ {recov > 0
|
|
|
|
|
+ ? <span className="font-medium text-indigo-700">{fmt(recov)}</span>
|
|
|
|
|
+ : <span className="text-gray-300">—</span>}
|
|
|
|
|
+ </td>
|
|
|
<td className="py-2 pr-6 text-right">
|
|
<td className="py-2 pr-6 text-right">
|
|
|
{d.reg !== 0
|
|
{d.reg !== 0
|
|
|
? <span className={d.reg > 0 ? 'text-green-600' : 'text-orange-600'}>
|
|
? <span className={d.reg > 0 ? 'text-green-600' : 'text-orange-600'}>
|
|
@@ -398,6 +418,9 @@ export default function LeaseDetail() {
|
|
|
<td className="pt-2 pr-6 text-right font-bold text-gray-900">
|
|
<td className="pt-2 pr-6 text-right font-bold text-gray-900">
|
|
|
{fmt(years.reduce((s, y) => s + byYear[y].charges, 0))}
|
|
{fmt(years.reduce((s, y) => s + byYear[y].charges, 0))}
|
|
|
</td>
|
|
</td>
|
|
|
|
|
+ <td className="pt-2 pr-6 text-right font-bold text-indigo-800">
|
|
|
|
|
+ {fmt(years.reduce((s, y) => s + (chargesByYear[y] || 0), 0))}
|
|
|
|
|
+ </td>
|
|
|
<td className="pt-2 pr-6 text-right font-bold text-gray-900">
|
|
<td className="pt-2 pr-6 text-right font-bold text-gray-900">
|
|
|
{fmt(years.reduce((s, y) => s + byYear[y].reg, 0))}
|
|
{fmt(years.reduce((s, y) => s + byYear[y].reg, 0))}
|
|
|
</td>
|
|
</td>
|
|
@@ -412,6 +435,7 @@ export default function LeaseDetail() {
|
|
|
<div className="md:hidden space-y-2">
|
|
<div className="md:hidden space-y-2">
|
|
|
{years.map(y => {
|
|
{years.map(y => {
|
|
|
const d = byYear[y]
|
|
const d = byYear[y]
|
|
|
|
|
+ const recov = chargesByYear[y] || 0
|
|
|
const net = d.rent + d.charges - d.reg
|
|
const net = d.rent + d.charges - d.reg
|
|
|
return (
|
|
return (
|
|
|
<div key={y} className="bg-gray-50 rounded-xl px-4 py-3">
|
|
<div key={y} className="bg-gray-50 rounded-xl px-4 py-3">
|
|
@@ -421,7 +445,12 @@ export default function LeaseDetail() {
|
|
|
</div>
|
|
</div>
|
|
|
<div className="text-xs text-gray-500 space-y-0.5">
|
|
<div className="text-xs text-gray-500 space-y-0.5">
|
|
|
<div className="flex justify-between"><span>Loyers</span><span>{fmt(d.rent)}</span></div>
|
|
<div className="flex justify-between"><span>Loyers</span><span>{fmt(d.rent)}</span></div>
|
|
|
- <div className="flex justify-between"><span>Charges</span><span>{fmt(d.charges)}</span></div>
|
|
|
|
|
|
|
+ <div className="flex justify-between"><span>Charges encaissées</span><span>{fmt(d.charges)}</span></div>
|
|
|
|
|
+ {recov > 0 && (
|
|
|
|
|
+ <div className="flex justify-between font-medium text-indigo-700">
|
|
|
|
|
+ <span>Charges récupérables réelles</span><span>{fmt(recov)}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
{d.reg !== 0 && (
|
|
{d.reg !== 0 && (
|
|
|
<div className={`flex justify-between font-medium ${d.reg > 0 ? 'text-green-600' : 'text-orange-600'}`}>
|
|
<div className={`flex justify-between font-medium ${d.reg > 0 ? 'text-green-600' : 'text-orange-600'}`}>
|
|
|
<span>Régularisations</span>
|
|
<span>Régularisations</span>
|