import { path, propEq, pathEq, groupBy, prop, map, sum, filter, concat, pathOr, toPairs, keys, head, find } from 'ramda' import React, { Component } from 'react' import { connect } from 'react-redux' import { withRouter } from 'react-router' import { Link } from 'react-router-dom' import { formValueSelector } from 'redux-form' import './Results.css' import '../engine/mecanismViews/Somme.css' import { capitalise0, humanFigure } from '../utils' import { nameLeaf, encodeRuleName } from 'Engine/rules' // Filtered variables and rules can't be filtered in a uniform way, for now let paidBy = payer => item => pathEq(['explanation', item.explanation.type, 'dû par'], payer, item) let filteredBy = pathEq(['cotisation', 'dû par']) export let byName = groupBy(prop('dottedName')) export let cell = (branch, payer, analysis) => { let row = byBranch(analysis)[branch], items = filter(item => paidBy(payer)(item) || filteredBy(payer)(item), row), values = map(prop('nodeValue'), items) return sum(values) } export let subCell = (row, name, payer) => { let cells = row[name], items = filter( item => paidBy(payer)(item) || filteredBy(payer)(item), cells ), values = map(prop('nodeValue'), items) return sum(values) } export let byBranch = analysis => { let sal = analysis.cache['contrat salarié . cotisations salariales'] let pat = analysis.cache['contrat salarié . cotisations patronales'] let l1 = sal ? sal.explanation.formule.explanation.explanation : [], l2 = pat ? pat.explanation.formule.explanation.explanation : [], explanations = concat(l1, l2), result = groupBy( pathOr('autre', ['explanation', 'cotisation', 'branche']), explanations ) return result } @withRouter @connect(state => ({ analysis: state.analysis, targetNames: state.targetNames, situationGate: state.situationGate, inversions: formValueSelector('conversation')(state, 'inversions'), done: state.done })) export default class ResultsGrid extends Component { render() { let { analysis, situationGate, targetNames, inversions, done } = this.props if (!done) return null if (!analysis) return null let extract = x => (typeof x == 'string' ? +x : (x && x.nodeValue) || 0), fromEval = name => find(propEq('dottedName', name), analysis.targets), fromDict = name => analysis.cache[name], get = name => extract(situationGate(name) || fromEval(name) || fromDict(name)) let results = byBranch(analysis), brut = get('contrat salarié . salaire brut'), net = get('contrat salarié . salaire net'), total = get('contrat salarié . salaire total') let inversion = path(['contrat salarié ', ' salaire de base'], inversions), relevantSalaries = new Set( targetNames .concat(inversion ? [nameLeaf(inversion)] : []) .concat(['salaire de base']) ) return (
{toPairs(results).map(([branch, values]) => { let props = { key: branch, branch, values, analysis, relevantSalaries } return })} )} {relevantSalaries.has('salaire total') && [ , ]}
{humanFigure(2)(brut)}{' '} Salaire brut
{relevantSalaries.has('salaire net') && ( <> = {humanFigure(2)(net)}{' '} Salaire net = {humanFigure(2)(total)}{' '} Salaire total
) } } class Row extends Component { state = { folded: true } render() { let { branch, values, analysis, relevantSalaries } = this.props, detail = byName(values) let title = name => { let node = head(detail[name]) return node.title || capitalise0(node.name) } let aggregateRow = ( this.setState({ folded: !this.state.folded })} > {capitalise0(branch)}  {this.state.folded ? 'déplier >' : 'replier'} {this.state.folded ? ( <> {relevantSalaries.has('salaire net') && ( <> - {humanFigure(2)(cell(branch, 'salarié', analysis))} )} {relevantSalaries.has('salaire total') && ( <> + {humanFigure(2)(cell(branch, 'employeur', analysis))} )} ) : ( )} ) let detailRows = this.state.folded ? [] : keys(detail).map(subCellName => ( {title(subCellName)} {relevantSalaries.has('salaire net') && ( <> - {humanFigure(2)(subCell(detail, subCellName, 'salarié'))} )} {relevantSalaries.has('salaire total') && ( <> + {humanFigure(2)(subCell(detail, subCellName, 'employeur'))} )} )) // returns an array of return concat([aggregateRow], detailRows) } } // TODO Ce code est beaucoup trop spécifique // C'est essentiellement une copie de Row class ReductionRow extends Component { state = { folded: true } render() { let { relevantSalaries, node } = this.props if (!relevantSalaries.has('salaire total')) return null let value = node ? node.nodeValue : 0 let aggregateRow = ( this.setState({ folded: !this.state.folded })} > Réductions   {this.state.folded ? 'déplier >' : 'replier'} {this.state.folded ? ( <> {relevantSalaries.has('salaire net') && ( <> + {humanFigure(2)(0)} )} {relevantSalaries.has('salaire total') && ( <> - {humanFigure(2)(value)} )} ) : ( )} ) let detailRow = this.state.folded ? null : ( Réductions de cotisations {relevantSalaries.has('salaire net') && ( <> + {humanFigure(2)(0)} )} {relevantSalaries.has('salaire total') && ( <> - {humanFigure(2)(value)} )} ) // returns an array of return [aggregateRow, detailRow] } }