This commit is contained in:
2026-08-20 11:54:23 +02:00
parent cd426cce19
commit 1a3dbaa8c6
4 changed files with 105 additions and 21 deletions
+19 -3
View File
@@ -25,6 +25,22 @@ function personName(data,id){return data.persons?.find(p=>p.id===id)?.name||'Ohn
function personIdsOf(item){return Array.isArray(item?.personIds)?item.personIds.filter(Boolean):typeof item?.personId==='string'&&item.personId?[item.personId]:[];}
function personLabel(data,item){const ids=personIdsOf(item);return ids.length?ids.map(id=>personName(data,id)).join(', '):'Ohne Person';}
function personFactor(item,personId='all'){if(personId==='all')return 1;const ids=personIdsOf(item);return ids.includes(personId)&&ids.length?1/ids.length:0;}
function ownerIdsOf(account){return Array.isArray(account?.ownerPersonIds)?[...new Set(account.ownerPersonIds.filter(Boolean))]:[];}
function transferFactorForAccount(data,item,personId='all',accountId=''){
if(personId==='all')return 1;
const from=data.accounts.find(a=>a.id===item.fromAccountId);const to=data.accounts.find(a=>a.id===item.toAccountId);const selected=data.accounts.find(a=>a.id===accountId);
let ids=[];
if(selected?.ownership==='personal')ids=ownerIdsOf(selected);
else if(item.toAccountId===accountId&&from?.ownership==='personal')ids=ownerIdsOf(from);
else if(item.fromAccountId===accountId&&to?.ownership==='personal')ids=ownerIdsOf(to);
else return personFactor(item,personId);
return ids.includes(personId)?1:0;
}
function transferPersonLabel(data,item){
const from=data.accounts.find(a=>a.id===item.fromAccountId);const to=data.accounts.find(a=>a.id===item.toAccountId);
if(from?.ownership==='personal'&&to?.ownership==='personal'&&ownerIdsOf(from).length&&ownerIdsOf(to).length)return `${ownerIdsOf(from).map(id=>personName(data,id)).join(', ')}${ownerIdsOf(to).map(id=>personName(data,id)).join(', ')}`;
return personLabel(data,item);
}
export function buildAnnualForecast(data,year,accountId,personId='all',includeTransfers=true){
const rows=MONTHS.map((name,index)=>({name,index,income:0,expense:0,transferIn:0,transferOut:0,displayIncome:0,displayExpense:0,balance:0,items:[]}));
@@ -37,7 +53,7 @@ export function buildAnnualForecast(data,year,accountId,personId='all',includeTr
for(let m=0;m<12;m++)if(occursInMonth(item,year,m)){const amount=effectiveAmount(item,year,m)*factor;rows[m].expense+=amount;rows[m].items.push({...item,kind:'expense',reportAmount:amount});}
}
if(includeTransfers) for(const item of data.transfers||[]){
const factor=personFactor(item,personId); if(!factor||(item.fromAccountId!==accountId&&item.toAccountId!==accountId))continue;
const factor=transferFactorForAccount(data,item,personId,accountId); if(!factor||(item.fromAccountId!==accountId&&item.toAccountId!==accountId))continue;
for(let m=0;m<12;m++)if(occursInMonth(item,year,m)){
const amount=Number(item.amount||0)*factor;
if(item.toAccountId===accountId){rows[m].transferIn+=amount;rows[m].items.push({...item,kind:'transfer',direction:'in',reportAmount:amount});}
@@ -52,11 +68,11 @@ function occurrenceRows(data,year,accountId,personId='all',includeTransfers=true
const result=[];
const push=(item,kind,monthIndex,direction='',factor=1)=>{
const amount=(kind==='transfer'?Number(item.amount||0):effectiveAmount(item,year,monthIndex))*factor;
result.push({monthIndex,month:MONTHS[monthIndex],kind,direction,name:item.name,person:personLabel(data,item),category:categoryName(data,item.categoryId),amount});
result.push({monthIndex,month:MONTHS[monthIndex],kind,direction,name:item.name,person:kind==='transfer'?transferPersonLabel(data,item):personLabel(data,item),category:categoryName(data,item.categoryId),amount});
};
for(const item of data.incomes||[]){const factor=personFactor(item,personId);if(factor&&item.accountId===accountId)for(let m=0;m<12;m++)if(occursInMonth(item,year,m))push(item,'income',m,'',factor);}
for(const item of data.expenses||[]){const factor=personFactor(item,personId);if(factor&&item.accountId===accountId)for(let m=0;m<12;m++)if(occursInMonth(item,year,m))push(item,'expense',m,'',factor);}
if(includeTransfers) for(const item of data.transfers||[]){const factor=personFactor(item,personId);if(factor&&(item.fromAccountId===accountId||item.toAccountId===accountId))for(let m=0;m<12;m++)if(occursInMonth(item,year,m)){
if(includeTransfers) for(const item of data.transfers||[]){const factor=transferFactorForAccount(data,item,personId,accountId);if(factor&&(item.fromAccountId===accountId||item.toAccountId===accountId))for(let m=0;m<12;m++)if(occursInMonth(item,year,m)){
if(item.toAccountId===accountId)push(item,'transfer',m,'in',factor);
if(item.fromAccountId===accountId)push(item,'transfer',m,'out',factor);
}}