|
1 |
| -use crate::input::InputCart as Cart; |
2 |
| -use crate::input::InputCartLines as CartLine; |
3 |
| -use crate::input::InputCartLinesMerchandise::ProductVariant; |
4 |
| -use crate::input::InputCartLinesMerchandiseOnProductVariant; |
5 |
| -use crate::output::CartLineInput; |
6 |
| -use crate::output::CartOperation; |
7 |
| -use crate::output::ExpandOperation; |
8 |
| -use crate::output::ExpandedItem; |
9 |
| -use crate::output::MergeOperation; |
10 |
| -use crate::output::PriceAdjustment; |
11 |
| -use crate::output::PriceAdjustmentValue; |
12 |
| -use serde::Deserialize; |
13 |
| -use shopify_function::prelude::*; |
14 |
| -use shopify_function::Result; |
15 |
| -use std::collections::HashMap; |
| 1 | +use std::process; |
| 2 | +pub mod run; |
16 | 3 |
|
17 |
| -generate_types!( |
18 |
| - query_path = "./input.graphql", |
19 |
| - schema_path = "./schema.graphql" |
20 |
| -); |
21 |
| - |
22 |
| -#[allow(clippy::upper_case_acronyms)] |
23 |
| -type URL = String; |
24 |
| - |
25 |
| -#[derive(Clone, Debug, PartialEq)] |
26 |
| -struct ComponentParent { |
27 |
| - pub id: ID, |
28 |
| - pub component_reference: Vec<ID>, |
29 |
| - pub component_quantities: Vec<i64>, |
30 |
| - pub price_adjustment: Option<f64>, |
31 |
| -} |
32 |
| - |
33 |
| -#[derive(Clone, Debug, Deserialize)] |
34 |
| -pub struct ComponentParentMetafield { |
35 |
| - pub id: ID, |
36 |
| - pub component_reference: ComponentParentMetafieldReference, |
37 |
| - pub component_quantities: ComponentParentMetafieldQuantities, |
38 |
| - pub price_adjustment: Option<ComponentParentMetafieldPriceAdjustment>, |
39 |
| -} |
40 |
| - |
41 |
| -#[derive(Clone, Debug, Deserialize)] |
42 |
| -pub struct ComponentParentMetafieldReference { |
43 |
| - pub value: Vec<String>, |
44 |
| -} |
45 |
| - |
46 |
| -#[derive(Clone, Debug, Deserialize)] |
47 |
| -pub struct ComponentParentMetafieldQuantities { |
48 |
| - pub value: Vec<i64>, |
49 |
| -} |
50 |
| - |
51 |
| -#[derive(Clone, Debug, Deserialize)] |
52 |
| -pub struct ComponentParentMetafieldPriceAdjustment { |
53 |
| - pub value: f64, |
54 |
| -} |
55 |
| - |
56 |
| -#[shopify_function] |
57 |
| -fn function(input: input::ResponseData) -> Result<output::FunctionResult> { |
58 |
| - let cart_operations: Vec<CartOperation> = get_merge_cart_operations(&input.cart) |
59 |
| - .chain(get_expand_cart_operations(&input.cart)) |
60 |
| - .collect(); |
61 |
| - |
62 |
| - Ok(output::FunctionResult { |
63 |
| - operations: cart_operations, |
64 |
| - }) |
65 |
| -} |
66 |
| - |
67 |
| -// merge operation logic |
68 |
| - |
69 |
| -fn get_merge_cart_operations(cart: &Cart) -> impl Iterator<Item = CartOperation> + '_ { |
70 |
| - let merge_parent_defintions = get_merge_parent_definitions(cart); |
71 |
| - |
72 |
| - let mut cart_lines: Vec<CartLine> = Vec::new(); |
73 |
| - cart.lines |
74 |
| - .iter() |
75 |
| - .for_each(|line| cart_lines.push(line.clone())); |
76 |
| - |
77 |
| - merge_parent_defintions |
78 |
| - .into_iter() |
79 |
| - .filter_map(move |definition| { |
80 |
| - let components_in_cart = get_components_in_cart(&mut cart_lines, &definition); |
81 |
| - (components_in_cart.len() == definition.component_reference.len()).then(|| { |
82 |
| - let cart_lines: Vec<CartLineInput> = components_in_cart |
83 |
| - .into_iter() |
84 |
| - .map(|component| CartLineInput { |
85 |
| - cart_line_id: component.cart_line_id, |
86 |
| - quantity: component.quantity, |
87 |
| - }) |
88 |
| - .collect(); |
89 |
| - |
90 |
| - let price = definition |
91 |
| - .price_adjustment |
92 |
| - .map(|price_adjustment| PriceAdjustment { |
93 |
| - percentage_decrease: Some(PriceAdjustmentValue { |
94 |
| - value: Decimal(price_adjustment), |
95 |
| - }), |
96 |
| - }); |
97 |
| - |
98 |
| - let merge_operation = MergeOperation { |
99 |
| - parent_variant_id: definition.id, |
100 |
| - title: None, |
101 |
| - cart_lines, |
102 |
| - image: None, |
103 |
| - price, |
104 |
| - }; |
105 |
| - |
106 |
| - CartOperation::Merge(merge_operation) |
107 |
| - }) |
108 |
| - }) |
109 |
| -} |
110 |
| - |
111 |
| -fn get_components_in_cart( |
112 |
| - cart_lines: &mut Vec<CartLine>, |
113 |
| - definition: &ComponentParent, |
114 |
| -) -> Vec<CartLineInput> { |
115 |
| - let line_results: Vec<CartLineInput> = definition |
116 |
| - .component_reference |
117 |
| - .iter() |
118 |
| - .zip(definition.component_quantities.iter()) |
119 |
| - .filter_map(|(reference, &quantity)| { |
120 |
| - cart_lines.iter().find_map(move |line| { |
121 |
| - matches!( |
122 |
| - &line.merchandise, |
123 |
| - ProductVariant(merchandise) if reference == &merchandise.id && line.quantity >= quantity, |
124 |
| - ).then(|| CartLineInput { cart_line_id: line.id.clone(), quantity }) |
125 |
| - }) |
126 |
| - }) |
127 |
| - .collect(); |
128 |
| - |
129 |
| - update_cart_lines_from_function_result(cart_lines, line_results.clone()); |
130 |
| - |
131 |
| - line_results |
132 |
| -} |
133 |
| - |
134 |
| -fn update_cart_lines_from_function_result( |
135 |
| - cart_lines: &mut Vec<CartLine>, |
136 |
| - line_results: Vec<CartLineInput>, |
137 |
| -) { |
138 |
| - let mut cart_line_tracker: HashMap<String, i64> = cart_lines |
139 |
| - .iter() |
140 |
| - .map(|cart_line| (cart_line.id.clone(), cart_line.quantity)) |
141 |
| - .collect(); |
142 |
| - |
143 |
| - for line_result in line_results.iter() { |
144 |
| - if let Some(target_cart_line) = cart_lines |
145 |
| - .iter() |
146 |
| - .find(|cart_line| cart_line.id == line_result.cart_line_id) |
147 |
| - { |
148 |
| - let new_quantity = cart_line_tracker[&target_cart_line.id] - line_result.quantity; |
149 |
| - cart_line_tracker.insert(target_cart_line.id.clone(), new_quantity); |
150 |
| - } |
151 |
| - } |
152 |
| - |
153 |
| - cart_lines.retain(|line| cart_line_tracker[&line.id] > 0); |
154 |
| - |
155 |
| - for cart_line in cart_lines.iter_mut() { |
156 |
| - if cart_line_tracker[&cart_line.id] > 0 { |
157 |
| - cart_line.quantity = cart_line_tracker[&cart_line.id]; |
158 |
| - } |
159 |
| - } |
160 |
| -} |
161 |
| - |
162 |
| -fn get_merge_parent_definitions(cart: &Cart) -> Vec<ComponentParent> { |
163 |
| - let mut merge_parent_defintions: Vec<ComponentParent> = Vec::new(); |
164 |
| - |
165 |
| - for line in cart.lines.iter() { |
166 |
| - if let ProductVariant(merchandise) = &line.merchandise { |
167 |
| - merge_parent_defintions.extend(get_component_parents(merchandise)); |
168 |
| - } |
169 |
| - } |
170 |
| - |
171 |
| - merge_parent_defintions |
172 |
| -} |
173 |
| - |
174 |
| -fn get_component_parents( |
175 |
| - variant: &InputCartLinesMerchandiseOnProductVariant, |
176 |
| -) -> impl Iterator<Item = ComponentParent> { |
177 |
| - variant |
178 |
| - .component_parents |
179 |
| - .as_ref() |
180 |
| - .map(|component_parents_metafield| { |
181 |
| - let value: Vec<ComponentParentMetafield> = |
182 |
| - serde_json::from_str(&component_parents_metafield.value).unwrap(); |
183 |
| - value.into_iter().map(|parent_definition| { |
184 |
| - let price = parent_definition |
185 |
| - .price_adjustment |
186 |
| - .as_ref() |
187 |
| - .map(|price_adjustment| price_adjustment.value); |
188 |
| - |
189 |
| - ComponentParent { |
190 |
| - id: parent_definition.id, |
191 |
| - component_reference: parent_definition.component_reference.value, |
192 |
| - component_quantities: parent_definition.component_quantities.value, |
193 |
| - price_adjustment: price, |
194 |
| - } |
195 |
| - }) |
196 |
| - }) |
197 |
| - .into_iter() |
198 |
| - .flatten() |
199 |
| -} |
200 |
| - |
201 |
| -// expand operation logic |
202 |
| - |
203 |
| -fn get_expand_cart_operations(cart: &Cart) -> impl Iterator<Item = CartOperation> + '_ { |
204 |
| - cart.lines.iter().filter_map(|line| { |
205 |
| - if let ProductVariant(merchandise) = &line.merchandise { |
206 |
| - let component_references: Vec<ID> = get_component_references(merchandise); |
207 |
| - let component_quantities: Vec<i64> = get_component_quantities(merchandise); |
208 |
| - |
209 |
| - if component_references.is_empty() |
210 |
| - || component_references.len() != component_quantities.len() |
211 |
| - { |
212 |
| - None |
213 |
| - } else { |
214 |
| - let expand_relationships: Vec<ExpandedItem> = component_references |
215 |
| - .into_iter() |
216 |
| - .zip(component_quantities.iter()) |
217 |
| - .map(|(reference, &quantity)| ExpandedItem { |
218 |
| - merchandise_id: reference, |
219 |
| - quantity, |
220 |
| - price: None, |
221 |
| - }) |
222 |
| - .collect(); |
223 |
| - |
224 |
| - let price = get_price_adjustment(merchandise); |
225 |
| - |
226 |
| - CartOperation::Expand(ExpandOperation { |
227 |
| - cart_line_id: line.id.clone(), |
228 |
| - expanded_cart_items: expand_relationships, |
229 |
| - price, |
230 |
| - image: None, |
231 |
| - title: None, |
232 |
| - }) |
233 |
| - .into() |
234 |
| - } |
235 |
| - } else { |
236 |
| - None |
237 |
| - } |
238 |
| - }) |
239 |
| -} |
240 |
| - |
241 |
| -fn get_component_quantities(variant: &InputCartLinesMerchandiseOnProductVariant) -> Vec<i64> { |
242 |
| - if let Some(component_quantities_metafield) = &variant.component_quantities { |
243 |
| - serde_json::from_str(&component_quantities_metafield.value).unwrap() |
244 |
| - } else { |
245 |
| - Vec::new() |
246 |
| - } |
247 |
| -} |
248 |
| - |
249 |
| -fn get_component_references(variant: &InputCartLinesMerchandiseOnProductVariant) -> Vec<ID> { |
250 |
| - if let Some(component_reference_metafield) = &variant.component_reference { |
251 |
| - serde_json::from_str(&component_reference_metafield.value).unwrap() |
252 |
| - } else { |
253 |
| - Vec::new() |
254 |
| - } |
255 |
| -} |
256 |
| - |
257 |
| -fn get_price_adjustment( |
258 |
| - variant: &InputCartLinesMerchandiseOnProductVariant, |
259 |
| -) -> Option<PriceAdjustment> { |
260 |
| - variant |
261 |
| - .price_adjustment |
262 |
| - .as_ref() |
263 |
| - .map(|price_adjustment| PriceAdjustment { |
264 |
| - percentage_decrease: Some(PriceAdjustmentValue { |
265 |
| - value: Decimal(price_adjustment.value.parse().unwrap()), |
266 |
| - }), |
267 |
| - }) |
| 4 | +fn main() { |
| 5 | + eprintln!("Please invoke a named export."); |
| 6 | + process::exit(1); |
268 | 7 | }
|
0 commit comments