Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4391 - Pan-European Reasonableness Check 3.2 Table fix #4395

Draft
wants to merge 8 commits into
base: development
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { PropsCell } from '../props'
const Calculated: React.FC<PropsCell> = (props) => {
const { nodeValue, row } = props

const value = !Objects.isEmpty(nodeValue.raw) ? Numbers.format(nodeValue.raw, row.props?.format?.integer ? 0 : 2) : ''
const value = !Objects.isEmpty(nodeValue?.raw)
? Numbers.format(nodeValue.raw, row.props?.format?.integer ? 0 : 2)
: ''

return <div>{value}</div>
}
Expand Down
5 changes: 3 additions & 2 deletions src/i18n/resources/en/panEuropean/panEuropean.json
Original file line number Diff line number Diff line change
Expand Up @@ -1013,10 +1013,11 @@
"growingStockPerHa": "Growing stock per hectar (1.2a/1.1a) - {{year}}",
"netAnnualIncrementPerHa": "Net annual increment per ha (3.1/1.1a) - {{year}}",
"reasonabilityCheck": "Reasonableness check",
"roundwoodRemovalAsPctOfGrowingStockSupply": "Roundwood removals as percent of growing stock on Forest available for wood supply (3.2 / 1.2a) - {{year}}",
"roundwoodRemovalAsPctOfGrowingStockTotal": "Roundwood removals as percent of growing stock on Forest and Other wooded land (3.2 / 1.2a) - {{year}}",
"roundwoodRemovalAsPctOfGrowingStockSupply": "Roundwood removals as percent of Growing stock on Forest available for wood supply (3.2 / 1.2a)",
"roundwoodRemovalAsPctOfGrowingStockTotal": "Roundwood removals as percent of Growing stock on Forest and Other wooded land (3.2 / 1.2a)",
"soilCarbon": "Soil carbon (1.4a/1.1a) - {{year}}",
"totalWithDamageOverTotal": "Area with damage as a share of Total forest area (2.4/1.1a) - {{year}}",
"unit": "Unit",
"variable": "Variable - Year"
},
"recreationFacilities": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
import { AssessmentNames, ColProps, ColType, RowProps, RowType } from 'meta/assessment'

import { AssessmentController } from 'server/controller/assessment'
import { BaseProtocol, Schemas } from 'server/db'
import { ColRepository } from 'server/repository/assessment/col'
import { RowRepository } from 'server/repository/assessment/row'
import { TableRepository } from 'server/repository/assessment/table'

const years = [2020, 2015, 2010, 2005, 2000, 1990]

const getRoundwoodSupplyYearsCols = (year: number, cycleUuid: string): Array<ColProps> => {
let index = years.indexOf(year)
if (year === 2020) index += 2 // Offset var name and unit '%'
return [
{
// year col
colType: ColType.placeholder,
index,
labels: {
[cycleUuid]: {
label: year.toString(),
},
},
style: {
[cycleUuid]: {
justifyContent: 'center',
},
},
},
{
// Forest col
colType: ColType.placeholder,
index: index + 1,
},
{
// FAWS col
colName: 'FAWS',
colType: ColType.calculated,
calculateFn: {
[cycleUuid]: `table_3_2._of_which_forest_available_for_wood_supply_${year}.net_annual_increment / (table_1_2a._of_which_available_for_wood_supply_${year}.total * 1000)`,
},
index: index + 2,
},
{
// OWL col
colType: ColType.placeholder,
index: index + 3,
},
{
// FOWL col
colType: ColType.placeholder,
index: index + 4,
},
]
}

const getRoundwoodTotalYearsCols = (year: number, cycleUuid: string): Array<ColProps> => {
let index = years.indexOf(year)
if (year === 2020) index += 2 // Offset var name and unit '%'
return [
{
// year col
colType: ColType.placeholder,
index,
labels: {
[cycleUuid]: {
label: year.toString(),
},
},
style: {
[cycleUuid]: {
justifyContent: 'center',
},
},
},
{
// Forest col
colType: ColType.placeholder,
index: index + 1,
},
{
// FAWS col
colType: ColType.placeholder,
index: index + 2,
},
{
// OWL col
colType: ColType.placeholder,
index: index + 3,
},
{
// FOWL col
colType: ColType.calculated,
// TODO: add calculateFn
// colName: '',
// calculateFn: {
// [cycleUuid]: '',
// },
index: index + 4,
},
]
}

export default async (client: BaseProtocol) => {
const { assessment, cycle } = await AssessmentController.getOneWithCycle(
{ assessmentName: AssessmentNames.panEuropean, cycleName: '2025' },
client
)

const cycleUuid = cycle.uuid
const schemaAssessment = Schemas.getName(assessment)
const tableName = 'reasonability_check_3_2'
const table = await TableRepository.getOne({ assessment, cycle, tableName })

// 1. Add new grid template columns & update column names
const gridTemplateColumns = '250px repeat(2, min-content) repeat(4, minmax(min-content, 1fr))'

await client.query(
`update ${schemaAssessment}.table
set props = jsonb_set(
jsonb_set(
jsonb_set(
props,
'{style}',
coalesce(props->'style', '{}'::jsonb),
true
),
'{style,${cycleUuid}}',
$1::jsonb,
true
),
'{columnNames,${cycleUuid}}',
$2::jsonb
)
where props->>'name' = '${tableName}'
`,
[JSON.stringify({ gridTemplateColumns }), JSON.stringify(['unit', 'year', 'forest', 'FAWS', 'OWL', 'FOWL'])]
)

// 2. Delete current cols
await client.query(
`delete from ${schemaAssessment}.col
where id in (
select c.id
from ${schemaAssessment}.col c
join ${schemaAssessment}.row r on c.row_id = r.id
join ${schemaAssessment}.table t on r.table_id = t.id
where t.props->>'name' = '${tableName}'
);`,
[]
)
// 3. Delete current rows
await client.query(
`delete from ${schemaAssessment}.row
where id in (
select r.id
from ${schemaAssessment}.row r
join ${schemaAssessment}.table t on r.table_id = t.id
where t.props->>'name' = '${tableName}'
);`,
[]
)

// 4. Insert new rows and cols for Roundwood Supply and Roundwood Total
const headerRowProps: RowProps = {
index: 'header_0',
type: RowType.header,
}

const headerCols: Array<ColProps> = [
{
colType: ColType.header,
index: 0,
labels: {
[cycle.uuid]: {
key: 'panEuropean.variable',
},
},
},
{
colType: ColType.header,
index: 1,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.unit',
},
},
},
{
colType: ColType.header,
index: 2,
labels: {
[cycle.uuid]: {
key: 'common.year',
},
},
},
{
colType: ColType.header,
index: 3,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.forest',
},
},
},

{
colType: ColType.header,
index: 4,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.FAWS',
},
},
},

{
colType: ColType.header,
index: 5,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.OWL',
},
},
},
{
colType: ColType.header,
index: 6,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.FOWL',
},
},
},
]

const headerRow = await RowRepository.create({ assessment, cycles: [cycle], rowProps: headerRowProps, table }, client)
headerCols.forEach(async (colProps) => {
await ColRepository.create({ assessment, cycles: [cycle], row: headerRow, colProps }, client)
})

const roundwoodSupplyRows: Array<RowProps> = years.map((year, index) => {
return {
index,
label: {
key: 'panEuropean.reasonabilityChecks.roundwoodRemovalAsPctOfGrowingStockSupply',
},
type: RowType.data,
variableName: `roundwoodRemovalAsPctOfGrowingStockSupply_${year}`,
}
})

const roundwoodSupplyVarAndUnitCols: Array<ColProps> = [
{
colType: ColType.header,
index: 0,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.roundwoodRemovalAsPctOfGrowingStockSupply',
},
},
style: {
[cycle.uuid]: {
colSpan: 1,
rowSpan: 6,
},
},
},
{
colType: ColType.placeholder,
index: 1,
labels: {
[cycle.uuid]: {
label: '%',
},
},
style: {
[cycle.uuid]: {
colSpan: 1,
justifyContent: 'center',
rowSpan: 6,
},
},
},
]

const roundwoodTotalRows: Array<RowProps> = years.map((year, index) => {
return {
index,
label: {
key: 'panEuropean.reasonabilityChecks.roundwoodRemovalAsPctOfGrowingStockTotal',
},
type: RowType.data,
variableName: `roundwoodRemovalAsPctOfGrowingStockTotal_${year}`,
}
})

const roundwoodTotalVarAndUnitCols: Array<ColProps> = [
{
colType: ColType.header,
index: 0,
labels: {
[cycle.uuid]: {
key: 'panEuropean.reasonabilityChecks.roundwoodRemovalAsPctOfGrowingStockTotal',
},
},
style: {
[cycle.uuid]: {
colSpan: 1,
rowSpan: 6,
},
},
},
{
colType: ColType.placeholder,
index: 1,
labels: {
[cycle.uuid]: {
label: '%',
},
},
style: {
[cycle.uuid]: {
colSpan: 1,
justifyContent: 'center',
rowSpan: 6,
},
},
},
]

roundwoodSupplyRows.forEach(async (rowProps) => {
const row = await RowRepository.create({ assessment, cycles: [cycle], rowProps, table }, client)
if (rowProps.index === 0) {
roundwoodSupplyVarAndUnitCols.forEach(async (colProps) => {
await ColRepository.create({ assessment, cycles: [cycle], row, colProps }, client)
})
}
const year = years[Number(rowProps.index)]
const yearCols = getRoundwoodSupplyYearsCols(year, cycle.uuid)
yearCols.forEach(async (colProps) => {
await ColRepository.create({ assessment, cycles: [cycle], row, colProps }, client)
})
})

roundwoodTotalRows.forEach(async (rowProps) => {
const row = await RowRepository.create({ assessment, cycles: [cycle], rowProps, table }, client)
if (rowProps.index === 0) {
roundwoodTotalVarAndUnitCols.forEach(async (colProps) => {
await ColRepository.create({ assessment, cycles: [cycle], row, colProps }, client)
})
}
const year = years[Number(rowProps.index)]
const yearCols = getRoundwoodTotalYearsCols(year, cycle.uuid)
yearCols.forEach(async (colProps) => {
await ColRepository.create({ assessment, cycles: [cycle], row, colProps }, client)
})
})

// 5. Generate cache
await AssessmentController.generateMetaCache(client)
}