# -*- coding: utf-8 -*-
# 项目: jdg-hd-node-farm
# Copyright 2018 JDG <www.yunside.com>
# Created by LLH <lianghua.liu@yunside.com> at 2018/8/9

from odoo import models, fields, api

from odoo.exceptions import Warning, ValidationError

import logging

_logger = logging.getLogger(__name__)


class VoucherGatherPush(models.Model):
    """
    SAP汇总凭证推送
    提供凭证汇总推送操作入口
    查看凭证汇总推送反馈结果，维护凭证汇总推送历史记录
    """
    _name = 'jd.int.voucher.gather.push'
    _description = u'凭证汇总推送'

    number = fields.Char(string=u'单号', required=True, default='/', readonly=True,
                         help=u'单号自动生成')
    date_start = fields.Date(string=u'起始日期', required=True)
    date_end = fields.Date(string=u'结束日期', required=True)
    uid_push = fields.Many2one('res.users', string=u'推送人', default=lambda self: self.env.user.id)
    company_id = fields.Many2one('res.company', string=u'公司',
                                 default=lambda self: self.env.user.company_id.id)
    state = fields.Selection([('draft', u'草稿'),
                              ('push', u'已推送'),
                              ('revoke', u'已撤销')], string=u'状态', default='draft', readonly=True)
    note = fields.Text(string=u'备注')
    voucher_id = fields.Many2one('jd.int.voucher', string=u'凭证定义', required=True)
    # description = fields.Char(string=u'业务描述', related='voucher_id.description', store=True)
    res_model = fields.Char(string=u'来源单据模型', related='voucher_id.res_model', store=True)
    time_push = fields.Datetime(string=u'推送时间')
    result = fields.Selection([('success', u'成功'),
                               ('fail', u'失败')], string=u'推送结果')
    output = fields.Char(string=u'输出')
    record_id = fields.Many2one('jd.int.voucher.record', string=u'凭证记录')
    biz_line_ids = fields.One2many('jd.int.voucher.gather.push.biz.line', 'record_id', string=u'凭证推送单据明细')

    @api.multi
    def _check_date_exit(self):
        """
        子类中可以重写该方法，增减判断条件。
        :return:
        """
        for item in self:
            domain = []
            if item.date_start and item.date_end:
                domain = [('date_start', '<=', item.date_end),
                          ('date_end', '>=', item.date_start),
                          ('state', '=', 'push'),
                          ('voucher_id', '=', item.voucher_id.id),
                          ('company_id', '=', self.env.user.company_id.id),
                          ('id', '!=', item.id)]
            record = self.env[self._name].search(domain)
            if record and len(record) > 0:
                return False
        return True

    @api.multi
    def _check_date(self):
        for item in self:
            if item.date_start and item.date_end:
                date_start_int = int("".join(item.date_start.split("-")))
                date_end_int = int("".join(item.date_end.split("-")))
                if date_end_int < date_start_int:
                    return False
        return True

    _constraints = [
        (_check_date_exit, u'已经存在时间范围重叠的内容！', ['date_start', 'date_end', 'company_id', 'voucher_id']),
        (_check_date, u'开始时间晚于结束时间！', ['date_start', 'date_end']),
    ]

    @api.multi
    def get_order(self):
        """
        根据所选的凭证定义、来源单据模型以及起止日期，获取单据明细
        :return:
        """
        for i in self:
            if not i.voucher_id or i.res_model:
                raise ValidationError(u'凭证定义与来源单据不能为空')

            # 业务层可能需要根据来源单据类型判断，使用不同的domain
            search_domain = [('date', '>=', i.date_start), ('date', '<=', i.date_end),
                             ('state', 'in', ('audit', 'closed')), ('company_id', '=', i.company_id.id)]

            order_recs = self.env[i.res_model].search(search_domain)
            if len(order_recs) == 0:
                raise Warning(u'指定的起止日期没有查询到需要推送凭证的业务单据')
            biz_line_list = []
            for rec in order_recs:
                biz_line_list.append({
                    'voucher_id': i.voucher_id.id,
                    'res_order': str(rec._name) + ',' + str(rec.id),
                    'date': rec.date
                })
            i.biz_line_ids = biz_line_list

    @api.multi
    def do_push(self):
        """
        调用推送方法,返回推送结果，反写明细输出内容
        草稿状态执行，通过状态进行控制
        【业务层中继承实现】
        :return:
        """
        for i in self:
            # 业务层获取data
            # data = {}
            # i.voucher_id.config_id.do_voucher_push(**data)
            i.state = 'push'
            pass

    @api.multi
    def do_revoke(self):
        """
        调用撤销方法,返回推送结果，反写明细输出内容
        推送状态执行，通过状态进行控制
        【业务层中继承实现】
        :return:
        """
        for i in self:
            # 业务层获取data
            # data = {}
            # i.voucher_id.config_id.do_voucher_revoke(**data)
            i.state = 'revoke'
            pass

    @api.model
    def create(self, values):
        """
        获取自动单号
        :param values:
        :return:
        """
        if values.get('number', '/') == '/':
            values.update({
                'number': self.env['ir.sequence'].next_by_code(self._name)
            })
        return super(VoucherGatherPush, self).create(values)


class VoucherGatherPushBizLine(models.Model):
    _name = 'jd.int.voucher.gather.push.biz.line'
    _description = u'凭证汇总推送单据明细'

    record_id = fields.Many2one('jd.int.voucher.gather.push', string=u'汇总凭证推送', ondelete='cascade')
    voucher_id = fields.Many2one('jd.int.voucher', string=u'凭证定义', required=True)
    res_order = fields.Reference(string=u'来源单据', selection='_reference_models')
    date = fields.Date(string=u'单据业务日期')

    @api.model
    def _reference_models(self):
        models = self.env['ir.model'].search([('state', '!=', 'manual')])
        return [(model.model, model.name)
                for model in models
                if not model.model.startswith('ir.')]
