Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

response.status_code on insert a product #99

Open
dinhopereira opened this issue Apr 4, 2024 · 3 comments
Open

response.status_code on insert a product #99

dinhopereira opened this issue Apr 4, 2024 · 3 comments

Comments

@dinhopereira
Copy link

dinhopereira commented Apr 4, 2024

I have been trying to use a simple code to post a product on WooCommerce from Python.

Im trying this code:

import sys
import googlemaps
from woocommerce import API
import base64



wcapi = API(
    url="https://mysite.com", 
    consumer_key="ck_e6*********************************b9c5", # Your consumer key
    consumer_secret="cs_3e*********************************e7de19", # Your consumer secret
    wp_api=True, # Enable the WP REST API integration
    version="wc/v3", # WooCommerce WP REST API version
    query_string_auth=True,
    timeout=10
)

data = {
    "name": "Premium Quality",
    "type": "simple",
    "description": "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.",
    "short_description": "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.",
}

response = wcapi.post("products", data)

print("Status: ", response.status_code)
if response.status_code == 201:
    print("Success")
else:
    print("Error")
    # print(response.text)


sys.exit()

I have gotten the "200" status.
Notthing was post on woocommerce.

After i tryed delete with the code:

print(wcapi.delete("products/108", params={"force": True}).json())

And deleted success.
Where am I going wrong?

Tks

@dinhopereira
Copy link
Author

response = wcapi.post("products", data)

response is a empty array

My server is a litepeed and the log below:

SERVER-IP - - [05/Apr/2024:11:32:34 +0000] "POST /wp-admin/admin-ajax.php?action=async_litespeed&nonce=b07b1c4d32&litespeed_type=imgoptm HTTP/1.1" 200 696 "-" "WordPress/6.5; https://www.mydomain.com"
MYIP - - [05/Apr/2024:11:32:33 +0000] "GET /wp-json/wc/v3/products?consumer_key=ck_***************************6feb6c7ecb9c5&consumer_secret=cs_3e0****************************f07e7de19 HTTP/1.1" 200 1097 "-" "WooCommerce-Python-REST-API/3.0.0"
SERVER-IP - - [05/Apr/2024:11:32:33 +0000] "POST /wp-cron.php?doing_wp_cron=1712316753.5901479721069335937500 HTTP/1.1" 200 424 "-" "WordPress/6.5; https://www.mydomain.com"
MYIP - - [05/Apr/2024:11:32:32 +0000] "POST /wp-json/wc/v3/products?consumer_key=ck_***************************6feb6c7ecb9c5&consumer_secret=cs_3e0****************************f07e7de19 HTTP/1.1" 301 1089 "-" "WooCommerce-Python-REST-API/3.0.0"

@nickolaschang
Copy link

Hope this helps, remeber that your CSV file MUST have all the headers equal to whatever info you want to update, for example if you want to update a products name (or add) you need to have a 'name' header in your csv file and etc..

import pandas as pd
import logging
import threading
import time
import tkinter as tk
from tkinter import filedialog, Button, Frame, ttk
from tkinter.scrolledtext import ScrolledText
from woocommerce import API

Define WooCommerce API credentials

WC_URL = 'insert website here'
WC_CONSUMER_KEY = 'insert key here'
WC_CONSUMER_SECRET = 'insert secret here'

Define a global variable for the root window

root = None

class TextHandler(logging.Handler):
def init(self, widget):
super().init()
self.widget = widget

def emit(self, record):
	self.widget.config(state='normal')
	self.widget.insert('end', self.format(record) + '\n')
	self.widget.config(state='disabled')
	self.widget.see('end')

def configure_wc_api():
return API(
url=WC_URL,
consumer_key=WC_CONSUMER_KEY,
consumer_secret=WC_CONSUMER_SECRET,
version="wc/v3",
timeout=300 # Set a higher timeout (in seconds)
)

def make_api_call(wcapi, method, endpoint, data=None, retries=1, delay=0.5):
for attempt in range(retries):
try:
if method.lower() == 'get':
response = wcapi.get(endpoint)
elif method.lower() == 'post':
response = wcapi.post(endpoint, data)
elif method.lower() == 'put':
response = wcapi.put(endpoint, data)
else:
raise ValueError(f"Unsupported HTTP method: {method}")

		if response.status_code == 200:
			logging.info(f"Connection to database Successful... Continuing")
			return response
		elif response.status_code == 201:
			logging.info(f"Product created successfully.")
			return response
		elif response.status_code == 404:
			logging.warning(f"WARNING - Product not found")
			return None
		else:
			logging.error(
				f"ERROR - API call failed with status {response.status_code} for {endpoint}:\n{response.text}")
			time.sleep(delay)
	except Exception as e:
		logging.error(f"ERROR - API call failed with exception for {endpoint}:\n{str(e)}")
		time.sleep(delay)
return None

def process_csv(wcapi, filename, progress_var, total_rows_label):
start_time = time.time()
df = pd.read_csv(filename, encoding='utf-8')
total_rows = len(df)

batch_size = 10
batch = []
final_batch = False  # Flag to track if it's the final batch

for i, row in df.iterrows():
	sku = row.get('sku')
	id_column = row.get('id')

	if not sku and not id_column:
		continue  # Skip rows without SKU and ID

	data = create_product_data(row)

	if id_column:
		data['id'] = id_column
		response = make_api_call(wcapi, 'get', f"products/{id_column}")
		if response and response.status_code == 200:
			batch.append((data, "update"))
			process_product(data, i, total_rows, "update")
		else:
			logging.warning(
				f"WARNING - Product not found for {data.get('name', '')} (SKU: {data.get('sku', '')}, ID: {data.get('id', '')}), creating...")
			batch.append((data, "create"))
			process_product(data, i, total_rows, "create")

	if sku:
		response = make_api_call(wcapi, 'get', f"products?sku={sku}")
		if response and response.status_code == 200:
			product_data = response.json()
			if product_data:
				product_id = product_data[0]['id']
				data['id'] = product_id
				batch.append((data, "update"))
				process_product(data, i, total_rows, "update")
			else:
				logging.warning(
					f"WARNING - Product not found for {data.get('name', '')} (SKU: {data.get('sku', '')}, ID: {data.get('id', '')}), creating...")
				batch.append((data, "create"))
				process_product(data, i, total_rows, "create")

	if len(batch) >= batch_size:
		process_batch(wcapi, batch)
		batch = []

	# Calculate and display estimated time remaining
	elapsed_time = time.time() - start_time
	if elapsed_time > 0:
		completed_percentage = (i + 1) / total_rows * 100
		estimated_total_time = elapsed_time / (completed_percentage / 100)
		estimated_remaining_time = estimated_total_time - elapsed_time
		total_rows_label.config(
			text=f"{completed_percentage:.2f}% complete, estimated time remaining: {int(estimated_remaining_time)} seconds")

if batch:
	process_batch(wcapi, batch)

logging.info("All updates done.")

def create_product_data(row):
# Here you can edit as many fields as you want to edit, keep in mind to follow wcapi standards
data = {
"sku": row['sku'],
"name": row['name'],
"regular_price": row['regular_price'],
"description": row.get('description', ''),
"stock_quantity": int(row['stock_quantity']) if row['stock_quantity'] else None,
"manage_stock": True,
"images": [],
"attributes": [],
"categories": [],
}

image_url = row.get('image_url')
if not pd.isna(image_url):
	data["images"].append({"src": image_url})

data = {k: v if v is not None and (not isinstance(v, float) or not pd.isna(v)) else None for k, v in data.items()}

dimensions_data = {
	"weight": row.get('weight', ''),
	"length": row.get('length', ''),
	"width": row.get('width', ''),
	"height": row.get('height', ''),
}

for key, value in dimensions_data.items():
	if pd.isna(value):
		dimensions_data[key] = ''

if any(dimensions_data.values()):
	data["dimensions"] = dimensions_data

return data

def process_product(data, row_index, total_rows, action):
product_name = data.get('name', 'No Product Name Found in CSV')
if action == "update":
logging.info(f"Processing Row {row_index + 1} of {total_rows}")
logging.info(f"Product '{product_name}' (SKU: {data.get('sku', '')}, ID: {data.get('id', '')}) found")
logging.info(f"Updating Product...\n")
elif action == "create":
logging.info(
f"Product '{product_name}' (SKU: {data.get('sku', '')}, ID: {data.get('id', '')}) not found, creating...")
logging.info(f"Creating Product...\n")

def process_batch(wcapi, batch_data):
batch_action = batch_data[0][1]
logging.info(f"Processing {batch_action} batch...")
products = [data[0] for data in batch_data]
for item in products:
logging.info(
f"Product Sent to be {batch_action.capitalize()}d in WooCommerce, ID:{item.get('id', '')} / SKU: {item.get('sku', '')} / Product: {item.get('name', '')}")
response = make_api_call(wcapi, 'post', "products/batch", {batch_action: products})
if response and response.status_code != 200:
logging.error(
f"ERROR - API call failed with status {response.status_code} for products/batch:\n{response.text}")
else:
logging.info(f"Waiting for the batch to be processed...")
time.sleep(0.5) # Add a sleep time for waiting
logging.info('Processing Done! Moving on to next batch..\n')

def select_and_process_csv(progress_var, total_rows_label):
file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])

if file_path:
	wcapi = configure_wc_api()
	thread = threading.Thread(target=process_csv, args=(wcapi, file_path, progress_var, total_rows_label))
	thread.start()

def main():
global root
root = tk.Tk()
root.title("Change your title name")
root.geometry("600x600")

frame = Frame(root)
frame.pack(fill='both', expand=True)

progress_var = tk.DoubleVar()
progress_bar = ttk.Progressbar(frame, orient="horizontal", length=300, variable=progress_var, mode='determinate')
progress_bar.pack(pady=10)

total_rows_label = tk.Label(frame, text="0% complete, estimated time remaining: calculating...")
total_rows_label.pack()

button = ttk.Button(frame, text="Select and Process CSV File",
                    command=lambda: select_and_process_csv(progress_var, total_rows_label))
button.pack(pady=10)

log_text = ScrolledText(frame, wrap='word', state='disabled', width=80, height=20, font=("Calibri", 12))
log_text.pack(fill='both', expand=True)

logging.basicConfig(
	level=logging.INFO,
	format='%(asctime)s %(levelname)s %(message)s',
	handlers=[
		logging.FileHandler('Product_Sync_Results.txt', mode='w'),
		TextHandler(log_text)
	]
)

root.mainloop()

if name == "main":
main()

@nickolaschang
Copy link

nickolaschang commented Apr 9, 2024

Since GitHub makes a mess with the code you can use this file and paste it on your IDE
SynProducts.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants