1
1
use shopify_function:: prelude:: * ;
2
2
use shopify_function:: Result ;
3
3
4
- use serde:: { Serialize } ;
4
+ use serde:: { Deserialize , Serialize } ;
5
5
6
6
// Use the shopify_function crate to generate structs for the function input and output
7
7
generate_types ! (
8
8
query_path = "./input.graphql" ,
9
9
schema_path = "./schema.graphql"
10
10
) ;
11
11
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
+
13
39
#[ shopify_function]
14
40
fn function ( input : input:: ResponseData ) -> Result < output:: FunctionResult > {
15
41
let no_discount = output:: FunctionResult {
16
42
discounts : vec ! [ ] ,
17
43
discount_application_strategy : output:: DiscountApplicationStrategy :: FIRST ,
18
44
} ;
19
45
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
+
21
53
let targets = input. cart . lines
22
54
. 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 )
26
57
. filter_map ( |line| match & line. merchandise {
27
58
input:: InputCartLinesMerchandise :: ProductVariant ( variant) => Some ( variant) ,
28
59
input:: InputCartLinesMerchandise :: CustomProduct => None ,
29
60
} )
30
- // Use the variant id to create a discount target
31
61
. map ( |variant| output:: Target {
32
62
product_variant : Some ( output:: ProductVariantTarget {
33
63
id : variant. id . to_string ( ) ,
@@ -37,22 +67,19 @@ fn function(input: input::ResponseData) -> Result<output::FunctionResult> {
37
67
. collect :: < Vec < output:: Target > > ( ) ;
38
68
39
69
if targets. is_empty ( ) {
40
- // You can use STDERR for debug logs in your function
41
70
eprintln ! ( "No cart lines qualify for volume discount." ) ;
42
71
return Ok ( no_discount) ;
43
72
}
44
73
45
- // The shopify_function crate serializes your function result and writes it to STDOUT
46
74
Ok ( output:: FunctionResult {
47
75
discounts : vec ! [ output:: Discount {
48
76
message: None ,
49
- // Apply the discount to the collected targets
50
77
targets,
51
- // Define a percentage-based discount
78
+ // Use the configured percentage instead of a hardcoded value
52
79
value: output:: Value {
53
80
fixed_amount: None ,
54
81
percentage: Some ( output:: Percentage {
55
- value: "10.0" . to_string( )
82
+ value: config . percentage . to_string( )
56
83
} )
57
84
}
58
85
} ] ,
0 commit comments