Rewritten from python 2.7 to python 3.11
This commit is contained in:
commit
d70da1d39d
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.11 (mssql2mysql)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (mssql2mysql)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/mssql2mysql.iml" filepath="$PROJECT_DIR$/.idea/mssql2mysql.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/mssql2mysql.iml
generated
Normal file
10
.idea/mssql2mysql.iml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
269
abacus2woo.py
Normal file
269
abacus2woo.py
Normal file
@ -0,0 +1,269 @@
|
||||
import ast
|
||||
import sqlite3
|
||||
import sys
|
||||
import time
|
||||
import pyodbc
|
||||
from woocommerce import API
|
||||
|
||||
# import all_from_woo
|
||||
|
||||
conn = sqlite3.connect('imd.db') # intermediary db
|
||||
c = conn.cursor()
|
||||
|
||||
# Create table in SLQLite - we use this for syncing
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS products (id INTEGER NOT NULL PRIMARY KEY ON CONFLICT IGNORE, aid INTEGER,
|
||||
sifra TEXT, naziv TEXT, price REAL, qty INTEGER, snc INTEGER, grupa INTEGER)''')
|
||||
# all_from_woo.initSQLite()
|
||||
|
||||
# Connect to WooCommerce API
|
||||
wcapi = API(
|
||||
url="https://www.rasterdoo.com/",
|
||||
consumer_key="ck_b3169b1723f6f39a965ed04ecfa77860fb89bbf5",
|
||||
consumer_secret="cs_a83f0217ed8d6191ab7de9df06a0c2b652f6bd57",
|
||||
wp_api=True,
|
||||
timeout=360,
|
||||
version="wc/v2"
|
||||
)
|
||||
print("Resting for for a bit...")
|
||||
# time.sleep(50)
|
||||
|
||||
print("Connecting to MS SQL server")
|
||||
'''
|
||||
cnxn = pyodbc.connect('Driver={SQL Server};'
|
||||
'Server=SERVER-BS;'
|
||||
'Database=abacus_raster;'
|
||||
'Trusted_Connection=yes;')
|
||||
'''
|
||||
cnxn = pyodbc.connect('DRIVER={SQL Server};'
|
||||
'SERVER=raster.mywire.org,1433;'
|
||||
'DATABASE=abacus_raster;'
|
||||
'UID=sa;'
|
||||
'PWD=!Pos456!;'
|
||||
'TDS_Version=7.3;')
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
|
||||
# Prvi artikal pocetnog stanja 2019 se vodi pod brojem "306570", za 2020 pod brojem "396498".
|
||||
# Ako racunamo lager za artikle od njega dobicemo pravo stanje za 2019. Ukoliko ovo ne uradimo,
|
||||
# lager se racuna od pocetka rada sa Abacusom - i vodi do gresaka.
|
||||
# prvo nadjemo id_document pocetnog stanja (prvog dokumenta u godini)
|
||||
# /****** Script for SelectTopNRows command from SSMS ******/
|
||||
# SELECT id_dokument, id_vrsta, broj_dok, datum
|
||||
# FROM abacus_raster.dbo.artikal_dokument
|
||||
# WHERE (datum > CONVERT(DATETIME, '2020-12-31 00:00:00', 102))
|
||||
#
|
||||
# A onda nadjemo artikal u lageru - Stari kod:
|
||||
# SELECT id_artikal, multiply * kol AS qty
|
||||
# FROM abacus_raster.dbo.artikal_dnevnik
|
||||
# WHERE (multiply <> 0) AND id_dnevnik >=396498.
|
||||
cursor.execute('''SELECT a.id_artikal,
|
||||
SUM (a.qty) AS stanje
|
||||
INTO tmplager
|
||||
FROM (SELECT artikal_dnevnik.id_artikal,
|
||||
artikal_dnevnik.multiply*artikal_dnevnik.kol AS 'qty'
|
||||
FROM abacus_raster.dbo.artikal_dnevnik artikal_dnevnik, abacus_raster.dbo.artikal_dokument artikal_dokument
|
||||
WHERE artikal_dnevnik.id_dokument = artikal_dokument.id_dokument AND ((artikal_dokument.datum_fak>={d '2024-01-01'})) AND (artikal_dokument.id_vrsta <> 18) ) \
|
||||
AS a INNER JOIN
|
||||
abacus_raster.dbo.artikal ON a.id_artikal = abacus_raster.dbo.artikal.id_artikal
|
||||
GROUP BY a.id_artikal ''')
|
||||
|
||||
cursor.execute('''SELECT abacus_raster.dbo.artikal_cijenik.id_artikal, abacus_raster.dbo.artikal_cijenik.cijena,
|
||||
abacus_raster.dbo.artikal.naziv, abacus_raster.dbo.artikal.sifra,
|
||||
tmplager.stanje, abacus_raster.dbo.artikal.id_grupa, tmplager.id_artikal AS tid
|
||||
FROM abacus_raster.dbo.artikal_cijenik INNER JOIN
|
||||
abacus_raster.dbo.artikal INNER JOIN
|
||||
tmplager ON abacus_raster.dbo.artikal.id_artikal = tmplager.id_artikal ON
|
||||
abacus_raster.dbo.artikal_cijenik.id_artikal = abacus_raster.dbo.artikal.id_artikal
|
||||
WHERE (abacus_raster.dbo.artikal_cijenik.id_mjesto = 2) AND abacus_raster.dbo.artikal.id_grupa <> 11''')
|
||||
# Save products from Abacus in SQLite table
|
||||
row = cursor.fetchone()
|
||||
print("Abacus row in works:"), row #
|
||||
snc = 0
|
||||
for row in cursor:
|
||||
while row is not None:
|
||||
# print("Abacus row entered for loop and it is not None")
|
||||
# input("Press Enter to continue...") #
|
||||
aid = row[0]
|
||||
aprice = float(row[1])
|
||||
aname = row[2]
|
||||
asifra = row[3]
|
||||
aqty = int(row[4])
|
||||
agroup = row[5]
|
||||
print("MS Sql group value:", agroup)
|
||||
# This dictionary matches abacus product category id to equivalent id in woocommerce
|
||||
groupdict = {
|
||||
1: 21472, 2: 21473, 4: 21474, 5: 21475, 10: 21476, 11: 21477, 13: 21477, 15: 21477, 19: 21478, 24: 21479,
|
||||
30: 21480, 32: 21481, 33: 21482, 37: 21483, 38: 21484, 44: 21485, 45: 21486, 47: 21477, 48: 21477
|
||||
}
|
||||
print("Coverted to Woocommerce group it becomes wgroup:", groupdict[agroup])
|
||||
if agroup in groupdict:
|
||||
wgroup = groupdict[agroup]
|
||||
print("Group in abacusu is from dictionary:", agroup, " - while woocommerce now holds:", wgroup) #
|
||||
else:
|
||||
wgroup = 3557
|
||||
print("Group ", agroup, "does not exist in dictionary - we put it in woocommerce group -other-:", wgroup) #
|
||||
|
||||
# Test id Woo product exists in SQLite table
|
||||
q = (asifra,)
|
||||
c.execute('SELECT * FROM products WHERE sifra=?', q)
|
||||
print("Abacus data to be saved in SQLite:", aid, aprice, aname, asifra, aqty, wgroup)
|
||||
# input("Press Enter to continue...") #
|
||||
# We test SqlLite rows so that we update the table only with products that changed
|
||||
trow = c.fetchone()
|
||||
if trow is not None:
|
||||
tnaziv = trow[3]
|
||||
tprice = trow[4]
|
||||
tqty = trow[5]
|
||||
tgroup = trow[7]
|
||||
# print("There is an SQLite trow we need to check for an update: "), tnaziv, tprice, tqty, tgroup
|
||||
if aprice != tprice:
|
||||
snc = 1
|
||||
print("bad price")
|
||||
if aqty != tqty:
|
||||
snc = 1
|
||||
print("bad qty")
|
||||
if aname != tnaziv:
|
||||
snc = 1
|
||||
print("bad naziv")
|
||||
if wgroup != tgroup:
|
||||
snc = 1
|
||||
print(wgroup, "bad tgroup: ", tgroup)
|
||||
if snc == 1:
|
||||
# print("=======")
|
||||
c.execute('''UPDATE products SET aid = ?, price = ?, qty =?, naziv = ?,
|
||||
snc = ?, grupa = ? WHERE sifra = ?''',
|
||||
(aid, aprice, aqty, aname, snc, wgroup, asifra))
|
||||
conn.commit()
|
||||
c.execute('SELECT * FROM products WHERE sifra=?', q)
|
||||
trow = c.fetchone()
|
||||
print(trow)
|
||||
print("=======")
|
||||
# input("Press Enter to continue...")
|
||||
else:
|
||||
print("If sqlite trow does not exist (is ", trow, "), then first create one in Woo", aid, asifra, aname,
|
||||
aprice, aqty, wgroup)
|
||||
# input("Press Enter to continue...") #
|
||||
aprice = str(aprice)
|
||||
data = {
|
||||
"sku": asifra,
|
||||
"name": aname,
|
||||
"regular_price": aprice,
|
||||
"description": "",
|
||||
"managing_stock": "true",
|
||||
"in_stock": "true",
|
||||
"status": "publish",
|
||||
"stock_quantity": aqty,
|
||||
"categories": [
|
||||
{
|
||||
"id": wgroup
|
||||
}
|
||||
],
|
||||
}
|
||||
w = wcapi.post("products", data).json()
|
||||
|
||||
|
||||
# w = wcapi.get("products/categories").json()
|
||||
|
||||
class ListStream:
|
||||
def __init__(self):
|
||||
self.data = []
|
||||
|
||||
def write(self, s):
|
||||
self.data.append(s)
|
||||
|
||||
|
||||
sys.stdout = x = ListStream()
|
||||
print(w)
|
||||
sys.stdout = sys.__stdout__
|
||||
wresponse = (x.data[0])
|
||||
print("Full woo response: ", wresponse)
|
||||
# print("wresponse:", wresponse[38:53])
|
||||
if wresponse[38:53] == "duplicirani SKU":
|
||||
# if wresponse[26:40] == "duplicated SKU":
|
||||
d = ast.literal_eval(wresponse)
|
||||
errd = d.get('data')
|
||||
print(errd)
|
||||
rogueone = errd.get('resource_id')
|
||||
print("We have a duplicated product in Woo: ", rogueone)
|
||||
c.execute('INSERT INTO products VALUES (?,?,?,?,?,?,?,?)',
|
||||
(rogueone, aid, asifra, aname, aprice, aqty, 1, wgroup)) # if no product it will create
|
||||
print("Inserting rogueone in SQLlite data:", rogueone, aid, asifra, aname, aprice, aqty, 1, wgroup)
|
||||
conn.commit()
|
||||
# rgpath = "\"products/" + str(rogueone) + "\""
|
||||
# print rgpath
|
||||
# rg = wcapi.get(rogueone).json()
|
||||
# print("The rogueone:", rg)
|
||||
else:
|
||||
print("Since trow was NONE, we had to create it on woo, get the id (woo), then save it (SQLite):",
|
||||
type(w), w)
|
||||
wid = w.get('id')
|
||||
wsku = w.get('sku')
|
||||
wname = w.get('name')
|
||||
wprice = w.get('price')
|
||||
wqty = w.get('qty')
|
||||
if wname is None:
|
||||
print("Why problems? ...:", wid, aid, wsku, wname, wprice, wqty)
|
||||
else:
|
||||
c.execute('INSERT INTO products VALUES (?,?,?,?,?,?,?,"")',
|
||||
(wid, aid, wsku, wname, wprice, wqty, 1)) # if no product it will create
|
||||
conn.commit()
|
||||
row = cursor.fetchone()
|
||||
# print("Resting for for a bit...")
|
||||
# time.sleep(5)
|
||||
conn.close()
|
||||
|
||||
# Update Woo with our SQLite table
|
||||
conn = sqlite3.connect('imd.db') # intermediary db
|
||||
c = conn.cursor()
|
||||
c.execute('''SELECT * FROM products WHERE snc = 1 ORDER BY naziv''')
|
||||
trow = c.fetchone()
|
||||
|
||||
print("Selected for update:", trow)
|
||||
# cleantrow is not None:
|
||||
grupa = 0
|
||||
while trow is not None:
|
||||
id = trow[0]
|
||||
tnaziv = trow[3]
|
||||
tprice = str(trow[4])
|
||||
tqty = trow[5]
|
||||
tgroup = trow[7]
|
||||
# print type(id), type(tnaziv), type(tprice), type(tqty), "Grupa:", type(tgroup), tgroup
|
||||
# input("Press enter ...")
|
||||
data = {
|
||||
"id": id,
|
||||
"manage_stock": "true",
|
||||
"stock_quantity": tqty,
|
||||
"name": tnaziv,
|
||||
"status": "publish",
|
||||
"regular_price": tprice,
|
||||
"categories": [
|
||||
{
|
||||
"id": tgroup
|
||||
}
|
||||
],
|
||||
}
|
||||
# print data
|
||||
uplink = "products/" + str(id)
|
||||
# print uplink
|
||||
up = wcapi.put((uplink), data).json()
|
||||
print(up)
|
||||
# input("Press enter ...")
|
||||
if trow is None:
|
||||
break
|
||||
else:
|
||||
trow = c.fetchone()
|
||||
print("___________________________________________")
|
||||
print("Selected next for update:", trow)
|
||||
c.execute('UPDATE products SET snc = 0')
|
||||
conn.commit()
|
||||
|
||||
# Drop the temporary table
|
||||
|
||||
print("Preparing to drop the tmptable")
|
||||
cursor.execute('''drop table tmplager''')
|
||||
print("Dropped the tmptable")
|
||||
cursor.close()
|
||||
|
||||
del cursor
|
||||
conn.close() # close sqlite connection
|
||||
print("All done!")
|
||||
78
all_from_woo.py
Normal file
78
all_from_woo.py
Normal file
@ -0,0 +1,78 @@
|
||||
def initSQLite():
|
||||
# The following will download all existing woocommerce products and save them in SQLite.
|
||||
# From that point the synchronization can start in local.
|
||||
from woocommerce import API
|
||||
import sqlite3
|
||||
import pyodbc
|
||||
|
||||
conn = sqlite3.connect('imd.db') # intermediary db
|
||||
c = conn.cursor()
|
||||
# Create table in SLQLite - we use this for syncing
|
||||
c.execute('DROP TABLE products')
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS products (id INTEGER NOT NULL PRIMARY KEY ON CONFLICT IGNORE, aid INTEGER,
|
||||
sifra TEXT, naziv TEXT, price REAL, qty INTEGER, snc INTEGER, grupa INTEGER)''')
|
||||
|
||||
|
||||
# Connect to WooCommerce API
|
||||
wcapi = API(
|
||||
url="https://www.rasterdoo.com/",
|
||||
consumer_key="ck_b3169b1723f6f39a965ed04ecfa77860fb89bbf5",
|
||||
consumer_secret="cs_a83f0217ed8d6191ab7de9df06a0c2b652f6bd57",
|
||||
wp_api=True,
|
||||
version="wc/v2"
|
||||
)
|
||||
r = wcapi.get("products") # get woo web page where products are
|
||||
h = int(r.headers['X-WP-TotalPages']) # in the header we see number of tot pages
|
||||
print("Total pages:", h)
|
||||
|
||||
for page_no in range(1, h+1): # lets go through pages
|
||||
goto_page = 'products?page=' + str(page_no)
|
||||
print(page_no, "(", h, ")")
|
||||
r = wcapi.get(goto_page)
|
||||
page_txt = r.json() # contents of one page ar stored in variable
|
||||
# We fill our SQLite table with Woo Products
|
||||
for product in page_txt: # first we go through products in this page
|
||||
wsku = product.get('sku')
|
||||
wid = product.get('id')
|
||||
wname = product.get('name')
|
||||
wprice = product.get('regular_price')
|
||||
wqty = product.get('stock_quantity')
|
||||
if wqty is None:
|
||||
wqty = 0
|
||||
# FIX THIS! - It does not update - just inserts if new ...
|
||||
c.execute('INSERT INTO products VALUES (?,?,?,?,?,?,?,?)',
|
||||
(wid, "", wsku, wname, wprice, wqty, 0)) # if no product it will create
|
||||
c.execute('UPDATE products SET aid = ?, sifra = ?, naziv = ?, price = ?, qty = ?, snc = ? WHERE id = ?',
|
||||
("", wsku, wname, wprice, wqty, 0, wid, ""))
|
||||
print("Insert woocommerce data to SQLlite:", wid, "", wsku, wname, wprice, wqty, 0)
|
||||
conn.commit()
|
||||
|
||||
print("")
|
||||
print("Fixing some problems with decimals...")
|
||||
c.execute('''UPDATE products SET price = replace( price, ',', '.' ) WHERE price LIKE ?''', ('%,%',))
|
||||
conn.commit()
|
||||
|
||||
# Sometimes woo has a product, but abacus does not, meaning we don't have them anymore. SO, qty needs to be 0.
|
||||
print("Checking if products on woo exist on abacus")
|
||||
# list of woo products
|
||||
c.execute('''SELECT sifra, naziv, qty FROM products''')
|
||||
trow = c.fetchone()
|
||||
# find them on abacus
|
||||
cnxn = pyodbc.connect('Driver={SQL Server};'
|
||||
'Server=SERVER-BS;'
|
||||
'Database=abacus_raster;'
|
||||
'Trusted_Connection=yes;')
|
||||
cursor = cnxn.cursor()
|
||||
|
||||
while trow is not None:
|
||||
sifra = trow[0]
|
||||
naziv = trow[1]
|
||||
cursor.execute('''SELECT id_artikal, sifra, naziv FROM abacus_raster.dbo.artikal WHERE sifra = ?''', (sifra, ))
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
print(sifra, naziv, " - does not exist on abacus, at least we should set qty to 0")
|
||||
c.execute('''UPDATE products SET qty = 0 WHERE sifra = ?''', (sifra,))
|
||||
conn.commit()
|
||||
trow = c.fetchone()
|
||||
|
||||
conn.close()
|
||||
Loading…
Reference in New Issue
Block a user