commit 542a7820f5711a86fcc2f54b0eac765148f61a3a Author: Vladyslav Shatrovskyi Date: Sat Feb 10 14:17:43 2024 +0200 first release diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..50df6c9 --- /dev/null +++ b/.env.sample @@ -0,0 +1,6 @@ +DB_HOST=DB_HOST +USERS=USERS +PASSW=PASSW +DATABASE=DATABASE + +SPREADSHEET_ID=SPREADSHEET_ID diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff519f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,161 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ +creds_service_acc.json diff --git a/dev_xlsx.py b/dev_xlsx.py new file mode 100644 index 0000000..3dbe64b --- /dev/null +++ b/dev_xlsx.py @@ -0,0 +1,21 @@ +import os +import gspread +from oauth2client.service_account import ServiceAccountCredentials +from dotenv import load_dotenv + + +load_dotenv() + +# SET UP GOOGLE SPREADSHEET +SPREADSHEET_ID = os.getenv('SPREADSHEET_ID') +SCOPES = [ + 'https://www.googleapis.com/auth/spreadsheets', + 'https://www.googleapis.com/auth/drive' +] + +CREDENTIALS = ServiceAccountCredentials.from_json_keyfile_name('creds_service_acc.json', SCOPES) +client = gspread.authorize(CREDENTIALS) + + +# Open the spreadsheet using the correct spreadsheet key +spreadsheet = client.open_by_key(SPREADSHEET_ID) diff --git a/models.py b/models.py new file mode 100644 index 0000000..c180857 --- /dev/null +++ b/models.py @@ -0,0 +1,57 @@ +import os +from dotenv import load_dotenv +from peewee import * + + +load_dotenv() + +DATABASE = os.getenv("DATABASE") +DB_HOST = os.getenv("DB_HOST") +USERS = os.getenv("USERS") +PASSW = os.getenv("PASSW") + + +db = MySQLDatabase( + database=DATABASE, user=USERS, password=PASSW, host=DB_HOST, port=3306 +) + + +class Price(Model): + sku = CharField() + Название_позиции_укр = CharField(null=True) + РРЦ = IntegerField(null=True) + Количество = IntegerField(null=True) + Цена_Prom_розница = IntegerField(null=True) + Скидка_в_процент_Prom_розница = IntegerField(null=True) + Время_скидки_Prom_розница = CharField(null=True) + Минимальный_объем_заказа = IntegerField(null=True) + Цена_Prom_Оптовыей_сайт = IntegerField(null=True) + Минимальный_заказ_опт = IntegerField(null=True) + Скидка_в_процент_Prom_опт = IntegerField(null=True) + Время_скидки_Prom_опт = CharField(null=True) + Уникальный_идентификатор_prom_розн = IntegerField(null=True) + Цена_розн_розетка_r = IntegerField(null=True) + Цена_старая_розетка = IntegerField(null=True) + Цена_розн_эпицентр_e = IntegerField(null=True) + Цена_розн_алло_a = IntegerField(null=True) + Цена_опенкарт_дроп_os = IntegerField(null=True) + Цена_опенкарт_опт_os = IntegerField(null=True) + Цена_опенкарт_крупнопт_os = IntegerField(null=True) + Уникальный_идентификатор_prom_опт = IntegerField(null=True) + ID_KCRM = IntegerField(null=True) + Уникальный_идентификатор_Rozetka = IntegerField(null=True) + Уникальный_идентификатор_OS = IntegerField(null=True) + Штрих_code = IntegerField(null=True) + Дата_скидки_OC = DateField(null=True) + Скидка_дроп_процент = IntegerField(null=True) + Скидка_опт_процент = IntegerField(null=True) + Скидка_Крупный_опт_процент = IntegerField(null=True) + Цена_опенкарт_дроп_pro_os = IntegerField(null=True) + Цена_опенкарт_крупнопт_ТОВ_os = IntegerField(null=True) + Скидка_дропPRO_процент = IntegerField(null=True) + + class Meta: + database = db + +# Connect to the database and create tables +db.create_tables([Price]) diff --git a/update_spredsheet.py b/update_spredsheet.py new file mode 100644 index 0000000..7385242 --- /dev/null +++ b/update_spredsheet.py @@ -0,0 +1,36 @@ +from dev_xlsx import spreadsheet +from models import Price + + +def fetch_data_from_database(): + # Query the database for the data + data = {} + for price in Price.select(): + data[price.sku] = price.Количество # Assuming 'sku' is the key + return data + + +def update_spreadsheet_with_new_values(new_values): + # Open the first worksheet + worksheet = spreadsheet.get_worksheet(0) + + # Get all values from the worksheet + values = worksheet.get_all_values() + headers = values[0] + + # Find the index of 'Количество' column + quantity_index = headers.index('Количество') + + # Update values in the spreadsheet + for row in values[1:]: # Skip the header row + sku = row[0] # Assuming SKU is the first column + if sku in new_values and row[quantity_index] != str(new_values[sku]): # Compare as strings + worksheet.update_cell(values.index(row) + 1, quantity_index + 1, str(new_values[sku])) # Adjust to 1-based index + + +if __name__ == "__main__": + # Fetch data from the database + data_from_database = fetch_data_from_database() + + # Compare values and update the spreadsheet + update_spreadsheet_with_new_values(data_from_database) diff --git a/xlsx_to_db_transformer.py b/xlsx_to_db_transformer.py new file mode 100644 index 0000000..f543e0c --- /dev/null +++ b/xlsx_to_db_transformer.py @@ -0,0 +1,78 @@ +import pandas as pd + +from dev_xlsx import spreadsheet +from models import Price, db + + +def spreadsheet_transform(): + try: + # Select the first worksheet + worksheet = spreadsheet.get_worksheet(0) + # Get all values from the worksheet + values = worksheet.get_all_values() + # Convert values to DataFrame + df = pd.DataFrame(values[1:], columns=values[0]) + except Exception as e: + print(f"Error retrieving data from Google Spreadsheet: {e}") + return + + column_mapping = { + "": "sku", + "Название_позиции_укр": "Название_позиции_укр", + "РРЦ": "РРЦ", + "Количество": "Количество", + "Цена Prom розница": "Цена_Prom_розница", + "Скидка в % Prom розница": "Скидка_в_процент_Prom_розница", + "Время скидки Prom розница": "Время_скидки_Prom_розница", + "Минимальный_объем_заказа": "Минимальный_объем_заказа", + "Цена Prom Оптовыей сайт": "Цена_Prom_Оптовыей_сайт", + "Минимальный_заказ_опт": "Минимальный_заказ_опт", + "Скидка в % Prom опт": "Скидка_в_процент_Prom_опт", + "Время скидки Prom опт": "Время_скидки_Prom_опт", + "Уникальный_идентификатор prom розн": "Уникальный_идентификатор_prom_розн", + "Цена_розн_розетка_r": "Цена_розн_розетка_r", + "Цена старая розетка": "Цена_старая_розетка", + "Цена_розн_эпицентр_e": "Цена_розн_эпицентр_e", + "Цена_розн_алло_a": "Цена_розн_алло_a", + "Цена_опенкарт_дроп_os": "Цена_опенкарт_дроп_os", + "Цена_опенкарт_опт_os": "Цена_опенкарт_опт_os", + "Цена_опенкарт_крупнопт_os": "Цена_опенкарт_крупнопт_os", + "Уникальный_идентификатор prom опт": "Уникальный_идентификатор_prom_опт", + "ID KCRM": "ID_KCRM", + "Уникальный_идентификатор Rozetka": "Уникальный_идентификатор_Rozetka", + "Уникальный_идентификатор OS": "Уникальный_идентификатор_OS", + "Штрих code": "Штрих_code", + "Дата скидки OC": "Дата_скидки_OC", + "Скидка дроп %": "Скидка_дроп_процент", + "Скидка опт %": "Скидка_опт_процент", + "Скидка Крупный опт % ": "Скидка_Крупный_опт_процент", + "Цена_опенкарт_дроп_pro_os": "Цена_опенкарт_дроп_pro_os", + "Цена_опенкарт_крупнопт-ТОВ_os": "Цена_опенкарт_крупнопт_ТОВ_os", + "Скидка дропPRO %": "Скидка_дропPRO_процент" + } + + # Iterate over rows and save to the database + try: + # Iterate over rows and save to the database + for index, row in df.iterrows(): + # Create a dictionary to store mapped data + mapped_data = {} + for column_name, field_name in column_mapping.items(): + # Map DataFrame column to model field + mapped_data[field_name] = row[column_name] + try: + # Create a Price object using mapped data + Price.create(**mapped_data) + except Exception as e: + print(f"Error inserting row {index}: {e}") + print("Data inserted successfully.") + except Exception as e: + print(f"Error inserting data into the database: {e}") + finally: + # Close the database connection + db.close() + + +# run script when you want to update all db +if __name__ == "__main__": + spreadsheet_transform()