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

"""
BPM 请求记录
"""

from odoo import models, fields, api
import logging
from odoo.exceptions import ValidationError
from suds.client import Client
import simplejson
import json

_logger = logging.getLogger(__name__)


class BpmRecord(models.Model):
    """
    请求记录；
    提供请求接口，对正在发起请求的业务单据锁止操作（写、删除）
    """
    _name = 'jd.int.bpm.record'
    _description = u'BPM请求记录'

    number = fields.Char(string=u'编码', readonly=True, help=u'bpm系统返回的流水编号')
    date = fields.Datetime(string=u'日期', default=fields.Date.context_today)
    uid_push = fields.Many2one('res.users', string=u'推送人')
    state = fields.Selection([('valid', u'生效'),
                              ('done', u'已完成'),
                              ('refused', u'已拒绝'),
                              ('invalid', u'失效')], string=u'状态', required=True, default='valid')
    note = fields.Text(string=u'备注')
    res_order = fields.Reference(string=u'来源单据', selection='_reference_models', readonly=True)

    @api.model
    def check_exit(self, origin_rec):
        """
        检查来源单据是否有正在推送的BPM记录。
        Created By YGJ.
        :param origin_rec: 拼接格式为 '模型名,记录id'  如：'model.biz.order,id'
        :return:
        """
        bpm_rec = self.env['jd.int.bpm.record'].sudo().search([('res_order', '=', origin_rec), ('state', '=', 'valid')])
        if bpm_rec and len(bpm_rec) > 0:
            return True
        else:
            return False

    @api.multi
    def do_done(self):
        """
        状态由生效转变为已完成
        :return:
        """
        for record in self:
            if record.state == 'valid':
                return record.write({
                    'state': 'done'
                })
            else:
                raise ValidationError('只有生效的记录才可以完成')

    @api.multi
    def do_refused(self):
        """
        状态由生效转变为已拒绝
        :return:
        """
        for record in self:
            if record.state == 'valid':
                return record.write({
                    'state': 'refused'
                })
            else:
                raise ValidationError('只有生效的记录才可以拒绝')

    @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.')]

    def get_bpm_config(self):
        """
        从接口配置模型下获取BPM连接配置
        :return: data
        """
        bpm_result = self.env['jd.int.config'].search([('system_type', '=', 'bpm')])
        if len(bpm_result) > 1:
            raise ValidationError('系统查找到多条bpm的配置记录，请检查')
        if not bpm_result:
            raise ValidationError('系统没有找到生效的bpm配置记录，请检查')
        data = {
            'code': 0,
            'msg': u'没有找到生效的bpm配置'
        }
        if len(bpm_result) == 1:
            data.update({
                'link': bpm_result.link,
                'login': bpm_result.login,
                'password': bpm_result.password,
                'location_url': bpm_result.wsdl_link,
                'code': 1,
                'msg': u'返回bpm配置相关信息...'
            })
        return data

    def do_bpm_post(self, method, model_name, biz_id, user_code, workflow_code, data, sub_name=None, sub_data=None):
        """
        单据确认的时候调用该接口
        发起请求，生成生效的请求记录
        :param method:
        :param model_name:
        :param biz_id:
        :param user_code:
        :param workflow_code:
        :param data:
        :param sub_name:
        :param sub_data:
        :return:
        """
        crs = self.get_bpm_config()
        url = str(crs.get('link', None))
        location_url = str(crs.get('location_url', None))
        result = {
            'code': 0,
            'msg': u'bpm流程创建失败',
            'data': {}
        }
        if url:
            # 请求bpm接口 生成bpm实例
            bpm_client = Client(url, location=location_url)
            workflow = bpm_client.factory.create(method)
            data_json = json.dumps([{'ItemName': key, 'ItemValue': value} for key, value in data.items()])
            sub_data_list = []
            for s in sub_data:
                for k, v in s.items():
                    s_a = []
                    s_a.append({
                        'ItemName': k,
                        'ItemValue': v
                    })
                    sub_data_list.append(s_a)
            sub_data_json = json.dumps(sub_data_list)
            try:
                bpm_result = bpm_client.service.StartWorkflowWithJson(workflow_code, user_code, True, data_json,
                                                                      sub_name, sub_data_json)
                # 流程设置成功，新建一条记录
                if bpm_result.Success:
                    vals = {
                        'number': bpm_result.SerialNum,
                        'uid_push': self.env.user.id,
                        'res_order': model_name + ',' + str(biz_id),
                    }
                    record_result = self.env['jd.int.bpm.record'].create(vals)
                    result.update({
                        'code': 1,
                        'msg': u'bpm流程创建成功',
                        'data': {
                            'record_id': record_result.id,
                            'record_number': record_result.number
                        }
                    })

                    return result
                else:
                    result.update({
                        'code': 0,
                        'msg': u'bpm流程创建失败, 创建失败原因是：%s' % (bpm_result.Message)
                    })
                    return result
            except Exception as e:
                _logger.info(e.message)
                result.update({
                    'code': 0,
                    'msg': e.message
                })
                return result

    def do_callback(self, data):
        """
        bpm回调接口
        执行单据的回调方法，改变请求记录的状态
        bpm审批完成返回一个流水编号以及审批结果。根据流水编号查找来源单据进行分发处理
        :return:
        """
        # 返回
        number = data.get('SerialNum', None)
        is_pass = data.get('IsSuccess', None)
        reason = data.get('Reason', None)
        if not number:
            return
        if not is_pass:
            return
        record_rs = self.env['jd.int.bpm.record'].search([('number', '=', number)])
        if record_rs:
            res_str = record_rs.res_order
            model_name = res_str.split(',')[0]
            biz_id = res_str.split(',')[1]
            biz = self.env[model_name].browse(biz_id)
            if is_pass:
                record_rs.do_done()
                record_rs.write({
                    'note': reason
                })
            if not is_pass:
                record_rs.do_refused()
                record_rs.write({
                    'note': reason
                })
            # 封装data数据到下游业务层
            new_data = {
                'is_pass': is_pass,
                'reason': reason
            }
            # 执行这条业务单据的bpm_callback方法。
            biz.do_bpm_callback('', new_data)
        else:
            return
