[FIX][T4494] Revamped some logics in the importer

Merged Hermes requested to merge T4494 into 12.0
Compare and
1 file
+ 163
125
Preferences
File browser
Compare changes
@@ -183,16 +183,6 @@ class CustomerPurchaseOrderImporter(models.Model):
return branch
def get_config(self, partner):
CustomerPurchaseOrderConfig = self.env['customer.purchase.order.config']
if partner:
config = CustomerPurchaseOrderConfig.search([('partner', '=', partner)])
return config
return False
"""Config methods receive a dict with all the values of each file --some of which will
probably be empty. The product lines key ('pre_order_line_ids') is a list of tuples
with the format (0, 0, {...product data...}). The dict has the following structure:
@@ -233,6 +223,16 @@ class CustomerPurchaseOrderImporter(models.Model):
keys cannot be accessed by the key 'original', and they mustn't be modified.
"""
def get_config(self, partner):
CustomerPurchaseOrderConfig = self.env['customer.purchase.order.config']
if not partner:
return False
config = CustomerPurchaseOrderConfig.search([('partner', '=', partner)])
return config
def get_config_basic_vals(self, vals):
return vals
@@ -285,15 +285,14 @@ class CustomerPurchaseOrderImporter(models.Model):
return vals
def get_config_internal_code(self, partner):
def get_config_internal_code(self, partner, product_type=False):
_configs = self.get_config(partner)
config = None
if not _configs:
return False
if _configs:
for _config in _configs:
if _config.config_type == 'internal_code':
config = _config
break
config = _configs.filtered(
lambda x: x.config_type == 'internal_code' and x.product_type == product_type
)
return config
@@ -454,6 +453,7 @@ class CustomerPurchaseOrderImporter(models.Model):
def get_full_file_data(self, lines):
msg_list = []
address = None
config_lines = None
partner = None
branch = None
product_type = None
@@ -461,8 +461,8 @@ class CustomerPurchaseOrderImporter(models.Model):
header_data = self.get_header_data(lines)
# PO number
po_number = header_data['purchase_order_number']
if not po_number:
order_number = header_data['purchase_order_number']
if not order_number:
msg_list.append(_('~ Purchase order number not found.\n'))
# Partner
@@ -482,11 +482,12 @@ class CustomerPurchaseOrderImporter(models.Model):
else:
# Product type
product_codes = self.get_product_codes(lines[1:])
_product_type = self.get_product_type(product_codes, partner)
product_type = _product_type['product_type']
config_lines = self._get_config_lines(product_codes, partner)
products = self.get_products(product_codes, config_lines)
if _product_type['errors']:
msg_list.extend(_product_type['errors'])
product_type, product_type_errors = self.get_product_type(products)
if product_type_errors:
msg_list.extend(product_type_errors)
address = partner.address_get(['invoice'])
@@ -507,11 +508,11 @@ class CustomerPurchaseOrderImporter(models.Model):
else:
# Pricelist
pricelist = branch.zone_accounts_line_ids.rp_za_pricelist
po_exists = self.purchase_order_exists_for_branch(po_number, branch)
if po_exists:
order_exists = self.purchase_order_exists_for_branch(order_number, branch)
if order_exists:
msg_list.append(
_('~ Purchase order ORD{} already exists for branch {}.\n').format(
po_number, branch.name
order_number, branch.name
)
)
@@ -533,17 +534,17 @@ class CustomerPurchaseOrderImporter(models.Model):
msg_list.extend(dates['errors'])
# Product lines
po_lines = self.get_product_lines(lines, partner, product_type, pricelist, branch)
order_lines = self.get_product_lines(lines, products, pricelist, branch)
if po_lines['errors']:
msg_list.extend(po_lines['errors'])
if order_lines['errors']:
msg_list.extend(order_lines['errors'])
if msg_list:
msg_list += [partner.name.upper() if partner else 'PARTNER_NOT_FOUND_']
return msg_list
else:
po_data = {
'name': 'ORD' + po_number,
order_data = {
'name': 'ORD' + order_number,
'partner': partner.id,
'partner_invoice_id': address['invoice'],
'partner_shipping_id': branch.id,
@@ -552,13 +553,13 @@ class CustomerPurchaseOrderImporter(models.Model):
'delivery_date': delivery_date,
'due_date': due_date,
'manual_create': False,
'summary_code': po_lines['summary_code'],
'summary_qty': po_lines['summary_qty'],
'pre_order_line_ids': po_lines['po_lines'],
'summary_code': order_lines['summary_code'],
'summary_qty': order_lines['summary_qty'],
'pre_order_line_ids': order_lines['order_lines'],
'product_type': product_type.id,
}
return po_data
return order_data
"""All data is retrieved from the file with these two methods. Not all of it is
required nor used to create a purchase order, though it may be used in future
@@ -733,39 +734,60 @@ class CustomerPurchaseOrderImporter(models.Model):
partner = ResPartner.search([('partner_ean_code', '=', ean_code)])
return partner
def get_product(self, config, code, is_ean_code=False, partner=None, description=''):
def _get_config_lines(self, codes, partner):
CustomerPurchaseOrderConfigLine = self.env['customer.purchase.order.config.line']
ProductProduct = self.env['product.product']
errors = []
config_lines = CustomerPurchaseOrderConfigLine.search(
[
('customer_purchase_order_config_id.partner', '=', partner.id),
'|',
('product_internal_code', 'in', codes),
('product_ean13_code', 'in', codes),
]
)
product = ProductProduct.search(['|', ('barcode', '=', code), ('default_code', '=', code)])
return config_lines
if code and partner:
if config:
config_line = CustomerPurchaseOrderConfigLine.search(
[
('product_internal_code', '=', code),
('customer_purchase_order_config_id', '=', config.id),
]
)
def _get_product(self, product, description=''):
errors = []
if config_line:
product = config_line.product
code = list(product.keys())[0]
product = product[code]['product']
if not product:
errors.append(_('~ Product %s with code %s not found.\n') % (description, code))
elif len(product) > 1:
errors.append(_('~ More than one product found with EAN code %s.\n') % code)
product = None
return {'product': product, 'errors': errors}
return product, errors
def get_product_codes(self, lines):
codes = []
for line in lines:
codes.append(line[10:24].replace(' ', ''))
def get_products(self, codes, config_lines):
ProductProduct = self.env['product.product']
products = []
for code in codes:
config_line = None
product = ProductProduct.search(['|', ('barcode', '=', code), ('default_code', '=', code)])
if not product:
if config_lines:
config_line = config_lines.filtered(
lambda x: x.product_ean13_code == code or x.product_internal_code == code
)
product = config_line.product
data = {
code: {'config_line': config_line, 'product': product},
'type': product.product_type_id if product else None,
}
products.append(data)
return products
def get_product_codes(self, lines):
codes = [x[10:24].replace(' ', '') for x in lines]
return codes
def get_product_data(self, line):
@@ -867,8 +889,14 @@ class CustomerPurchaseOrderImporter(models.Model):
'modified': additional_line_expense,
},
'box_qty': {'original': box_qty, 'modified': box_qty},
'box_qty_ean_set': {'original': box_qty_ean_set, 'modified': box_qty_ean_set},
'box_qty_pallets': {'original': box_qty_pallets, 'modified': box_qty_pallets},
'box_qty_ean_set': {
'original': box_qty_ean_set,
'modified': box_qty_ean_set,
},
'box_qty_pallets': {
'original': box_qty_pallets,
'modified': box_qty_pallets,
},
'comeback': {'original': comeback, 'modified': comeback},
'discount1': {'original': discount1, 'modified': discount1},
'discount2': {'original': discount2, 'modified': discount2},
@@ -878,23 +906,44 @@ class CustomerPurchaseOrderImporter(models.Model):
'discount6': {'original': discount6, 'modified': discount6},
'ean13_code': {'original': ean13_code, 'modified': ean13_code},
'errors': [],
'gross_price_unit': {'original': gross_price_unit, 'modified': gross_price_unit},
'gross_price_unit': {
'original': gross_price_unit,
'modified': gross_price_unit,
},
'internal_tax': {'original': internal_tax, 'modified': internal_tax},
'item_colour_description': {
'original': item_colour_description,
'modified': item_colour_description,
},
'item_description1': {'original': item_description1, 'modified': item_description1},
'item_description2': {'original': item_description2, 'modified': item_description2},
'item_description3': {'original': item_description3, 'modified': item_description3},
'item_description4': {'original': item_description4, 'modified': item_description4},
'item_description1': {
'original': item_description1,
'modified': item_description1,
},
'item_description2': {
'original': item_description2,
'modified': item_description2,
},
'item_description3': {
'original': item_description3,
'modified': item_description3,
},
'item_description4': {
'original': item_description4,
'modified': item_description4,
},
'item_short_description': {
'original': item_short_description,
'modified': item_short_description,
},
'item_size_description': {'original': item_size_description, 'modified': item_size_description},
'item_size_description': {
'original': item_size_description,
'modified': item_size_description,
},
'line_number': {'original': line_number, 'modified': line_number},
'line_total_amount': {'original': line_total_amount, 'modified': line_total_amount},
'line_total_amount': {
'original': line_total_amount,
'modified': line_total_amount,
},
'net_price_unit': {'original': net_price_unit, 'modified': net_price_unit},
'ordered_qty': {'original': ordered_qty, 'modified': ordered_qty},
'supplier_product_internal_code': {
@@ -907,19 +956,22 @@ class CustomerPurchaseOrderImporter(models.Model):
'vat_tax': {'original': vat_tax, 'modified': vat_tax},
}
def get_product_lines(self, lines, partner, product_type, pricelist, branch):
def get_product_lines(self, lines, products, pricelist, branch):
PreSaleOrder = self.env['pre.sale.order']
errors = []
po_lines = []
product = None
summary_code = 0
summary_qty = 0
po_lines = []
errors = []
order_lines = []
order_lines = []
_last_line_is_empty = len(lines[-1]) == 0
product_lines = lines[1 : -1 if _last_line_is_empty else None]
for line in product_lines:
po_line = ()
order_line = ()
if len(line) > 0:
product_data = self.get_product_data(line)
@@ -928,79 +980,56 @@ class CustomerPurchaseOrderImporter(models.Model):
ordered_qty = product_data['ordered_qty']['original']
product_description = product_data['item_short_description']['original']
config = self.get_config_internal_code(partner.id if partner else None)
_product = self.get_product(
config, ean13_code, is_ean_code=True, partner=partner, description=product_description
)
if _product.get('errors'):
errors.extend(_product.get('errors'))
_product = [p for p in products if ean13_code in p.keys()][0]
product, product_errors = self._get_product(_product, product_description)
if product_errors:
errors.extend(product_errors)
continue
product = _product.get('product')
if product:
if branch and ean13_code:
self.save_branch_ean_code(branch, ean13_code, product)
if product_type:
summary_code += int(product.default_code)
summary_qty += ordered_qty
product_data.update(
{
'box_kg': product.box_kgs,
'content': product.content,
'is_maxipiece': product.is_maxipiece,
'name': product.name,
'product_id': product.id,
'product_uom': product.uom_id.id,
'pricelist_price': (
PreSaleOrder._get_pricelist_price(product, pricelist)
if pricelist
else 0.0
),
'tax_id': [(6, 0, product.taxes_id.ids)],
}
)
summary_code += int(product.default_code)
summary_qty += ordered_qty
product_data.update(
{
'box_kg': product.box_kgs,
'content': product.content,
'is_maxipiece': product.is_maxipiece,
'name': product.name,
'product_id': product.id,
'product_uom': product.uom_id.id,
'pricelist_price': (
PreSaleOrder._get_pricelist_price(product, pricelist) if pricelist else 0.0
),
'tax_id': [(6, 0, product.taxes_id.ids)],
}
)
po_line = (0, 0, product_data)
order_line = (0, 0, product_data)
po_lines.append(po_line)
order_lines.append(order_line)
return {
'po_lines': po_lines,
'order_lines': order_lines,
'summary_code': summary_code,
'summary_qty': summary_qty,
'errors': errors,
}
def get_product_type(self, product_codes, partner):
ProductType = self.env['product.type']
def get_product_type(self, products):
product_type = False
errors = []
product_types = []
product_type = None
if product_codes and partner:
for code in product_codes:
config = self.get_config_internal_code(partner.id if partner else None)
_product = self.get_product(config, code, partner=partner)
product = _product.get('product')
if not product:
continue
else:
if product.product_type_id:
product_types.append(product.product_type_id.id)
else:
continue
product_types = set(product_types)
product_types = list(set([p['type'] for p in products if p['type'] is not None]))
if product_types:
if len(product_types) > 1:
errors.append(_('~ Some products have different product types.\n'))
else:
product_type = ProductType.browse(list(product_types)[0])
product_type = product_types[0]
if not product_type:
errors.append(
@@ -1011,7 +1040,7 @@ class CustomerPurchaseOrderImporter(models.Model):
)
)
return {'product_type': product_type, 'errors': errors}
return product_type, errors
def get_time_offset(self):
try:
@@ -1036,11 +1065,11 @@ class CustomerPurchaseOrderImporter(models.Model):
return False
def purchase_order_exists_for_branch(self, po_num, branch):
def purchase_order_exists_for_branch(self, order_num, branch):
PreSaleOrder = self.env['pre.sale.order']
purchase_order = PreSaleOrder.search_count(
[('name', '=', 'ORD' + po_num), ('partner_shipping_id', '=', branch.id)]
[('name', '=', 'ORD' + order_num), ('partner_shipping_id', '=', branch.id)]
)
return purchase_order
@@ -1052,8 +1081,13 @@ class CustomerPurchaseOrderImporter(models.Model):
[('branch_id', '=', branch.id), ('ean13_code', '=', ean13_code)]
)
if not branch_ean_code:
BranchEanCode.create({'branch_id': branch.id, 'ean13_code': ean13_code, 'product_id': product.id})
BranchEanCode.create(
{
'branch_id': branch.id,
'ean13_code': ean13_code,
'product_id': product.id,
}
)
def start_date_is_earlier(self, start_date, end_date):
return start_date <= end_date
@@ -1119,7 +1153,11 @@ class CustomerPurchaseOrderImporter(models.Model):
processed_path = IrConfigParameter.sudo().get_param('po_importer_processed_path')
rejected_path = import_path + 'RECHAZADOS\\'
return {'import': import_path, 'processed': processed_path, 'rejected': rejected_path}
return {
'import': import_path,
'processed': processed_path,
'rejected': rejected_path,
}
# Rebuild the values of the file to be imported so as to adapt product values to the
# pre-sale order line values format --removes original dict format from method.