<commit_before># -*- coding: utf-8 -*-

from odoo.osv import osv
# from odoo.osv import fields
from utils import create_name, safe_division
import odoo.addons.decimal_precision as dp
from odoo.exceptions import UserError
from odoo import models
from odoo import fields
from odoo import api


class wh_inventory(models.Model):
    _name = 'wh.inventory'
    _order = 'date DESC, id DESC'

    INVENTORY_STATE = [
        ('draft', u'草稿'),
        ('query', u'查询中'),
        ('confirmed', u'待确认盘盈盘亏'),
        ('done', u'完成'),
    ]

    @api.model
    def _get_default_warehouse_impl(self):
        if self.env.context.get('warehouse_type', 'stock'):
            return self.env['warehouse'].get_warehouse_by_type(
                    self.env.context.get('warehouse_type', 'stock'))
    @api.model
    def _get_default_warehouse(self):
        '''获取盘点仓库'''
        return self._get_default_warehouse_impl()

    date = fields.Date(u'日期', default=fields.Date.context_today,
                       help=u'盘点单创建日期，默认为当前天')
    name = fields.Char(u'名称', copy=False, default='/',
                       help=u'单据编号，创建时会自动生成')
    warehouse_id = fields.Many2one('warehouse', u'仓库', required=True, default=_get_default_warehouse,
                                   help=u'盘点单盘点的仓库')
    goods = fields.Char(u'产品',
                        help=u'盘点单盘点的产品')
    uos_not_zero = fields.Boolean(u'辅助数量不为0',
                                  help=u'True: 盘点单盘点的是系统辅助单位库存或系统库存不为0;'
                                       u'False: 盘点单盘点的是系统库存不为0的情况。')
    out_id = fields.Many2one('wh.out', u'盘亏单据', copy=False,
                             help=u'盘亏生成的其他出库单单据')
    in_id = fields.Many2one('wh.in', u'盘盈单据', copy=False,
                            help=u'盘盈生成的其他入库单单据')
    state = fields.Selection(
        INVENTORY_STATE, u'状态', copy=False, default='draft',
        help=u'盘点单状态，新建时状态为草稿;'
             u'点击查询后为审核后状态为查询中;'
             u'有盘亏盘盈时生成的其他出入库单没有审核时状态为待确认盘盈盘亏;'
             u'盘亏盘盈生成的其他出入库单审核后状态为完成')
    line_ids = fields.One2many(
        'wh.inventory.line', 'inventory_id', u'明细', copy=False,
        help=u'盘点单的明细行')
    note = fields.Text(u'备注',
                       help=u'可以为该单据添加一些需要的标识信息')

    @api.multi
    def requery_inventory(self):
        self.delete_confirmed_wh()
        self.state = 'query'

    @api.model
    @create_name
    def create(self, vals):
        return super(wh_inventory, self).create(vals)

    @api.multi
    def unlink(self):
        for inventory in self:
            if inventory.state == 'done':
                raise UserError(u'不可以删除一个完成的单据')

            inventory.delete_confirmed_wh()

        return super(wh_inventory, self).unlink()

    def delete_confirmed_wh(self):
        for inventory in self:
            if inventory.state == 'confirmed':
                if (inventory.out_id and inventory.out_id.state == 'done') \
                  or (inventory.in_id and inventory.in_id.state == 'done'):
                    raise UserError(u'请先反审核掉相关的盘盈盘亏单据')
                else:
                    inventory.out_id.unlink()
                    inventory.in_id.unlink()

        return True

    def check_done(self):
        for inventory in self:
            if inventory.state == 'confirmed' and \
              (not inventory.out_id or inventory.out_id.state == 'done') and \
              (not inventory.in_id or inventory.in_id.state == 'done'):
                self.state = 'done'
                return True
            if inventory.state == 'done' and \
              (not inventory.out_id or inventory.out_id.state != 'done') and \
              (not inventory.in_id or inventory.in_id.state != 'done'):
                self.state = 'confirmed'
                return True
        return False

    @api.multi
    def open_out(self):
        for inventory in self:
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'wh.out',
                'view_mode': 'form',
                'res_id': inventory.out_id.id,
            }

    @api.multi
    def open_in(self):
        for inventory in self:
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'wh.in',
                'view_mode': 'form',
                'res_id': inventory.in_id.id,
            }

    def delete_line(self):
        self.line_ids.unlink()

    def create_losses_out(self, inventory, out_line):
        inventory_warehouse = self.env.ref('warehouse.warehouse_inventory')
        out_vals = {
            'warehouse_dest_id': inventory_warehouse.id,
            'warehouse_id': inventory.warehouse_id.id,
            'type': 'inventory',
            'line_out_ids': [],
        }

        for line in out_line:
            out_vals['line_out_ids'].append(
                [0, False, line.get_move_line(wh_type='out')])

        out_id = self.env['wh.out'].create(out_vals)
        inventory.out_id = out_id

    def create_overage_in(self, inventory, in_line):
        inventory_warehouse = self.env.ref('warehouse.warehouse_inventory')
        in_vals = {
            'warehouse_dest_id': inventory.warehouse_id.id,
            'warehouse_id': inventory_warehouse.id,
            'type': 'inventory',
            'line_in_ids': [],
        }

        for line in in_line:
            in_vals['line_in_ids'].append(
                [0, False, line.get_move_line(wh_type='in')])

        in_id = self.env['wh.in'].create(in_vals)
        inventory.in_id = in_id

    @api.multi
    def generate_inventory(self):
        for inventory in self:
            out_line, in_line = [], []
            for line in inventory.line_ids:
                if (line.difference_qty > 0 and line.difference_uos_qty < 0) or \
                (line.difference_qty < 0 and line.difference_uos_qty > 0):
                    raise UserError(
                        u'产品"%s"行上盘盈盘亏数量与辅助单位的盘盈盘亏数量盈亏方向不一致' 
                             % line.goods_id.name)
                if line.difference_qty < 0 or line.difference_uos_qty < 0:
                    out_line.append(line)
                elif line.difference_qty > 0 or line.difference_uos_qty > 0:
                    in_line.append(line)

            if out_line:
                self.create_losses_out(inventory, out_line)

            if in_line:
                self.create_overage_in(inventory, in_line)

            if  len(out_line) + len(in_line) == 0:
                inventory.state = 'done'

            if out_line or in_line:
                inventory.state = 'confirmed'

        return True

    def get_line_detail(self, uos_zero=False):
        for inventory in self:
            if uos_zero:
                remaining_text = 'line.uos_qty_remaining > 0'
            else:
                remaining_text = 'line.qty_remaining > 0'

            sql_text = '''
                SELECT wh.id as warehouse_id,
                       goods.id as goods_id,
                       line.attribute_id as attribute_id,
                       line.lot as lot,
                       uom.id as uom_id,
                       uos.id as uos_id,
                       sum(line.qty_remaining) as qty,
                       sum(line.uos_qty_remaining) as uos_qty

                FROM wh_move_line line
                LEFT JOIN goods goods ON line.goods_id = goods.id
                    LEFT JOIN uom uom ON goods.uom_id = uom.id
                    LEFT JOIN uom uos ON goods.uos_id = uos.id
                LEFT JOIN warehouse wh ON line.warehouse_dest_id = wh.id

                WHERE {}
                  AND wh.type = 'stock'
                  AND line.state = 'done'
                  %s

                GROUP BY
                  wh.id, line.lot, line.attribute_id, goods.id, uom.id, uos.id
            '''.format(remaining_text)

            extra_text = ''
            if inventory.warehouse_id:
                extra_text += ' AND wh.id = %s' % inventory.warehouse_id.id

            if inventory.goods:
                extra_text += " AND goods.name ILIKE '%%%s%%' " \
                    % inventory.goods

            inventory.env.cr.execute(sql_text % extra_text)
            return inventory.env.cr.dictfetchall()

    @api.multi
    def query_inventory(self):
        line_obj = self.env['wh.inventory.line']
        for inventory in self:
            inventory.delete_line()
            line_ids = inventory.get_line_detail(inventory.uos_not_zero)
            for line in line_ids:
                line_obj.create_wh_inventory_line_by_data(inventory.id,line)
            if line_ids:
                inventory.state = 'query'
        return True


class wh_inventory_line(models.Model):
    _name = 'wh.inventory.line'

    LOT_TYPE = [
        ('out', u'出库'),
        ('in', u'入库'),
        ('nothing', u'不做处理'),
    ]

    @api.multi
    @api.depends('inventory_qty', 'real_qty')
    def _get_difference_qty(self):
        for line in self:
            line.difference_qty = line.inventory_qty - line.real_qty

    @api.multi
    @api.depends('inventory_uos_qty', 'real_uos_qty')
    def _get_difference_uos_qty(self):
        for line in self:
            line.difference_uos_qty = line.inventory_uos_qty - line.real_uos_qty

    inventory_id = fields.Many2one('wh.inventory', u'盘点', ondelete='cascade',
                                   help=u'盘点单行对应的盘点单')<commit_msg>[FIX] 盘点单，去掉 辅助数量不为0 情况<commit_after># -*- coding: utf-8 -*-

from odoo.osv import osv
# from odoo.osv import fields
from utils import create_name, safe_division
import odoo.addons.decimal_precision as dp
from odoo.exceptions import UserError
from odoo import models
from odoo import fields
from odoo import api


class wh_inventory(models.Model):
    _name = 'wh.inventory'
    _order = 'date DESC, id DESC'

    INVENTORY_STATE = [
        ('draft', u'草稿'),
        ('query', u'查询中'),
        ('confirmed', u'待确认盘盈盘亏'),
        ('done', u'完成'),
    ]

    @api.model
    def _get_default_warehouse_impl(self):
        if self.env.context.get('warehouse_type', 'stock'):
            return self.env['warehouse'].get_warehouse_by_type(
                    self.env.context.get('warehouse_type', 'stock'))
    @api.model
    def _get_default_warehouse(self):
        '''获取盘点仓库'''
        return self._get_default_warehouse_impl()

    date = fields.Date(u'日期', default=fields.Date.context_today,
                       help=u'盘点单创建日期，默认为当前天')
    name = fields.Char(u'名称', copy=False, default='/',
                       help=u'单据编号，创建时会自动生成')
    warehouse_id = fields.Many2one('warehouse', u'仓库', required=True, default=_get_default_warehouse,
                                   help=u'盘点单盘点的仓库')
    goods = fields.Char(u'产品',
                        help=u'盘点单盘点的产品')
    out_id = fields.Many2one('wh.out', u'盘亏单据', copy=False,
                             help=u'盘亏生成的其他出库单单据')
    in_id = fields.Many2one('wh.in', u'盘盈单据', copy=False,
                            help=u'盘盈生成的其他入库单单据')
    state = fields.Selection(
        INVENTORY_STATE, u'状态', copy=False, default='draft',
        help=u'盘点单状态，新建时状态为草稿;'
             u'点击查询后为审核后状态为查询中;'
             u'有盘亏盘盈时生成的其他出入库单没有审核时状态为待确认盘盈盘亏;'
             u'盘亏盘盈生成的其他出入库单审核后状态为完成')
    line_ids = fields.One2many(
        'wh.inventory.line', 'inventory_id', u'明细', copy=False,
        help=u'盘点单的明细行')
    note = fields.Text(u'备注',
                       help=u'可以为该单据添加一些需要的标识信息')

    @api.multi
    def requery_inventory(self):
        self.delete_confirmed_wh()
        self.state = 'query'

    @api.model
    @create_name
    def create(self, vals):
        return super(wh_inventory, self).create(vals)

    @api.multi
    def unlink(self):
        for inventory in self:
            if inventory.state == 'done':
                raise UserError(u'不可以删除一个完成的单据')

            inventory.delete_confirmed_wh()

        return super(wh_inventory, self).unlink()

    def delete_confirmed_wh(self):
        for inventory in self:
            if inventory.state == 'confirmed':
                if (inventory.out_id and inventory.out_id.state == 'done') \
                  or (inventory.in_id and inventory.in_id.state == 'done'):
                    raise UserError(u'请先反审核掉相关的盘盈盘亏单据')
                else:
                    inventory.out_id.unlink()
                    inventory.in_id.unlink()

        return True

    def check_done(self):
        for inventory in self:
            if inventory.state == 'confirmed' and \
              (not inventory.out_id or inventory.out_id.state == 'done') and \
              (not inventory.in_id or inventory.in_id.state == 'done'):
                self.state = 'done'
                return True
            if inventory.state == 'done' and \
              (not inventory.out_id or inventory.out_id.state != 'done') and \
              (not inventory.in_id or inventory.in_id.state != 'done'):
                self.state = 'confirmed'
                return True
        return False

    @api.multi
    def open_out(self):
        for inventory in self:
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'wh.out',
                'view_mode': 'form',
                'res_id': inventory.out_id.id,
            }

    @api.multi
    def open_in(self):
        for inventory in self:
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'wh.in',
                'view_mode': 'form',
                'res_id': inventory.in_id.id,
            }

    def delete_line(self):
        self.line_ids.unlink()

    def create_losses_out(self, inventory, out_line):
        inventory_warehouse = self.env.ref('warehouse.warehouse_inventory')
        out_vals = {
            'warehouse_dest_id': inventory_warehouse.id,
            'warehouse_id': inventory.warehouse_id.id,
            'type': 'inventory',
            'line_out_ids': [],
        }

        for line in out_line:
            out_vals['line_out_ids'].append(
                [0, False, line.get_move_line(wh_type='out')])

        out_id = self.env['wh.out'].create(out_vals)
        inventory.out_id = out_id

    def create_overage_in(self, inventory, in_line):
        inventory_warehouse = self.env.ref('warehouse.warehouse_inventory')
        in_vals = {
            'warehouse_dest_id': inventory.warehouse_id.id,
            'warehouse_id': inventory_warehouse.id,
            'type': 'inventory',
            'line_in_ids': [],
        }

        for line in in_line:
            in_vals['line_in_ids'].append(
                [0, False, line.get_move_line(wh_type='in')])

        in_id = self.env['wh.in'].create(in_vals)
        inventory.in_id = in_id

    @api.multi
    def generate_inventory(self):
        for inventory in self:
            out_line, in_line = [], []
            for line in inventory.line_ids:
                if (line.difference_qty > 0 and line.difference_uos_qty < 0) or \
                (line.difference_qty < 0 and line.difference_uos_qty > 0):
                    raise UserError(
                        u'产品"%s"行上盘盈盘亏数量与辅助单位的盘盈盘亏数量盈亏方向不一致' 
                             % line.goods_id.name)
                if line.difference_qty < 0 or line.difference_uos_qty < 0:
                    out_line.append(line)
                elif line.difference_qty > 0 or line.difference_uos_qty > 0:
                    in_line.append(line)

            if out_line:
                self.create_losses_out(inventory, out_line)

            if in_line:
                self.create_overage_in(inventory, in_line)

            if  len(out_line) + len(in_line) == 0:
                inventory.state = 'done'

            if out_line or in_line:
                inventory.state = 'confirmed'

        return True

    def get_line_detail(self):
        for inventory in self:
            remaining_text = 'line.qty_remaining > 0'

            sql_text = '''
                SELECT wh.id as warehouse_id,
                       goods.id as goods_id,
                       line.attribute_id as attribute_id,
                       line.lot as lot,
                       uom.id as uom_id,
                       uos.id as uos_id,
                       sum(line.qty_remaining) as qty,
                       sum(line.uos_qty_remaining) as uos_qty

                FROM wh_move_line line
                LEFT JOIN goods goods ON line.goods_id = goods.id
                    LEFT JOIN uom uom ON goods.uom_id = uom.id
                    LEFT JOIN uom uos ON goods.uos_id = uos.id
                LEFT JOIN warehouse wh ON line.warehouse_dest_id = wh.id

                WHERE {}
                  AND wh.type = 'stock'
                  AND line.state = 'done'
                  %s

                GROUP BY
                  wh.id, line.lot, line.attribute_id, goods.id, uom.id, uos.id
            '''.format(remaining_text)

            extra_text = ''
            if inventory.warehouse_id:
                extra_text += ' AND wh.id = %s' % inventory.warehouse_id.id

            if inventory.goods:
                extra_text += " AND goods.name ILIKE '%%%s%%' " \
                    % inventory.goods

            inventory.env.cr.execute(sql_text % extra_text)
            return inventory.env.cr.dictfetchall()

    @api.multi
    def query_inventory(self):
        line_obj = self.env['wh.inventory.line']
        for inventory in self:
            inventory.delete_line()
            line_ids = inventory.get_line_detail()
            for line in line_ids:
                line_obj.create_wh_inventory_line_by_data(inventory.id,line)
            if line_ids:
                inventory.state = 'query'
        return True


class wh_inventory_line(models.Model):
    _name = 'wh.inventory.line'

    LOT_TYPE = [
        ('out', u'出库'),
        ('in', u'入库'),
        ('nothing', u'不做处理'),
    ]

    @api.multi
    @api.depends('inventory_qty', 'real_qty')
    def _get_difference_qty(self):
        for line in self:
            line.difference_qty = line.inventory_qty - line.real_qty

    @api.multi
    @api.depends('inventory_uos_qty', 'real_uos_qty')
    def _get_difference_uos_qty(self):
        for line in self:
            line.difference_uos_qty = line.inventory_uos_qty - line.real_uos_qty

    inventory_id = fields.Many2one('wh.inventory', u'盘点', ondelete='cascade',
                                   help=u'盘点单行对应的盘点单')
{'fraction_non_alphanumeric': 0.10586186251564796, 'fraction_numerical': 0.002231535405214173, 'mean_word_length': 1.7164399763453577, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1514178', 'n_tokens_mistral': 6326, 'n_tokens_neox': 6210, 'n_words': 1091}