P5-4896 remove esales
This commit is contained in:
@@ -34,8 +34,6 @@ List of available configuration options:
|
|||||||
| `SQLALCHEMY_DATABASE_URI` | Database connection string. e.g: `postgresql://user:password@localhost/photowall` |
|
| `SQLALCHEMY_DATABASE_URI` | Database connection string. e.g: `postgresql://user:password@localhost/photowall` |
|
||||||
| `DEBUG` | Enable/disable debug mode |
|
| `DEBUG` | Enable/disable debug mode |
|
||||||
| `API_KEYS` | A list of api keys that are used to authenticate to the API. If this list is empty authentication will be disabled. |
|
| `API_KEYS` | A list of api keys that are used to authenticate to the API. If this list is empty authentication will be disabled. |
|
||||||
| `ESALES_URL` | URL to the eSales server. If its a cloud cluster it has the format `username:password` |
|
|
||||||
| `ESALES_IMPORT_DIR` | XML-files that should be imported to eSales are temporarily stored in this directory. e.g: `/tmp/esales`
|
|
||||||
| `BERNARD_QUEUE_URL` | URL to Bernard queue (used for running Photowall background tasks)
|
| `BERNARD_QUEUE_URL` | URL to Bernard queue (used for running Photowall background tasks)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
@@ -44,10 +42,6 @@ Starting the application:
|
|||||||
|
|
||||||
`$ python manage.py runserver`
|
`$ python manage.py runserver`
|
||||||
|
|
||||||
Running the eSales import
|
|
||||||
|
|
||||||
`$ python manage.py run_esales_import`
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
To run unit tests:
|
To run unit tests:
|
||||||
|
|||||||
+1
-2
@@ -1,5 +1,5 @@
|
|||||||
from flask import Flask, jsonify, Response, request
|
from flask import Flask, jsonify, Response, request
|
||||||
from api.extensions import db, esales, bernard
|
from api.extensions import db, bernard
|
||||||
from api.validators import ValidationError
|
from api.validators import ValidationError
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ def create_app(config_name="config"):
|
|||||||
app.config.from_object(config_name)
|
app.config.from_object(config_name)
|
||||||
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
esales.init_app(app)
|
|
||||||
bernard.init_app(app)
|
bernard.init_app(app)
|
||||||
|
|
||||||
# register errors handlers
|
# register errors handlers
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from esales.flask_esales import Esales
|
|
||||||
from api.lib.bernard import Bernard
|
from api.lib.bernard import Bernard
|
||||||
|
|
||||||
|
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
esales = Esales()
|
|
||||||
bernard = Bernard()
|
bernard = Bernard()
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import json
|
|||||||
|
|
||||||
class Bernard(object):
|
class Bernard(object):
|
||||||
def __init__(self, app=None):
|
def __init__(self, app=None):
|
||||||
self.sqs = boto3.client("sqs", region_name='eu-west-1')
|
self.sqs = boto3.client("sqs", region_name="eu-west-1")
|
||||||
if app:
|
if app:
|
||||||
self.init_app(app)
|
self.init_app(app)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from api import db, tasks
|
from api import db
|
||||||
from api.models import Designer
|
from api.models import Designer
|
||||||
from api.helpers import pagination_to_dict, check_api_key
|
from api.helpers import pagination_to_dict, check_api_key
|
||||||
from api.validators import validate_jsonschema
|
from api.validators import validate_jsonschema
|
||||||
@@ -58,5 +58,5 @@ def update(id):
|
|||||||
setattr(designer, k, v)
|
setattr(designer, k, v)
|
||||||
db.session.add(designer)
|
db.session.add(designer)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
tasks.esales.update_designer(designer)
|
|
||||||
return jsonify(designer.to_json())
|
return jsonify(designer.to_json())
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from . import esales
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
from flask import current_app
|
|
||||||
from api.models.locale import Locale
|
|
||||||
from esales.models import Category, CategoryTree
|
|
||||||
from esales.utils import ImportFile
|
|
||||||
|
|
||||||
|
|
||||||
def update_designer(designer):
|
|
||||||
category = Category(
|
|
||||||
"root/designers/{}".format(designer.path),
|
|
||||||
display_name=designer.name,
|
|
||||||
visible_search=designer.visible_search,
|
|
||||||
visible_list=designer.visible_list,
|
|
||||||
visible_productpage=designer.visible_productpage,
|
|
||||||
visible_designerpage=designer.visible_designerpage,
|
|
||||||
exclude_from_overview=designer.exclude_from_overview,
|
|
||||||
send_to_bottom=designer.send_to_bottom,
|
|
||||||
no_follow=designer.no_follow,
|
|
||||||
hidden=1,
|
|
||||||
path="/designers/{}".format(designer.path),
|
|
||||||
)
|
|
||||||
importfile = ImportFile()
|
|
||||||
for locale in Locale.query.all():
|
|
||||||
tree = CategoryTree("categories_{}".format(locale.value))
|
|
||||||
tree.add_category(category)
|
|
||||||
importfile.add_operation("update", tree)
|
|
||||||
|
|
||||||
directory = current_app.config.get("ESALES_IMPORT_DIR")
|
|
||||||
importfile.write(directory)
|
|
||||||
@@ -2,6 +2,4 @@ SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@host/db_name'
|
|||||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
API_KEYS = ['secretkey']
|
API_KEYS = ['secretkey']
|
||||||
ESALES_URL = 'username:password'
|
|
||||||
ESALES_IMPORT_DIR = '/tmp/esales'
|
|
||||||
BERNARD_QUEUE_URL = 'https://sqs.eu-west-1.amazonaws.com/<queue_id>/<queue_name>'
|
BERNARD_QUEUE_URL = 'https://sqs.eu-west-1.amazonaws.com/<queue_id>/<queue_name>'
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from .cluster import Cluster
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger("esales")
|
|
||||||
|
|
||||||
|
|
||||||
class CommandException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Cluster(object):
|
|
||||||
|
|
||||||
def __init__(self, url=None):
|
|
||||||
self.url = url
|
|
||||||
|
|
||||||
def run_command(self, command):
|
|
||||||
""" execute a command against the esales cluster """
|
|
||||||
try:
|
|
||||||
# find the location of the jar file (provided by apptus) that is
|
|
||||||
# used to execute the commands
|
|
||||||
jar = os.path.abspath(os.path.dirname(
|
|
||||||
__file__) + "/command/command.jar")
|
|
||||||
subprocess.check_output(
|
|
||||||
"java -jar {0} {1}".format(jar, command).split(), stderr=subprocess.STDOUT)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
message = "Could not execute command {0}. Error: {1}".format(
|
|
||||||
command, e.output)
|
|
||||||
logger.error(message)
|
|
||||||
raise CommandException(message)
|
|
||||||
except OSError:
|
|
||||||
sys.exit("Java not found on this system")
|
|
||||||
|
|
||||||
def import_products_and_categories(self, pattern):
|
|
||||||
""" imports products and categories into the eSales cluster """
|
|
||||||
i = 0
|
|
||||||
for f in sorted(glob.iglob(pattern)):
|
|
||||||
if os.path.isfile(f):
|
|
||||||
logger.info("Importing {}".format(f))
|
|
||||||
try:
|
|
||||||
self.run_command("import -p {0} {1}".format(self.url, f))
|
|
||||||
i += 1
|
|
||||||
except CommandException as e:
|
|
||||||
logger.error("Failed to import {}".format(f))
|
|
||||||
finally:
|
|
||||||
os.remove(f)
|
|
||||||
|
|
||||||
logger.info("Imported {} file(s)".format(i))
|
|
||||||
return i
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,15 +0,0 @@
|
|||||||
from .cluster import Cluster
|
|
||||||
|
|
||||||
|
|
||||||
class Esales(object):
|
|
||||||
|
|
||||||
def __init__(self, app=None):
|
|
||||||
self.cluster = Cluster()
|
|
||||||
|
|
||||||
if app:
|
|
||||||
self.init_app(app)
|
|
||||||
|
|
||||||
def init_app(self, app):
|
|
||||||
if not 'ESALES_URL' in app.config:
|
|
||||||
raise Exception('ESALES_URL missing in config')
|
|
||||||
self.cluster.url = app.config.get('ESALES_URL')
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
from xml.etree.cElementTree import Element, SubElement
|
|
||||||
|
|
||||||
|
|
||||||
class Category(object):
|
|
||||||
""" represents an eSales category """
|
|
||||||
|
|
||||||
def __init__(self, key, display_name=None, **kwargs):
|
|
||||||
self.key = key
|
|
||||||
self.display_name = display_name
|
|
||||||
self.attributes = {}
|
|
||||||
for k, v in kwargs.items():
|
|
||||||
self.attributes[k] = v
|
|
||||||
|
|
||||||
@property
|
|
||||||
def etree(self):
|
|
||||||
root = Element("category", key=self.key)
|
|
||||||
if self.display_name:
|
|
||||||
SubElement(root, "display_name").text = self.display_name
|
|
||||||
if self.attributes:
|
|
||||||
attributes = SubElement(root, "attributes")
|
|
||||||
for k, v in self.attributes.items():
|
|
||||||
SubElement(attributes, k).text = str(v)
|
|
||||||
|
|
||||||
return root
|
|
||||||
|
|
||||||
|
|
||||||
class CategoryTree(object):
|
|
||||||
"""represents an eSales CategoryTree"""
|
|
||||||
|
|
||||||
def __init__(self, product_attribute):
|
|
||||||
self.categories = []
|
|
||||||
self.product_attribute = product_attribute
|
|
||||||
|
|
||||||
def add_category(self, category):
|
|
||||||
self.categories.append(category)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def etree(self):
|
|
||||||
root = Element("category_tree",
|
|
||||||
product_attribute=self.product_attribute)
|
|
||||||
for category in self.categories:
|
|
||||||
root.append(category.etree)
|
|
||||||
|
|
||||||
return root
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
import os
|
|
||||||
import uuid
|
|
||||||
import time
|
|
||||||
from xml.etree.cElementTree import ElementTree, Element, SubElement, dump
|
|
||||||
|
|
||||||
|
|
||||||
class ImportFile(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.operations = []
|
|
||||||
|
|
||||||
def add_operation(self, operation, model):
|
|
||||||
assert operation in ["create", "update", "delete"]
|
|
||||||
self.operations.append((operation, model))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def etree(self):
|
|
||||||
root = Element("operations")
|
|
||||||
for name, model in self.operations:
|
|
||||||
operation = SubElement(root, name)
|
|
||||||
operation.append(model.etree)
|
|
||||||
return root
|
|
||||||
|
|
||||||
def dump_xml(self):
|
|
||||||
return dump(self.etree)
|
|
||||||
|
|
||||||
def write(self, directory, filename=None):
|
|
||||||
if not os.path.exists(directory):
|
|
||||||
os.makedirs(directory)
|
|
||||||
if not filename:
|
|
||||||
filename = "{}.xml".format(time.time())
|
|
||||||
xml = ElementTree(self.etree)
|
|
||||||
xml.write("{}/{}".format(directory, filename),
|
|
||||||
encoding="UTF-8", xml_declaration=True)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from flask.ext.script import Manager, prompt_bool
|
from flask.ext.script import Manager, prompt_bool
|
||||||
from api import create_app, db, esales
|
from api import create_app, db
|
||||||
from api.models import Designer
|
from api.models import Designer
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
@@ -27,11 +27,5 @@ def seed_db():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
@manager.command
|
|
||||||
def run_esales_import():
|
|
||||||
print("Importing products and categories into eSales")
|
|
||||||
pattern = "{}/*.xml".format(app.config.get("ESALES_IMPORT_DIR"))
|
|
||||||
esales.cluster.import_products_and_categories(pattern)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
manager.run()
|
manager.run()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ SERVER_NAME = "localhost"
|
|||||||
SQLALCHEMY_DATABASE_URI = "sqlite://"
|
SQLALCHEMY_DATABASE_URI = "sqlite://"
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||||
PRESERVE_CONTEXT_ON_EXCEPTION = False
|
PRESERVE_CONTEXT_ON_EXCEPTION = False
|
||||||
ESALES_URL = ""
|
|
||||||
TESTING = True
|
TESTING = True
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
SQLALCHEMY_ECHO = False
|
SQLALCHEMY_ECHO = False
|
||||||
|
|||||||
@@ -56,14 +56,3 @@ class TestEndpoints(flask_testing.TestCase):
|
|||||||
"/designers/", data=json.dumps(data), content_type="application/json"
|
"/designers/", data=json.dumps(data), content_type="application/json"
|
||||||
)
|
)
|
||||||
self.assert400(response)
|
self.assert400(response)
|
||||||
|
|
||||||
@patch("api.tasks.esales.update_designer")
|
|
||||||
def test_update_designer(self, esales_update_designer):
|
|
||||||
designer = self._add_designer("designer1")
|
|
||||||
data = {"name": "test"}
|
|
||||||
response = self.client.put(
|
|
||||||
"/designers/1", data=json.dumps(data), content_type="application/json"
|
|
||||||
)
|
|
||||||
self.assertTrue(esales_update_designer.called)
|
|
||||||
self.assertEqual("test", response.json["name"])
|
|
||||||
self.assertEqual("test", Designer.query.get(1).name)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user