|
| 1 | +use serde::Serialize; |
| 2 | + |
| 3 | +mod api; |
| 4 | +use api::*; |
| 5 | + |
| 6 | +#[allow(unused_must_use)] |
| 7 | +fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 8 | + let input: Input = serde_json::from_reader(std::io::BufReader::new(std::io::stdin()))?; |
| 9 | + |
| 10 | + let mut out = std::io::stdout(); |
| 11 | + let mut serializer = serde_json::Serializer::new(&mut out); |
| 12 | + |
| 13 | + cart_transform(&input.cart).serialize(&mut serializer); |
| 14 | + |
| 15 | + Ok(()) |
| 16 | +} |
| 17 | + |
| 18 | +fn cart_transform(cart: &Cart) -> FunctionResult { |
| 19 | + let mut merge_cart_operations: Vec<CartOperation> = get_merge_cart_operations(cart); |
| 20 | + let expand_cart_operations: Vec<CartOperation> = get_expand_cart_operations(cart); |
| 21 | + |
| 22 | + merge_cart_operations.extend(expand_cart_operations); |
| 23 | + |
| 24 | + return FunctionResult { |
| 25 | + operations: merge_cart_operations, |
| 26 | + }; |
| 27 | +} |
| 28 | + |
| 29 | +// merge operation logic |
| 30 | + |
| 31 | +fn get_merge_cart_operations(cart: &Cart) -> Vec<CartOperation> { |
| 32 | + let merge_parent_defintions: Vec<ComponentParent> = get_merge_parent_definitions(cart); |
| 33 | + let mut result: Vec<MergeOperation> = Vec::new(); |
| 34 | + |
| 35 | + for definition in merge_parent_defintions.iter() { |
| 36 | + let (components_in_cart, parent_variant_quantity) = |
| 37 | + get_components_in_cart(cart, definition); |
| 38 | + if components_in_cart.len() == definition.component_reference.len() { |
| 39 | + let cart_lines: Vec<CartLineMergeOperation> = components_in_cart |
| 40 | + .iter() |
| 41 | + .map(|component| CartLineMergeOperation { |
| 42 | + cartLineId: component.cartLineId.clone(), |
| 43 | + quantity: parent_variant_quantity * component.quantity, |
| 44 | + }) |
| 45 | + .collect(); |
| 46 | + |
| 47 | + let merge_operation: MergeOperation = MergeOperation { |
| 48 | + parentVariantId: definition.id.clone(), |
| 49 | + title: None, |
| 50 | + cartLines: cart_lines.clone(), |
| 51 | + quantity: parent_variant_quantity.clone(), |
| 52 | + image: None, |
| 53 | + price: None, |
| 54 | + }; |
| 55 | + |
| 56 | + result.push(merge_operation); |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + return result.iter().map(|op| CartOperation::merge(op.clone())).collect(); |
| 61 | +} |
| 62 | + |
| 63 | +fn get_components_in_cart( |
| 64 | + cart: &Cart, |
| 65 | + definition: &ComponentParent, |
| 66 | +) -> (Vec<CartLineMergeOperation>, i32) { |
| 67 | + let mut line_results: Vec<CartLineMergeOperation> = Vec::new(); |
| 68 | + let mut maximum_available_component: Vec<i32> = Vec::new(); |
| 69 | + for (reference, quantity) in definition |
| 70 | + .component_reference |
| 71 | + .iter() |
| 72 | + .zip(definition.component_quantities.iter()) |
| 73 | + { |
| 74 | + for line in cart.lines.iter() { |
| 75 | + if let Some(merchandise) = &line.merchandise { |
| 76 | + if reference == &merchandise.id && &line.quantity >= quantity { |
| 77 | + line_results.push(CartLineMergeOperation { |
| 78 | + cartLineId: line.id.clone(), |
| 79 | + quantity: quantity.clone(), |
| 80 | + }); |
| 81 | + let maximum_available = if quantity > &0 { |
| 82 | + line.quantity / quantity |
| 83 | + } else { |
| 84 | + 0 |
| 85 | + }; |
| 86 | + maximum_available_component.push(maximum_available) |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | + } |
| 91 | + let parent_variant_quantity: i32 = match maximum_available_component.iter().min() { |
| 92 | + Some(available) => available.clone(), |
| 93 | + None => 0, |
| 94 | + }; |
| 95 | + |
| 96 | + return (line_results, parent_variant_quantity); |
| 97 | +} |
| 98 | + |
| 99 | +fn get_merge_parent_definitions(cart: &Cart) -> Vec<ComponentParent> { |
| 100 | + let mut merge_parent_defintions: Vec<ComponentParent> = Vec::new(); |
| 101 | + |
| 102 | + for line in cart.lines.iter() { |
| 103 | + if let Some(merchandise) = &line.merchandise { |
| 104 | + merge_parent_defintions.append(&mut get_component_parents(&merchandise)); |
| 105 | + } |
| 106 | + } |
| 107 | + merge_parent_defintions.dedup_by(|a, b| a.id == b.id); |
| 108 | + return merge_parent_defintions; |
| 109 | +} |
| 110 | + |
| 111 | +fn get_component_parents(variant: &ProductVariant) -> Vec<ComponentParent> { |
| 112 | + let mut component_parents: Vec<ComponentParent> = Vec::new(); |
| 113 | + if let Some(component_parents_metafield) = &variant.component_parents { |
| 114 | + let value: Vec<ComponentParentMetafield> = |
| 115 | + serde_json::from_str(&component_parents_metafield.value).unwrap(); |
| 116 | + for parent_definition in value.iter() { |
| 117 | + component_parents.push(ComponentParent { |
| 118 | + id: parent_definition.id.clone(), |
| 119 | + component_reference: parent_definition.component_reference.value.clone(), |
| 120 | + component_quantities: parent_definition.component_quantities.value.clone(), |
| 121 | + }); |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + return component_parents; |
| 126 | +} |
| 127 | + |
| 128 | +// expand operation logic |
| 129 | + |
| 130 | +fn get_expand_cart_operations(cart: &Cart) -> Vec<CartOperation> { |
| 131 | + let mut result: Vec<ExpandOperation> = Vec::new(); |
| 132 | + |
| 133 | + for line in cart.lines.iter() { |
| 134 | + if let Some(merchandise) = &line.merchandise { |
| 135 | + let component_references: Vec<ID> = get_component_references(&merchandise); |
| 136 | + let component_quantities: Vec<i32> = get_component_quantities(&merchandise); |
| 137 | + |
| 138 | + if component_references.is_empty() || component_references.len() != component_quantities.len() { |
| 139 | + continue; |
| 140 | + } |
| 141 | + |
| 142 | + let mut expand_relationships: Vec<ExpandRelationship> = Vec::new(); |
| 143 | + |
| 144 | + for (reference, quantity) in component_references.iter().zip(component_quantities.iter()) { |
| 145 | + let expand_relationship: ExpandRelationship = ExpandRelationship { |
| 146 | + merchandiseId: reference.clone(), |
| 147 | + quantity: quantity.clone(), |
| 148 | + }; |
| 149 | + |
| 150 | + expand_relationships.push(expand_relationship); |
| 151 | + } |
| 152 | + |
| 153 | + let expand_operation: ExpandOperation = ExpandOperation{ |
| 154 | + cartLineId: line.id.clone(), |
| 155 | + expandedCartItems: expand_relationships, |
| 156 | + price: None, |
| 157 | + }; |
| 158 | + |
| 159 | + result.push(expand_operation); |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + return result.iter().map(|op| CartOperation::expand(op.clone())).collect(); |
| 164 | +} |
| 165 | + |
| 166 | +fn get_component_quantities(variant: &ProductVariant) -> Vec<i32> { |
| 167 | + if let Some(component_quantities_metafield) = &variant.component_quantities { |
| 168 | + return serde_json::from_str(&component_quantities_metafield.value).unwrap(); |
| 169 | + } |
| 170 | + |
| 171 | + return Vec::new(); |
| 172 | +} |
| 173 | + |
| 174 | +fn get_component_references(variant: &ProductVariant) -> Vec<ID> { |
| 175 | + if let Some(component_reference_metafield) = &variant.component_reference { |
| 176 | + return serde_json::from_str(&component_reference_metafield.value).unwrap(); |
| 177 | + } |
| 178 | + |
| 179 | + return Vec::new(); |
| 180 | +} |
0 commit comments