Initial contribution (#14529)
Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
aae63e9488
commit
4d47f33012
@ -402,6 +402,7 @@
|
|||||||
/bundles/org.openhab.transform.regex/ @openhab/add-ons-maintainers
|
/bundles/org.openhab.transform.regex/ @openhab/add-ons-maintainers
|
||||||
/bundles/org.openhab.transform.rollershutterposition/ @jsjames
|
/bundles/org.openhab.transform.rollershutterposition/ @jsjames
|
||||||
/bundles/org.openhab.transform.scale/ @clinique
|
/bundles/org.openhab.transform.scale/ @clinique
|
||||||
|
/bundles/org.openhab.transform.vat/ @jlaur
|
||||||
/bundles/org.openhab.transform.xpath/ @openhab/add-ons-maintainers
|
/bundles/org.openhab.transform.xpath/ @openhab/add-ons-maintainers
|
||||||
/bundles/org.openhab.transform.xslt/ @openhab/add-ons-maintainers
|
/bundles/org.openhab.transform.xslt/ @openhab/add-ons-maintainers
|
||||||
/bundles/org.openhab.voice.googlestt/ @GiviMAD
|
/bundles/org.openhab.voice.googlestt/ @GiviMAD
|
||||||
|
|||||||
@ -2006,6 +2006,11 @@
|
|||||||
<artifactId>org.openhab.transform.scale</artifactId>
|
<artifactId>org.openhab.transform.scale</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.transform.vat</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.transform.xpath</artifactId>
|
<artifactId>org.openhab.transform.xpath</artifactId>
|
||||||
|
|||||||
13
bundles/org.openhab.transform.vat/NOTICE
Normal file
13
bundles/org.openhab.transform.vat/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
||||||
41
bundles/org.openhab.transform.vat/README.md
Normal file
41
bundles/org.openhab.transform.vat/README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# VAT Transformation Service
|
||||||
|
|
||||||
|
The VAT Transformation Service adds VAT (Value-Added Tax) to a given input amount.
|
||||||
|
The input string must be either an ISO 3166 alpha-2 country code or a percentage, i.e. numerical format.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Display
|
||||||
|
|
||||||
|
```java
|
||||||
|
Number CurrentSpotPrice "Current Spot Price incl. VAT [VAT(12.5):%s]" <price>
|
||||||
|
```
|
||||||
|
|
||||||
|
### In a Rule
|
||||||
|
|
||||||
|
Add Danish VAT to price:
|
||||||
|
|
||||||
|
```java
|
||||||
|
var Number price = 499
|
||||||
|
logInfo("Price", "Price incl. VAT: " + transform("VAT", "DK", price.toString))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage as a Profile
|
||||||
|
|
||||||
|
The functionality of this `TransformationService` can also be used in a `Profile` on an `ItemChannelLink`.
|
||||||
|
This is the most powerful usage since VAT will be added without providing any explicit country code, percentage or configuration.
|
||||||
|
To use this, an `.items` file can be configured as follows:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Number CurrentSpotPrice "Current Spot Price" <price> { channel="<channelUID>" [profile="transform:VAT"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
To override VAT percentage for configured system country:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Number CurrentSpotPrice "Current Spot Price" <price> { channel="<channelUID>" [profile="transform:VAT", percentage="12.5"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
If VAT is not known for the configured country or the provided percentage is invalid, the default is 0%, so the input value will be put into the transformation without any changes.
|
||||||
|
|
||||||
|
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
|
||||||
17
bundles/org.openhab.transform.vat/pom.xml
Normal file
17
bundles/org.openhab.transform.vat/pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||||
|
<version>4.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.transform.vat</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: Transformation Service :: Value-Added Tax</name>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<features name="org.openhab.transform.vat-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||||
|
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||||
|
|
||||||
|
<feature name="openhab-transformation-vat" description="Value-Added Tax Transformation" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<bundle start-level="75">mvn:org.openhab.addons.bundles/org.openhab.transform.vat/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.transform.vat.internal;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||||
|
import org.openhab.core.transform.TransformationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VATTransformationConstants} class defines constants
|
||||||
|
* used across the whole profile.
|
||||||
|
*
|
||||||
|
* @author Jacob Laursen - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VATTransformationConstants {
|
||||||
|
|
||||||
|
public static final ProfileTypeUID PROFILE_TYPE_UID = new ProfileTypeUID(
|
||||||
|
TransformationService.TRANSFORM_PROFILE_SCOPE, "VAT");
|
||||||
|
|
||||||
|
public static final Map<String, String> RATES = Map.ofEntries(
|
||||||
|
// European Union countries
|
||||||
|
Map.entry("AT", "20"), // Austria
|
||||||
|
Map.entry("BE", "21"), // Belgium
|
||||||
|
Map.entry("BG", "20"), // Bulgaria
|
||||||
|
Map.entry("HR", "25"), // Croatia
|
||||||
|
Map.entry("CY", "19"), // Cyprus
|
||||||
|
Map.entry("CZ", "21"), // Czech Republic
|
||||||
|
Map.entry("DK", "25"), // Denmark
|
||||||
|
Map.entry("EE", "20"), // Estonia
|
||||||
|
Map.entry("FI", "24"), // Finland
|
||||||
|
Map.entry("FR", "20"), // France
|
||||||
|
Map.entry("DE", "19"), // Germany
|
||||||
|
Map.entry("GR", "24"), // Greece
|
||||||
|
Map.entry("HU", "27"), // Hungary
|
||||||
|
Map.entry("IE", "23"), // Ireland
|
||||||
|
Map.entry("IT", "22"), // Italy
|
||||||
|
Map.entry("LV", "21"), // Latvia
|
||||||
|
Map.entry("LT", "21"), // Lithuania
|
||||||
|
Map.entry("LU", "17"), // Luxembourg
|
||||||
|
Map.entry("MT", "18"), // Malta
|
||||||
|
Map.entry("NL", "21"), // Netherlands
|
||||||
|
Map.entry("PL", "23"), // Poland
|
||||||
|
Map.entry("PT", "23"), // Portugal
|
||||||
|
Map.entry("RO", "19"), // Romania
|
||||||
|
Map.entry("SK", "20"), // Slovakia
|
||||||
|
Map.entry("SI", "22"), // Slovenia
|
||||||
|
Map.entry("ES", "21"), // Spain
|
||||||
|
Map.entry("SE", "25"), // Sweden
|
||||||
|
|
||||||
|
// Non-European Union countries
|
||||||
|
Map.entry("AL", "20"), // Albania
|
||||||
|
Map.entry("DZ", "19"), // Algeria
|
||||||
|
Map.entry("AD", "4.5"), // Andorra
|
||||||
|
Map.entry("AO", "14"), // Angola
|
||||||
|
Map.entry("AG", "15"), // Antigua and Barbuda
|
||||||
|
Map.entry("AR", "21"), // Argentina
|
||||||
|
Map.entry("AM", "20"), // Armenia
|
||||||
|
Map.entry("AU", "10"), // Australia
|
||||||
|
Map.entry("AZ", "18"), // Azerbaijan
|
||||||
|
Map.entry("BS", "12"), // Bahamas
|
||||||
|
Map.entry("BH", "10"), // Bahrain
|
||||||
|
Map.entry("BD", "15"), // Bangladesh
|
||||||
|
Map.entry("BB", "17.5"), // Barbados
|
||||||
|
Map.entry("BY", "20"), // Belarus
|
||||||
|
Map.entry("BZ", "12.5"), // Belize
|
||||||
|
Map.entry("BJ", "18"), // Benin
|
||||||
|
Map.entry("BO", "13"), // Bolivia
|
||||||
|
Map.entry("BA", "17"), // Bosnia and Herzegovina
|
||||||
|
Map.entry("BW", "12"), // Botswana
|
||||||
|
Map.entry("BR", "20"), // Brazil
|
||||||
|
Map.entry("BF", "18"), // Burkina Faso
|
||||||
|
Map.entry("BI", "18"), // Burundi
|
||||||
|
Map.entry("KH", "10"), // Cambodia
|
||||||
|
Map.entry("CM", "19.25"), // Cameroon
|
||||||
|
Map.entry("CA", "5"), // Canada
|
||||||
|
Map.entry("CV", "15"), // Cape Verde
|
||||||
|
Map.entry("CF", "19"), // Central African Republic
|
||||||
|
Map.entry("TD", "18"), // Chad
|
||||||
|
Map.entry("CL", "19"), // Chile
|
||||||
|
Map.entry("CN", "13"), // China
|
||||||
|
Map.entry("CO", "19"), // Colombia
|
||||||
|
Map.entry("CR", "13"), // Costa Rica
|
||||||
|
Map.entry("CD", "16"), // Democratic Republic of the Congo
|
||||||
|
Map.entry("DM", "15"), // Dominica
|
||||||
|
Map.entry("DO", "18"), // Dominican Republic
|
||||||
|
Map.entry("EC", "12"), // Ecuador
|
||||||
|
Map.entry("EG", "14"), // Egypt
|
||||||
|
Map.entry("SV", "13"), // El Salvador
|
||||||
|
Map.entry("GQ", "15"), // Equatorial Guinea
|
||||||
|
Map.entry("ET", "15"), // Ethiopia
|
||||||
|
Map.entry("FO", "25"), // Faroe Islands
|
||||||
|
Map.entry("FJ", "15"), // Fiji
|
||||||
|
Map.entry("GA", "18"), // Gabon
|
||||||
|
Map.entry("GM", "15"), // Gambia
|
||||||
|
Map.entry("GE", "18"), // Georgia
|
||||||
|
Map.entry("GH", "15"), // Ghana
|
||||||
|
Map.entry("GD", "15"), // Grenada
|
||||||
|
Map.entry("GT", "12"), // Guatemala
|
||||||
|
Map.entry("GN", "18"), // Guinea
|
||||||
|
Map.entry("GW", "15"), // Guinea-Bissau
|
||||||
|
Map.entry("GY", "16"), // Guyana
|
||||||
|
Map.entry("HT", "10"), // Haiti
|
||||||
|
Map.entry("HN", "15"), // Honduras
|
||||||
|
Map.entry("IS", "24"), // Iceland
|
||||||
|
Map.entry("IN", "5.5"), // India
|
||||||
|
Map.entry("ID", "11"), // Indonesia
|
||||||
|
Map.entry("IR", "9"), // Iran
|
||||||
|
Map.entry("IM", "20"), // Isle of Man
|
||||||
|
Map.entry("IL", "17"), // Israel
|
||||||
|
Map.entry("CI", "18"), // Ivory Coast
|
||||||
|
Map.entry("JM", "12.5"), // Jamaica
|
||||||
|
Map.entry("JP", "10"), // Japan
|
||||||
|
Map.entry("JE", "5"), // Jersey
|
||||||
|
Map.entry("JO", "16"), // Jordan
|
||||||
|
Map.entry("KZ", "12"), // Kazakhstan
|
||||||
|
Map.entry("KE", "16"), // Kenya
|
||||||
|
Map.entry("KG", "20"), // Kyrgyzstan
|
||||||
|
Map.entry("LA", "10"), // Laos
|
||||||
|
Map.entry("LB", "11"), // Lebanon
|
||||||
|
Map.entry("LS", "14"), // Lesotho
|
||||||
|
Map.entry("LI", "7.7"), // Liechtenstein
|
||||||
|
Map.entry("MG", "20"), // Madagascar
|
||||||
|
Map.entry("MW", "16.5"), // Malawi
|
||||||
|
Map.entry("MY", "6"), // Malaysia
|
||||||
|
Map.entry("MV", "6"), // Maldives
|
||||||
|
Map.entry("ML", "18"), // Mali
|
||||||
|
Map.entry("MR", "14"), // Mauritania
|
||||||
|
Map.entry("MU", "15"), // Mauritius
|
||||||
|
Map.entry("MX", "16"), // Mexico
|
||||||
|
Map.entry("MD", "20"), // Moldova
|
||||||
|
Map.entry("MC", "19.6"), // Monaco
|
||||||
|
Map.entry("MN", "10"), // Mongolia
|
||||||
|
Map.entry("ME", "21"), // Montenegro
|
||||||
|
Map.entry("MA", "20"), // Morocco
|
||||||
|
Map.entry("MZ", "17"), // Mozambique
|
||||||
|
Map.entry("NA", "15"), // Namibia
|
||||||
|
Map.entry("NP", "13"), // Nepal
|
||||||
|
Map.entry("NZ", "15"), // New Zealand
|
||||||
|
Map.entry("NI", "15"), // Nicaragua
|
||||||
|
Map.entry("NE", "19"), // Niger
|
||||||
|
Map.entry("NG", "7.5"), // Nigeria
|
||||||
|
Map.entry("NU", "5"), // Niue
|
||||||
|
Map.entry("MK", "18"), // North Macedonia
|
||||||
|
Map.entry("NO", "25"), // Norway
|
||||||
|
Map.entry("PK", "17"), // Pakistan
|
||||||
|
Map.entry("PW", "10"), // Palau
|
||||||
|
Map.entry("PS", "16"), // Palestine
|
||||||
|
Map.entry("PA", "7"), // Panama
|
||||||
|
Map.entry("PG", "10"), // Papua New Guinea
|
||||||
|
Map.entry("PY", "10"), // Paraguay
|
||||||
|
Map.entry("PE", "18"), // Peru
|
||||||
|
Map.entry("PH", "12"), // Philippines
|
||||||
|
Map.entry("CG", "16"), // Republic of Congo
|
||||||
|
Map.entry("RU", "20"), // Russia
|
||||||
|
Map.entry("RW", "18"), // Rwanda
|
||||||
|
Map.entry("KN", "17"), // Saint Kitts and Nevis
|
||||||
|
Map.entry("VC", "15"), // Saint Vincent and the Grenadines
|
||||||
|
Map.entry("WS", "15"), // Samoa
|
||||||
|
Map.entry("SA", "15"), // Saudi Arabia
|
||||||
|
Map.entry("SN", "18"), // Senegal
|
||||||
|
Map.entry("RS", "20"), // Serbia
|
||||||
|
Map.entry("SC", "15"), // Seychelles
|
||||||
|
Map.entry("SL", "15"), // Sierra Leone
|
||||||
|
Map.entry("SG", "8"), // Singapore
|
||||||
|
Map.entry("ZA", "15"), // South Africa
|
||||||
|
Map.entry("KR", "10"), // South Korea
|
||||||
|
Map.entry("LK", "12"), // Sri Lanka
|
||||||
|
Map.entry("SD", "17"), // Sudan
|
||||||
|
Map.entry("CH", "7.7"), // Switzerland
|
||||||
|
Map.entry("TW", "5"), // Taiwan
|
||||||
|
Map.entry("TJ", "20"), // Tajikistan
|
||||||
|
Map.entry("TZ", "18"), // Tanzania
|
||||||
|
Map.entry("TH", "10"), // Thailand
|
||||||
|
Map.entry("TG", "18"), // Togo
|
||||||
|
Map.entry("TO", "15"), // Tonga
|
||||||
|
Map.entry("TT", "12.5"), // Trinidad and Tobago
|
||||||
|
Map.entry("TN", "18"), // Tunisia
|
||||||
|
Map.entry("TR", "18"), // Turkey
|
||||||
|
Map.entry("TM", "15"), // Turkmenistan
|
||||||
|
Map.entry("UG", "18"), // Uganda
|
||||||
|
Map.entry("UA", "20"), // Ukraine
|
||||||
|
Map.entry("AE", "5"), // United Arab Emirates
|
||||||
|
Map.entry("GB", "20"), // United Kingdom
|
||||||
|
Map.entry("UY", ""), // Uruguay
|
||||||
|
Map.entry("UZ", "12"), // Uzbekistan
|
||||||
|
Map.entry("VU", "13"), // Vanuatu
|
||||||
|
Map.entry("VN", "10"), // Vietnam
|
||||||
|
Map.entry("VE", "12"), // Venezuela
|
||||||
|
Map.entry("ZM", "16"), // Zambia
|
||||||
|
Map.entry("ZW", "15") // Zimbabwe
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.transform.vat.internal;
|
||||||
|
|
||||||
|
import static org.openhab.transform.vat.internal.VATTransformationConstants.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
import org.openhab.core.transform.TransformationException;
|
||||||
|
import org.openhab.core.transform.TransformationService;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This {@link TransformationService} adds VAT to the input according to configured country.
|
||||||
|
*
|
||||||
|
* @author Jacob Laursen - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = { TransformationService.class }, property = { "openhab.transform=VAT" })
|
||||||
|
public class VATTransformationService implements TransformationService {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VATTransformationService.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String transform(String valueString, String sourceString) throws TransformationException {
|
||||||
|
QuantityType<?> source;
|
||||||
|
try {
|
||||||
|
source = new QuantityType<>(sourceString);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.warn("Input value '{}' could not be converted to a valid number", sourceString);
|
||||||
|
throw new TransformationException("VAT Transformation can only be used with numeric inputs", e);
|
||||||
|
}
|
||||||
|
BigDecimal value;
|
||||||
|
try {
|
||||||
|
value = new BigDecimal(valueString);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
String rate = RATES.get(valueString);
|
||||||
|
if (rate == null) {
|
||||||
|
logger.warn("Input value '{}' could not be converted to a valid number or country code", valueString);
|
||||||
|
throw new TransformationException("VAT Transformation can only be used with numeric inputs", e);
|
||||||
|
}
|
||||||
|
value = new BigDecimal(rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addVAT(source, value).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuantityType<?> addVAT(QuantityType<?> source, BigDecimal percentage) {
|
||||||
|
return source.multiply(percentage.divide(new BigDecimal("100")).add(BigDecimal.ONE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.transform.vat.internal.config;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VATConfig} class contains the parameters for the VAT transformation.
|
||||||
|
*
|
||||||
|
* @author Jacob Laursen - initial contribution
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VATConfig {
|
||||||
|
public String percentage = "";
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.transform.vat.internal.profile;
|
||||||
|
|
||||||
|
import static org.openhab.transform.vat.internal.VATTransformationConstants.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.i18n.LocaleProvider;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileContext;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||||
|
import org.openhab.core.thing.profiles.StateProfile;
|
||||||
|
import org.openhab.core.transform.TransformationException;
|
||||||
|
import org.openhab.core.transform.TransformationHelper;
|
||||||
|
import org.openhab.core.transform.TransformationService;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.Type;
|
||||||
|
import org.openhab.transform.vat.internal.config.VATConfig;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile to offer the {@link VATTransformationService} on an ItemChannelLink.
|
||||||
|
*
|
||||||
|
* @author Jacob Laursen - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class VATTransformationProfile implements StateProfile {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(VATTransformationProfile.class);
|
||||||
|
|
||||||
|
private final ProfileCallback callback;
|
||||||
|
private final TransformationService service;
|
||||||
|
private final LocaleProvider localeProvider;
|
||||||
|
|
||||||
|
private VATConfig configuration;
|
||||||
|
|
||||||
|
public VATTransformationProfile(final ProfileCallback callback, final TransformationService service,
|
||||||
|
final ProfileContext context, LocaleProvider localeProvider) {
|
||||||
|
this.callback = callback;
|
||||||
|
this.service = service;
|
||||||
|
this.localeProvider = localeProvider;
|
||||||
|
this.configuration = context.getConfiguration().as(VATConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProfileTypeUID getProfileTypeUID() {
|
||||||
|
return PROFILE_TYPE_UID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCommandFromItem(Command command) {
|
||||||
|
callback.handleCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateUpdateFromItem(State state) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCommandFromHandler(Command command) {
|
||||||
|
callback.sendCommand((Command) transformState(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateUpdateFromHandler(State state) {
|
||||||
|
callback.sendUpdate((State) transformState(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type transformState(Type state) {
|
||||||
|
String result = state.toFullString();
|
||||||
|
try {
|
||||||
|
result = TransformationHelper.transform(service, getVATPercentage(), "%s", result);
|
||||||
|
} catch (TransformationException e) {
|
||||||
|
logger.warn("Could not apply '{}' transformation on state '{}' with value '{}'.", PROFILE_TYPE_UID.getId(),
|
||||||
|
state, getVATPercentage());
|
||||||
|
}
|
||||||
|
Type resultType = state;
|
||||||
|
if (result != null) {
|
||||||
|
if (state instanceof DecimalType) {
|
||||||
|
resultType = DecimalType.valueOf(result);
|
||||||
|
} else if (state instanceof QuantityType) {
|
||||||
|
resultType = QuantityType.valueOf(result);
|
||||||
|
}
|
||||||
|
logger.debug("Transformed '{}' into '{}'", state, resultType);
|
||||||
|
}
|
||||||
|
return resultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVATPercentage() {
|
||||||
|
if (!configuration.percentage.isBlank()) {
|
||||||
|
return getOverriddenVAT();
|
||||||
|
}
|
||||||
|
|
||||||
|
String country = localeProvider.getLocale().getCountry();
|
||||||
|
String rate = RATES.get(country);
|
||||||
|
if (rate == null) {
|
||||||
|
logger.warn("No VAT rate for country {}", country);
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOverriddenVAT() {
|
||||||
|
String percentage = configuration.percentage.trim();
|
||||||
|
if (percentage.endsWith("%")) {
|
||||||
|
percentage = percentage.substring(0, percentage.length() - 1).trim();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(percentage).toString();
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.warn("{} is not a valid percentage", percentage);
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.transform.vat.internal.profile;
|
||||||
|
|
||||||
|
import static org.openhab.transform.vat.internal.VATTransformationConstants.PROFILE_TYPE_UID;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.i18n.LocaleProvider;
|
||||||
|
import org.openhab.core.i18n.LocalizedKey;
|
||||||
|
import org.openhab.core.library.CoreItemFactory;
|
||||||
|
import org.openhab.core.thing.profiles.Profile;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileContext;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileFactory;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileType;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileTypeProvider;
|
||||||
|
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||||
|
import org.openhab.core.thing.profiles.i18n.ProfileTypeI18nLocalizationService;
|
||||||
|
import org.openhab.core.transform.TransformationService;
|
||||||
|
import org.openhab.core.util.BundleResolver;
|
||||||
|
import org.osgi.framework.Bundle;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VATTransformationProfileFactory} is responsible for creating profiles.
|
||||||
|
*
|
||||||
|
* @author Jacob Laursen - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = { ProfileFactory.class, ProfileTypeProvider.class })
|
||||||
|
public class VATTransformationProfileFactory implements ProfileFactory, ProfileTypeProvider {
|
||||||
|
|
||||||
|
private final LocaleProvider localeProvider;
|
||||||
|
private final ProfileTypeI18nLocalizationService profileTypeI18nLocalizationService;
|
||||||
|
private final Map<LocalizedKey, ProfileType> localizedProfileTypeCache = new ConcurrentHashMap<>();
|
||||||
|
private final Bundle bundle;
|
||||||
|
|
||||||
|
private @NonNullByDefault({}) TransformationService transformationService;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public VATTransformationProfileFactory(final @Reference LocaleProvider localeProvider,
|
||||||
|
final @Reference ProfileTypeI18nLocalizationService profileTypeI18nLocalizationService,
|
||||||
|
final @Reference BundleResolver bundleResolver) {
|
||||||
|
this.localeProvider = localeProvider;
|
||||||
|
this.profileTypeI18nLocalizationService = profileTypeI18nLocalizationService;
|
||||||
|
this.bundle = bundleResolver.resolveBundle(VATTransformationProfileFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
|
||||||
|
return Set.of(createLocalizedProfileType(ProfileTypeBuilder.newState(PROFILE_TYPE_UID, PROFILE_TYPE_UID.getId())
|
||||||
|
.withSupportedItemTypes(CoreItemFactory.NUMBER).build(), locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback,
|
||||||
|
ProfileContext profileContext) {
|
||||||
|
return new VATTransformationProfile(callback, transformationService, profileContext, localeProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProfileType createLocalizedProfileType(ProfileType profileType, @Nullable Locale locale) {
|
||||||
|
final LocalizedKey localizedKey = new LocalizedKey(profileType.getUID(),
|
||||||
|
locale != null ? locale.toLanguageTag() : null);
|
||||||
|
|
||||||
|
final ProfileType cachedlocalizedProfileType = localizedProfileTypeCache.get(localizedKey);
|
||||||
|
if (cachedlocalizedProfileType != null) {
|
||||||
|
return cachedlocalizedProfileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ProfileType localizedProfileType = profileTypeI18nLocalizationService.createLocalizedProfileType(bundle,
|
||||||
|
profileType, locale);
|
||||||
|
localizedProfileTypeCache.put(localizedKey, localizedProfileType);
|
||||||
|
|
||||||
|
return localizedProfileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
|
||||||
|
return List.of(PROFILE_TYPE_UID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Reference(target = "(openhab.transform=VAT)")
|
||||||
|
public void addTransformationService(TransformationService service) {
|
||||||
|
this.transformationService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTransformationService(TransformationService service) {
|
||||||
|
this.transformationService = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<addon:addon id="vat" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||||
|
|
||||||
|
<type>transformation</type>
|
||||||
|
<name>VAT transformation</name>
|
||||||
|
<description>Transforms the input by adding Value-Added Tax according to configured country or percentage.</description>
|
||||||
|
|
||||||
|
</addon:addon>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<config-description:config-descriptions
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||||
|
|
||||||
|
<config-description uri="profile:transform:VAT">
|
||||||
|
<parameter name="percentage" type="text">
|
||||||
|
<label>VAT Percentage</label>
|
||||||
|
<description>Manually configured VAT percentage (overriding VAT rate for configured country).</description>
|
||||||
|
<advanced>true</advanced>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</config-description:config-descriptions>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
# add-on
|
||||||
|
|
||||||
|
addon.vat.name = VAT transformation
|
||||||
|
addon.vat.description = Transforms the input by adding Value-Added Tax according to configured country or percentage.
|
||||||
|
|
||||||
|
# profile
|
||||||
|
|
||||||
|
profile-type.transform.VAT.label = Value-Added Tax
|
||||||
|
profile.config.transform.VAT.percentage.label = VAT Percentage
|
||||||
|
profile.config.transform.VAT.percentage.description = Manually configured VAT percentage (overriding VAT rate for configured country).
|
||||||
@ -41,6 +41,7 @@
|
|||||||
<module>org.openhab.transform.regex</module>
|
<module>org.openhab.transform.regex</module>
|
||||||
<module>org.openhab.transform.rollershutterposition</module>
|
<module>org.openhab.transform.rollershutterposition</module>
|
||||||
<module>org.openhab.transform.scale</module>
|
<module>org.openhab.transform.scale</module>
|
||||||
|
<module>org.openhab.transform.vat</module>
|
||||||
<module>org.openhab.transform.xpath</module>
|
<module>org.openhab.transform.xpath</module>
|
||||||
<module>org.openhab.transform.xslt</module>
|
<module>org.openhab.transform.xslt</module>
|
||||||
<!-- bindings -->
|
<!-- bindings -->
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user