<commit_before># -*- coding: utf-8 -*-
# © 2013-2018 Didotech srl (<EMAIL>)

import logging
import multiprocessing
import threading
import time
from datetime import datetime

import decimal_precision as dp
import pooler
from openerp.osv import orm, fields
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp.tools.config import config
from openerp.tools.translate import _

_logger = logging.getLogger(__name__)
_logger.setLevel(logging.DEBUG)

ENABLE_CACHE = config.get('product_cache', False)
CACHE_TYPE = config.get('cache_type', 'dictionary')


class product_product(orm.Model):
    """
    Inherit Product in order to add an "Bom Stock" field
    """

    class UpdateCachePrice(threading.Thread):

        def __init__(self, cr, uid, product_product_obj, split_ids, context=None):
            self.cr = pooler.get_db(cr.dbname).cursor()
            self.product_product_obj = product_product_obj
            self.uid = uid
            self.context = context
            self.product_ids = split_ids

            threading.Thread.__init__(self)

        def run(self):
            try:
                time.sleep(5)
                for product in self.product_product_obj.browse(self.cr, self.uid, self.product_ids, self.context):
                    cost_price = product['cost_price']
                return True
            except Exception as e:
                # Rollback
                _logger.error(u'Error: {error}'.format(error=e))
                self.cr.rollback()
            finally:
                if not self.cr.closed:
                    self.cr.close()
            return True

        def terminate(self):
            if not self.cr.closed:
                self.cr.close()
            return True

    _inherit = 'product.product'
    
    # def _get_prefered_supplier(self, cr, uid, ids, field_name, args, context):
    #     res = {}
    #     for line in self.browse(cr, uid, ids, context):
    #         res[line.id] = line.seller_ids and line.seller_ids[0].name.id or False
    #     return res

    def __init__(self, cr, uid):
        super(product_product, self).__init__(cr, uid)

        if CACHE_TYPE == 'redis':
            try:
                from openerp.addons.core_extended.redis import Redis
                host = config.get('redis_host', 'localhost')

                self.product_cost_cache = Redis(host, database=cr.db_name, model=self._name)
            except:
                _logger.error("Unable to import Redis")
                from openerp.addons.core_extended.dict_cache import SimpleCache
                self.product_cost_cache = SimpleCache()
        else:
            from openerp.addons.core_extended.dict_cache import SimpleCache
            self.product_cost_cache = SimpleCache()

    def _hook_compute_purchase_price_no_supplier(self, product):
        return product.standard_price

    def product_cache(func):
        def cached_product(self, cr, uid, product, bom_properties, context=None):
            if product.id in self.product_cost_cache and not context.get('partner_name', False):
                _logger.debug('Returning from cache')
                return self.product_cost_cache[product.id]
            else:
                value = func(self, cr, uid, product, bom_properties, context=context)
                self.product_cost_cache[product.id] = value
                return value

        if ENABLE_CACHE:
            return cached_product
        else:
            return func

    @product_cache
    def _get_subproduct_cost_price(self, cr, uid, product, bom_properties, context=None):
        return product.cost_price

    @product_cache
    def _compute_product_purchase_price(self, cr, uid, product, bom_properties, context=None):
        context = context or self.pool['res.users'].context_get(cr, uid)
        bom_properties = bom_properties or []
        user = self.pool['res.users'].browse(cr, uid, uid, context)

        bom_obj = self.pool['mrp.bom']
        uom_obj = self.pool['product.uom']

        debug_logger = True

        if ENABLE_CACHE:
            if debug_logger:
                _logger.debug(u'[{product.default_code}] {product.name}'.format(product=product))
            # cached_price = self.product_cost_cache.get(product_id, 0)

        bom_id = bom_obj._bom_find(cr, uid, product.id, product_uom=None, properties=bom_properties)
        price = 0.
        if bom_id:
            sub_bom_ids = bom_obj.search(cr, uid, [('bom_id', '=', bom_id)], context=context)
            sub_products = bom_obj.browse(cr, uid, sub_bom_ids, context)

            if ENABLE_CACHE and debug_logger:
                _logger.debug(
                    u'[{product.default_code}] Start Explosion ========================'.format(product=product))

            for sub_product in sub_products:
                if sub_product.product_id.id == product.id:
                    error = "Product '{product.name}' (id: {product.id}) is referenced to itself".format(
                        product=product)
                    _logger.error(error)
                    continue

                # std_price = sub_product.standard_price
                # if ENABLE_CACHE:
                #     if sub_product.product_id.id in self.product_cost_cache:
                #         std_price = self.product_cost_cache[sub_product.product_id.id]
                #     else:
                #         std_price = sub_product.product_id.cost_price
                #         self.product_cost_cache[sub_product.product_id.id] = std_price
                # else:
                #     std_price = sub_product.product_id.cost_price
                std_price = self._get_subproduct_cost_price(cr, uid, sub_product.product_id, False, context)

                to_uom = sub_product.product_id.uom_po_id or sub_product.product_id.uom_id

                uos_coeff = sub_product.product_id.uos_coeff or 1
                if sub_product.product_uom.category_id.id != sub_product.product_id.uom_id.category_id.id:
                    qty = sub_product.product_qty * uos_coeff
                else:
                    product_qty = uom_obj._compute_qty(cr, uid,
                                               from_uom_id=sub_product.product_uom.id,
                                               qty=sub_product.product_qty,
                                               to_uom_id=to_uom.id)
                    qty = product_qty * uos_coeff

                if ENABLE_CACHE and debug_logger:
                    _logger.debug(
                        u'[{product.default_code}] price += {std_price} * {qty} \t ({total_line})'.format(product=sub_product.product_id,
                                                                                        std_price=std_price, qty=qty, total_line=std_price * qty))

                # print(std_price, qty)
                price += std_price * qty

            if sub_products:
                # Don't use browse when we already have it
                bom = sub_products[0].bom_id
            else:
                bom = bom_obj.browse(cr, uid, bom_id, context)

            if bom.routing_id and not context.get('exclude_routing', False):
                for wline in bom.routing_id.workcenter_lines:
                    wc = wline.workcenter_id
                    cycle = wline.cycle_nbr
                    # hour = (wc.time_start + wc.time_stop + cycle * wc.time_cycle) * (wc.time_efficiency or 1.0)
                    cost_efficiency = wline._get_cost_efficiency()[wline.id]
                    cost = (wc.costs_cycle * cycle + wc.costs_hour * (
                                wline.hour_nbr + (wc.time_start or 0.0) + (wc.time_stop or 0.0))) * (
                                       wc.time_efficiency or 1.0)
                    price += cost * cost_efficiency
            price /= bom.product_qty
            price = uom_obj._compute_price(cr, uid, bom.product_uom.id, price, bom.product_id.uom_id.id)
            if ENABLE_CACHE and debug_logger:
                _logger.debug(
                    u'==== SUM [{product.default_code}] bom_price = {price}'.format(product=product, price=price))

            return price
        else:
            # no BoM: use standard_price
            # use standard_price if no supplier indicated

            # if product_id in self.product_cost_cache and ENABLE_CACHE and not context.get('partner_name', False):
            #     return self.product_cost_cache[product_id]
<commit_msg>[product_bom] IMP add more log<commit_after># -*- coding: utf-8 -*-
# © 2013-2018 Didotech srl (<EMAIL>)

import logging
import multiprocessing
import threading
import time
from datetime import datetime

import decimal_precision as dp
import pooler
from openerp.osv import orm, fields
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp.tools.config import config
from openerp.tools.translate import _

_logger = logging.getLogger(__name__)
_logger.setLevel(logging.DEBUG)

ENABLE_CACHE = config.get('product_cache', False)
CACHE_TYPE = config.get('cache_type', 'dictionary')


class product_product(orm.Model):
    """
    Inherit Product in order to add an "Bom Stock" field
    """

    class UpdateCachePrice(threading.Thread):

        def __init__(self, cr, uid, product_product_obj, split_ids, context=None):
            self.cr = pooler.get_db(cr.dbname).cursor()
            self.product_product_obj = product_product_obj
            self.uid = uid
            self.context = context
            self.product_ids = split_ids

            threading.Thread.__init__(self)

        def run(self):
            try:
                time.sleep(5)
                for product in self.product_product_obj.browse(self.cr, self.uid, self.product_ids, self.context):
                    cost_price = product['cost_price']
                return True
            except Exception as e:
                # Rollback
                _logger.error(u'Error: {error}'.format(error=e))
                self.cr.rollback()
            finally:
                if not self.cr.closed:
                    self.cr.close()
            return True

        def terminate(self):
            if not self.cr.closed:
                self.cr.close()
            return True

    _inherit = 'product.product'
    
    # def _get_prefered_supplier(self, cr, uid, ids, field_name, args, context):
    #     res = {}
    #     for line in self.browse(cr, uid, ids, context):
    #         res[line.id] = line.seller_ids and line.seller_ids[0].name.id or False
    #     return res

    def __init__(self, cr, uid):
        super(product_product, self).__init__(cr, uid)

        if CACHE_TYPE == 'redis':
            try:
                from openerp.addons.core_extended.redis import Redis
                host = config.get('redis_host', 'localhost')

                self.product_cost_cache = Redis(host, database=cr.db_name, model=self._name)
            except:
                _logger.error("Unable to import Redis")
                from openerp.addons.core_extended.dict_cache import SimpleCache
                self.product_cost_cache = SimpleCache()
        else:
            from openerp.addons.core_extended.dict_cache import SimpleCache
            self.product_cost_cache = SimpleCache()

    def _hook_compute_purchase_price_no_supplier(self, product):
        return product.standard_price

    def product_cache(func):
        def cached_product(self, cr, uid, product, bom_properties, context=None):
            if product.id in self.product_cost_cache and not context.get('partner_name', False):
                _logger.debug('Returning from cache')
                return self.product_cost_cache[product.id]
            else:
                value = func(self, cr, uid, product, bom_properties, context=context)
                self.product_cost_cache[product.id] = value
                return value

        if ENABLE_CACHE:
            return cached_product
        else:
            return func

    @product_cache
    def _get_subproduct_cost_price(self, cr, uid, product, bom_properties, context=None):
        return product.cost_price

    @product_cache
    def _compute_product_purchase_price(self, cr, uid, product, bom_properties, context=None):
        context = context or self.pool['res.users'].context_get(cr, uid)
        bom_properties = bom_properties or []
        user = self.pool['res.users'].browse(cr, uid, uid, context)

        bom_obj = self.pool['mrp.bom']
        uom_obj = self.pool['product.uom']

        debug_logger = True

        if ENABLE_CACHE:
            if debug_logger:
                _logger.debug(u'[{product.default_code}] {product.name}'.format(product=product))
            # cached_price = self.product_cost_cache.get(product_id, 0)

        bom_id = bom_obj._bom_find(cr, uid, product.id, product_uom=None, properties=bom_properties)
        price = 0.
        if bom_id:
            sub_bom_ids = bom_obj.search(cr, uid, [('bom_id', '=', bom_id)], context=context)
            sub_products = bom_obj.browse(cr, uid, sub_bom_ids, context)

            if ENABLE_CACHE and debug_logger:
                _logger.debug(
                    u'[{product.default_code}] Start Explosion ========================'.format(product=product))

            for sub_product in sub_products:
                if sub_product.product_id.id == product.id:
                    error = "Product '{product.name}' (id: {product.id}) is referenced to itself".format(
                        product=product)
                    _logger.error(error)
                    continue

                # std_price = sub_product.standard_price
                # if ENABLE_CACHE:
                #     if sub_product.product_id.id in self.product_cost_cache:
                #         std_price = self.product_cost_cache[sub_product.product_id.id]
                #     else:
                #         std_price = sub_product.product_id.cost_price
                #         self.product_cost_cache[sub_product.product_id.id] = std_price
                # else:
                #     std_price = sub_product.product_id.cost_price
                std_price = self._get_subproduct_cost_price(cr, uid, sub_product.product_id, False, context)

                to_uom = sub_product.product_id.uom_po_id or sub_product.product_id.uom_id

                uos_coeff = sub_product.product_id.uos_coeff or 1
                if sub_product.product_uom.category_id.id != sub_product.product_id.uom_id.category_id.id:
                    qty = sub_product.product_qty * uos_coeff
                else:
                    product_qty = uom_obj._compute_qty(cr, uid,
                                               from_uom_id=sub_product.product_uom.id,
                                               qty=sub_product.product_qty,
                                               to_uom_id=to_uom.id)
                    qty = product_qty * uos_coeff

                if ENABLE_CACHE and debug_logger:
                    _logger.debug(
                        u'[{product.default_code}] price += {std_price} * {qty} \t ({total_line})'.format(product=sub_product.product_id,
                                                                                        std_price=std_price, qty=qty, total_line=std_price * qty))

                # print(std_price, qty)
                price += std_price * qty

            if sub_products:
                # Don't use browse when we already have it
                bom = sub_products[0].bom_id
            else:
                bom = bom_obj.browse(cr, uid, bom_id, context)

            if debug_logger:
                _logger.debug(u"cost without Routing {}".format(price))
            if bom.routing_id and not context.get('exclude_routing', False):
                for wline in bom.routing_id.workcenter_lines:
                    wc = wline.workcenter_id
                    cycle = wline.cycle_nbr
                    # hour = (wc.time_start + wc.time_stop + cycle * wc.time_cycle) * (wc.time_efficiency or 1.0)
                    cost_efficiency = wline._get_cost_efficiency()[wline.id]
                    cost = (wc.costs_cycle * cycle + wc.costs_hour * (
                                wline.hour_nbr + (wc.time_start or 0.0) + (wc.time_stop or 0.0))) * (
                                       wc.time_efficiency or 1.0)
                    routing_cost = cost * cost_efficiency
                    if debug_logger:
                        _logger.debug(u"Add WC {} cost {} * efficiency {} = {}".format(wline.name, cost, cost_efficiency, routing_cost))
                    price += routing_cost
            price /= bom.product_qty
            price = uom_obj._compute_price(cr, uid, bom.product_uom.id, price, bom.product_id.uom_id.id)
            if ENABLE_CACHE and debug_logger:
                _logger.debug(
                    u'==== SUM [{product.default_code}] bom_price = {price}'.format(product=product, price=price))

            return price
        else:
            # no BoM: use standard_price
            # use standard_price if no supplier indicated

            # if product_id in self.product_cost_cache and ENABLE_CACHE and not context.get('partner_name', False):
            #     return self.product_cost_cache[product_id]

{'fraction_non_alphanumeric': 0.09093540171335958, 'fraction_numerical': 0.0026626533919888863, 'mean_word_length': 1.8416118421052632, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2463527', 'n_tokens_mistral': 5105, 'n_tokens_neox': 4828, 'n_words': 1020}