995 lines
41 KiB
Python
995 lines
41 KiB
Python
# -*- coding: UTF-8 -*-
|
|
# This file is part electronic_mail_template module for Tryton.
|
|
# The COPYRIGHT file at the top level of this repository contains
|
|
# the full copyright notices and license terms.
|
|
from decimal import Decimal
|
|
from trytond.pool import Pool
|
|
from trytond.transaction import Transaction
|
|
import requests
|
|
from urllib.parse import urlencode
|
|
from datetime import datetime, date
|
|
# from .web_channel import SaleWebChannel
|
|
# from .web import Shop
|
|
import json
|
|
from .exceptions import NotProductFoundError, NotProductFound
|
|
from trytond.i18n import gettext
|
|
from trytond.exceptions import UserError
|
|
|
|
HEADERS = {
|
|
'Accept': 'application/json',
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
# class MercadoLibreTwo(Shop):
|
|
# 'MercadoLibre'
|
|
# __name__ = 'sale.web_channel.mercado_libre'
|
|
|
|
# @classmethod
|
|
# def __setup__(cls):
|
|
# super(MercadoLibre, cls).__setup__()
|
|
|
|
# def _get_context(self):
|
|
# user_ = self._get_user()
|
|
# return {
|
|
# 'company': user_.company.id,
|
|
# 'user': user_.id,
|
|
# 'shops': [user_.shop.id],
|
|
# 'shop': user_.shop.id,
|
|
# 'language': 'es'
|
|
# }
|
|
|
|
# def _get_user(self):
|
|
# User = Pool().get('res.user')
|
|
# user, = User.search([
|
|
# ('login', '=', 'mercado.libre')
|
|
# ])
|
|
# return user
|
|
|
|
# def _create_product(self, codes, line={}):
|
|
# item = line['item']
|
|
# pool = Pool()
|
|
# Product = pool.get('product.product')
|
|
# Template = pool.get('product.template')
|
|
# description = ''
|
|
# if item.get('variation_attributes'):
|
|
# var = item['variation_attributes'][0]
|
|
# if var['id'] and var['name']:
|
|
# description = var['id'] + ' ' + var['name']
|
|
# create_template = {
|
|
# 'name': item['title'],
|
|
# 'list_price': line['unit_price'],
|
|
# 'sale_price_w_tax': line['full_unit_price'],
|
|
# 'type': 'goods',
|
|
# 'salable': True,
|
|
# 'purchasable': True,
|
|
# 'purchase_uom': 1,
|
|
# 'sale_uom': 1,
|
|
# 'default_uom': 1,
|
|
# 'account_category': 7,
|
|
# }
|
|
# template, = Template.create([create_template])
|
|
# create_product = []
|
|
# for code in codes:
|
|
# create_product.append({
|
|
# 'code': code,
|
|
# 'description': description,
|
|
# 'template': template.id
|
|
# })
|
|
# return Product.create(create_product)
|
|
|
|
# def _create_party(self, customer):
|
|
# _pool = Pool()
|
|
# City = _pool.get('party.city_code')
|
|
# Party = _pool.get('party.party')
|
|
# PartyObligationTax = _pool.get('party.obligation_tax')
|
|
# email = customer.get('email', '@')
|
|
# shipment_address, phone, city = '', '', None
|
|
# if customer.get('receiver_address'):
|
|
# receiver_address = customer['receiver_address']
|
|
# shipment_address = receiver_address['address_line']
|
|
# phone = receiver_address['receiver_phone'] or '000'
|
|
# city_name = receiver_address['city']['name']
|
|
# if city_name:
|
|
# cities = City.search([
|
|
# ('name', '=', city_name)
|
|
# ])
|
|
# if cities:
|
|
# city = cities[0]
|
|
# if customer['billing_info']['doc_type'] == 'NIT':
|
|
# type_document = '31'
|
|
# customer_name = customer['billing_info']['business_name']
|
|
# type_person = 'persona_juridica'
|
|
# else:
|
|
# customer_name = customer['billing_info']['first_name'] + ' ' + customer['billing_info']['last_name']
|
|
# type_document = '13'
|
|
# type_person = 'persona_natural'
|
|
|
|
# create_customer = {
|
|
# 'id_reference': str(customer['id']),
|
|
# 'name': customer_name.upper(),
|
|
# 'type_document': type_document,
|
|
# 'type_person': type_person,
|
|
# 'id_number': customer['billing_info']['doc_number'],
|
|
# 'addresses': [('create', [{
|
|
# 'street': shipment_address,
|
|
# }])],
|
|
# 'contact_mechanisms': [
|
|
# ('create', [
|
|
# {'type': 'phone', 'value': phone},
|
|
# {'type': 'email', 'value': email},
|
|
# ])
|
|
# ]
|
|
# }
|
|
# if not city:
|
|
# city = City(149)
|
|
# create_customer['addresses'][0][1][0]['department_code'] = city.department.id
|
|
# create_customer['addresses'][0][1][0]['city_code'] = city.id
|
|
# party, = Party.create([create_customer])
|
|
# PartyObligationTax.create([{
|
|
# 'party': party.id,
|
|
# 'obligation_fiscal': 6,
|
|
# }])
|
|
# return party
|
|
|
|
# def get_shipment_api(self, shipment_id):
|
|
# if not shipment_id:
|
|
# return None
|
|
# URI = 'https://api.mercadolibre.com/shipments/%s?access_token=%s' % (
|
|
# shipment_id, self.access_token)
|
|
# res = self.get_response(URI)
|
|
# return res.json()
|
|
|
|
# def get_billing_info_api(self, order_id):
|
|
# if not order_id:
|
|
# return None
|
|
# URI = 'https://api.mercadolibre.com/orders/%s/billing_info?access_token=%s' % (
|
|
# order_id, self.access_token)
|
|
# res = self.get_response(URI)
|
|
# return res.json()
|
|
|
|
# def _return_sale(self, sale):
|
|
# pool = Pool()
|
|
# Sale = pool.get('sale.sale')
|
|
# Date = pool.get('ir.date')
|
|
# ctx = self._get_context()
|
|
# dev_sales = []
|
|
# sales = [sale]
|
|
# if sale.pack_id:
|
|
# sales = Sale.search([
|
|
# ('pack_id', '=', sale.pack_id)
|
|
# ])
|
|
# with Transaction().set_context(ctx):
|
|
# return_sales = Sale.copy(sales)
|
|
# for return_sale, sale in zip(return_sales, sales):
|
|
# return_sale.origin = sale
|
|
# return_sale.reference = sale.reference
|
|
# return_sale.state = 'draft'
|
|
# return_sale.sale_date = Date.today()
|
|
# if sale.invoice_type == '1':
|
|
# return_sale.invoice_type = '91'
|
|
# for line in return_sale.lines:
|
|
# if line.type == 'line':
|
|
# line.quantity *= -1
|
|
# line.save()
|
|
# if return_sale.untaxed_amount_cache:
|
|
# return_sale.untaxed_amount_cache *= -1
|
|
# if return_sale.tax_amount_cache:
|
|
# return_sale.tax_amount_cache *= -1
|
|
# if return_sale.total_amount_cache:
|
|
# return_sale.total_amount_cache *= -1
|
|
# return_sale.save()
|
|
# Sale.quote([return_sale])
|
|
# Sale.write([return_sale], {'state': 'confirmed'})
|
|
# dev_sales.append(return_sale)
|
|
# return dev_sales
|
|
|
|
# def create_lines_sale(self, sale, sale_, freight=False):
|
|
# _pool = Pool()
|
|
# SaleLine = _pool.get('sale.line')
|
|
# Product = _pool.get('product.product')
|
|
# create_lines = []
|
|
# sale_items = sale_['order_items']
|
|
# ctx = self._get_context()
|
|
# sfm_id = sale_['shipping']['id']
|
|
# # reference = sale.reference.split(',')
|
|
# # reference_order = str(sale_['id'])
|
|
# # if reference_order not in reference:
|
|
# # sale.referece = sale.reference + ',' + reference_order
|
|
# # sale.save()
|
|
# with Transaction().set_context(ctx):
|
|
# for line in sale_items:
|
|
# item = line['item']
|
|
# sku_code = item['seller_sku']
|
|
|
|
# if sku_code:
|
|
# generic = False
|
|
# if sku_code.count('+') > 0:
|
|
# codes = sku_code.split('+')
|
|
# line['unit_price'] = Decimal(
|
|
# round((line['unit_price'] / 2), 2))
|
|
# else:
|
|
# codes = [sku_code]
|
|
|
|
# products = Product.search([
|
|
# ('code', 'in', codes),
|
|
# ('active', '=', True)
|
|
# ])
|
|
# description = ''
|
|
# if not products:
|
|
# products = self._create_product(codes, line)
|
|
# else:
|
|
# if not self.generic_product:
|
|
# raise NotProductFoundError(
|
|
# gettext('sale_web_channel.msg_product_generic_not_found'))
|
|
# products = [self.generic_product]
|
|
# generic = True
|
|
# description = ''
|
|
# raise NotProductFound(
|
|
# gettext('sale_web_channel.msg_product_not_found', s=self.generic_product.rec_name))
|
|
# for product in products:
|
|
# Tax = _pool.get('account.tax')
|
|
# un_price = Tax.reverse_compute(Decimal(line['unit_price']),
|
|
# product.customer_taxes_used)
|
|
# create_lines.append({
|
|
# 'sale': sale.id,
|
|
# 'type': 'line',
|
|
# 'unit': product.default_uom.id,
|
|
# 'quantity': line['quantity'],
|
|
# 'unit_price': round(Decimal(un_price), 3),
|
|
# 'unit_price_full': Decimal(line['unit_price']),
|
|
# 'product': product.id,
|
|
# 'taxes': [('add', product.customer_taxes_used)],
|
|
# 'description': description,
|
|
# })
|
|
# if freight and self.freight_product:
|
|
# product = self.freight_product
|
|
# URI = 'https://api.mercadolibre.com/shipments/%s/costs?access_token=%s' % (
|
|
# sfm_id, self.access_token)
|
|
# result = self.get_response(URI).json()
|
|
# shipping_amount = result['receiver']['cost']
|
|
# create_lines.append({
|
|
# 'sale': sale.id,
|
|
# 'type': 'line',
|
|
# 'unit': product.default_uom.id,
|
|
# 'quantity': 1,
|
|
# 'unit_price': Decimal(shipping_amount),
|
|
# 'unit_price_full': Decimal(shipping_amount),
|
|
# 'product': product.id,
|
|
# 'description': 'FLETE',
|
|
# })
|
|
# SaleLine.create(create_lines)
|
|
# return generic
|
|
|
|
# def validate_sale(self, sale_):
|
|
# if sale_.get('pack_id'):
|
|
# # if not sale_.get('shipping'):
|
|
# # return
|
|
# # shipment_id = sale_['shipping']['id']
|
|
# # URI = 'https://api.mercadolibre.com/shipments/%s/items?access_token=%s' % (
|
|
# # shipment_id, self.access_token)
|
|
# # res = self.get_response(URI)
|
|
# # shipment_items = res.json()
|
|
# # if len(shipment_items) > 1:
|
|
# URI = 'https://api.mercadolibre.com/packs/%s?access_token=%s' % (
|
|
# sale_.get('pack_id'), self.access_token)
|
|
# response = self.get_response(URI)
|
|
# response = response.json()
|
|
# if response.get('orders'):
|
|
# ids = ''
|
|
# for item in response['orders']:
|
|
# order_id = str(item['id'])
|
|
# if order_id != str(sale_['id']):
|
|
# URI2 = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
|
|
# order_id, self.access_token)
|
|
# order = self.get_response(URI2)
|
|
# sale_order = order.json()
|
|
# ids += ',' + order_id
|
|
# sale_['order_items'].extend(sale_order['order_items'])
|
|
# sale_['id'] = str(sale_['id']) + ids
|
|
# return self._create_sale(sale_)
|
|
# else:
|
|
# return self._create_sale(sale_)
|
|
# else:
|
|
# return self._create_sale(sale_)
|
|
|
|
# def _create_sale(self, sale_):
|
|
# _pool = Pool()
|
|
# Sale = _pool.get('sale.sale')
|
|
# print(sale_, 'que eres amigo')
|
|
# reference = '%' + str(sale_['id']).split(',')[0] + '%'
|
|
# dom = [
|
|
# ('reference', 'like', reference)
|
|
# ]
|
|
# sales = Sale.search(dom)
|
|
# if sales:
|
|
# if len(sales) == 1 and sale_['status'] == 'cancelled':
|
|
# sale = sales[0]
|
|
# if not sale.invoices:
|
|
# self.cancel_sales([sale], sale.pack_id)
|
|
# else:
|
|
# dev_sales = self._return_sale(sale)
|
|
# self._finish_sale(dev_sales[0], type='return')
|
|
# return True
|
|
# return False
|
|
# Party = _pool.get('party.party')
|
|
# User = _pool.get('res.user')
|
|
# sfm_id = sale_['shipping']['id']
|
|
# shipment_ = self.get_shipment_api(sfm_id)
|
|
# if sale_.get('buyer'):
|
|
# sale_id = str(sale_['id']).split(',')[0]
|
|
# billing_info = self.get_billing_info_api(sale_id)
|
|
# customer = sale_['buyer']
|
|
# dom_party = [('id_reference', '=', str(customer['id']))]
|
|
# if billing_info and billing_info['billing_info'].get('doc_number'):
|
|
# dom_party = [('id_number', '=', str(
|
|
# billing_info['billing_info']['doc_number']))]
|
|
# parties = Party.search(dom_party)
|
|
# if parties:
|
|
# party = parties[0]
|
|
# else:
|
|
# customer['receiver_address'] = shipment_['receiver_address']
|
|
# customer['billing_info'] = billing_info['billing_info']
|
|
# for dic in customer['billing_info']['additional_info']:
|
|
# customer['billing_info'][list(dic.values())[0].lower()
|
|
# ] = list(dic.values())[1]
|
|
# try:
|
|
# customer['billing_info']['additional_info'].pop()
|
|
# except Exception as e:
|
|
# msg = 'sin informacion de tercero' + e
|
|
# raise UserError(
|
|
# gettext('sale_web_channel.msg_billing_info', msg=msg))
|
|
# party = self._create_party(customer)
|
|
# ctx = self._get_context()
|
|
# user_ = User(ctx['user'])
|
|
# date_created = sale_['date_created'].split('T')
|
|
# year, month, day = date_created[0].split('-')
|
|
# sale_date = date(int(year), int(month), int(day))
|
|
# with Transaction().set_user(ctx['user']):
|
|
# sale, = Sale.create([{
|
|
# 'payment_term': 1,
|
|
# 'party': party.id,
|
|
# 'sale_date': sale_date,
|
|
# 'comment': shipment_['status'],
|
|
# 'state': 'draft',
|
|
# 'company': ctx['company'],
|
|
# 'currency': user_.company.currency.id,
|
|
# 'shop': user_.shop.id,
|
|
# 'reference': str(sale_['id']),
|
|
# 'invoice_address': Party.address_get(party, type='invoice'),
|
|
# 'shipment_address': Party.address_get(party, type='delivery'),
|
|
# 'description': 'VENTA WEB ',
|
|
# 'channel': self.id,
|
|
# 'invoice_type': self.invoice_type,
|
|
# 'pack_id': str(sale_['pack_id']) if sale_['pack_id'] else '',
|
|
# }])
|
|
# generic = self.create_lines_sale(
|
|
# sale, sale_, freight=True)
|
|
# sale.untaxed_amount_cache = sale.untaxed_amount
|
|
# if sale_['status'] == 'cancelled':
|
|
# sale.state = 'cancelled'
|
|
# else:
|
|
# Sale.quote([sale])
|
|
# if not generic:
|
|
# sale.state = 'confirmed'
|
|
# sale.save()
|
|
# # if shipment_['status'] in ['shipped', 'delivered']:
|
|
# # self._finish_sale(sale)
|
|
# return sale
|
|
|
|
# def cancel_sales(self, sales, pack_id=None):
|
|
# Sale = Pool().get('sale.sale')
|
|
# if pack_id:
|
|
# sales = Sale.search([('pack_id', '=', pack_id)])
|
|
# for sale in sales:
|
|
# sale.state = 'cancelled'
|
|
# sale.save()
|
|
|
|
# def _get_shipment_amount(self, order_id, shipment={}):
|
|
# URI = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
|
|
# order_id, self.access_token)
|
|
# res = self.get_response(URI)
|
|
# sale_ = res.json()
|
|
# shipping_amount = 0
|
|
# if sale_.get('payments'):
|
|
# shipping_amount = sale_['payments'][0]['shipping_cost']
|
|
# return shipping_amount
|
|
|
|
# def get_access_token(self, refresh_token, client_id, client_secret):
|
|
# params = {'grant_type': 'refresh_token',
|
|
# 'client_id': client_id,
|
|
# 'client_secret': client_secret,
|
|
# 'refresh_token': refresh_token
|
|
# }
|
|
|
|
# uri = 'https://api.mercadolibre.com/oauth/token'
|
|
|
|
# response = requests.post(uri, params=urlencode(params),
|
|
# headers=HEADERS, data=params)
|
|
# res = response.json()
|
|
# if res.get('error', None):
|
|
# raise UserError(res.get('message') + ' Error:' + res.get('error'))
|
|
# return res['access_token'], res['refresh_token']
|
|
|
|
# @classmethod
|
|
# def get_response(cls, URI, params={}):
|
|
# response = requests.get(URI, headers=HEADERS, params=urlencode(params))
|
|
# print(response)
|
|
# return response
|
|
|
|
# def _validate_token(self):
|
|
# access_token = self.access_token
|
|
# refresh_token = self.refresh_token
|
|
# client_id = self.app_id
|
|
# client_secret = self.secret_key
|
|
# if self.status_token != 'active':
|
|
# access_token, refresh_token = self.get_access_token(
|
|
# refresh_token, client_id, client_secret
|
|
# )
|
|
# self.write([self], {'access_token': access_token,
|
|
# 'refresh_token': refresh_token,
|
|
# 'creation_time': datetime.now()
|
|
# })
|
|
# return access_token, refresh_token, client_id, client_secret
|
|
|
|
# @classmethod
|
|
# def _get_channel(cls):
|
|
# channels = cls.search([
|
|
# ('state', '=', 'active'),
|
|
# ('channel_name', '=', 'mercadolibre'),
|
|
# ])
|
|
# if channels:
|
|
# return channels[0]
|
|
# else:
|
|
# return None
|
|
|
|
# @classmethod
|
|
# def request_api(cls, data):
|
|
# channel = cls._get_channel()
|
|
# response = {'status': 'error', 'msg_response': 'Fail in process !!!'}
|
|
# if not channel:
|
|
# return response
|
|
# access_token, refresh_token, client_id, client_secret = channel._validate_token()
|
|
# if data.get('resource') and data['resource'].count('orders'):
|
|
# order_id = str(data['resource'].replace('/orders/', ''))
|
|
# URI = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
|
|
# order_id, access_token)
|
|
# result = cls.get_response(URI).json()
|
|
# res = channel.validate_sale(result)
|
|
# if res:
|
|
# response = {
|
|
# 'status': 'ok',
|
|
# 'msg_response': 'Successfull process !!!',
|
|
# 'order': order_id
|
|
# }
|
|
# else:
|
|
# response = {
|
|
# 'status': 'ok',
|
|
# 'msg_response': 'Sale processed before !!!',
|
|
# 'order': order_id
|
|
# }
|
|
# elif data.get('resource') and data['resource'].count('shipments'):
|
|
# shipment_id = str(data['resource'].replace('/shipments/', ''))
|
|
# shipment_ = channel.get_shipment_api(shipment_id)
|
|
# order_id = shipment_['order_id']
|
|
|
|
# Sale = Pool().get('sale.sale')
|
|
# sales = Sale.search([
|
|
# ('reference', 'ilike', '%' + str(order_id) + '%')
|
|
# ])
|
|
# response.update({'order': order_id})
|
|
# if not sales:
|
|
# return response
|
|
|
|
# sale = sales[0]
|
|
# if sale.invoices:
|
|
# return response
|
|
|
|
# if len(sales) > 1:
|
|
# channel.upload_note(
|
|
# sale, 'Error, al generar factura orden duplicada')
|
|
# return response
|
|
|
|
# if shipment_.get('tracking_number'):
|
|
# Sale.write([sale], {
|
|
# 'description': 'GUIA DE ENVIO NO. ' + shipment_['tracking_number'],
|
|
# 'tracking_number': shipment_['tracking_number']
|
|
# })
|
|
# if shipment_['status'] in ['shipped', 'delivered']:
|
|
# try:
|
|
# channel._finish_sale(sale)
|
|
# except:
|
|
# channel.upload_note(sale, 'Error al finalizar factura')
|
|
# response = {'status': 'ok',
|
|
# 'msg_response': 'Successfull process !!!',
|
|
# 'order': order_id}
|
|
# else:
|
|
# return {'status': 'none', 'msg_response': 'Don`t process this topic'}
|
|
# return response
|
|
|
|
# def _finish_sale(self, sale, type='invoice'):
|
|
# ctx = self._get_context()
|
|
# pool = Pool()
|
|
# Sale = pool.get('sale.sale')
|
|
# Invoice = pool.get('account.invoice')
|
|
# Date = pool.get('ir.date')
|
|
# with Transaction().set_context(ctx):
|
|
# Sale.process([sale])
|
|
# if not sale.invoices:
|
|
# return
|
|
# invoice = sale.invoices[0]
|
|
# invoice.invoice_date = Date.today()
|
|
# if type == 'return':
|
|
# sale_origin = sale.origin
|
|
# if sale_origin.invoices:
|
|
# inv_origin = sale_origin.invoices[0]
|
|
# invoice.credit_note_concept = '2'
|
|
# invoice.original_invoice = inv_origin.id
|
|
# invoice.save()
|
|
# Invoice.validate_invoice([invoice])
|
|
# if invoice.invoice_type not in ('C', 'P', 'M'):
|
|
# try:
|
|
# invoice.submit([invoice])
|
|
# if not invoice.cufe:
|
|
# return
|
|
# except:
|
|
# self.upload_note(sale, 'Error de envio DIAN')
|
|
# try:
|
|
# Invoice.post([invoice])
|
|
# self.upload_note(sale, 'Factura generada')
|
|
# self.upload_invoice(sale)
|
|
# except:
|
|
# pass
|
|
|
|
# def upload_invoice(self, sale):
|
|
# if not sale.reference or not sale.invoices:
|
|
# return
|
|
|
|
# invoice = sale.invoices[0]
|
|
# pack_id = sale.reference
|
|
# if sale.pack_id:
|
|
# pack_id = sale.pack_id
|
|
# URI = 'https://api.mercadolibre.com/packs/%s/fiscal_documents?access_token=%s' % (
|
|
# pack_id, self.access_token)
|
|
# if sale.uploaded_invoice:
|
|
# response = requests.delete(URI)
|
|
|
|
# report = self.render_report(invoice)
|
|
# file = {"fiscal_document": report}
|
|
# response = requests.post(URI, files=file)
|
|
# print(response.status_code)
|
|
# message = 'Error al subir factura'
|
|
# if response.status_code in [200, 201, 202]:
|
|
# res = response.json()
|
|
# upload_ids = 'Upload ids: ' + ', '.join(list(res['ids']))
|
|
# sale.write([sale], {
|
|
# 'uploaded_invoice': True,
|
|
# 'document_invoice': upload_ids,
|
|
# })
|
|
# message = 'Factura Cargada exitosamente'
|
|
# self.upload_note(sale, message)
|
|
|
|
# def upload_note(self, sale, message):
|
|
# URI = 'https://api.mercadolibre.com/orders/%s/notes?access_token=%s' % (
|
|
# sale.reference, self.access_token)
|
|
|
|
# params = {"note": message}
|
|
# request = json.dumps(params)
|
|
# response = requests.post(URI, headers=HEADERS, data=request)
|
|
# if not response.status_code in [200, 201, 202]:
|
|
# self.send_mail_notification(
|
|
# 'error al crear nota en orden ' + sale.reference)
|
|
|
|
|
|
class MercadoLibre:
|
|
'MercadoLibre'
|
|
def __init__(self, web_shop):
|
|
self.access_token = web_shop.access_token if web_shop.access_token else ''
|
|
self.generic_product = web_shop.generic_product
|
|
self.refresh_token = web_shop.refresh_token
|
|
self.id = web_shop.id
|
|
self.app_id = web_shop.app_id
|
|
self.secret_key = web_shop.secret_key
|
|
self.freight_product = web_shop.freight_product
|
|
self.invoice_type = web_shop.invoice_type
|
|
|
|
def _get_context(self):
|
|
user_ = self._get_user()
|
|
return {
|
|
'company': user_.company.id,
|
|
'user': user_.id,
|
|
'shops': [user_.shop.id],
|
|
'shop': user_.shop.id,
|
|
'language': 'es'
|
|
}
|
|
|
|
def _get_user(self):
|
|
User = Pool().get('res.user')
|
|
user, = User.search([
|
|
('login', '=', 'mercado.libre')
|
|
])
|
|
return user
|
|
|
|
def _create_product(self, codes, line={}):
|
|
item = line['item']
|
|
pool = Pool()
|
|
Product = pool.get('product.product')
|
|
Template = pool.get('product.template')
|
|
description = ''
|
|
if item.get('variation_attributes'):
|
|
var = item['variation_attributes'][0]
|
|
if var['id'] and var['name']:
|
|
description = var['id'] + ' ' + var['name']
|
|
create_template = {
|
|
'name': item['title'],
|
|
'list_price': line['unit_price'],
|
|
'sale_price_w_tax': line['full_unit_price'],
|
|
'type': 'goods',
|
|
'salable': True,
|
|
'purchasable': True,
|
|
'purchase_uom': 1,
|
|
'sale_uom': 1,
|
|
'default_uom': 1,
|
|
'account_category': 7,
|
|
}
|
|
template, = Template.create([create_template])
|
|
create_product = []
|
|
for code in codes:
|
|
create_product.append({
|
|
'code': code,
|
|
'description': description,
|
|
'template': template.id
|
|
})
|
|
return Product.create(create_product)
|
|
|
|
def _create_party(self, customer):
|
|
_pool = Pool()
|
|
City = _pool.get('party.city_code')
|
|
Party = _pool.get('party.party')
|
|
PartyObligationTax = _pool.get('party.obligation_tax')
|
|
email = customer.get('email', '@')
|
|
shipment_address, phone, city = '', '', None
|
|
if customer.get('receiver_address'):
|
|
receiver_address = customer['receiver_address']
|
|
shipment_address = receiver_address['address_line']
|
|
phone = receiver_address['receiver_phone'] or '000'
|
|
city_name = receiver_address['city']['name']
|
|
if city_name:
|
|
cities = City.search([
|
|
('name', '=', city_name)
|
|
])
|
|
if cities:
|
|
city = cities[0]
|
|
if customer['billing_info']['doc_type'] == 'NIT':
|
|
type_document = '31'
|
|
customer_name = customer['billing_info']['business_name']
|
|
type_person = 'persona_juridica'
|
|
else:
|
|
customer_name = customer['billing_info']['first_name'] + ' ' + customer['billing_info']['last_name']
|
|
type_document = '13'
|
|
type_person = 'persona_natural'
|
|
|
|
create_customer = {
|
|
'id_reference': str(customer['id']),
|
|
'name': customer_name.upper(),
|
|
'type_document': type_document,
|
|
'type_person': type_person,
|
|
'id_number': customer['billing_info']['doc_number'],
|
|
'addresses': [('create', [{
|
|
'street': shipment_address,
|
|
}])],
|
|
'contact_mechanisms': [
|
|
('create', [
|
|
{'type': 'phone', 'value': phone},
|
|
{'type': 'email', 'value': email},
|
|
])
|
|
]
|
|
}
|
|
if not city:
|
|
city = City(149)
|
|
create_customer['addresses'][0][1][0]['department_code'] = city.department.id
|
|
create_customer['addresses'][0][1][0]['city_code'] = city.id
|
|
party, = Party.create([create_customer])
|
|
PartyObligationTax.create([{
|
|
'party': party.id,
|
|
'obligation_fiscal': 6,
|
|
}])
|
|
return party
|
|
|
|
def get_shipment_api(self, shipment_id):
|
|
if not shipment_id:
|
|
return None
|
|
URI = 'https://api.mercadolibre.com/shipments/%s?access_token=%s' % (
|
|
shipment_id, self.access_token)
|
|
res = self.get_response(URI)
|
|
return res.json()
|
|
|
|
def get_billing_info_api(self, order_id):
|
|
if not order_id:
|
|
return None
|
|
URI = 'https://api.mercadolibre.com/orders/%s/billing_info?access_token=%s' % (
|
|
order_id, self.access_token)
|
|
res = self.get_response(URI)
|
|
return res.json()
|
|
|
|
def _return_sale(self, sale):
|
|
pool = Pool()
|
|
Sale = pool.get('sale.sale')
|
|
Date = pool.get('ir.date')
|
|
ctx = self._get_context()
|
|
dev_sales = []
|
|
sales = [sale]
|
|
if sale.pack_id:
|
|
sales = Sale.search([
|
|
('pack_id', '=', sale.pack_id)
|
|
])
|
|
with Transaction().set_context(ctx):
|
|
return_sales = Sale.copy(sales)
|
|
for return_sale, sale in zip(return_sales, sales):
|
|
return_sale.origin = sale
|
|
return_sale.reference = sale.reference
|
|
return_sale.state = 'draft'
|
|
return_sale.sale_date = Date.today()
|
|
if sale.invoice_type == '1':
|
|
return_sale.invoice_type = '91'
|
|
for line in return_sale.lines:
|
|
if line.type == 'line':
|
|
line.quantity *= -1
|
|
line.save()
|
|
if return_sale.untaxed_amount_cache:
|
|
return_sale.untaxed_amount_cache *= -1
|
|
if return_sale.tax_amount_cache:
|
|
return_sale.tax_amount_cache *= -1
|
|
if return_sale.total_amount_cache:
|
|
return_sale.total_amount_cache *= -1
|
|
return_sale.save()
|
|
Sale.quote([return_sale])
|
|
Sale.write([return_sale], {'state': 'confirmed'})
|
|
dev_sales.append(return_sale)
|
|
return dev_sales
|
|
|
|
def create_lines_sale(self, sale, sale_items, sfm_id, freight=False):
|
|
_pool = Pool()
|
|
SaleLine = _pool.get('sale.line')
|
|
Product = _pool.get('product.product')
|
|
create_lines = []
|
|
# sale_items = sale_['order_items']
|
|
ctx = self._get_context()
|
|
# sfm_id = sale_items[0]['shipping']['id']
|
|
# reference = sale.reference.split(',')
|
|
# reference_order = str(sale_['id'])
|
|
# if reference_order not in reference:
|
|
# sale.referece = sale.reference + ',' + reference_order
|
|
# sale.save()
|
|
with Transaction().set_context(ctx):
|
|
for line in sale_items:
|
|
sku_code = line['item']['seller_sku']
|
|
|
|
if sku_code:
|
|
generic = False
|
|
if sku_code.count('+') > 0:
|
|
codes = sku_code.split('+')
|
|
line['unit_price'] = Decimal(
|
|
round((line['unit_price'] / 2), 2))
|
|
else:
|
|
codes = [sku_code]
|
|
|
|
products = Product.search([
|
|
('code', 'in', codes),
|
|
('active', '=', True)
|
|
])
|
|
description = ''
|
|
if not products:
|
|
products = self._create_product(codes, line)
|
|
else:
|
|
if not self.generic_product:
|
|
raise NotProductFoundError(
|
|
gettext('sale_web_channel.msg_product_generic_not_found'))
|
|
products = [self.generic_product]
|
|
generic = True
|
|
description = ''
|
|
raise NotProductFound(
|
|
gettext('sale_web_channel.msg_product_not_found', s=self.generic_product.rec_name))
|
|
for product in products:
|
|
Tax = _pool.get('account.tax')
|
|
un_price = Tax.reverse_compute(Decimal(line['unit_price']),
|
|
product.customer_taxes_used)
|
|
create_lines.append({
|
|
'sale': sale.id,
|
|
'type': 'line',
|
|
'unit': product.default_uom.id,
|
|
'quantity': line['quantity'],
|
|
'unit_price': round(Decimal(un_price), 3),
|
|
'unit_price_full': Decimal(line['unit_price']),
|
|
'product': product.id,
|
|
'taxes': [('add', product.customer_taxes_used)],
|
|
'description': description,
|
|
})
|
|
if freight and self.freight_product:
|
|
product = self.freight_product
|
|
URI = 'https://api.mercadolibre.com/shipments/%s/costs?access_token=%s' % (
|
|
sfm_id, self.access_token)
|
|
result = self.get_response(URI).json()
|
|
shipping_amount = result['receiver']['cost']
|
|
create_lines.append({
|
|
'sale': sale.id,
|
|
'type': 'line',
|
|
'unit': product.default_uom.id,
|
|
'quantity': 1,
|
|
'unit_price': Decimal(shipping_amount),
|
|
'unit_price_full': Decimal(shipping_amount),
|
|
'product': product.id,
|
|
'description': 'FLETE',
|
|
})
|
|
SaleLine.create(create_lines)
|
|
return generic
|
|
|
|
def validate_sale(self, sale_):
|
|
if sale_.get('id'):
|
|
# URI = 'https://api.mercadolibre.com/packs/%s?access_token=%s' % (
|
|
# sale_.get('pack_id'), self.access_token)
|
|
# response = self.get_response(URI)
|
|
# response = response.json()
|
|
# print(response.get('orders'), 'response.get')
|
|
if sale_.get('orders'):
|
|
ids = ''
|
|
sale_['order_items'] = []
|
|
for item in sale_['orders']:
|
|
order_id = str(item['id'])
|
|
URI2 = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
|
|
order_id, self.access_token)
|
|
order = self.get_response(URI2)
|
|
sale_order = order.json()
|
|
ids += ',' + order_id
|
|
sale_['order_items'].append(sale_order)
|
|
sale_['id'] = str(sale_['id']) + ids
|
|
# sale_['id'] = str(sale_['id']) + ids
|
|
return self._create_sale(sale_)
|
|
else:
|
|
return self._create_sale(sale_)
|
|
else:
|
|
return self._create_sale(sale_)
|
|
|
|
def _create_sale(self, sale_):
|
|
_pool = Pool()
|
|
Sale = _pool.get('sale.sale')
|
|
# reference = '%' + str(sale_['id']).split(',')[0] + '%'
|
|
try:
|
|
ids = [str(order['id']) for order in sale_['orders']]
|
|
pack_id = str(sale_['id']).split(',')[0]
|
|
reference = ', '.join(ids)
|
|
sfm_id = sale_['order_items'][0]['shipping']['id']
|
|
sale_id = str(sale_['id']).split(',')[1]
|
|
sale_items = sale_['order_items'][0]['order_items']
|
|
except KeyError:
|
|
ids = sale_['id']
|
|
pack_id = None
|
|
reference = sale_['id']
|
|
sfm_id = sale_['shipping']['id']
|
|
sale_id = sale_['id']
|
|
sale_items = sale_['order_items']
|
|
dom = [
|
|
('reference', 'like', reference)
|
|
]
|
|
sales = Sale.search(dom)
|
|
if sales:
|
|
if len(sales) == 1 and sale_['status'] == 'cancelled':
|
|
sale = sales[0]
|
|
if not sale.invoices:
|
|
self.cancel_sales([sale], sale.pack_id)
|
|
else:
|
|
dev_sales = self._return_sale(sale)
|
|
self._finish_sale(dev_sales[0], type='return')
|
|
return True
|
|
return False
|
|
sale_data = sale_['order_items'][0]
|
|
Party = _pool.get('party.party')
|
|
User = _pool.get('res.user')
|
|
shipment_ = self.get_shipment_api(sfm_id)
|
|
if sale_.get('buyer'):
|
|
billing_info = self.get_billing_info_api(sale_id)
|
|
customer = sale_['buyer']
|
|
dom_party = [('id_reference', '=', str(customer['id']))]
|
|
if billing_info and billing_info['billing_info'].get('doc_number'):
|
|
dom_party = [('id_number', '=', str(
|
|
billing_info['billing_info']['doc_number']))]
|
|
parties = Party.search(dom_party)
|
|
if parties:
|
|
party = parties[0]
|
|
else:
|
|
customer['receiver_address'] = shipment_['receiver_address']
|
|
customer['billing_info'] = billing_info['billing_info']
|
|
for dic in customer['billing_info']['additional_info']:
|
|
customer['billing_info'][list(dic.values())[0].lower()
|
|
] = list(dic.values())[1]
|
|
try:
|
|
customer['billing_info']['additional_info'].pop()
|
|
except Exception as e:
|
|
msg = 'sin informacion de tercero' + e
|
|
raise UserError(
|
|
gettext('sale_web_channel.msg_billing_info', msg=msg))
|
|
party = self._create_party(customer)
|
|
ctx = self._get_context()
|
|
user_ = User(ctx['user'])
|
|
date_created = sale_['date_created'].split('T')
|
|
year, month, day = date_created[0].split('-')
|
|
sale_date = date(int(year), int(month), int(day))
|
|
with Transaction().set_user(ctx['user']):
|
|
sale, = Sale.create([{
|
|
'payment_term': 1,
|
|
'party': party.id,
|
|
'sale_date': sale_date,
|
|
'comment': shipment_['status'],
|
|
'state': 'draft',
|
|
'company': ctx['company'],
|
|
'currency': user_.company.currency.id,
|
|
'shop': user_.shop.id,
|
|
'reference': reference,
|
|
'invoice_address': Party.address_get(party, type='invoice'),
|
|
'shipment_address': Party.address_get(party, type='delivery'),
|
|
'description': 'VENTA WEB ',
|
|
'web_shop': self.id,
|
|
'web_id': pack_id if pack_id else sale_id,
|
|
'invoice_type': self.invoice_type,
|
|
'pack_id': pack_id,
|
|
}])
|
|
generic = self.create_lines_sale(
|
|
sale, sale_items, sfm_id, freight=True)
|
|
sale.untaxed_amount_cache = sale.untaxed_amount
|
|
if sale_['status'] == 'cancelled':
|
|
sale.state = 'cancelled'
|
|
else:
|
|
Sale.quote([sale])
|
|
if not generic:
|
|
sale.state = 'confirmed'
|
|
sale.save()
|
|
# if shipment_['status'] in ['shipped', 'delivered']:
|
|
# self._finish_sale(sale)
|
|
return sale
|
|
|
|
@classmethod
|
|
def get_response(cls, URI, params={}):
|
|
response = requests.get(URI, headers=HEADERS, params=urlencode(params))
|
|
return response
|
|
|
|
def get_access_token(self, refresh_token, client_id, client_secret):
|
|
params = {'grant_type': 'refresh_token',
|
|
'client_id': client_id,
|
|
'client_secret': client_secret,
|
|
'refresh_token': refresh_token
|
|
}
|
|
uri = 'https://api.mercadolibre.com/oauth/token'
|
|
response = requests.post(uri, params=urlencode(params),
|
|
headers=HEADERS, data=params)
|
|
res = response.json()
|
|
if res.get('error', None):
|
|
raise UserError(res.get('message') + ' Error:' + res.get('error'))
|
|
return res['access_token'], res['refresh_token']
|
|
|
|
def _validate_token(self):
|
|
access_token = self.access_token
|
|
refresh_token = self.refresh_token
|
|
client_id = self.app_id
|
|
client_secret = self.secret_key
|
|
access_token, refresh_token = self.get_access_token(
|
|
refresh_token, client_id, client_secret
|
|
)
|
|
# return access_token, refresh_token, client_id, client_secret
|
|
return access_token
|
|
|
|
def _validate_number_id(self, number_id, access_token):
|
|
URI = 'https://api.mercadolibre.com/packs/%s?access_token=%s' % (
|
|
number_id, access_token)
|
|
result = self.get_response(URI).json()
|
|
if result['status'] != 404:
|
|
return self.validate_sale(result)
|
|
else:
|
|
URI = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
|
|
number_id, access_token)
|
|
result = self.get_response(URI).json()
|
|
if result['pack_id']:
|
|
URI = 'https://api.mercadolibre.com/packs/%s?access_token=%s' % (
|
|
result['pack_id'], access_token)
|
|
result2 = self.get_response(URI).json()
|
|
return self.validate_sale(result2)
|
|
return self._create_sale(result)
|