a little bit farther
This commit is contained in:
@ -1,8 +1,16 @@
|
|||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
import { Shop, ShopifyProduct, ShopifyProductsQuery, ShopifyProductsResponse, ShopifyProductSetInput, ShopifyProductVariant } from "./shopifyApi"
|
import {
|
||||||
|
Shop,
|
||||||
|
ShopifyProduct,
|
||||||
|
ShopifyProductsQuery,
|
||||||
|
ShopifyProductsResponse,
|
||||||
|
ShopifyProductSetInput,
|
||||||
|
ShopifyVariant,
|
||||||
|
ShopifyProductSetQuery,
|
||||||
|
VariantOptionValueInput,
|
||||||
|
} from "./shopifyApi"
|
||||||
import { getCellRangeByColumnName, getRowByColumnValue } from "./sheetUtils"
|
import { getCellRangeByColumnName, getRowByColumnValue } from "./sheetUtils"
|
||||||
|
|
||||||
|
|
||||||
export class Product {
|
export class Product {
|
||||||
shopify_id: string = ""
|
shopify_id: string = ""
|
||||||
title: string = ""
|
title: string = ""
|
||||||
@ -19,6 +27,9 @@ export class Product {
|
|||||||
weight_grams: number = 0
|
weight_grams: number = 0
|
||||||
photos: string = ""
|
photos: string = ""
|
||||||
shopify_product: ShopifyProduct
|
shopify_product: ShopifyProduct
|
||||||
|
shopify_default_variant_id: string
|
||||||
|
shopify_default_option_id: string
|
||||||
|
shopify_default_option_value_id: string
|
||||||
|
|
||||||
constructor(sku: string = "") {
|
constructor(sku: string = "") {
|
||||||
if (sku == "") {
|
if (sku == "") {
|
||||||
@ -58,14 +69,11 @@ export class Product {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MatchToShopifyProduct(shop: Shop) {
|
MatchToShopifyProduct(shop: Shop) {
|
||||||
if (this.shopify_id.startsWith("gid://shopify/Product/")) {
|
/* if (this.shopify_id.startsWith("gid://shopify/Product/")) {
|
||||||
return
|
return
|
||||||
}
|
} */
|
||||||
|
|
||||||
let query = new ShopifyProductsQuery(
|
let query = new ShopifyProductsQuery("sku:" + this.sku, ["id", "title"])
|
||||||
"sku:" + this.sku,
|
|
||||||
["id", "title"]
|
|
||||||
)
|
|
||||||
console.log(query.JSON)
|
console.log(query.JSON)
|
||||||
let response = shop.shopifyGraphQLAPI(query.JSON)
|
let response = shop.shopifyGraphQLAPI(query.JSON)
|
||||||
console.log(response)
|
console.log(response)
|
||||||
@ -80,6 +88,32 @@ export class Product {
|
|||||||
}
|
}
|
||||||
this.shopify_product = productsResponse.products.edges[0].node
|
this.shopify_product = productsResponse.products.edges[0].node
|
||||||
this.shopify_id = this.shopify_product.id.toString()
|
this.shopify_id = this.shopify_product.id.toString()
|
||||||
|
this.shopify_default_variant_id =
|
||||||
|
productsResponse.products.edges[0].node.variants.nodes[0].id
|
||||||
|
console.log(JSON.stringify(productsResponse, null, 2))
|
||||||
|
console.log(JSON.stringify(productsResponse.products, null, 2))
|
||||||
|
console.log(JSON.stringify(productsResponse.products.edges[0], null, 2))
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(productsResponse.products.edges[0].node, null, 2)
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
productsResponse.products.edges[0].node.options[0],
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
productsResponse.products.edges[0].node.options[0].id,
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
this.shopify_default_option_id =
|
||||||
|
productsResponse.products.edges[0].node.options[0].id
|
||||||
|
this.shopify_default_option_value_id =
|
||||||
|
productsResponse.products.edges[0].node.options[0].optionValues[0].id
|
||||||
let productInventorySheet =
|
let productInventorySheet =
|
||||||
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("product_inventory")
|
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("product_inventory")
|
||||||
let row = getRowByColumnValue("product_inventory", "sku", this.sku)
|
let row = getRowByColumnValue("product_inventory", "sku", this.sku)
|
||||||
@ -90,24 +124,32 @@ export class Product {
|
|||||||
|
|
||||||
ToShopifyProductSet() {
|
ToShopifyProductSet() {
|
||||||
let sps = new ShopifyProductSetInput()
|
let sps = new ShopifyProductSetInput()
|
||||||
sps.category = this.category
|
//TODO: map category IDs
|
||||||
|
//sps.category = this.category
|
||||||
sps.id = this.shopify_id
|
sps.id = this.shopify_id
|
||||||
sps.productType = this.product_type
|
sps.productType = this.product_type
|
||||||
sps.tags = this.tags
|
sps.tags = this.tags
|
||||||
sps.title = this.title
|
sps.title = this.title
|
||||||
sps.descriptionHtml = this.description
|
sps.descriptionHtml = this.description
|
||||||
sps.variants = []
|
sps.variants = []
|
||||||
let variant = new ShopifyProductVariant()
|
let variant = new ShopifyVariant()
|
||||||
variant.id = 1
|
//TODO: handle multiple variants
|
||||||
|
variant.id = this.shopify_default_variant_id
|
||||||
variant.sku = this.sku
|
variant.sku = this.sku
|
||||||
variant.price = this.price
|
variant.price = this.price
|
||||||
variant.weight = this.weight_grams
|
|
||||||
sps.variants.push(variant)
|
sps.variants.push(variant)
|
||||||
|
let opt = new ShopifyVa
|
||||||
|
let options = new VariantOptionValueInput()
|
||||||
|
options.id = this.shopify_default_option_value_id
|
||||||
return sps
|
return sps
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateShopifyProduct(shop: Shop) {
|
UpdateShopifyProduct(shop: Shop) {
|
||||||
let sps = this.ToShopifyProductSet()
|
let sps = this.ToShopifyProductSet()
|
||||||
console.log("sps: " + JSON.stringify(sps))
|
console.log("sps: " + JSON.stringify(sps))
|
||||||
|
let query = new ShopifyProductSetQuery(sps)
|
||||||
|
console.log(JSON.stringify(query))
|
||||||
|
let response = shop.shopifyGraphQLAPI(query.JSON)
|
||||||
|
console.log(JSON.stringify(response, null, 2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -552,10 +552,13 @@ export class Shop {
|
|||||||
var url = this.buildURL(endpoint)
|
var url = this.buildURL(endpoint)
|
||||||
console.log(UrlFetchApp.getRequest(url, options))
|
console.log(UrlFetchApp.getRequest(url, options))
|
||||||
var resp = UrlFetchApp.fetch(url, options)
|
var resp = UrlFetchApp.fetch(url, options)
|
||||||
console.log(resp.getContentText())
|
let content = resp.getContentText()
|
||||||
|
console.log(content)
|
||||||
|
let content_json = JSON.parse(content)
|
||||||
|
console.log(JSON.stringify(content_json, null, 2))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: JSON.parse(resp.getContentText()),
|
content: content_json,
|
||||||
headers: resp.getHeaders(),
|
headers: resp.getHeaders(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,7 +617,7 @@ export class ShopifyProduct {
|
|||||||
body_html: string
|
body_html: string
|
||||||
created_at: Date
|
created_at: Date
|
||||||
handle: string
|
handle: string
|
||||||
id: number
|
id: string
|
||||||
images: ProductImage[]
|
images: ProductImage[]
|
||||||
options: ProductOption[]
|
options: ProductOption[]
|
||||||
product_type: string
|
product_type: string
|
||||||
@ -625,10 +628,14 @@ export class ShopifyProduct {
|
|||||||
template_suffix: string
|
template_suffix: string
|
||||||
title: string
|
title: string
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
variants: ShopifyProductVariant[]
|
variants: ShopifyVariantNodes
|
||||||
vendor: string
|
vendor: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ShopifyVariantNodes {
|
||||||
|
nodes: ShopifyProductVariant[]
|
||||||
|
}
|
||||||
|
|
||||||
class ProductImage {
|
class ProductImage {
|
||||||
id: number
|
id: number
|
||||||
product_id: number
|
product_id: number
|
||||||
@ -642,11 +649,25 @@ class ProductImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProductOption {
|
class ProductOption {
|
||||||
id: number
|
id: string
|
||||||
product_id: number
|
product_id: number
|
||||||
name: string
|
name: string
|
||||||
position: number
|
position: number
|
||||||
values: string[]
|
values: string[]
|
||||||
|
optionValues?: ShopifyProductOptionValues
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShopifyProductOptionValues {
|
||||||
|
id?: string
|
||||||
|
name?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShopifyVariantOptionValueInput {
|
||||||
|
id?: string
|
||||||
|
linkedMetafieldValue?: string
|
||||||
|
name?: string
|
||||||
|
optionId?: string
|
||||||
|
optionName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ShopifyProductVariant {
|
export class ShopifyProductVariant {
|
||||||
@ -657,7 +678,7 @@ export class ShopifyProductVariant {
|
|||||||
grams: number
|
grams: number
|
||||||
weight: number
|
weight: number
|
||||||
weight_unit: string
|
weight_unit: string
|
||||||
id: number
|
id: string
|
||||||
inventory_item_id: number
|
inventory_item_id: number
|
||||||
inventory_management: string
|
inventory_management: string
|
||||||
inventory_policy: string
|
inventory_policy: string
|
||||||
@ -680,9 +701,39 @@ class Products {
|
|||||||
|
|
||||||
class ProductEdge {
|
class ProductEdge {
|
||||||
node: ShopifyProduct
|
node: ShopifyProduct
|
||||||
|
variants?: ShopifyVariants
|
||||||
|
options?: ShopifyProductOption[]
|
||||||
cursor: string
|
cursor: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ShopifyProductOption {
|
||||||
|
id?: string
|
||||||
|
name?: string
|
||||||
|
optionValues?: ShopifyProductOptionValue[]
|
||||||
|
values?: ShopifyProductOptionValue[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShopifyProductOptionValue {
|
||||||
|
id?: string
|
||||||
|
name?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShopifyVariants {
|
||||||
|
nodes?: ShopifyVariant[]
|
||||||
|
node?: ShopifyVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ShopifyVariant {
|
||||||
|
id?: string
|
||||||
|
sku?: string
|
||||||
|
price?: number
|
||||||
|
compareAtPrice?: number
|
||||||
|
barcode?: string
|
||||||
|
position?: number
|
||||||
|
nodes?: ShopifyProductVariant[]
|
||||||
|
optionValues?: VariantOptionValueInput[]
|
||||||
|
}
|
||||||
|
|
||||||
class PageInfo {
|
class PageInfo {
|
||||||
hasNextPage: boolean
|
hasNextPage: boolean
|
||||||
hasPreviousPage: boolean
|
hasPreviousPage: boolean
|
||||||
@ -714,7 +765,22 @@ export class ShopifyProductsQuery {
|
|||||||
this.GQL = `{
|
this.GQL = `{
|
||||||
products(first: ${pageSize}${cursorText}${queryText}) {
|
products(first: ${pageSize}${cursorText}${queryText}) {
|
||||||
edges {
|
edges {
|
||||||
node { ${fields.join(" ")} }
|
node {
|
||||||
|
${fields.join(" ")}
|
||||||
|
variants(first:1) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
optionValues {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
hasNextPage
|
hasNextPage
|
||||||
@ -736,38 +802,35 @@ export class ShopifyProductsResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ShopifyProductSetQuery {
|
export class ShopifyProductSetQuery {
|
||||||
GQL: string
|
GQL: string = `mutation setProduct($productSet: ProductSetInput!) {
|
||||||
JSON: JSON
|
productSet(input: $productSet) {
|
||||||
constructor(
|
product {
|
||||||
query: string = "",
|
id
|
||||||
fields: string[] = ["id", "title", "handle"],
|
|
||||||
cursor: string = "",
|
|
||||||
pageSize: number = 10
|
|
||||||
) {
|
|
||||||
let cursorText: string
|
|
||||||
if (cursor == "") {
|
|
||||||
cursorText = ""
|
|
||||||
} else {
|
|
||||||
cursorText = `, after: "${cursor}"`
|
|
||||||
}
|
}
|
||||||
let queryText: string
|
productSetOperation {
|
||||||
if (query == "") {
|
id
|
||||||
queryText = ""
|
status
|
||||||
} else {
|
userErrors {
|
||||||
queryText = `, query: "${query}"`
|
code
|
||||||
|
field
|
||||||
|
message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.GQL = `{
|
userErrors {
|
||||||
products(first: ${pageSize}${cursorText}${queryText}) {
|
code
|
||||||
edges {
|
field
|
||||||
node { ${fields.join(" ")} }
|
message
|
||||||
}
|
|
||||||
pageInfo {
|
|
||||||
hasNextPage
|
|
||||||
endCursor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
let j = `{"query": ${formatGqlForJSON(this.GQL)}}`
|
JSON: JSON
|
||||||
|
constructor(product: ShopifyProductSetInput, synchronous: boolean = true) {
|
||||||
|
let j = `{
|
||||||
|
"query": ${formatGqlForJSON(this.GQL)},
|
||||||
|
"variables": {
|
||||||
|
"productSet": ${JSON.stringify(product)}
|
||||||
|
}
|
||||||
|
}`
|
||||||
console.log(j)
|
console.log(j)
|
||||||
this.JSON = JSON.parse(j)
|
this.JSON = JSON.parse(j)
|
||||||
}
|
}
|
||||||
@ -782,8 +845,30 @@ export class ShopifyProductSetInput {
|
|||||||
status: string = "DRAFT"
|
status: string = "DRAFT"
|
||||||
tags: string
|
tags: string
|
||||||
title: string
|
title: string
|
||||||
variants: ShopifyProductVariant[]
|
|
||||||
vendor: string
|
vendor: string
|
||||||
|
variants: ShopifyVariant[]
|
||||||
|
productOptions: ShopifyProductOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProductVariantSetInput {
|
||||||
|
barcode: string
|
||||||
|
compareAtPrice: number
|
||||||
|
id: string
|
||||||
|
optionValues: VariantOptionValueInput[] = []
|
||||||
|
position?: number
|
||||||
|
price?: number
|
||||||
|
requiresComponents?: boolean
|
||||||
|
sku?: string
|
||||||
|
taxable?: boolean
|
||||||
|
taxCode?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VariantOptionValueInput {
|
||||||
|
id?: string
|
||||||
|
linkedMetafieldValue?: string
|
||||||
|
name?: string
|
||||||
|
optionId?: string
|
||||||
|
optionName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatGqlForJSON(gql: string) {
|
function formatGqlForJSON(gql: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user