FileAttachmentDynamic = function(filename) {
return new Function("FileAttachment", `return FileAttachment("${filename}")`)(FileAttachment)
}
// Vaihdetaan tekstin väri
color = function(vari) {
if(vari > 0){
return "green"
}else{
return "red"
}
}
// Pyöristys
pyoristys = function(n, places) {
if (!places) return Math.round(n);
const d = 10 ** places;
return Math.round(n * d) / d;
}
//Euromerkintä
eurot = function(number) {
return number.toLocaleString('fi-FI', { style: 'currency', currency: 'EUR',minimumFractionDigits: 0 });
}
// Euromuutoksen laskeminen kertoimella
muutoskerroin = function(x, y) {
return (1+x/100)*y;
}
// Muutosprosentti
muutosprosentti = function(x, y) {
return pyoristys(((x-y)/y)*100,1);
}
// Tuhatjakaja
tuhatjakaja = function(x) {
return x/1000;
}
// Euromuutoksen laskeminen kertoimella
palkkakerroin = function(x, y) {
return 100*((1+x/100)*(1+y/100)-1);
}
// Jako-osuuden asukaskerroin
asukaskerroin = function(x, y) {
return (x/y);
}
// Jako-osuuden veroprosenttikerroin miinus1/miinus3 vuotta miinus 1 vuoden kerroin
veroprosenttikerroin = function(x, y) {
return (x/y);
}
// Kunnan muok. kunnallisvero, alkuvuosi ja loppuvuosi
kunnallisvero_muokkaus = function(kunnallisvero,asukaskerroin,veroprosentti) {
return kunnallisvero*asukaskerroin*veroprosentti;
}
//Tekstimuutokset
fn_nousu_lasku_txt = function(arvo){
if(arvo > 0) {
return "kasvanut"
}
else {
return "laskenut";
}
}
//TARVITAAN KARTOISSA
serialize = {
const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg";
return function serialize(svg) {
svg = svg.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(svg, NodeFilter.SHOW_ELEMENT);
while (walker.nextNode()) {
for (const attr of walker.currentNode.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
}
}
}
svg.setAttributeNS(xmlns, "xmlns", svgns);
svg.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(svg);
return new Blob([string], {type: "image/svg+xml"});
};
}
function toSVG(chart) {
if (chart.nodeName !== "FIGURE") {
return chart;
}
// the chart needs to be in the body if we want to read values, positions, sizes…
document.body.appendChild(chart);
const [x0, y0, width, height] = getBounds([chart]);
const nodes = [];
for (const node of d3
.select(chart)
.selectChildren("h1,h2,h3,div,figcaption,svg")) {
switch (node.nodeName.toLowerCase()) {
case "div":
{
const children = d3.select(node).selectChildren("div,span");
const height = getBounds([node, ...children])[3] + 2;
const svg = d3
.select(chart)
.append("svg")
.attr("width", width)
.attr("height", height);
nodes.push(svg.node());
const swatches = svg
.selectAll()
.data(
Array.from(children, (d) => {
const svg = d3.select(d).select("svg").node();
const bbox = svg.getBBox();
return {
style: window.getComputedStyle(d),
svg,
width: bbox.width,
height: bbox.height,
text: d.textContent,
bounds: getBounds([d])
};
})
)
.join("g")
.attr(
"transform",
(d) => `translate(${d.bounds[0] - x0},${10 + d.bounds[1] - y0})`
);
swatches
.append((d) => d.svg) // "rect")
.attr("width", (d) => d.width)
.attr("height", (d) => d.height)
.attr("y", (d) => `${-parseFloat(d.height) / 2}px`);
swatches
.append("text")
.text((d) => d.text)
.attr("x", (d) => d.width)
.attr("dx", 5)
.attr("dy", "0.38em")
.attr("font-family", (d) => d.style.fontFamily)
.attr("font-size", (d) => d.style.fontSize)
.attr("fill", (d) => d.style.color);
}
break;
case "figcaption":
case "h1":
case "h2":
case "h3":
{
const svg = d3
.select(chart)
.append("svg")
.attr("width", width)
.attr("overflow", "visible");
nodes.push(svg.node());
const children = d3.select(node).selectChildren();
let h = 0;
for (const d of children.size() > 0
? children.selectChildren()
: [node]) {
const style = window.getComputedStyle(d);
const t = svg
.append("g")
.attr("transform", `translate(0,${h})`)
.append(() =>
d3
.select(
Plot.text([d.textContent], {
text: (d) => d,
lineWidth:
(1.06 * parseFloat(style.width)) /
parseFloat(style.fontSize),
lineHeight: 1.2,
frameAnchor: "top-left"
}).plot()
)
.select("text")
.attr("font-family", style.fontFamily)
.attr("font-size", 1.08 * parseFloat(style.fontSize))
.attr("font-weight", style.fontWeight)
.attr("fill", style.color)
.node()
);
h += getBounds([t.node()])[3] + 4;
}
svg.attr("height", h);
}
break;
case "svg":
d3.select(chart).append(() => node);
nodes.push(node);
break;
}
}
return serializeAll(nodes)
.then((blob) => blob.text())
.then((c) => {
document.body.removeChild(chart);
return Object.assign(svg`${c}`, chart);
});
}
// Given an array of SVG elements, composites them into a single SVG element,
// and then serializes the result to a blob.
async function serializeAll(elements, {padding = 10} = {}) {
const fragment = location.href + "#";
let root;
if (elements.length === 1) {
root = elements[0].cloneNode(true); // optimize common case
} else {
const [ox, oy, dx, dy] = getBounds(elements);
root = document.createElementNS(svgns, "svg");
root.setAttribute("width", dx + 2 * padding);
root.setAttribute("height", dy + 2 * padding);
root.setAttribute("viewBox", [-padding, -padding, dx + 2 * padding, dy + 2 * padding]);
for (const element of elements) {
const svg = root.appendChild(element.cloneNode(true));
const { x, y, width, height } = element.getBoundingClientRect();
svg.setAttribute("x", x - ox);
svg.setAttribute("y", y - oy);
svg.setAttribute("width", width);
svg.setAttribute("height", height);
}
}
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
while (walker.nextNode()) {
const node = walker.currentNode;
for (const attr of node.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
}
}
}
root.setAttributeNS(xmlns, "xmlns", svgns);
root.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
const serializer = new XMLSerializer();
const string = serializer.serializeToString(root);
return new Blob([string], { type: "image/svg+xml" });
}
function getBounds(elements) {
let x1 = Infinity;
let y1 = x1;
let x2 = -x1;
let y2 = x2;
for (const element of elements) {
const { x, y, width, height } = element.getBoundingClientRect();
if (x < x1) x1 = x;
if (x + width > x2) x2 = x + width;
if (y < y1) y1 = y;
if (y + height > y2) y2 = y + height;
}
return [x1, y1, x2 - x1, y2 - y1];
}
// based on https://observablehq.com/@gka/cheap-fit-text-to-circle
function lines(text, targetWidth) {
const CHAR_W = {
"a":7,"B":8,"C":8,"c":6,"D":9,"f":4,"G":9,"H":9,"I":3,"i":3,"J":5,"j":3,"K":8,"k":6,
"l":3,"M":11,"m":11,"N":9,"O":9,"P":8,"Q":9,"R":8,"r":4,"S":8,"s":6,"t":4,"U":9,"v":6,
"W":11,"w":9,"x":6,"y":6,"z":5,".":2,",":2,":":2,";":2
};
function measureWidth(text) { return d3.sum(text, char => CHAR_W[char] || CHAR_W["a"]) * 0.8; };
const words = text.split(" ");
let line;
let lineWidth0 = Infinity;
const lines = [];
for (let i = 0, n = words.length; i < n; ++i) {
let lineText1 = (line ? line.text + " " : "") + words[i];
let lineWidth1 = measureWidth(lineText1);
if ((lineWidth0 + lineWidth1) / 2 < targetWidth) {
line.width = lineWidth0 = lineWidth1;
line.text = lineText1;
} else {
lineWidth0 = measureWidth(words[i]);
line = {width: lineWidth0, text: words[i]};
lines.push(line);
}
}
return lines;
}
xmlns = "http://www.w3.org/2000/xmlns/"
xlinkns = "http://www.w3.org/1999/xlink"
svgns = "http://www.w3.org/2000/svg"
Avainsanat
Kuntien talouden neljännesvuosiraportti, talous, yhteistyö, avoin lähdekoodi, Tutkihallintoa.fi, tietojohtaminen
Toimintakulut
Avustukset
Avustukset sisältävät kotitalouksille maksetut tuet ja avustukset samoin kuin yhteisöille myönnetyt tuet ja avustukset. Kotitalouksille myönnettyjä avustuksia ovat mm. toimeentulotuki ja omaishoidon tuki. Yhteisöille myönnettyjä avustuksia ovat mm. yhdistyksille, seuroille ja tiehoitokunnille maksettavat toiminta-avustukset.
Aineet, tarvikkeet, tavarat
Aineisiin, tarvikkeisiin ja tavaroihin luetaan mm. toimisto- ja koulutarvikkeet, kirjallisuus, lääkkeet ja hoitotarvikkeet sekä sähkön hankintamenot.
Henkilöstömenot
Henkilöstömenot sisältävät ennakonpidätyksen alaiset palkat ja palkkiot ja niihin verrattavat kulut sekä välittömästi palkan, palkkion tms. perusteella määräytyvät kulut, kuten eläkekulut, sosiaaliturvamaksut ja lakisääteiset ja vapaaehtoiset henkilövakuutusmaksut.
Muut toimintamenot
Muihin toimintamenoihin sisältyvät mm. vuokrakulut, vahingonkorvaukset ja kunnan maksamat välittömät verot.
Palvelujen ostot
Palvelujen ostot pitää sisällään sekä suoraan asiakkaalle eli kuntalaisille ostetut palvelut, että palvelut, joita kunta käyttää omassa palvelutuotannossaan. Asiakaspalvelut ovat kuntalaisille tarkoitettuja lopputuotepalveluja, joita kunta ostaa muilta palvelujen tuottajilta. Muut kuin asiakaspalvelumaksut ovat kunnan suoritetuotannossa käyttämiä palveluja mm. toimisto- ja asiantuntijapalvelut, ICT-palvelut sekä puhtaanapito- ja pesulapalvelut.(Lähde: Tutkihallintoa.fi 2024)
Toimintakulut
Toimintakulut € per asukas
Toimintakulut jakautuminen
Lähteet
Tutkihallintoa.fi. 2024. Kuntatalouden ABC. Tutkihallintoa.fi. https://www.tutkihallintoa.fi/kuntatalouden-abc/.