For discussing the development and usage of Checkout UI extensions, post-purchase extensions, web pixels, Customer Accounts UI extensions, and POS UI extensions
Hello, In our new shop we have following shipping requirements: Non frozen products can be shipped at any Time, frozen products have to have a weight of at least 4000 grams.
To Validate this Requirements i wrote following checkout and cart validation extension.
Its working pretty much correcty, but it fires the error while im adding products to an empty cart and when i want to reduce the quantity of frozen products to a weight of under 4000 grams. How can i make this extension only throwing errors when on checkout site and keep shop functionality working in my shop?.
Best Regards
/** * @typedef {import("../generated/api").InputQuery} InputQuery * @typedef {import("../generated/api").FunctionResult} FunctionResult */ export default /** * @param {InputQuery} input * @returns {FunctionResult} */ (input) => { const min_weight_frozen = 4000; let sum_weight_frozen = 0 let item_count_frozen = 0 for(let item of input.cart.lines){ if(item.quantity){ if(item.merchandise?.product?.lagerung.value.includes("TK") || item.merchandise?.product?.eigenschaften.value.includes("gefroren") || item.merchandise?.product?.hinweis.value.includes("Gefroren")){ if(item.merchandise?.weightUnit == "KILOGRAMS"){ sum_weight_frozen += item.merchandise.weight * 1000 * item.quantity } else{ sum_weight_frozen += item.merchandise.weight * item.quantity } item_count_frozen += 1 } } } let cart_is_valid = false if(sum_weight_frozen >= min_weight_frozen && item_count_frozen != 0){ cart_is_valid = true } else if(item_count_frozen == 0){ cart_is_valid = true } const min_weight_frozen_kg = min_weight_frozen / 1000 const sum_weight_frozen_kg = sum_weight_frozen / 1000 let input_string = JSON.stringify(input) const weightError = { localizedMessage: `Wir versenden gefrorene Produkte erst ab einem gesamt Mindestgewicht von ${min_weight_frozen_kg}kg. Das gesamt Gewicht Ihrer gefrorenen Produkte liegt bei ${sum_weight_frozen_kg}kg. ${sum_weight_frozen} ${item_count_frozen} ${input_string} hallo`, target: "cart" } let errors = [] if(cart_is_valid == false){ errors.push(weightError) } return { errors } };
Solved! Go to the solution
This is an accepted solution.
Hi CSilvas,
I have a Solution for my Problem if i check the buyerJourney step before
Thats my updated query.
query Input {
buyerJourney{
step
}
cart {
lines {
quantity
merchandise{
...on ProductVariant {
id
weight
weightUnit
product {
lagerung:metafield(namespace:"sl_ART",key:"extra_LAGERUNGSEMPFEHLUNG"){
value
}
eigenschaften:metafield(namespace:"sl_ART",key:"extra_PRODUKTEIGENSCHAFTEN"){
value
}
hinweis:metafield(namespace:"sl_ART",key:"extra_HINWEISWICHTIG"){
value
}
}
}
}
}
}
}
.
Thats my new Code:
// @TS-check
/**
* @typedef {import("../generated/api").InputQuery} InputQuery
* @typedef {import("../generated/api").FunctionResult} FunctionResult
*/
export default /**
* @Anonymous {InputQuery} input
* @returns {FunctionResult}
*/
(input) => {
let errors = []
if(input.buyerJourney.step != "CART_INTERACTION"){
const min_weight_frozen = 4000;
let sum_weight_frozen = 0
let item_count_frozen = 0
for(let item of input.cart.lines){
if(item.quantity){
if(item.merchandise?.product?.lagerung?.value?.includes("TK") || item.merchandise?.product?.eigenschaften?.value?.includes("gefroren") || item.merchandise?.product?.hinweis?.value?.includes("Gefroren")){
if(item.merchandise?.weightUnit == "KILOGRAMS"){
sum_weight_frozen += item.merchandise.weight * 1000 * item.quantity
}
else{
sum_weight_frozen += item.merchandise.weight * item.quantity
}
item_count_frozen += 1
}
}
}
let cart_is_valid = false
if(sum_weight_frozen >= min_weight_frozen && item_count_frozen != 0){
cart_is_valid = true
}
else if(item_count_frozen == 0){
cart_is_valid = true
}
const min_weight_frozen_kg = min_weight_frozen / 1000
const sum_weight_frozen_kg = sum_weight_frozen / 1000
const weightError = {
localizedMessage: `Wir versenden gefrorene Produkte erst ab einem gesamt Mindestgewicht von ${min_weight_frozen_kg}kg. Das Gesamtgewicht Ihrer gefrorenen Produkte liegt bei ${sum_weight_frozen_kg}kg.`,
target: "$.cart"
}
if(cart_is_valid == false){
errors.push(weightError)
}
}
return {
errors
}
};
Im pushing my custom Error only when not in buyerJourney.step = "CART_INTERACTION"
Possible Values for this you can find here.
Oddly enough, I have the exact opposite problem. I have a validation script I would like to run at Cart and Checkout level but it is only running at Checkout. Would you like to compare notes and see if we can switch our situations :D!?
import type { RunInput, FunctionRunResult } from "../generated/api";
export function run(input: RunInput): FunctionRunResult {
if (
input.cart.lines.length > 0 &&
!(
// For some reason Shopify reverses the order of cart lines when a customer clicks the "Check out" button.
// We compensate by allowing the signature to be at the beginning or the end of the lines.
(
input.cart.lines[0].signature?.value?.length == 64 ||
input.cart.lines[input.cart.lines.length - 1].signature?.value
?.length == 64
)
)
) {
return {
errors: [
{
localizedMessage:
"Something unexpected happened. Please contact support!",
target: "cart",
},
],
};
}
return {
errors: [],
};
}
This is an accepted solution.
Hi CSilvas,
I have a Solution for my Problem if i check the buyerJourney step before
Thats my updated query.
query Input {
buyerJourney{
step
}
cart {
lines {
quantity
merchandise{
...on ProductVariant {
id
weight
weightUnit
product {
lagerung:metafield(namespace:"sl_ART",key:"extra_LAGERUNGSEMPFEHLUNG"){
value
}
eigenschaften:metafield(namespace:"sl_ART",key:"extra_PRODUKTEIGENSCHAFTEN"){
value
}
hinweis:metafield(namespace:"sl_ART",key:"extra_HINWEISWICHTIG"){
value
}
}
}
}
}
}
}
.
Thats my new Code:
// @TS-check
/**
* @typedef {import("../generated/api").InputQuery} InputQuery
* @typedef {import("../generated/api").FunctionResult} FunctionResult
*/
export default /**
* @Anonymous {InputQuery} input
* @returns {FunctionResult}
*/
(input) => {
let errors = []
if(input.buyerJourney.step != "CART_INTERACTION"){
const min_weight_frozen = 4000;
let sum_weight_frozen = 0
let item_count_frozen = 0
for(let item of input.cart.lines){
if(item.quantity){
if(item.merchandise?.product?.lagerung?.value?.includes("TK") || item.merchandise?.product?.eigenschaften?.value?.includes("gefroren") || item.merchandise?.product?.hinweis?.value?.includes("Gefroren")){
if(item.merchandise?.weightUnit == "KILOGRAMS"){
sum_weight_frozen += item.merchandise.weight * 1000 * item.quantity
}
else{
sum_weight_frozen += item.merchandise.weight * item.quantity
}
item_count_frozen += 1
}
}
}
let cart_is_valid = false
if(sum_weight_frozen >= min_weight_frozen && item_count_frozen != 0){
cart_is_valid = true
}
else if(item_count_frozen == 0){
cart_is_valid = true
}
const min_weight_frozen_kg = min_weight_frozen / 1000
const sum_weight_frozen_kg = sum_weight_frozen / 1000
const weightError = {
localizedMessage: `Wir versenden gefrorene Produkte erst ab einem gesamt Mindestgewicht von ${min_weight_frozen_kg}kg. Das Gesamtgewicht Ihrer gefrorenen Produkte liegt bei ${sum_weight_frozen_kg}kg.`,
target: "$.cart"
}
if(cart_is_valid == false){
errors.push(weightError)
}
}
return {
errors
}
};
Im pushing my custom Error only when not in buyerJourney.step = "CART_INTERACTION"
Possible Values for this you can find here.