362 lines
14 KiB
Python
362 lines
14 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 itertools import chain
|
|
from trytond.transaction import Transaction
|
|
import requests
|
|
from urllib.parse import urlencode
|
|
from datetime import datetime, date
|
|
from web_channel import SaleWebChannel
|
|
import json
|
|
|
|
__all__ = ['Shopify']
|
|
|
|
HEADERS = {
|
|
'Accept': 'application/json',
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
|
|
class Shopify(SaleWebChannel):
|
|
'Shopify'
|
|
__name__ = 'sale.web_channel.shopify'
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(Shopify, cls).__setup__()
|
|
cls._error_messages.update({
|
|
'product_not_found': ('Product Not Found'),
|
|
})
|
|
|
|
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', '=', 'shopify')
|
|
)
|
|
return user
|
|
|
|
def _create_product(self, codes, line={}):
|
|
pool = Pool()
|
|
Product = pool.get('product.product')
|
|
Template = pool.get('product.template')
|
|
description = line['variant_title']
|
|
list_price = round(float(line['price'])/1.19, 2)
|
|
sale_price_w_tax = round(Decimal(line['price']), 2)
|
|
print(list_price)
|
|
print(sale_price_w_tax)
|
|
create_template = {
|
|
'name': line['title'],
|
|
'list_price': 1,
|
|
'sale_price_w_tax': 1,
|
|
'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,
|
|
'id_reference': '',
|
|
'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['email']
|
|
shipment_address, phone, city = '', '', None
|
|
if customer.get('default_address'):
|
|
default_address = customer['default_address']
|
|
shipment_address = default_address['address1']
|
|
phone = default_address['phone'] or '000'
|
|
city_name = default_address['city']
|
|
if city_name:
|
|
cities = City.search([
|
|
('name', '=', city_name)
|
|
])
|
|
if cities:
|
|
city = cities[0]
|
|
customer_name = customer['first_name'] + ' ' + customer['last_name']
|
|
create_customer = {
|
|
'id_reference': str(customer['id']),
|
|
'name': customer_name.upper(),
|
|
'type_document': '13',
|
|
'id_number': default_address['company'],
|
|
'addresses': [('create', [{
|
|
'street': shipment_address,
|
|
}])],
|
|
'contact_mechanisms': [
|
|
('create', [
|
|
{'type': 'phone', 'value': phone.replace(" ","")},
|
|
{'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 _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_sale(self, sale_):
|
|
_pool = Pool()
|
|
Sale = _pool.get('sale.sale')
|
|
sales = Sale.search([
|
|
('reference', '=', str(sale_['id']))
|
|
])
|
|
if sales:
|
|
return False
|
|
SaleLine = _pool.get('sale.line')
|
|
Party = _pool.get('party.party')
|
|
Product = _pool.get('product.product')
|
|
User = _pool.get('res.user')
|
|
if sale_.get('customer'):
|
|
customer = sale_['customer']
|
|
dom_party = [('id_number', '=', str(customer['default_address']['company']))]
|
|
parties = Party.search(dom_party)
|
|
if parties:
|
|
party = parties[0]
|
|
else:
|
|
party = self._create_party(customer)
|
|
sale_items = sale_['line_items']
|
|
create_lines = []
|
|
ctx = self._get_context()
|
|
user_ = User(ctx['user'])
|
|
date_created = sale_['created_at'].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': 'GUIA DE ENVIO NO. ' + sale_['fulfillments'][0]['tracking_number']
|
|
if sale_['fulfillment_status'] == 'fulfilled' else '',
|
|
'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 SHOPIFY ' + sale_['name'] +' - '+
|
|
sale_['fulfillment_status'] if sale_['fulfillment_status'] == 'fulfilled'
|
|
else 'VENTA SHOPIFY ' + sale_['name'],
|
|
'channel': self.id,
|
|
'invoice_type': self.invoice_type,
|
|
'pack_id': ''
|
|
}])
|
|
|
|
with Transaction().set_context(ctx):
|
|
for line in sale_items:
|
|
if line['title'] == 'Tip':
|
|
if self.tip_product:
|
|
product = self.tip_product
|
|
total_tip = line['price']
|
|
create_lines.append({
|
|
'sale': sale.id,
|
|
'type': 'line',
|
|
'unit': product.default_uom.id,
|
|
'quantity': 1,
|
|
'unit_price': Decimal(total_tip),
|
|
'unit_price_full': Decimal(total_tip),
|
|
'discount': 0,
|
|
'product': product.id,
|
|
'description': 'BONIFICACION',
|
|
})
|
|
else:
|
|
sku_code = line['sku']
|
|
if sku_code.count('+') > 0:
|
|
codes = sku_code.split('+')
|
|
line['price'] = round(Decimal(line['price']) / 2, 2)
|
|
discount = round(sum([Decimal(n['amount']) for n in line['discount_allocations']]) / 2, 2)
|
|
else:
|
|
codes = [sku_code]
|
|
discount = round(sum([Decimal(n['amount']) for n in line['discount_allocations']]))
|
|
products = Product.search([
|
|
('code', 'in', codes),
|
|
('active', '=', True)
|
|
])
|
|
description = ''
|
|
if not products:
|
|
products = self._create_product(codes, line)
|
|
for product in products:
|
|
Tax = _pool.get('account.tax')
|
|
un_price = Tax.reverse_compute((Decimal(line['price']) - discount),
|
|
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': round(Decimal(line['price']),2),
|
|
'discount': 0,
|
|
'product': product.id,
|
|
'taxes': [('add', product.customer_taxes_used)],
|
|
'description': description,
|
|
})
|
|
if self.freight_product:
|
|
product = self.freight_product
|
|
shipping_amount = sale_['shipping_lines'][0]['price']
|
|
create_lines.append({
|
|
'sale': sale.id,
|
|
'type': 'line',
|
|
'unit': product.default_uom.id,
|
|
'discount': 0,
|
|
'quantity': 1,
|
|
'unit_price': Decimal(shipping_amount),
|
|
'unit_price_full': Decimal(shipping_amount),
|
|
'product': product.id,
|
|
'description': 'FLETE',
|
|
})
|
|
SaleLine.create(create_lines)
|
|
sale.untaxed_amount_cache = sale.untaxed_amount
|
|
if sale_['cancel_reason'] != None:
|
|
sale.state = 'cancel'
|
|
else:
|
|
Sale.quote([sale])
|
|
print('*******************', sale.state )
|
|
sale.save()
|
|
return sale
|
|
|
|
@classmethod
|
|
def get_response(cls, URI, params={}):
|
|
response = requests.get(URI, headers=HEADERS, params=urlencode(params))
|
|
return response
|
|
|
|
@classmethod
|
|
def _get_channel(cls):
|
|
channels = cls.search([
|
|
('state', '=', 'active'),
|
|
('channel_name', '=', 'shopify'),
|
|
])
|
|
if channels:
|
|
return channels[0]
|
|
else:
|
|
return None
|
|
|
|
@classmethod
|
|
def request_api(cls, data, header):
|
|
response = {'status': 'error', 'msg': 'Fail in process !!!'}
|
|
channel = cls._get_channel()
|
|
if not channel:
|
|
return response
|
|
if header.count('create'):
|
|
res = channel._create_sale(data)
|
|
if res:
|
|
response = {'status': 'ok', 'msg': 'Successfull create sale !!!'}
|
|
elif header.count('fulfilled'):
|
|
cls.order_fulfilled(data)
|
|
response = {'status': 'ok', 'msg': 'Successfull process sale !!!'}
|
|
elif header.count('paid'):
|
|
pass
|
|
elif header.count('updated'):
|
|
pass
|
|
elif header.coun('cancelled'):
|
|
cls.order_cancelled(data)
|
|
response = {'status': 'ok', 'msg': 'Successfull cancel sale !!!'}
|
|
return response
|
|
|
|
@classmethod
|
|
def order_cancelled(cls, data):
|
|
order_id = data.get('id')
|
|
Sale = Pool().get('sale.sale')
|
|
sales = Sale.search([
|
|
('reference', '=', str(order_id))
|
|
])
|
|
if not sales:
|
|
return response
|
|
Sale.cancel(sales)
|
|
|
|
@classmethod
|
|
def order_fulfilled(cls, data):
|
|
order_id = data.get('id')
|
|
Sale = Pool().get('sale.sale')
|
|
sales = Sale.search([
|
|
('reference', '=', str(order_id))
|
|
])
|
|
if not sales:
|
|
return response
|
|
|
|
sale = sales[0]
|
|
if sale.invoices:
|
|
return response
|
|
else:
|
|
Sale.confirm([sales])
|
|
|
|
if len(sales) > 1:
|
|
# channel.upload_note(sale, 'Error, al generar factura orden duplicada')
|
|
return response
|
|
|
|
if data.get('fulfillment_status') == 'fulfilled':
|
|
Sale.write([sale], {
|
|
'description': sale.description +' - '+ data['fulfillment_status'],
|
|
'comment': 'GUIA DE ENVIO NO. ' + data['fulfillments'][0]['tracking_number'],
|
|
'tracking_number': data['fulfillments'][0]['tracking_number']
|
|
})
|