diff --git a/amazon_integration/__init__.py b/amazon_integration/__init__.py new file mode 100644 index 00000000..9b429614 --- /dev/null +++ b/amazon_integration/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/amazon_integration/__manifest__.py b/amazon_integration/__manifest__.py new file mode 100644 index 00000000..b5b1eb79 --- /dev/null +++ b/amazon_integration/__manifest__.py @@ -0,0 +1,30 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Amazon Integration', + 'summary': """ + Amazon Integration""", + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'website': 'https://github.com/OCA/connector-ecommerce', + 'depends': ['sale_management', 'stock'], + 'category': 'Sales', + 'author': 'Domatix, ' + 'Odoo Community Association (OCA)', + 'external_dependencies': { + 'python': [ + 'mws', + ], + }, + 'data': ['security/ir.model.access.csv', + 'data/ir_cron.xml', + 'data/product_data.xml', + 'views/amazon_marketplace.xml', + 'views/amazon_seller.xml', + 'views/res_config_settings.xml', + 'views/amazon_menuitems.xml', + 'views/sale_order.xml', + ], + 'development_status': 'Alpha', + 'installable': True, +} diff --git a/amazon_integration/data/ir_cron.xml b/amazon_integration/data/ir_cron.xml new file mode 100644 index 00000000..56ec552f --- /dev/null +++ b/amazon_integration/data/ir_cron.xml @@ -0,0 +1,18 @@ + + + + + Amazon: import orders + + code + model.import_orders() + + 1 + hours + -1 + + + 1000 + + + diff --git a/amazon_integration/data/product_data.xml b/amazon_integration/data/product_data.xml new file mode 100644 index 00000000..a6e3ee5a --- /dev/null +++ b/amazon_integration/data/product_data.xml @@ -0,0 +1,23 @@ + + + + + Amazon Shipping Costs + SHIP AMAZON + service + 0.0 + + + Amazon Gift Costs + GIFT AMAZON + service + 0.0 + + + Amazon Product Not Found + Amazon Not Found + product + 0.0 + + + diff --git a/amazon_integration/i18n/es.po b/amazon_integration/i18n/es.po new file mode 100644 index 00000000..cb6f5939 --- /dev/null +++ b/amazon_integration/i18n/es.po @@ -0,0 +1,556 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * amazon_integration +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-11-07 13:26+0000\n" +"PO-Revision-Date: 2019-11-07 13:26+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +msgid "Amazon User\n" +" " +msgstr "" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_kanban +msgid "Import Market Orders" +msgstr "Importar pedidos" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__access_key +msgid "Access Key" +msgstr "Clave de acceso" + +#. module: amazon_integration +#: model:ir.model,name:amazon_integration.model_amazon_seller +msgid "Account for Amazon MWS" +msgstr "Cuenta para Amazon MWS" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_needaction +msgid "Action Needed" +msgstr "Acción Necesaria" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_ids +msgid "Activities" +msgstr "Actividades" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_state +msgid "Activity State" +msgstr "Estado de la actividad" + +#. module: amazon_integration +#: model:ir.ui.menu,name:amazon_integration.amazon_menu +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +msgid "Amazon" +msgstr "" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_sale_order__amazon_fulfillment +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_order_search +msgid "Amazon Fulfillment" +msgstr "" + +#. module: amazon_integration +#: model:product.product,name:amazon_integration.amazon_gift_product +#: model:product.template,name:amazon_integration.amazon_gift_product_product_template +msgid "Amazon Gift Costs" +msgstr "Costes de regalo de Amazon" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_ref_form +msgid "Amazon Info" +msgstr "Información de Amazon" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_sale_order__amazon_marketplace_id +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_form +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_order_search +msgid "Amazon Marketplace" +msgstr "" + +#. module: amazon_integration +#: model:ir.model,name:amazon_integration.model_amazon_marketplace +msgid "Amazon Markets from a seller" +msgstr "Amazon martketplaces de un vendedor" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_sale_order_line__amazon_order_item_id +msgid "Amazon Order Item Id" +msgstr "" + +#. module: amazon_integration +#: model:product.product,name:amazon_integration.amazon_not_found_product +#: model:product.template,name:amazon_integration.amazon_not_found_product_product_template +msgid "Amazon Product Not Found" +msgstr "Amazon producto no encontrado" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_sale_order__amazon_reference +msgid "Amazon Reference" +msgstr "Amazon referencia" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_form +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_search +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_tree +msgid "Amazon Seller" +msgstr "Amazon Vendedor" + +#. module: amazon_integration +#: model:product.product,name:amazon_integration.amazon_shipping_product +#: model:product.template,name:amazon_integration.amazon_shipping_product_product_template +msgid "Amazon Shipping Costs" +msgstr "Costes de envío de Amazon" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_search +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_tree +msgid "Amazon marketplace" +msgstr "Amazon marketplace" + +#. module: amazon_integration +#: model:ir.actions.server,name:amazon_integration.ir_cron_import_amazon_orders_ir_actions_server +#: model:ir.cron,cron_name:amazon_integration.ir_cron_import_amazon_orders +#: model:ir.cron,name:amazon_integration.ir_cron_import_amazon_orders +msgid "Amazon: import orders" +msgstr "Amazon: importar órdenes" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_attachment_count +msgid "Attachment Count" +msgstr "Conteo de archivos adjuntos" + +#. module: amazon_integration +#: model_terms:ir.actions.act_window,help:amazon_integration.amazon_seller_action +msgid "Click to create a new Seller." +msgstr "Pulsa para crear un nuevo vendedor" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__color +msgid "Color Index" +msgstr "Índice de Colores" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_res_config_settings__amazon_user_id +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +msgid "Commercial" +msgstr "Comercial" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__company_id +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__company_id +msgid "Company" +msgstr "Compañía" + +#. module: amazon_integration +#: model:ir.model,name:amazon_integration.model_res_config_settings +msgid "Config Settings" +msgstr "Ajustes de configuración" + +#. module: amazon_integration +#: model:ir.ui.menu,name:amazon_integration.amazon_config_menu +msgid "Configuration" +msgstr "Configuración" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__country_id +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__country_id +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_kanban +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_search +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_search +msgid "Country" +msgstr "País" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__create_uid +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__create_date +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: amazon_integration +#: model:ir.actions.act_window,name:amazon_integration.amazon_marketplace_dashboard_action +#: model:ir.ui.menu,name:amazon_integration.amazon_dashboard_menu +msgid "Dashboard" +msgstr "Tablero" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_seller__last_import_date_seller +msgid "Date from the last order synced" +msgstr "Fecha del último pedido sincronizado" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +msgid "Default products" +msgstr "Productos por defecto" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +msgid "Default user for sales" +msgstr "Comercial por defecto en ventas" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_kanban +msgid "Delete" +msgstr "Suprimir" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__display_name +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_kanban +msgid "Dropdown menu" +msgstr "Menú desplegable" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_kanban +msgid "Edit" +msgstr "Editar" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_order_search +#: selection:sale.order,amazon_fulfillment:0 +msgid "FBA" +msgstr "" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_order_search +#: selection:sale.order,amazon_fulfillment:0 +msgid "FBM" +msgstr "" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__fiscal_position_id +msgid "Fiscal Position" +msgstr "Posición fiscal" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_follower_ids +msgid "Followers" +msgstr "Seguidores" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_channel_ids +msgid "Followers (Channels)" +msgstr "Seguidores (Canales)" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_partner_ids +msgid "Followers (Partners)" +msgstr "Seguidores (Empresas)" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_search +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_search +msgid "Group By" +msgstr "Agrupar por" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__id +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__id +msgid "ID" +msgstr "" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_unread +msgid "If checked new messages require your attention." +msgstr "Si está marcado, hay nuevos mensajes que requieren su atención" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_needaction +msgid "If checked, new messages require your attention." +msgstr "Si está marcado, hay nuevos mensajes que requieren su atención." + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "Si se encuentra marcado, algunos mensajes tienen error de envío." + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_form +msgid "Import Market Orders" +msgstr "Importar pedidos" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_form +msgid "Import Marketplaces" +msgstr "Importar Marketplaces" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_form +msgid "Import Orders" +msgstr "Importar pedidos" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_form +msgid "Invoice Info" +msgstr "Facturación" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_is_follower +msgid "Is Follower" +msgstr "Es un seguidor" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__lang_id +msgid "Language" +msgstr "Idioma" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__last_import_date +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__last_import_date_seller +msgid "Last Import Date" +msgstr "Fecha de sincronización" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace____last_update +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__write_uid +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__write_date +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_main_attachment_id +msgid "Main Attachment" +msgstr "Adjuntos principales" + +#. module: amazon_integration +#: model:ir.actions.act_window,name:amazon_integration.amazon_marketplace_action +#: model:ir.ui.menu,name:amazon_integration.amazon_marketplace_menu +msgid "Marketplace" +msgstr "Marketplace" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__market_code +msgid "Marketplace ID" +msgstr "" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_form +msgid "Marketplace Settings" +msgstr "Ajustes del Marketplace" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__marketplace_ids +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_form +msgid "Marketplaces" +msgstr "Marketplaces" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__merchant_id +msgid "Merchant ID" +msgstr "" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_has_error +msgid "Message Delivery error" +msgstr "Error de Envío de Mensaje" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_ids +msgid "Messages" +msgstr "Mensajes" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__name +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__name +msgid "Name" +msgstr "Nombre" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "Siguiente plazo de actividad" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_summary +msgid "Next Activity Summary" +msgstr "Resumen de la siguiente actividad" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_type_id +msgid "Next Activity Type" +msgstr "Siguiente tipo de actividad" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_needaction_counter +msgid "Number of Actions" +msgstr "Número de acciones" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_has_error_counter +msgid "Number of error" +msgstr "Número de error" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "Número de mensajes que requieren una acción" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "Número de mensajes con error de envío" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__message_unread_counter +msgid "Number of unread messages" +msgstr "Número de mensajes no leidos" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_marketplace_form +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_res_config_settings_form +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_sale_ref_form +msgid "Order Info" +msgstr "Ventas" + +#. module: amazon_integration +#: selection:amazon.marketplace,activity_state:0 +msgid "Overdue" +msgstr "Atrasado" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__payment_term_id +msgid "Payment Term" +msgstr "Plazo de pago" + +#. module: amazon_integration +#: selection:amazon.marketplace,activity_state:0 +msgid "Planned" +msgstr "Planeado" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__pricelist_id +msgid "Pricelist" +msgstr "Tarifa" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__activity_user_id +msgid "Responsible User" +msgstr "Usuario responsable" + +#. module: amazon_integration +#: model:ir.model,name:amazon_integration.model_sale_order +msgid "Sale Order" +msgstr "Pedido de venta" + +#. module: amazon_integration +#: model:ir.model,name:amazon_integration.model_sale_order_line +msgid "Sales Order Line" +msgstr "Línea de pedido de venta" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_seller__secret_key +msgid "Secret Key" +msgstr "Clave secreta" + +#. module: amazon_integration +#: model:ir.actions.act_window,name:amazon_integration.amazon_seller_action +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__seller_id +#: model:ir.ui.menu,name:amazon_integration.amazon_seller_menu +msgid "Seller" +msgstr "Vendedor" + +#. module: amazon_integration +#: model:ir.actions.act_window,name:amazon_integration.amazon_res_config_settings_action +#: model:ir.ui.menu,name:amazon_integration.amazon_res_config_settings_menu +msgid "Settings" +msgstr "Configuración" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__activity_state +msgid "Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "Estado basado en actividades\n" +"Vencida: la fecha tope ya ha pasado\n" +"Hoy: La fecha tope es hoy\n" +"Planificada: futuras actividades." + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__tax_id +msgid "Tax" +msgstr "Impuesto" + +#. module: amazon_integration +#: selection:amazon.marketplace,activity_state:0 +msgid "Today" +msgstr "Hoy" + +#. module: amazon_integration +#: model:product.product,uom_name:amazon_integration.amazon_gift_product +#: model:product.product,uom_name:amazon_integration.amazon_not_found_product +#: model:product.product,uom_name:amazon_integration.amazon_shipping_product +#: model:product.template,uom_name:amazon_integration.amazon_gift_product_product_template +#: model:product.template,uom_name:amazon_integration.amazon_not_found_product_product_template +#: model:product.template,uom_name:amazon_integration.amazon_shipping_product_product_template +msgid "Unit(s)" +msgstr "Unidad(es)" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_unread +msgid "Unread Messages" +msgstr "Mensajes por leer" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__message_unread_counter +msgid "Unread Messages Counter" +msgstr "Contador de mensajes sin leer" + +#. module: amazon_integration +#: model:ir.model.fields,field_description:amazon_integration.field_amazon_marketplace__website_message_ids +msgid "Website Messages" +msgstr "Mensajes del sitio web" + +#. module: amazon_integration +#: model:ir.model.fields,help:amazon_integration.field_amazon_marketplace__website_message_ids +msgid "Website communication history" +msgstr "Historial de comunicaciones del sitio web" + +#. module: amazon_integration +#: model_terms:ir.ui.view,arch_db:amazon_integration.view_amazon_seller_form +msgid "e.g Spanish Seller" +msgstr "ej. Vendedor S.L." + +#. module: amazon_integration +#: model:product.product,weight_uom_name:amazon_integration.amazon_gift_product +#: model:product.product,weight_uom_name:amazon_integration.amazon_not_found_product +#: model:product.product,weight_uom_name:amazon_integration.amazon_shipping_product +#: model:product.template,weight_uom_name:amazon_integration.amazon_gift_product_product_template +#: model:product.template,weight_uom_name:amazon_integration.amazon_not_found_product_product_template +#: model:product.template,weight_uom_name:amazon_integration.amazon_shipping_product_product_template +msgid "kg" +msgstr "" diff --git a/amazon_integration/models/__init__.py b/amazon_integration/models/__init__.py new file mode 100644 index 00000000..e80b8490 --- /dev/null +++ b/amazon_integration/models/__init__.py @@ -0,0 +1,4 @@ +from . import amazon_seller +from . import amazon_marketplace +from . import res_config_settings +from . import sale_order diff --git a/amazon_integration/models/amazon_marketplace.py b/amazon_integration/models/amazon_marketplace.py new file mode 100644 index 00000000..649acbb0 --- /dev/null +++ b/amazon_integration/models/amazon_marketplace.py @@ -0,0 +1,59 @@ +from odoo import models, fields +from datetime import datetime + + +class AmazonMarketplace(models.Model): + _name = 'amazon.marketplace' + _description = 'Amazon Markets from a seller' + _inherit = ['mail.thread', 'mail.activity.mixin'] + + name = fields.Char( + string='Name', + track_visibility='onchange') + + market_code = fields.Char( + string='Marketplace ID', + track_visibility='onchange') + + color = fields.Integer( + string='Color Index') + + country_id = fields.Many2one( + comodel_name='res.country', + string='Country') + + lang_id = fields.Many2one( + comodel_name='res.lang', + string='Language') + + seller_id = fields.Many2one( + comodel_name='amazon.seller', + string='Seller') + + pricelist_id = fields.Many2one( + comodel_name='product.pricelist', + string='Pricelist') + + company_id = fields.Many2one( + comodel_name='res.company', + string='Company') + + last_import_date = fields.Datetime( + string='Last Import Date', + default=datetime.now()) + + fiscal_position_id = fields.Many2one( + comodel_name='account.fiscal.position', + string='Fiscal Position') + + payment_term_id = fields.Many2one( + comodel_name='account.payment.term', + string='Payment Term') + + # Import FBM and FBA orders + + def import_market_orders(self): + self.seller_id.import_orders(marketplaces=self, + seller=self.seller_id, + last_import_date=self.last_import_date, + single_market=True) diff --git a/amazon_integration/models/amazon_seller.py b/amazon_integration/models/amazon_seller.py new file mode 100644 index 00000000..ca5c21a7 --- /dev/null +++ b/amazon_integration/models/amazon_seller.py @@ -0,0 +1,438 @@ +from odoo import models, fields +from mws import Sellers, Orders +from dateutil.parser import parse +from datetime import datetime +import time +from dateutil import parser +import pytz +utc = pytz.utc + + +class AmazonSeller(models.Model): + _name = 'amazon.seller' + _description = 'Account for Amazon MWS' + + name = fields.Char( + string='Name', + required=True) + + company_id = fields.Many2one( + comodel_name='res.company', + string='Company', + default=lambda self: self.env['res.company']._company_default_get( + 'amazon.seller')) + + access_key = fields.Char( + string='Access Key') + + secret_key = fields.Char( + string='Secret Key') + + merchant_id = fields.Char( + string='Merchant ID') + + country_id = fields.Many2one( + comodel_name='res.country', + string='Country', + required=True) + + marketplace_ids = fields.One2many( + comodel_name='amazon.marketplace', + inverse_name='seller_id', + string='Marketplaces') + + last_import_date_seller = fields.Datetime( + string='Last Import Date', + default=datetime.now(), + help='Date from the last order synced') + + def get_marketplaces(self): + mws_connection = Sellers(access_key=str(self.access_key), + secret_key=str(self.secret_key), + account_id=str(self.merchant_id), + region=self.country_id.code, + ) + marketplace_obj = self.env['amazon.marketplace'] + pricelist_obj = self.env['product.pricelist'] + lang_obj = self.env['res.lang'] + country_obj = self.env['res.country'] + list_result = [] + try: + result = mws_connection.list_marketplace_participations() + result.parsed.get('ListParticipations', {}) + except Exception as e: + raise Warning('Given Credentials is incorrect, \ + please provide correct Credentials.' + str(e)) + + list_result.append(result) + next_token = result.parsed.get('NextToken', {}).get('value') + while next_token: + try: + result = mws_connection.\ + list_marketplace_participations_by_next_token(next_token) + except Exception as e: + raise Warning(str(e)) + next_token = result.parsed.get('NextToken', {}).get('value') + list_result.append(result) + + for element in list_result: + element = element.parsed + list_marketplaces = element.get('ListMarketplaces', {}) + marketplaces = list_marketplaces.get('Marketplace', []) + if not isinstance(marketplaces, list): + marketplaces = [marketplaces] + + for marketplace in marketplaces: + marketplace_id = marketplace.get( + 'MarketplaceId', {}).get('value', '') + country_code = marketplace.get('DefaultCountryCode', {}).get( + 'value') + name = marketplace.get('Name', {}).get('value', '') + lang_code = marketplace.get( + 'DefaultLanguageCode', {}).get('value', '') + currency_code = marketplace.get( + 'DefaultCurrencyCode', {}).get('value', '') + pricelist_id = pricelist_obj.search([( + 'name', '=', currency_code)]) + lang_id = lang_obj.search([('code', '=', lang_code)]) + country_id = country_obj.search([('code', '=', country_code)]) + + vals = { + 'seller_id': self.id, + 'name': name, + 'market_code': marketplace_id, + 'pricelist_id': pricelist_id and pricelist_id[0].id or + False, + 'lang_id': lang_id and lang_id[0].id or False, + 'country_id': country_id and country_id[0].id or + self.country_id and self.country_id.id or False, + 'company_id': self.company_id.id, + } + marketplace_rec = marketplace_obj.search( + [('seller_id', '=', self.id), + ('market_code', '=', marketplace_id)]) + if marketplace_rec: + marketplace_rec.write(vals) + else: + marketplace_obj.create(vals) + return True + + # Create FBM and FBA orders + def action_import_orders(self): + self.import_orders() + + def import_orders(self, marketplaces=False, seller=False, + last_import_date=False, single_market=False): + if not seller: + seller = self.env['amazon.seller'].search([], limit=1) + if not marketplaces: + marketplaces = seller.marketplace_ids + if not last_import_date: + last_import_date = seller.last_import_date_seller.isoformat( + sep='T') + else: + last_import_date = last_import_date.isoformat(sep='T') + + mws_obj = Orders(access_key=str(seller.access_key), + secret_key=str(seller.secret_key), + account_id=str(seller.merchant_id), + region=seller.country_id.code + ) + + has_next = True + next_token = None + orders_data = [] + market_obj = self.env['amazon.marketplace'] + marketplaceids = marketplaces.mapped('market_code') + orderstatus = ('Unshipped', 'PartiallyShipped', 'Shipped') + while has_next: + time.sleep(1) + order_data = mws_obj.list_orders( + marketplaceids=marketplaceids, + created_after=last_import_date, + orderstatus=orderstatus, + next_token=next_token, + ) + orders = order_data.parsed.get('Orders', {}).get('Order', []) + if orders and isinstance(orders, dict): + orders_data.append(orders) + elif orders and isinstance(orders, list): + orders_data += orders + for order in orders_data: + market_code = order.get( + 'MarketplaceId', {}).get( + 'value', False) + marketplace = market_obj.search([ + ('market_code', '=', market_code)]) + sale_channel = order.get( + 'SalesChannel', {}).get( + 'value', 'sale') + if sale_channel == 'Non-Amazon': + continue + seller._create_sale_order(order, marketplace, mws_obj) + # Date to synchronize every time an order is imported + last_purchase_date = order.get('PurchaseDate').get('value') + last_purchase_date = parse( + last_purchase_date).replace(tzinfo=None) + if single_market: + marketplace.last_import_date = last_purchase_date + else: + seller.last_import_date_seller = last_purchase_date + marketplace.last_import_date = last_purchase_date + # commit a batch of 100 orders due to request throttled from Amazon + self.env.cr.commit() + next_token = order_data.parsed.get('NextToken', {}).get('value') + has_next = bool(next_token) + + def _create_sale_order(self, order, marketplace, mws_obj): + IrDefault = self.env['ir.default'].sudo() + amazon_user = IrDefault.get('res.config.settings', 'amazon_user_id') + sale_obj = self.env['sale.order'] + amazon_order_ref = order.get('AmazonOrderId').get('value') + fulfillment_channel = order.get('FulfillmentChannel').get('value') + amazon_fulfillment = 'fba' if fulfillment_channel == 'AFN' else 'fbm' + date_order = parser.parse( + order.get('PurchaseDate').get('value')).astimezone(utc) + pricelist = marketplace.pricelist_id + invoice_partner, delivery_partner = self._get_partner(order) + order_found = sale_obj.search([ + ('amazon_reference', '=', amazon_order_ref)]) + if not order_found: + ord_lines = self._create_sale_order_lines( + amazon_order_ref, marketplace, mws_obj) + order = sale_obj.create({ + 'origin': amazon_order_ref, + 'date_order': date_order, + 'partner_id': invoice_partner.id, + 'partner_shipping_id': delivery_partner.id, + 'pricelist_id': pricelist.id, + 'order_line': [(0, 0, order_line) for order_line in ord_lines], + 'fiscal_position_id': marketplace.fiscal_position_id.id, + 'amazon_reference': amazon_order_ref, + 'amazon_fulfillment': amazon_fulfillment, + 'company_id': self.company_id.id, + 'user_id': amazon_user, + 'amazon_marketplace_id': marketplace.id, + 'payment_term_id': marketplace.payment_term_id.id, + }) + + def _get_partner(self, order): + partner_obj = self.env['res.partner'] + country_obj = self.env['res.country'] + lang_obj = self.env['res.lang'] + state_obj = self.env['res.country.state'] + shipping_address = order.get('ShippingAddress', {}) + country_code = shipping_address.get('CountryCode', {}).get('value') + country = country_obj.search([('code', '=', country_code)], limit=1) + lang = False + if country_code: + country_code_lower = country_code.lower() + lang = lang_obj.search([('iso_code', '=', country_code_lower)]) + state_code = shipping_address.get( + 'StateOrRegion', {}).get('value', False) + state = state_obj.search([ + ('country_id', '=', country.id), '|', + ('code', '=', state_code), + ('name', '=', state_code)], + limit=1) + if not state and country and state_code: + state = state_obj.create({ + 'country_id': country.id, + 'name': state_code, + 'code': state_code + }) + street = shipping_address.get('AddressLine1', {}).get('value', False) + street2 = shipping_address.get('AddressLine2', {}).get('value', False) + postalcode = shipping_address.get('PostalCode', {}).get('value', False) + deliv_name = shipping_address.get('Name', {}).get('value', False) + phone = shipping_address.get('Phone', {}).get('value', False) + city = shipping_address.get('City', {}).get('value', False) + email = order.get('BuyerEmail', {}).get('value', False) + invoice_name = order.get('BuyerName', {}).get('value', False) + domain = [] + street and domain.append(('street', '=', street)) + street2 and domain.append(('street2', '=', street2)) + email and domain.append(('email', '=', email)) + phone and domain.append(('phone', '=', phone)) + city and domain.append(('city', '=', city)) + postalcode and domain.append(('zip', '=', postalcode)) + state and domain.append(('state_id', '=', state.id)) + country and domain.append(('country_id', '=', country.id)) + deliv_name and domain.append(('name', '=', deliv_name)) + domain.append(('type', '=', 'delivery')) + delivery_vals = { + 'name': deliv_name, + 'is_company': False, + 'customer': True, + 'street': street, + 'street2': street2, + 'city': city, + 'country_id': country.id, + 'type': 'delivery', + 'phone': phone, + 'zip': postalcode, + 'state_id': state.id, + 'email': email, + 'lang': lang.code, + 'company_id': self.company_id.id + } + delivery_partner = partner_obj.search(domain, limit=1) + if not delivery_partner: + delivery_partner = partner_obj.create(delivery_vals) + domain.remove(('name', '=', deliv_name)) + domain.append(('name', '=', invoice_name)) + domain.remove(('type', '=', 'delivery')) + domain.append(('type', '=', 'invoice')) + invoice_partner = partner_obj.search(domain, limit=1) + if not invoice_partner: + if email: + invoice_partner = partner_obj.search([ + ('email', '=', email), + ('type', '=', 'invoice')], + limit=1) + if phone and not invoice_partner: + invoice_partner = partner_obj.search([ + ('phone', '=', phone), + ('type', '=', 'invoice')], + limit=1) + if not invoice_partner: + invoice_partner_vals = { + 'name': invoice_name, + 'is_company': False, + 'customer': True, + 'street': street, + 'street2': street2, + 'city': city, + 'country_id': country.id, + 'type': 'invoice', + 'phone': phone, + 'zip': postalcode, + 'state_id': state.id, + 'email': email, + 'lang': lang.code, + 'company_id': self.env.user.company_id.id + } + invoice_partner = partner_obj.create(invoice_partner_vals) + delivery_partner.parent_id = invoice_partner.id + return invoice_partner, delivery_partner + + def _create_sale_order_lines(self, amazon_order_ref, marketplace, + mws_obj): + product_obj = self.env['product.product'] + shipment_product_id = product_obj.search( + [('default_code', '=', 'SHIP AMAZON')], limit=1) + gift_product_id = product_obj.search( + [('default_code', '=', 'GIFT AMAZON')], limit=1) + not_found_product_id = product_obj.search( + [('default_code', '=', 'Amazon Not Found')], limit=1) + has_next = True + next_token = None + while has_next: + time.sleep(1) + order_items_data = mws_obj.list_order_items( + amazon_order_id=amazon_order_ref, + next_token=next_token, + ) + order_line_vals = [] + order_items_parsed = order_items_data.parsed + order_items = order_items_parsed.get('OrderItems').get('OrderItem') + lines = [] + if isinstance(order_items, dict): + lines.append(order_items) + elif isinstance(order_items, list): + lines += order_items + for item in lines: + sku = item.get('SellerSKU').get('value') + product = self.get_product(sku) + if not product: + product = not_found_product_id + # Order Lines + order_line_vals = self.get_item_values( + item, product, order_line_vals, marketplace) + shipping = item.get('ShippingPrice') + gift = item.get('GiftWrapPrice') + if shipping: + order_line_vals = self.get_shipping_values( + item, shipment_product_id, order_line_vals, + marketplace) + if gift: + order_line_vals = self.get_gift_values( + item, gift_product_id, order_line_vals, + marketplace) + next_token = order_items_parsed.get('NextToken', {}).get('value') + has_next = bool(next_token) + return order_line_vals + + def get_product(self, sku): + return self.env['product.product'].search([('default_code', '=', sku)], + limit=1) + + def get_item_values(self, item, product, order_line_vals, marketplace): + quantity = float(item.get('QuantityOrdered').get('value')) + item_price = float(item.get('ItemPrice').get('Amount').get('value')) + description = item.get('Title').get('value') + fiscal_position = marketplace.fiscal_position_id + product_tax = product.taxes_id.filtered( + lambda x: x.company_id.id == self.company_id.id) + tax = fiscal_position.map_tax(product_tax) + tax_reduce = tax.amount / 100 + 1 + item_price = item_price / tax_reduce + promotion_discount = float( + item.get('PromotionDiscount').get('Amount').get('value')) + if promotion_discount: + promotion_discount = promotion_discount / tax_reduce + amazon_order_item_id = item.get('OrderItemId').get('value') + item_vals = { + 'product_id': product.id, + 'product_uom_qty': quantity, + 'name': description, + 'tax_id': [(6, 0, tax.ids)], + 'price_unit': item_price, + 'discount': (promotion_discount / item_price) * 100, + 'amazon_order_item_id': amazon_order_item_id, + } + order_line_vals.append(item_vals) + return order_line_vals + + def get_shipping_values(self, item, shipment_product_id, + order_line_vals, marketplace): + fiscal_position = marketplace.fiscal_position_id + product_tax = shipment_product_id.taxes_id.filtered( + lambda x: x.company_id.id == self.company_id.id) + tax = fiscal_position.map_tax(product_tax) + tax_reduce = tax.amount / 100 + 1 + shipping_price = float( + item.get('ShippingPrice').get('Amount').get('value')) + shipping_price = shipping_price / tax_reduce + shipping_discount = float( + item.get('ShippingDiscount').get('Amount').get('value')) + if shipping_discount: + shipping_discount = shipping_discount / tax_reduce + item_shipping_vals = { + 'product_id': shipment_product_id.id, + 'product_uom_qty': 1, + 'tax_id': [(6, 0, tax.ids)], + 'price_unit': shipping_price, + 'discount': (shipping_discount / shipping_price) * 100, + } + order_line_vals.append(item_shipping_vals) + return order_line_vals + + def get_gift_values(self, item, gift_product_id, + order_line_vals, marketplace): + fiscal_position = marketplace.fiscal_position_id + product_tax = gift_product_id.taxes_id.filtered( + lambda x: x.company_id.id == self.company_id.id) + tax = fiscal_position.map_tax(product_tax) + tax_reduce = tax.amount / 100 + 1 + gift_wrap_price = float( + item.get('GiftWrapPrice').get('Amount').get('value')) + gift_wrap_price = gift_wrap_price / tax_reduce + item_gift_vals = { + 'product_id': gift_product_id.id, + 'product_uom_qty': 1, + 'tax_id': [(6, 0, tax.ids)], + 'price_unit': gift_wrap_price, + } + order_line_vals.append(item_gift_vals) + return order_line_vals diff --git a/amazon_integration/models/res_config_settings.py b/amazon_integration/models/res_config_settings.py new file mode 100644 index 00000000..4051ef18 --- /dev/null +++ b/amazon_integration/models/res_config_settings.py @@ -0,0 +1,28 @@ +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + amazon_user_id = fields.Many2one( + comodel_name='res.users', + string='Commercial') + + def set_values(self): + super(ResConfigSettings, self).set_values() + IrDefault = self.env['ir.default'].sudo() + IrDefault.set('res.config.settings', 'amazon_user_id', + self.amazon_user_id.id) + return True + + @api.model + def get_values(self): + res = super(ResConfigSettings, self).get_values() + IrDefault = self.env['ir.default'].sudo() + res.update( + { + 'amazon_user_id': IrDefault.get( + 'res.config.settings', 'amazon_user_id'), + } + ) + return res diff --git a/amazon_integration/models/sale_order.py b/amazon_integration/models/sale_order.py new file mode 100644 index 00000000..fb406626 --- /dev/null +++ b/amazon_integration/models/sale_order.py @@ -0,0 +1,24 @@ +from odoo import models, fields + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + amazon_reference = fields.Char( + string='Amazon Reference') + + amazon_fulfillment = fields.Selection( + [('fbm', 'FBM'), + ('fba', 'FBA')], + string='Amazon Fulfillment') + + amazon_marketplace_id = fields.Many2one( + comodel_name='amazon.marketplace', + string='Amazon Marketplace') + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + amazon_order_item_id = fields.Char( + string='Amazon Order Item Id') diff --git a/amazon_integration/readme/CONTRIBUTORS.rst b/amazon_integration/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..afcd98d8 --- /dev/null +++ b/amazon_integration/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Domatix `_: + + * Nacho Serra diff --git a/amazon_integration/readme/DESCRIPTION.rst b/amazon_integration/readme/DESCRIPTION.rst new file mode 100644 index 00000000..2f10d5eb --- /dev/null +++ b/amazon_integration/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module adds functionality to import FBA/FBM orders from Amazon in Odoo. diff --git a/amazon_integration/readme/USAGE.rst b/amazon_integration/readme/USAGE.rst new file mode 100644 index 00000000..00869bf6 --- /dev/null +++ b/amazon_integration/readme/USAGE.rst @@ -0,0 +1,6 @@ +#. Go to *Amazon* > Settings > Seller > Create and configure your credentials. +#. Click the button 'Import Marketplaces'. +#. Click the button 'Import orders' to import orders from every marketplace. +#. You can go to Amazon > Dashboard to see all your marketplaces and import orders from each one of them. +#. From Amazon > Settings > Marketplaces you can change their settings. +#. There is also a cron that will import orders every hour. diff --git a/amazon_integration/security/ir.model.access.csv b/amazon_integration/security/ir.model.access.csv new file mode 100644 index 00000000..b219d9da --- /dev/null +++ b/amazon_integration/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_amazon_seller,access_amazon_seller,model_amazon_seller,base.group_user,1,1,1,1 +access_amazon_marketplace,access_amazon_marketplace,model_amazon_marketplace,base.group_user,1,1,1,1 diff --git a/amazon_integration/static/description/icon.png b/amazon_integration/static/description/icon.png new file mode 100644 index 00000000..abaf2c5e Binary files /dev/null and b/amazon_integration/static/description/icon.png differ diff --git a/amazon_integration/views/amazon_marketplace.xml b/amazon_integration/views/amazon_marketplace.xml new file mode 100644 index 00000000..d45c111d --- /dev/null +++ b/amazon_integration/views/amazon_marketplace.xml @@ -0,0 +1,123 @@ + + + + view.amazon_marketplace.form + amazon.marketplace + +
+
+
+ + +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + + view.amazon_marketplace.tree + amazon.marketplace + + + + + + + + + + amazon.marketplace.dashboard + amazon.marketplace + + + + + + + + +
+
+
+
Country +
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ + + view.amazon_marketplace.search + amazon.marketplace + + + + + + + + + +
diff --git a/amazon_integration/views/amazon_menuitems.xml b/amazon_integration/views/amazon_menuitems.xml new file mode 100644 index 00000000..1c35d66b --- /dev/null +++ b/amazon_integration/views/amazon_menuitems.xml @@ -0,0 +1,56 @@ + + + + + + Marketplace + amazon.marketplace + tree,form + + + + Dashboard + ir.actions.act_window + amazon.marketplace + kanban,form + {'search_default_group_country_id':1} + form + + + + + Seller + amazon.seller + tree,form + +

+ Click to create a new Seller. +

+
+
+ + + Settings + res.config.settings + ir.actions.act_window + + form + inline + {'module' : 'amazon_integration'} + + + + + + + + + + + + + + + + +
diff --git a/amazon_integration/views/amazon_seller.xml b/amazon_integration/views/amazon_seller.xml new file mode 100644 index 00000000..9f4d29be --- /dev/null +++ b/amazon_integration/views/amazon_seller.xml @@ -0,0 +1,71 @@ + + + + view.amazon_seller.form + amazon.seller + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + view.amazon_seller.tree + amazon.seller + + + + + + + + + + view.amazon_seller.search + amazon.seller + + + + + + + + + + +
diff --git a/amazon_integration/views/res_config_settings.xml b/amazon_integration/views/res_config_settings.xml new file mode 100644 index 00000000..b49db515 --- /dev/null +++ b/amazon_integration/views/res_config_settings.xml @@ -0,0 +1,38 @@ + + + + + view.amazon_res_config_settings.form + res.config.settings + + + + +
+

Order Info

+
+
+
+
+ Amazon User + +
+ Default user for sales +
+
+
+
+
+
+
+ +
+
+ + + + + + diff --git a/amazon_integration/views/sale_order.xml b/amazon_integration/views/sale_order.xml new file mode 100644 index 00000000..0924deb7 --- /dev/null +++ b/amazon_integration/views/sale_order.xml @@ -0,0 +1,39 @@ + + + + view.amazon_sale_ref.form + sale.order + + + + + + + + + + + + + + + view.amazon_sale_order.search + sale.order + + + + + + + + + + + + + + + + + + diff --git a/amazon_integration/wizard/__init__.py b/amazon_integration/wizard/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..2d3f6c2b --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +mws==0.8.6