import pdb

from odoo import api, exceptions, fields, models, _
import datetime


class QualityControl(models.Model):
    _name = "quality.control"
    _description = "Quality Control"
    _order = 'id desc'

    scan = fields.Char('Scan')
    product_scan = fields.Char('Product Scan')
    warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse Location')
    qc_number = fields.Char('QC Number')
    irn_number = fields.Char('IRN Number')
    irn_id = fields.Integer('IRN ID')
    po_number = fields.Char('PO Number')
    po_id = fields.Integer('Purchase ID')
    remark = fields.Text('Remark')
    received_by = fields.Many2one('res.users', 'Received By', default=lambda self: self.env.uid)
    apqc_pushed = fields.Boolean('A/P QC Pushed')
    date_confirm = fields.Datetime('Confirmation Date',  select=False)
    state = fields.Selection([
        ('pending', 'Pending'),
        ('confirmed', 'Confirmed'),
        ('cancel', 'Cancelled'),

    ], 'Status',  copy=False, help="Gives the status of the WMS inbound", select=True , default='pending')
    qc_line = fields.One2many('quality.control.line', 'qc_line_id', 'QC Line', required=True)
    aqc_line = fields.One2many('accepted.quality.control.line', 'qc_id', 'AQC Line', required=False)
    pqc_line = fields.One2many('pending.quality.control.line', 'qc_id', 'PQC Line', required=False)

    def _set_po_id_in_line(self, record, po_id):
        for line_item in record.qc_line:
            line_item.po_id = po_id

        return record

    # calls at the time of create new record
    @api.model
    def create(self, vals):
        # generate QC number
        # QC0123456

        record = super(QualityControl, self).create(vals)

        qc_number = "QC0" + str(record.id)
        record.qc_number = qc_number

        record = self._set_po_id_in_line(record, record.po_id)

        # self.pool.get('inb.end.to.end').qc_data_create(record.po_number, record.po_id,
        #                                                record.id, qc_number, record.create_date)

        return record

    # calls at the time of update record
    def write(self, vals):

        # only update only if (received_quantity = accepted_quantity + pending_quantity)
        update_permission = list()

        if 'qc_line' in vals:
            for single_line in vals['qc_line']:
                if not not single_line[2]:
                    for qc_l in self.qc_line:

                        if qc_l.id == single_line[1]:

                            accepted_quantity = single_line[2]['accepted_quantity'] \
                                if 'accepted_quantity' in single_line[2] else qc_l.accepted_quantity
                            pending_quantity = single_line[2]['pending_quantity'] \
                                if 'pending_quantity' in single_line[2] else qc_l.pending_quantity

                            pending_quantity = pending_quantity * -1 if pending_quantity < 0 else pending_quantity

                            if qc_l.received_quantity == accepted_quantity + pending_quantity:
                                update_permission.append(True)
                            else:
                                update_permission.append(False)

        if False in update_permission:

             raise exceptions.ValidationError(_('QC line adjustment ERROR!'
                                                     ' \nReceived quantity should be equal to'
                                                     ' (accepted quantity + pending quantity)!!!'))

        else:

            record = super(QualityControl, self).write(vals)

            return record

    def confirm_wms_inbound_qc(self):

        qc_obj = self

        # 1. AQC will create with accepted quantity
        aqc_data = {
            'qc_number': str(qc_obj.qc_number),
            'qc_id': qc_obj.id,
            'warehouse_id': qc_obj.warehouse_id.id,
            'irn_number': str(qc_obj.irn_number),
            'irn_id': qc_obj.irn_id,
            'po_number': str(qc_obj.po_number),
            'po_id': qc_obj.po_id,
            'remark': str(qc_obj.remark),


        }
        put_data = {
            'qc_number': str(qc_obj.qc_number),
            'qc_id': qc_obj.id,
            'warehouse_id': qc_obj.warehouse_id.id,
            'irn_number': str(qc_obj.irn_number),
            'irn_id': qc_obj.irn_id,
            'po_number': str(qc_obj.po_number),
            'po_id': qc_obj.po_id,
            'remark': str(qc_obj.remark),

        }
        aqc_line_list = list()

        for aqc_line_item in qc_obj.qc_line:
            if aqc_line_item.accepted_quantity > 0:
                aqc_line_list.append([0, False,{
                     'qc_id': qc_obj.id,
                     'product': aqc_line_item.product,
                     'product_id': aqc_line_item.product_id,
                     'product_ean': aqc_line_item.product_ean,
                     'description': aqc_line_item.description,
                     'purchase_quantity': aqc_line_item.purchase_quantity,
                     'received_quantity': aqc_line_item.received_quantity,
                     'accepted_quantity': aqc_line_item.accepted_quantity,
                     'pending_quantity': aqc_line_item.pending_quantity

                     }])

        aqc_data['aqc_line'] = aqc_line_list

        if len(aqc_line_list) > 0:
            # Create aqc
            aqc_env = self.env['accepted.quality.control']
            saved_aqc_id = aqc_env.create(aqc_data)
            try:
                saved_aqc_id = saved_aqc_id.id
            except:
                pass

            # update qc status and apqc_pushed to true
            qc_state_update_query = "UPDATE quality_control SET state='confirmed', apqc_pushed=TRUE, " \
                                    "date_confirm='{0}' WHERE id={1}".format(str(fields.datetime.now()), qc_obj.id)
            self._cr.execute(qc_state_update_query)
            self._cr.commit()

            apqc_pushed_qc_line_update_query = "UPDATE quality_control_line SET apqc_pushed=TRUE WHERE " \
                                               "qc_line_id={0}".format(qc_obj.id)
            self._cr.execute(apqc_pushed_qc_line_update_query)
            self._cr.commit()

            # Confirm the aqc

            aqc_confirm_query = "UPDATE accepted_quality_control SET state='confirm', date_confirm='{0}' " \
                                "WHERE id={1}".format(str(fields.datetime.now()), saved_aqc_id)
            self._cr.execute(aqc_confirm_query)
            self._cr.commit()

            aqc_confirm_query_line = "UPDATE accepted_quality_control_line SET state='confirm', date_confirm='{0}'" \
                                     " WHERE aqc_id={1}".format(str(fields.datetime.now()), saved_aqc_id)
            self._cr.execute(aqc_confirm_query_line)
            self._cr.commit()


            # Generate Put away Process
            put_line_list = []

            for aqc_line_item in qc_obj.qc_line:
                if aqc_line_item.accepted_quantity > 0:
                    put_line_list.append([0, False,{
                          'product_id': aqc_line_item.product_id,
                          'qc_id': saved_aqc_id,
                          'location': '',
                          'product': aqc_line_item.product,
                          'remarks': '',
                          'quantity': aqc_line_item.accepted_quantity,
                          'po_number': str(qc_obj.po_number)
                    }])

            put_data['aqc_id']=saved_aqc_id
            put_data['putaway_line_view']=put_line_list
            put_env = self.env['putaway.process']
            saved_put_id = put_env.create(put_data)

        # 2. PQC will create with pending quantity
        pqc_data = {
            'qc_number': str(qc_obj.qc_number),
            'qc_id': qc_obj.id,
            'warehouse_id': qc_obj.warehouse_id.id,
            'irn_number': str(qc_obj.irn_number),
            'irn_id': qc_obj.irn_id,
            'po_number': str(qc_obj.po_number),
            'po_id': qc_obj.po_id,
            'remark': str(qc_obj.remark),
            'received_by': qc_obj.received_by.id,
        }
        pqc_line_list = list()

        for pqc_line_item in qc_obj.qc_line:

            if pqc_line_item.pending_quantity > 0:
                pqc_line_list.append([0, False,{
                     'qc_id': qc_obj.id,
                     'product': pqc_line_item.product,
                     'product_id': pqc_line_item.product_id,
                     'product_ean': pqc_line_item.product_ean,
                     'description': pqc_line_item.description,
                     'purchase_quantity': pqc_line_item.purchase_quantity,
                     'received_quantity': pqc_line_item.received_quantity,
                     'accepted_quantity': pqc_line_item.accepted_quantity,
                     'pending_quantity': pqc_line_item.pending_quantity,
                     'pqc_reject_quantity': pqc_line_item.pending_quantity,
                }])

        pqc_data['pqc_line'] = pqc_line_list

        if len(pqc_line_list) > 0:
            # Create pqc
            pqc_env = self.env['pending.quality.control']
            saved_pqc_id = pqc_env.create(pqc_data)

        # update inbound end-to-end
        # self.pool.get('inb.end.to.end').qc_confirm_update(str(qc_obj.po_number), qc_obj.po_id,
        #                                                   str(fields.datetime.now()))

        return True


    @api.onchange('product_scan')
    def po_qc_product_scan(self):

        try:

            po_number = str(self.po_number)

            product_scan = str(self.product_scan)

            if product_scan != 'False':
                qc_env = self.env['quality.control']
                qc_obj = qc_env.search([('qc_number', '=', self.qc_number)])


                for single_line in qc_obj.qc_line:

                    if str(single_line.product_ean) == product_scan:
                        if single_line.accepted_quantity < single_line.received_quantity:
                            single_line.accepted_quantity += 1
                        else:
                            raise exceptions.ValidationError(_('QC line adjustment ERROR!\n'
                                                               'Received quantity should be equal to '
                                                               '(accepted quantity + pending quantity)!!!'))
                        if single_line.pending_quantity > 0:
                            single_line.pending_quantity -= 1
                        else:
                            raise exceptions.ValidationError(_('QC line adjustment ERROR!\n'
                                                                'Received quantity should be equal to '
                                                               '(accepted quantity + pending quantity)!!!'))
                        break
                # self.irn_line[0].received_quantity

                self.product_scan = ""

        except:

            self.product_scan = ""


class QualityControlLine(models.Model):
    _name = "quality.control.line"
    _description = "Quality Control Line"

    qc_line_id = fields.Many2one('quality.control', 'QC Line ID', required=True,
                                       ondelete='cascade', select=True, readonly=True)
    po_id = fields.Many2one('purchase.order', 'PO ID', required=False,
                             ondelete='cascade', select=True, readonly=True)
    product = fields.Char('Product')
    product_id = fields.Integer('Product ID')
    product_ean = fields.Char('Product EAN')
    description = fields.Char('Description')
    purchase_quantity = fields.Float('Purchase Qty')
    received_quantity = fields.Float('Received Qty')
    accepted_quantity = fields.Float('Accepted Qty')
    pending_quantity = fields.Float('Pending Qty')
    apqc_pushed = fields.Boolean('A/P QC Pushed')
    state = fields.Selection([
        ('accept', 'Accept'),
        ('reject', 'Reject'),
        ('cancel', 'Cancelled'),
        ('pending', 'Pending'),
    ], 'Status', help="Gives the status of the WMS inbound line", select=True, default='pending')

    @api.onchange('accepted_quantity')
    def po_qc_product_scan(self):
        try:
            if self.accepted_quantity > 0:

                # po_line_obj[0].product_id.ean13
                # self.irn_line[0].product_ean

                # self.pending_quantity = self.pending_quantity - self.accepted_quantity
                self.pending_quantity = self.received_quantity - self.accepted_quantity
                self.save()
                # self.irn_line[0].received_quantity

                if self.pending_quantity < 0:
                    # raise error
                    raise exceptions.ValidationError(_('QC line adjustment ERROR!!! \n '
                                                       'Received quantity should be equal to'
                                                       ' (accepted quantity + pending quantity)!!!'))

                self.product_scan = ""

        except:

            self.product_scan = ""


class AcceptedQualityControl(models.Model):
    _name = "accepted.quality.control"
    _description = "Accepted Quality Control"
    _order = 'id desc'

    scan = fields.Char('Scan')
    product_scan = fields.Char('Product Scan')
    warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse Location', required=True)
    aqc_number = fields.Char('AQC Number')
    qc_number = fields.Char('QC Number')
    qc_id = fields.Char('QC ID')
    pqc_number = fields.Char('PQC Number')
    pqc_id = fields.Integer('PQC ID')
    irn_number = fields.Char('IRN Number')
    irn_id = fields.Integer('IRN ID')
    po_number = fields.Char('PO Number')
    po_id = fields.Integer('Purchase ID')
    remark = fields.Text('Remark')
    assigned = fields.Boolean('Assigned')
    received_by = fields.Many2one('res.users', 'Received By', default=lambda self: self.env.uid)
    date_confirm = fields.Datetime('Confirmation Date',select=False)
    state = fields.Selection([
        ('pending', 'Pending'),
        ('confirm', 'Confirmed'),
        ('cancel', 'Cancelled'),

    ], 'Status', copy=False, help="Gives the status of the WMS inbound", select=True, default='pending')
    aqc_line = fields.One2many('accepted.quality.control.line', 'aqc_id', 'AQC Line', required=True)

    @api.model
    def create(self, vals):
        # generate AQC number
        # AQC0123456

        record = super(AcceptedQualityControl, self).create(vals)

        aqc_number = "AQC0" + str(record.id)
        record.aqc_number = aqc_number

        # self.pool.get('inb.end.to.end').aqc_data_create(record.po_number, record.po_id, record.id, aqc_number, record.create_date)

        return record

    def confirm_wms_inbound_aqc(self):

        for single_id in self:
            aqc_confirm_query = "UPDATE accepted_quality_control SET state='confirm', date_confirm='{0}' WHERE " \
                                "id={1}".format(str(fields.datetime.now()), single_id.id)
            self._cr.execute(aqc_confirm_query)
            self._cr.commit()

            aqc_confirm_query_line = "UPDATE accepted_quality_control_line SET state='confirm', date_confirm='{0}' " \
                                     "WHERE aqc_id={1}".format(str(fields.datetime.now()), single_id.id)
            self._cr.execute(aqc_confirm_query_line)
            self._cr.commit()

        # update inbound end-to-end
        # self.pool.get('inb.end.to.end').aqc_confirm_update(str(self.po_number), self.po_id, str(fields.datetime.now()))

        return True


class AcceptedQualityControlLine(models.Model):
    _name = "accepted.quality.control.line"
    _description = "Accepted Quality Control Line"

    aqc_id = fields.Many2one('accepted.quality.control', 'AQC ID', required=True,
                                  ondelete='cascade', select=True, readonly=True)
    qc_id = fields.Many2one('quality.control', 'QC ID', required=False,
                              ondelete='cascade', select=True, readonly=True)
    product = fields.Char('Product')
    product_id = fields.Many2one('product.product', 'Product')
    product_ean = fields.Char('Product EAN')
    description = fields.Char('Description')
    purchase_quantity = fields.Float('Purchase Qty')
    received_quantity = fields.Float('Received Qty')
    accepted_quantity = fields.Float('Accepted Qty')
    date_confirm = fields.Datetime('Confirmation Date', select=False)
    pending_quantity = fields.Float('Pending Qty')
    remaining_quantity = fields.Float('Remaining GRN Received Qty') # It will calculate how many quantities are pending for GRN Receive. And This column is filling up from Put away process.
    state = fields.Selection([
        ('pending', 'Pending'),
        ('confirm', 'Confirmed'),
        ('cancel', 'Cancelled'),
    ], 'Status', help="Gives the status of the WMS inbound line", select=True, default='pending')


class PendingQualityControl(models.Model):
    _name = "pending.quality.control"
    _description = "Pending Quality Control"
    _order = 'id desc'

    scan = fields.Char('Scan')
    product_scan = fields.Char('Product Scan')
    warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse Location')
    pqc_number = fields.Char('PQC Number')
    qc_number = fields.Char('QC Number')
    qc_id = fields.Char('QC ID')
    irn_number = fields.Char('IRN Number')
    irn_id = fields.Integer('IRN ID')
    po_number = fields.Char('PO Number')
    po_id = fields.Integer('Purchase ID')
    remark = fields.Text('Remark')
    received_by = fields.Many2one('res.users', 'Received By', default=lambda self: self.env.uid)
    pqc_processed = fields.Boolean('PQC Processed')
    date_confirm = fields.Datetime('Confirmation Date',select=False)
    pqc_reject_reason = fields.Char('Rejection Reason')
    pqc_reject_by = fields.Many2one('res.users', 'PQC Rejection By')
    pqc_reject_date = fields.Datetime('PQC Rejection Date')
    pqc_accept_by = fields.Many2one('res.users', 'PQC Accept By')
    pqc_accept_date = fields.Datetime('PQC Accept Date')
    state = fields.Selection([
        ('return_to_vendor', 'Return to Vendor'),
        ('accept', 'Accept'),
        ('reject', 'Reject'),
        ('partially_reject', 'Partially Reject'),
        ('scrap', 'Scrap'),
        ('pending', 'Pending'),

    ], 'Status', copy=False, help="Gives the status of the WMS inbound", select=True , default='pending')
    pqc_line = fields.One2many('pending.quality.control.line', 'pqc_id', 'PQC Line', required=True)


    # calls at the time of update record
    def write(self, vals):

        # only update only if (pending_quantity = pqc_accept_quantity + pqc_reject_quantity)
        update_permission = list()

        if 'pqc_line' in vals:



            for single_line in vals['pqc_line']:
                if not not single_line[2]:
                    for pqc_l in self.pqc_line:

                        if pqc_l.id == single_line[1]:

                            pqc_accept_quantity = single_line[2]['pqc_accept_quantity'] \
                                if 'pqc_accept_quantity' in single_line[2] else pqc_l.pqc_accept_quantity
                            pqc_reject_quantity = single_line[2]['pqc_reject_quantity'] \
                                if 'pqc_reject_quantity' in single_line[2] else pqc_l.pqc_reject_quantity

                            if pqc_l.pending_quantity == pqc_accept_quantity + pqc_reject_quantity:
                                update_permission.append(True)
                            else:
                                update_permission.append(False)

        if False in update_permission:

            raise exceptions.ValidationError(_('PQC line adjustment ERROR!!! \n'
                                               'Pending quantity should be equal to '
                                               '(accepted quantity + rejected quantity)!!!'))

        else:
            record = super(PendingQualityControl, self).write(vals)

            return record

    @api.model
    def create(self, vals):
        # generate PQC number
        # PQC0123456
        record = super(PendingQualityControl, self).create(vals)

        pqc_number = "PQC0" + str(record.id)
        record.pqc_number = pqc_number

        # self.pool.get('inb.end.to.end').pqc_data_create(record.po_number, record.po_id, record.id, pqc_number,
        #                                                 record.create_date)

        return record

    @api.onchange('product_scan')
    def pqc_product_scan(self):

        try:
            po_number = str(self.po_number)
            product_scan = str(self.product_scan)
            product_not_in_po_order = True


            if product_scan != 'False':
                qty = 1
                if 'Prod' not in product_scan:

                    product_env = self.env['product.product']
                    product_obj = product_env.search(
                        ['|', '|', '|', '|', ('ean13', '=', str(product_scan)), ('gift_ean', '=', str(product_scan)),
                         ('box_ean', '=', str(product_scan)), ('case_ean', '=', str(product_scan)),
                         ('pallet_ean', '=', str(product_scan))])

                    if not product_obj.id:
                        raise exceptions.ValidationError(_(
                            'Product Not found.Please add EAN number in Product Configuration.'
                            ' Or contact with Your department head'))

                    if str(product_obj.gift_ean) == str(product_scan):
                        qty = 1
                    elif str(product_obj.box_ean) == str(product_scan):
                        qty = product_obj.holding_box_qty
                    elif str(product_obj.case_ean) == str(product_scan):
                        qty = product_obj.holding_case_qty
                    elif str(product_obj.pallet_ean) == str(product_scan):
                        qty = product_obj.holding_pallet_qty
                else:
                    get_list = product_scan.split('Prod')
                    product_id = int(get_list[1])

                    product_env = self.env['product.product']
                    product_obj = product_env.search([('id', '=', product_id)])
                    if not product_obj.id:
                        raise exceptions.ValidationError(_('Product Not found.Please scan properly with proper product'))

                po_env = self.env['purchase.order']
                po_obj = po_env.search([('name', '=', po_number)])

                po_line_env = self.env['purchase.order.line']
                po_line_obj = po_line_env.search([('order_id', '=', po_obj.id)])

                # po_line_obj[0].product_id.ean13
                # self.irn_line[0].product_ean
                for single_line in self.pqc_line:

                    # if str(single_line.product_id.id) == str(product_obj.id) and single_line.pending_quantity >= (single_line.pqc_accept_quantity + qty):
                    if str(single_line.product_id.id) == str(product_obj.id) and single_line.pqc_accept_quantity < single_line.pending_quantity:

                        single_line.pqc_accept_quantity += qty
                        single_line.pqc_reject_quantity -= qty
                        product_not_in_po_order = False
                        break
                # self.irn_line[0].received_quantity

                if product_not_in_po_order:
                    raise exceptions.ValidationError(_('Product Not found in this Order.Wrong product has been scanned'))


                self.product_scan = ""

        except:

            self.product_scan = ""

    def wms_inbound_pqc_total_receive(self):
        pqc_obj = self

        put_data = aqc_data = {
            'pqc_number': str(pqc_obj.pqc_number),
            'pqc_id': pqc_obj.id,
            'qc_number': str(pqc_obj.qc_number),
            'qc_id': str(pqc_obj.qc_id),
            'warehouse_id': pqc_obj.warehouse_id.id,
            'irn_number': str(pqc_obj.irn_number),
            'irn_id': pqc_obj.irn_id,
            'po_number': str(pqc_obj.po_number),
            'po_id': pqc_obj.po_id,
            'remark': str(pqc_obj.remark),
            'received_by': pqc_obj.received_by.id,
        }
        aqc_line_list = list()

        for aqc_line_item in pqc_obj.pqc_line:

            if aqc_line_item.pending_quantity > 0:
                aqc_line_list.append([0, False,{
                     'product': aqc_line_item.product,
                     'product_id': aqc_line_item.product_id.id,
                     'description': aqc_line_item.description,
                     'purchase_quantity': aqc_line_item.purchase_quantity,
                     'received_quantity': aqc_line_item.received_quantity,
                     'accepted_quantity': aqc_line_item.pending_quantity,
                     'pending_quantity': 0,
                }])

        aqc_data['aqc_line'] = aqc_line_list

        if len(aqc_line_list) > 0:
            # Create aqc
            aqc_env = self.env['accepted.quality.control']
            saved_aqc_id = aqc_env.create(aqc_data)
            saved_aqc_id= saved_aqc_id.id

            # update qc pqc_processed and status to true
            pqc_state_update_query = "UPDATE pending_quality_control SET pqc_processed= TRUE, state='accept' WHERE id={0}".format(pqc_obj.id)
            self._cr.execute(pqc_state_update_query)
            self._cr.commit()



            pqc_processed_pqc_line_update_query = "UPDATE pending_quality_control_line SET pqc_processed=TRUE " \
                                                  "WHERE pqc_id={0}".format(pqc_obj.id)
            self._cr.execute(pqc_processed_pqc_line_update_query)
            self._cr.commit()

            # Confirm the aqc



            aqc_confirm_query = "UPDATE accepted_quality_control SET state='confirm', date_confirm='{0}' " \
                                "WHERE id={1}".format(str(fields.datetime.now()), saved_aqc_id)
            self._cr.execute(aqc_confirm_query)
            self._cr.commit()

            aqc_confirm_query_line = "UPDATE accepted_quality_control_line SET state='confirm', date_confirm='{0}'" \
                                     " WHERE aqc_id={1}".format(str(fields.datetime.now()), saved_aqc_id)
            self._cr.execute(aqc_confirm_query_line)
            self._cr.commit()

            # Generate Put away Process
            put_line_list = []

            for aqc_line in aqc_line_list:
                put_line_list.append([0, False, {
                    'product_id': aqc_line[2]['product_id'],
                    'qc_id': saved_aqc_id,
                    'location': '',
                    'product': aqc_line[2]['product'],
                    'remarks': '',
                    'quantity': aqc_line[2]['accepted_quantity'],
                    'po_number': str(pqc_obj.po_number)
                }])

            put_data['aqc_id'] = saved_aqc_id
            put_data['putaway_line_view'] = put_line_list
            put_env = self.env['putaway.process']
            try:
                del put_data['aqc_line']
            except:
                pass
            saved_put_id = put_env.create(put_data)

        return True

    # not need. need to delete.
    def wms_inbound_pqc_reject(self):
        # need to check line items if state is set, before process
        # already set item will not process

        for pqc_id in self:
            # update qc pqc_processed and status to true
            pqc_state_update_query = "UPDATE pending_quality_control SET pqc_processed= TRUE, state='reject'" \
                                     " WHERE id={0}".format(pqc_id.id)
            self._cr.execute(pqc_state_update_query)
            self._cr.commit()

            pqc_processed_pqc_line_update_query = "UPDATE pending_quality_control_line SET pqc_processed=TRUE, " \
                                                  "state='reject' WHERE pqc_id={0}".format(pqc_id.id)
            self._cr.execute(pqc_processed_pqc_line_update_query)
            self._cr.commit()

        return True

    def wms_inbound_pqc_return_to_vendor(self):

        for pqc_id in self:
            # update qc pqc_processed and status to true
            pqc_state_update_query = "UPDATE pending_quality_control SET pqc_processed= TRUE, " \
                                     "state='return_to_vendor' WHERE id={0}".format(pqc_id.id)
            self._cr.execute(pqc_state_update_query)
            self._cr.commit()

            pqc_processed_pqc_line_update_query = "UPDATE pending_quality_control_line SET pqc_processed=TRUE, " \
                                                  "state='return_to_vendor' WHERE pqc_id={0}".format(pqc_id.id)
            self._cr.execute(pqc_processed_pqc_line_update_query)
            self._cr.commit()

        return True

    def wms_inbound_pqc_scrap(self):

        for pqc_id in self:
            # update qc pqc_processed and status to true
            pqc_state_update_query = "UPDATE pending_quality_control SET pqc_processed= TRUE, state='scrap' " \
                                     "WHERE id={0}".format(pqc_id.id)
            self._cr.execute(pqc_state_update_query)
            self._cr.commit()

            pqc_processed_pqc_line_update_query = "UPDATE pending_quality_control_line SET pqc_processed=TRUE, " \
                                                  "state='scrap' WHERE pqc_id={0}".format(pqc_id.id)
            self._cr.execute(pqc_processed_pqc_line_update_query)
            self._cr.commit()

        return True


class PendingQualityControlLine(models.Model):
    _name = "pending.quality.control.line"
    _description = "Pending Quality Control Line"

    pqc_id = fields.Many2one('pending.quality.control', 'PQC ID', required=True,
                                  ondelete='cascade', select=True, readonly=True)
    qc_id = fields.Many2one('quality.control', 'QC ID', required=False,
                             ondelete='cascade', select=True, readonly=True)
    product = fields.Char('Product')
    product_id = fields.Many2one('product.product', 'Product', required=True)
    product_ean = fields.Char('Product EAN')
    description = fields.Char('Description')
    purchase_quantity = fields.Float('Purchase Qty')
    received_quantity = fields.Float('Received Qty')
    accepted_quantity = fields.Float('Accepted Qty')
    pending_quantity = fields.Float('Pending Qty')
    pqc_accept_quantity = fields.Float('Accept Qty')
    pqc_reject_quantity = fields.Float('Reject Qty')
    pqc_processed = fields.Boolean('PQC Processed')
    remark = fields.Char('Remark')
    pqc_reject_reason = fields.Char('Rejection Reason')
    pqc_reject_by = fields.Many2one('res.users', 'PQC Rejection By')
    pqc_reject_date = fields.Datetime('PQC Rejection Date')
    state = fields.Selection([
        ('return_to_vendor', 'Return to Vendor'),
        ('accept', 'Accept'),
        ('reject', 'Reject'),
        ('partially_reject', 'Partially Reject'),
        ('scrap', 'Scrap'),
        ('pending', 'Pending')
    ], 'Status', help="Gives the status of the WMS inbound line", select=True, default='pending')

    def pqc_processed_status(self, pqc_id):
        pqc_line_status_list = list()
        status = 'partially_reject'
        pqc_line_obj = self.search([('pqc_id', '=', pqc_id)])
        pqc_line_id_list = [itm.id for itm in pqc_line_obj]


        if len(pqc_line_id_list) == 1:
            import pdb
            pdb.set_trace()
            if pqc_line_obj.pqc_accept_quantity == 0:
                status = 'reject'
            self.update_pqc_status(pqc_line_obj.pqc_id.id, status)
        else:
            for pqc_l in pqc_line_obj:
                pqc_line_status_list.append(pqc_l.pqc_processed)

            if pqc_line_status_list.count(False) == 1:
                self.update_pqc_status(pqc_line_obj[0].pqc_id.id, status)

        return True

    def update_pqc_status(self, pqc_id, status):
        pqc_process_status_update_query = "UPDATE pending_quality_control SET pqc_processed=TRUE, state='{0}' " \
                                          "WHERE id='{1}'".format(status, pqc_id)
        self._cr.execute(pqc_process_status_update_query)
        self._cr.commit()

        return True

    @api.onchange('pqc_accept_quantity')
    def pqc_accept_quantity_change(self):
        try:
            if self.pqc_accept_quantity >= 0:


                # po_line_obj[0].product_id.ean13
                # self.irn_line[0].product_ean

                # self.pending_quantity = self.pending_quantity - self.accepted_quantity
                self.pqc_reject_quantity = self.pending_quantity - self.pqc_accept_quantity

                self.save()
                # self.irn_line[0].received_quantity

                # if self.pending_quantity < 0:
                #     # raise error
                #     raise exceptions.ValidationError(_('QC line adjustment ERROR!!! \n '
                #                                        'Received quantity should be equal to'
                #                                        ' (accepted quantity + pending quantity)!!!'))
                #
                # self.product_scan = ""

        except:

            self.product_scan = ""

    def wms_inbound_pqc_line_process(self):

        pqc_line_obj = self

        context = pqc_line_obj._context
        pqc_obj = self.env['pending.quality.control']

        pqc_data = pqc_obj.browse([pqc_line_obj.pqc_id.id])

        pending_quantity = pqc_line_obj.pending_quantity
        pqc_reject_quantity = context['pqc_reject_quantity']\
            if not context['pqc_reject_quantity'] == 'pqc_reject_quantity' else pqc_line_obj.pqc_reject_quantity
        pqc_accept_quantity = context['pqc_accept_quantity'] \
            if not context['pqc_accept_quantity'] == 'pqc_accept_quantity' else pqc_line_obj.pqc_accept_quantity
        pqc_reject_reason = context['pqc_reject_reason'] \
            if not context['pqc_reject_reason'] == 'pqc_reject_reason' else pqc_line_obj.pqc_reject_reason

        if pqc_reject_reason == False:
            raise exceptions.ValidationError(_('QC line adjustment ERROR!! \n'
                                               'Must need to give reject reason!!!'))
        elif pending_quantity != pqc_reject_quantity + pqc_accept_quantity:
            raise exceptions.ValidationError(_('QC line adjustment ERROR!!!\n'
                                               ' Received quantity should be equal to '
                                               '(accepted quantity + pending quantity)!!!'))
        elif pending_quantity == pqc_reject_quantity + pqc_accept_quantity:

            # update pqc reject reason
            for pqc in pqc_data:
                # create AQC from pqc_line accept product
                put_data = aqc_data = {
                    'pqc_number': str(pqc.pqc_number),
                    'pqc_id': pqc.id,
                    'qc_number': str(pqc.qc_number),
                    'qc_id': str(pqc.qc_id),
                    'warehouse_id': pqc.warehouse_id.id,
                    'irn_number': str(pqc.irn_number),
                    'irn_id': pqc.irn_id,
                    'po_number': str(pqc.po_number),
                    'po_id': pqc.po_id,
                    'remark': str(pqc.remark),
                    'received_by': self._uid,
                }
                aqc_line_list = list()

                # update pqc line reject reason
                # update only if pqc_processed is not TRUE
                # irn_obj = self.pool.get('irn.control')
                if not pqc_line_obj.pqc_processed:

                    new_product_received_qty = pqc_line_obj.received_quantity - pqc_reject_quantity

                    # check partially_reject or reject
                    if pqc_accept_quantity > 0:
                        state = "partially_reject"

                        aqc_line_list.append([0, False,
                              {
                                  'qc_id': pqc_line_obj.qc_id.id,
                                  'product': pqc_line_obj.product,
                                  'product_id': pqc_line_obj.product_id.id,
                                  'description': pqc_line_obj.description,
                                  'purchase_quantity': pqc_line_obj.purchase_quantity,
                                  'received_quantity': new_product_received_qty,
                                  'accepted_quantity': pqc_accept_quantity,
                                  'pending_quantity': pending_quantity,
                              }])

                    else:
                        state = "reject"


                    uid=1
                    # pending_quality_control_line
                    pqc_line_reject_query = "UPDATE pending_quality_control_line SET pqc_reject_reason='{0}', " \
                                            "pqc_reject_by='{1}', pqc_reject_date='{2}', state='{3}', pqc_processed=TRUE, " \
                                            "received_quantity='{4}' WHERE id={5}".format(pqc_reject_reason, uid, str(fields.datetime.now()), state, new_product_received_qty, pqc_line_obj.id)
                    self._cr.execute(pqc_line_reject_query)
                    self._cr.commit()

                    # update irn_control
                    irn_update_query = "UPDATE irn_control SET state='partial_received' WHERE id='{0}'".format(
                        pqc.irn_id)
                    self._cr.execute(irn_update_query)
                    self._cr.commit()

                    # update irn_control_line
                    irn_line_update_query = "UPDATE irn_control_line SET state='partially_received'," \
                                            " received_quantity='{0}' WHERE irn_line_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, pqc.irn_id, pqc_line_obj.product_id.id)
                    self._cr.execute(irn_line_update_query)
                    self._cr.commit()

                    # update quality_control_line
                    qc_line_update_query = "UPDATE quality_control_line SET received_quantity='{0}' WHERE qc_line_id='{1}' AND product_id='{2}'".format(
                        new_product_received_qty, int(pqc.qc_id), pqc_line_obj.product_id.id)
                    self._cr.execute(qc_line_update_query)
                    self._cr.commit()

                    # update accepted_quality_control_line
                    aqc_line_update_query = "UPDATE accepted_quality_control_line SET received_quantity='{0}' " \
                                            "WHERE qc_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, int(pqc.qc_id), pqc_line_obj.product_id.id)
                    self._cr.execute(aqc_line_update_query)
                    self._cr.commit()

                    # update pending_quality_control_line
                    pqc_line_update_query = "UPDATE pending_quality_control_line SET received_quantity='{0}' WHERE " \
                                            "qc_id='{1}' AND product_id='{2}'".format(
                        new_product_received_qty, int(pqc.qc_id), pqc_line_obj.product_id.id)
                    self._cr.execute(pqc_line_update_query)
                    self._cr.commit()

                    aqc_data['aqc_line'] = aqc_line_list
                    if len(aqc_line_list) > 0:
                        # Create aqc
                        aqc_env = self.env['accepted.quality.control']
                        saved_aqc_id = aqc_env.create(aqc_data)
                        saved_aqc_id=saved_aqc_id.id

                        # Confirm the aqc
                        aqc_confirm_query = "UPDATE accepted_quality_control SET state='confirm', date_confirm='{0}' " \
                                            "WHERE id={1}".format(str(fields.datetime.now()), saved_aqc_id)
                        self._cr.execute(aqc_confirm_query)
                        self._cr.commit()

                        aqc_confirm_query_line = "UPDATE accepted_quality_control_line SET state='confirm', " \
                                                 "date_confirm='{0}' WHERE aqc_id={1}".format(
                            str(fields.datetime.now()), saved_aqc_id)
                        self._cr.execute(aqc_confirm_query_line)
                        self._cr.commit()

                        # Generate Put away Process
                        put_line_list = []

                        for aqc_line in aqc_line_list:
                            put_line_list.append([0, False, {
                                'product_id': aqc_line[2]['product_id'],
                                'qc_id': saved_aqc_id,
                                'location': '',
                                'product': aqc_line[2]['product'],
                                'remarks': '',
                                'quantity': pqc_accept_quantity,
                                'po_number': str(pqc.po_number)
                            }])

                        put_data['aqc_id'] = saved_aqc_id
                        put_data['putaway_line_view'] = put_line_list
                        put_env = self.env['putaway.process']
                        try:
                            del put_data['aqc_line']
                        except:
                            pass
                        saved_put_id = put_env.create(put_data)

                    self.pqc_processed_status(pqc.id)

        return {
            'type': 'ir.actions.client',
            'tag': 'reload',
        }


class PendingQualityControlReject(models.Model):
    _name = "pending.quality.control.reject"
    _description = "Pending quality control reject"

    pqc_reject_reason = fields.Char('Rejection Reason')
    pqc_reject_by = fields.Many2one('res.users', 'PQC Rejection By')
    pqc_reject_date = fields.Datetime('PQC Rejection Date',default=fields.datetime.now)

    def pqc_reject(self):
        context = self.context
        pqc_reject_reason = str(context['pqc_reject_reason'])
        pqc_reject_by = self._uid
        reject_ids = context['active_ids']

        pqc_obj = self.env['pending.quality.control']
        pqc_data = pqc_obj.browse(reject_ids)

        # update pqc reject reason
        for pqc in pqc_data:
            state = "reject"

            # create AQC from pqc_line accept product
            put_data = aqc_data = {
                'pqc_number': str(pqc.pqc_number),
                'pqc_id': pqc.id,
                'qc_number': str(pqc.qc_number),
                'qc_id': str(pqc.qc_id),
                'warehouse_id': pqc.warehouse_id.id,
                'irn_number': str(pqc.irn_number),
                'irn_id': pqc.irn_id,
                'po_number': str(pqc.po_number),
                'po_id': pqc.po_id,
                'remark': str(pqc.remark),
                'received_by': self._uid,
            }
            aqc_line_list = list()

            # update pqc line reject reason
            # update only if pqc_processed is not TRUE
            # irn_obj = self.pool.get('irn.control')
            for pqc_line_single in pqc.pqc_line:

                if not pqc_line_single.pqc_processed:

                    new_product_received_qty = pqc_line_single.received_quantity - pqc_line_single.pqc_reject_quantity

                    # check partially_reject or reject
                    if pqc_line_single.pqc_accept_quantity > 0:
                        state = "partially_reject"

                        aqc_line_list.append([0, False, {
                              'qc_id': pqc_line_single.qc_id.id,
                              'product': pqc_line_single.product,
                              'product_id': pqc_line_single.product_id.id,
                              'description': pqc_line_single.description,
                              'purchase_quantity': pqc_line_single.purchase_quantity,
                              'received_quantity': new_product_received_qty,
                              'accepted_quantity': pqc_line_single.pqc_accept_quantity,
                              'pending_quantity': pqc_line_single.pending_quantity,

                        }])

                    else:
                        state = "reject"

                    pqc_line_reject_query = "UPDATE pending_quality_control_line SET pqc_reject_reason='{0}', " \
                                            "pqc_reject_by='{1}', pqc_reject_date='{2}', state='{3}', " \
                                            "pqc_processed=TRUE, received_quantity='{4}' WHERE id={5}".\
                        format(pqc_reject_reason, pqc_reject_by, str(fields.datetime.now()), state,
                               new_product_received_qty, pqc_line_single.id)
                    self._cr.execute(pqc_line_reject_query)
                    self._cr.commit()

                    # what will happen to the rejected quantity!!!
                    # update to irn
                    irn_update_query = "UPDATE irn_control SET state='partial_received' WHERE id='{0}'".format(pqc.irn_id)
                    self._cr.execute(irn_update_query)
                    self._cr.commit()

                    # update to irn_line
                    irn_line_update_query = "UPDATE irn_control_line SET state='partially_received', " \
                                            "received_quantity='{0}' WHERE irn_line_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, pqc.irn_id, pqc_line_single.product_id.id)
                    self._cr.execute(irn_line_update_query)
                    self._cr.commit()

                    # QC line receive quantity update
                    qc_line_update_query = "UPDATE quality_control_line SET received_quantity='{0}' " \
                                           "WHERE qc_line_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, int(pqc.qc_id), pqc_line_single.product_id.id)
                    self._cr.execute(qc_line_update_query)
                    self._cr.commit()

                    # AQC line receive quantity update
                    aqc_line_update_query = "UPDATE accepted_quality_control_line SET received_quantity='{0}' " \
                                            "WHERE qc_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, int(pqc.qc_id), pqc_line_single.product_id.id)
                    self._cr.execute(aqc_line_update_query)
                    self._cr.commit()

                    # PQC line receive quantity update
                    pqc_line_update_query = "UPDATE pending_quality_control_line SET received_quantity='{0}' " \
                                            "WHERE qc_id='{1}' AND product_id='{2}'".\
                        format(new_product_received_qty, int(pqc.qc_id), pqc_line_single.product_id.id)
                    self._cr.execute(pqc_line_update_query)
                    self._cr.commit()

            # update pqc reason, status
            pqc_reject_query = "UPDATE pending_quality_control SET pqc_reject_reason='{0}', pqc_reject_by='{1}', " \
                               "pqc_reject_date='{2}', pqc_processed=TRUE, state='{3}' WHERE id={4}".\
                format(pqc_reject_reason, pqc_reject_by, str(fields.datetime.now()), state, pqc.id)
            self._cr.execute(pqc_reject_query)
            self._cr.commit()

            # new AQC will be created with accepted quantity
            aqc_data['aqc_line'] = aqc_line_list
            if len(aqc_line_list) > 0:
                # Create aqc
                aqc_env = self.env['accepted.quality.control']
                saved_aqc_id = aqc_env.create(aqc_data)

                # Confirm the aqc
                aqc_confirm_query = "UPDATE accepted_quality_control SET state='confirm', date_confirm='{0}' " \
                                    "WHERE id={1}".format(str(fields.datetime.now()), saved_aqc_id)
                self._cr.execute(aqc_confirm_query)
                self._cr.commit()

                aqc_confirm_query_line = "UPDATE accepted_quality_control_line SET state='confirm', " \
                                         "date_confirm='{0}' WHERE aqc_id={1}".format(str(fields.datetime.now()),
                                                                                      saved_aqc_id)
                self._cr.execute(aqc_confirm_query_line)
                self._cr.commit()

                # Generate Put away Process
                put_line_list = []

                for aqc_line in aqc_line_list:
                    put_line_list.append([0, False, {
                        'product_id': aqc_line[2]['product_id'],
                        'qc_id': saved_aqc_id,
                        'location': '',
                        'product': aqc_line[2]['product'],
                        'remarks': '',
                        'quantity': aqc_line[2]['accepted_quantity'],
                        'po_number': str(pqc.po_number)
                    }])

                put_data['aqc_id'] = saved_aqc_id
                put_data['putaway_line_view'] = put_line_list
                put_env = self.env['putaway.process']
                saved_put_id = put_env.create(put_data)

        return True