Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions org.xalgorithms.examples.ca_tax/ca_tax.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"document" : {
"region" : "CA-ON",
"subtotal" : 10.00
}
}
34 changes: 34 additions & 0 deletions org.xalgorithms.examples.ca_tax/ca_tax.rule
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

META
VERSION "0.0.3"
RUNTIME "0.4.0"
CRITICALITY "experimental"
MANAGER "Joseph Potvin <jpotvin@xalgorithms.org>"
MAINTAINER "Ryan Fleck <ryan.fleck@protonmail.com>";

EFFECTIVE
IN "CA-*"
FROM "2018-04-01T00:00"
TO "9999-12-30T23:59"
TIMEZONE "America/Toronto";

# WHEN document:transaction.currency == "CAD";

REQUIRE tax:provincial_vat:0.0.1 AS provincial_vat;

ASSEMBLE applicable_vat
COLUMNS FROM table:provincial_vat
WHEN @region == document:region;

MAP table:applicable_vat
USING HST = add(@GST, @PST);

ASSEMBLE apply_vat
COLUMN HST FROM table:applicable_vat;

MAP table:apply_vat
USING TaxRate = add(1, multiply(divide(1, 100), @HST));

MAP table:apply_vat
USING Total = multiply(@TaxRate, document:subtotal);

14 changes: 14 additions & 0 deletions org.xalgorithms.examples.ca_tax/provincial_vat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{ "region" : "CA-NL", "GST": 5, "PST": 10},
{ "region" : "CA-PE", "GST": 5, "PST": 10},
{ "region" : "CA-NS", "GST": 5, "PST": 10},
{ "region" : "CA-NB", "GST": 5, "PST": 10},
{ "region" : "CA-QC", "GST": 5, "PST": 10},
{ "region" : "CA-ON", "GST": 5, "PST": 8},
{ "region" : "CA-MB", "GST": 5, "PST": 8},
{ "region" : "CA-SK", "GST": 5, "PST": 5},
{ "region" : "CA-AB", "GST": 5, "PST": 0},
{ "region" : "CA-BC", "GST": 5, "PST": 7},
{ "region" : "CA-YT", "GST": 5, "PST": 0},
{ "region" : "CA-NT", "GST": 5, "PST": 0}
]
5 changes: 5 additions & 0 deletions org.xalgorithms.examples.ca_tax/provincial_vat.table
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
META
VERSION "0.0.1"
MAINTAINER "Ryan Fleck <ryan.fleck@protonmail.com>";

DATA provincial_vat.json 5071d3ac04ea2be8eafd8b23b3c9336a;
171 changes: 171 additions & 0 deletions org.xalgorithms.examples.qc_gas_tax/proximity-gas-tax.rule
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# GOAL: This rule operates on documents that are prepared by the
# Lichen application, originating as UBL invoices. It selects invoices
# that apply to consumer petrol sales (using ISIC and UNSPSC)
# coding. For any items in the invoice that required UNSPSC code, it
# will generate a revision that adds an allowance (discount) to the
# invoice.

EFFECTIVE
IN "CA-ON", "CA-QC"
FROM "2018-04-01T00:00"
TO "9999-12-30T23:59"
TIMEZONE "America/Toronto";

META
VERSION "0.0.2"
RUNTIME "0.4.0"
CRITICALITY "experimental"
MANAGER "Joseph Potvin <jpotvin@xalgorithms.org>"
MAINTAINER "Ryan Fleck <ryan.fleck@protonmail.com>";

# This rule only applies to invoices from suppliers in the consumer
# petrol industry (ISIC/G4711).
WHEN envelope:type == "invoice";
WHEN envelope:parties.supplier.industry.list_id == "ISIC";
WHEN envelope:parties.supplier.industry.value == "G4711";

# This rule only operates on invoice items that are coded as consumer
# petrol (UNSPSC/506505).
WHEN item:classification.list_name == "UNSPSC";
WHEN item:classification.value == "506505";
WHEN item:quantity.value > 0;

# load tables that add additional information
REQUIRE org.xalgorithms.examples.qc_gas_tax:supplier_distances:0.0.1;
REQUIRE org.xalgorithms.examples.qc_gas_tax:reductions_by_distance:0.0.1;

# PHASE ONE: Build a table that can be used to transform any items in
# the invoice that related to UNSPSC/506505. We will do this by
# loading a table of registered station distances against a table of
# discounts based on kilometer distance from the border. For this
# example, it is assumed that the author of the rule has some facility
# for generating the supplier distances table
#
# For the purposes of illustration, the supplier in the comment
# examples is "0002".
#
# Build a table that contains the seller information joined against the predefined
# reductions table.
#
# The first column selection build a basic table using the
# reductions_by_distance table. Quoting from the sample tables, this
# yields:
#
# [
# { "distance" : 20, "reduction" : 0.00 },
# { "distance" : 15, "reduction" : 0.02 },
# { "distance" : 10, "reduction" : 0.04 },
# { "distance" : 5, "reduction" : 0.06 },
# { "distance" : 0, "reduction" : 0.08 }
# ]
#
# The second COLUMN expression performs a cartesian product against
# the table-under-construction. It also applies a condition that ONLY
# accepts a row where the supplier from the invoice matches.
#
# This yields a final table:
#
# [
# { "distance" : 20, "reduction" : 0.00, "seller_distance" : 1.7 },
# { "distance" : 15, "reduction" : 0.02, "seller_distance" : 1.7 },
# { "distance" : 10, "reduction" : 0.04, "seller_distance" : 1.7 },
# { "distance" : 5, "reduction" : 0.06, "seller_distance" : 1.7 },
# { "distance" : 0, "reduction" : 0.08, "seller_distance" : 1.7 }
# ]
#
ASSEMBLE sellers_reductions
COLUMNS FROM table:reductions_by_distance
COLUMN seller_distance FROM table:supplier_distances WHEN "UsN8EB1QZU" == @supplier_id;
# WHEN envelope:parties.supplier.id.value == @supplier_id;

#
# In order to determine the correct reduction, we learn WHICH bracket
# of distance that the seller matches. We do this by performing a MAP,
# FILTER, REDUCE. The first step generates the difference in distance,
# yielding:
#
# [
# { "distance" : 20, "reduction" : 0.00, "seller_distance" : 1.7, "difference" : 18.3 },
# { "distance" : 15, "reduction" : 0.02, "seller_distance" : 1.7, "difference" : 13.3 },
# { "distance" : 10, "reduction" : 0.04, "seller_distance" : 1.7, "difference" : 8.3 },
# { "distance" : 5, "reduction" : 0.06, "seller_distance" : 1.7, "difference" : 3.3 },
# { "distance" : 0, "reduction" : 0.08, "seller_distance" : 1.7, "difference" : -1.7 }
# ]
#
MAP table:sellers_reductions
USING difference = subtract(@distance, @seller_distance);

# Since we will be reducing using min(), we should remove any rows that are < 0
#
# [
# { "distance" : 20, "reduction" : 0.00, "seller_distance" : 1.7, "difference" : 18.3 },
# { "distance" : 15, "reduction" : 0.02, "seller_distance" : 1.7, "difference" : 13.3 },
# { "distance" : 10, "reduction" : 0.04, "seller_distance" : 1.7, "difference" : 8.3 },
# { "distance" : 5, "reduction" : 0.06, "seller_distance" : 1.7, "difference" : 3.3 }
# ]
#
FILTER table:sellers_reductions
WHEN @difference >= 0;

# Using the REDUCE step, we determine the minimal distance and select
# it. The accumulator we use in the reduction (min_difference) is not
# retained in the resulting table.
#
#[
# { "distance" : 5, "reduction" : 0.06, "seller_distance" : 1.7, "difference" : 3.3 }
#]
#

## REDUCE table:sellers_reductions
## USING min_difference = min(min_difference, @difference)
## WHEN difference == @min_difference;

# PHASE TWO: We need to apply this final reduction ACROSS the items
# that appear in the invoice. Since this invoice originates as a UBL
# document formatted to our internal format it will have HIERARCHICAL
# columns (columns containing KEY/VALUE pair trees). Therefore the
# example will only contain the information relevant to the rule.
#
# The items table in the originating document might contain:
#
# [
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, price: { currency_code: "CAD", "value" : "10.00" } },
# { "classification" : { list_name: "UNSPSC", "value" : "111111" }, price: { currency_code: "CAD", "value" : "35.00" } },
# { "classification" : { list_name: "UNSPSC", "value" : "222222" }, price: { currency_code: "CAD", "value" : "15.00" } },
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, price: { currency_code: "CAD", "value" : "18.00" } }
# ]
#
#
# First, we use the items table as the basis for a new table. It is
# filtered according to the classification. We form additional columns
# using the cartesian product of the table we built in PHASE ONE. This yields:
#
# [
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, "price": { currency_code: "CAD", "value" : "10.00" }, "reduction" : .06 },
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, "price": { currency_code: "CAD", "value" : "18.00" }, "reduction" : .06 }
# ]
#
## ASSEMBLE item_reductions
## COLUMNS (id, classification, price) FROM table:items
## WHEN @classification.list_name == "UNSPSC"
## WHEN @classification.value == "506505"
## COLUMN reduction FROM table:sellers_reductions;
#
# We use MAP to add an additional NESTED COLUMN that translates to an
# allowance (a discount in this case) in UBL concepts, yielding:
#
# [
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, "price": { currency_code: "CAD", "value" : "10.00" }, "reduction" : .06, "allowance": { "charge" : false, "amount" : { "value" : 0.6, "currency_code" : "CAD" } },
# { "classification" : { list_name: "UNSPSC", "value" : "506505" }, "price": { currency_code: "CAD", "value" : "18.00" }, "reduction" : .06, "allowance": { "charge" : false, "amount" : { "value" : 1.08, "currency_code" : "CAD" } }
# ]
#
## MAP table:item_reductions
## USING allowance.charge = false
## USING allowance.amount.value = multiply(@price.value, @reduction)
## USING allowance.amount.currency_code = @price.currency_code;
#
# This issues a revision of the original items table, adding the
# ENTIRE allowance column.
### REVISE table:items
### ADD allowance FROM table:item_reductions WHEN id.value == @id.value;
#
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{ "distance" : 20, "reduction" : 0.00 },
{ "distance" : 15, "reduction" : 0.02 },
{ "distance" : 10, "reduction" : 0.04 },
{ "distance" : 5, "reduction" : 0.06 },
{ "distance" : 0, "reduction" : 0.08 }
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
META
VERSION "0.0.1"
MANAGER "Joseph Potvin <jpotvin@xalgorithms.org>"
MAINTAINER "Don Kelly <karfai@gmail.com>";

DATA reductions_by_distance.json 01s5vg2x4tr142gd320zy15tka67h722;
8 changes: 8 additions & 0 deletions org.xalgorithms.examples.qc_gas_tax/supplier_distances.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{ "supplier_id" : "YJ4gh6Ofdq", "seller_distance" : 2.2 },
{ "supplier_id" : "UsN8EB1QZU", "seller_distance" : 15.7 },
{ "supplier_id" : "uZz9cKtwhx", "seller_distance" : 0.4 },
{ "supplier_id" : "HcfUd49gPV", "seller_distance" : 12.2 },
{ "supplier_id" : "0DXKYXBZr8", "seller_distance" : 7.8 },
{ "supplier_id" : "nIT8sF9vS4", "seller_distance" : 24.3 }
]
6 changes: 6 additions & 0 deletions org.xalgorithms.examples.qc_gas_tax/supplier_distances.table
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
META
VERSION "0.0.1"
MANAGER "Joseph Potvin <jpotvin@xalgorithms.org>"
MAINTAINER "Don Kelly <karfai@gmail.com>";

DATA supplier_distances.json 152t1p6nhu85m5d9pi3qne75ni2g8xz4;