Skip to content

Commit bec3522

Browse files
committed
discount tutorial part 2 implemented
1 parent 09260cd commit bec3522

File tree

4 files changed

+47
-13
lines changed

4 files changed

+47
-13
lines changed

.graphqlrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function getProjects(path) {
2626

2727
const projects = {
2828
...getProjects("sample-apps/discounts-tutorial/extensions"),
29+
...getProjects("sample-apps/discounts/extensions"),
2930
...getProjects("checkout/rust/delivery-customization"),
3031
...getProjects("checkout/rust/payment-customization"),
3132
...getProjects("discounts/rust/order-discounts"),

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"discounts/rust/product-discounts/fixed-amount/Cargo.toml",
99
"discounts/rust/shipping-discounts/default/Cargo.toml",
1010
"discounts/rust/shipping-discounts/fixed-amount/Cargo.toml",
11-
"sample-apps/discounts-tutorial/extensions/volume/Cargo.toml"
11+
"sample-apps/discounts-tutorial/extensions/volume/Cargo.toml",
12+
"sample-apps/discounts/extensions/product-discount/Cargo.toml"
1213
]
1314
}

sample-apps/discounts/extensions/product-discount/input.graphql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ query Input {
1010
}
1111
}
1212
}
13+
discountNode {
14+
metafield(namespace: "discounts-tutorial", key: "function-configuration") {
15+
value
16+
}
17+
}
1318
}

sample-apps/discounts/extensions/product-discount/src/main.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,63 @@
11
use shopify_function::prelude::*;
22
use shopify_function::Result;
33

4-
use serde::{Serialize};
4+
use serde::{Deserialize, Serialize};
55

66
// Use the shopify_function crate to generate structs for the function input and output
77
generate_types!(
88
query_path = "./input.graphql",
99
schema_path = "./schema.graphql"
1010
);
1111

12-
// Use the shopify_function crate to declare your function entrypoint
12+
// Create a structure that matches the JSON structure that you'll use for your configuration
13+
#[derive(Serialize, Deserialize, PartialEq)]
14+
#[serde(rename_all(deserialize = "camelCase"))]
15+
struct Configuration {
16+
pub quantity: i64,
17+
pub percentage: f64,
18+
}
19+
20+
impl Configuration {
21+
const DEFAULT_QUANTITY: i64 = 999;
22+
const DEFAULT_PERCENTAGE: f64 = 0.0;
23+
24+
// Parse the JSON metafield value using serde
25+
fn from_str(value: &str) -> Self {
26+
serde_json::from_str(value).expect("Unable to parse configuration value from metafield")
27+
}
28+
}
29+
30+
impl Default for Configuration {
31+
fn default() -> Self {
32+
Configuration {
33+
quantity: Self::DEFAULT_QUANTITY,
34+
percentage: Self::DEFAULT_PERCENTAGE,
35+
}
36+
}
37+
}
38+
1339
#[shopify_function]
1440
fn function(input: input::ResponseData) -> Result<output::FunctionResult> {
1541
let no_discount = output::FunctionResult {
1642
discounts: vec![],
1743
discount_application_strategy: output::DiscountApplicationStrategy::FIRST,
1844
};
1945

20-
// Iterate all the lines in the cart to create discount targets
46+
// Get the configuration from the metafield on your function owner
47+
let config = match input.discount_node.metafield {
48+
Some(input::InputDiscountNodeMetafield { value }) =>
49+
Configuration::from_str(&value),
50+
None => return Ok(no_discount),
51+
};
52+
2153
let targets = input.cart.lines
2254
.iter()
23-
// Only include cart lines with a quantity higher than two
24-
.filter(|line| line.quantity >= 2)
25-
// Only include cart lines with a targetable product variant
55+
// Use the configured quantity instead of a hardcoded value
56+
.filter(|line| line.quantity >= config.quantity)
2657
.filter_map(|line| match &line.merchandise {
2758
input::InputCartLinesMerchandise::ProductVariant(variant) => Some(variant),
2859
input::InputCartLinesMerchandise::CustomProduct => None,
2960
})
30-
// Use the variant id to create a discount target
3161
.map(|variant| output::Target {
3262
product_variant: Some(output::ProductVariantTarget {
3363
id: variant.id.to_string(),
@@ -37,22 +67,19 @@ fn function(input: input::ResponseData) -> Result<output::FunctionResult> {
3767
.collect::<Vec<output::Target>>();
3868

3969
if targets.is_empty() {
40-
// You can use STDERR for debug logs in your function
4170
eprintln!("No cart lines qualify for volume discount.");
4271
return Ok(no_discount);
4372
}
4473

45-
// The shopify_function crate serializes your function result and writes it to STDOUT
4674
Ok(output::FunctionResult {
4775
discounts: vec![output::Discount {
4876
message: None,
49-
// Apply the discount to the collected targets
5077
targets,
51-
// Define a percentage-based discount
78+
// Use the configured percentage instead of a hardcoded value
5279
value: output::Value {
5380
fixed_amount: None,
5481
percentage: Some(output::Percentage {
55-
value: "10.0".to_string()
82+
value: config.percentage.to_string()
5683
})
5784
}
5885
}],

0 commit comments

Comments
 (0)