123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- # -*- coding: utf-8 -*-
- import json
- from odoo import http
- from odoo.http import request
- from odoo.utils import util
- from .base import BaseController
- import logging
- _logger = logging.getLogger(__name__)
- import _ast
- import re
- import csv
- try: # Python 3
- import configparser
- from threading import current_thread
- from xmlrpc.client import Fault, ServerProxy, MININT, MAXINT
- PY2 = False
- except ImportError: # Python 2
- import ConfigParser as configparser
- from threading import currentThread as current_thread
- from xmlrpclib import Fault, ServerProxy, MININT, MAXINT
- PY2 = True
- DOMAIN_OPERATORS = frozenset('!|&')
- _term_re = re.compile(
- '([\w._]+)\s*' '(=(?:like|ilike|\?)|[<>]=?|!?=(?!=)'
- '|(?<= )(?:like|ilike|in|not like|not ilike|not in|child_of))' '\s*(.*)')
- # Simplified ast.literal_eval which does not parse operators
- def _convert(node, _consts={'None': None, 'True': True, 'False': False}):
- if isinstance(node, _ast.Str):
- return node.s
- if isinstance(node, _ast.Num):
- return node.n
- if isinstance(node, _ast.Tuple):
- return tuple(map(_convert, node.elts))
- if isinstance(node, _ast.List):
- return list(map(_convert, node.elts))
- if isinstance(node, _ast.Dict):
- return dict([(_convert(k), _convert(v))
- for (k, v) in zip(node.keys, node.values)])
- if hasattr(node, 'value') and str(node.value) in _consts:
- return node.value # Python 3.4+
- if isinstance(node, _ast.Name) and node.id in _consts:
- return _consts[node.id] # Python <= 3.3
- raise ValueError('malformed or disallowed expression')
- if PY2:
- int_types = int, long
- class _DictWriter(csv.DictWriter):
- """Unicode CSV Writer, which encodes output to UTF-8."""
- def writeheader(self):
- # Method 'writeheader' does not exist in Python 2.6
- header = dict(zip(self.fieldnames, self.fieldnames))
- self.writerow(header)
- def _dict_to_list(self, rowdict):
- rowlst = csv.DictWriter._dict_to_list(self, rowdict)
- return [cell.encode('utf-8') if hasattr(cell, 'encode') else cell
- for cell in rowlst]
- else: # Python 3
- basestring = str
- int_types = int
- _DictWriter = csv.DictWriter
- def literal_eval(expression, _octal_digits=frozenset('01234567')):
- node = compile(expression, '<unknown>', 'eval', _ast.PyCF_ONLY_AST)
- if expression[:1] == '0' and expression[1:2] in _octal_digits:
- raise SyntaxError('unsupported octal notation')
- value = _convert(node.body)
- if isinstance(value, int_types) and not MININT <= value <= MAXINT:
- raise ValueError('overflow, int exceeds XML-RPC limits')
- return value
- def searchargs(params, kwargs=None, context=None):
- """Compute the 'search' parameters."""
- if not params:
- return []
- domain = params[0]
- if not isinstance(domain, list):
- return params
- for (idx, term) in enumerate(domain):
- if isinstance(term, basestring) and term not in DOMAIN_OPERATORS:
- m = _term_re.match(term.strip())
- if not m:
- raise ValueError('Cannot parse term %r' % term)
- (field, operator, value) = m.groups()
- try:
- value = literal_eval(value)
- except Exception:
- # Interpret the value as a string
- pass
- domain[idx] = (field, operator, value)
- return domain
- class Dropdown(http.Controller, BaseController):
- @http.route('/<string:sub_domain>/drop-down', auth='public', methods=['POST'], csrf=False)
- def drop_down(self, sub_domain, **kwargs): # 需要传递过来参数token
- param_list = self._get_params(
- ['token', 'model', 'count_per_page', 'page_index', 'search_field', 'search_value', 'order', 'filter',
- 'data_type', 'id_field', 'name_field']) # data_type:用于数据授权:当同一个档案要使用不同数据授权时,通过该字段区分
- if not param_list:
- return self.res_err(-1, u'未处理的请求类型,请联系开发者')
- user_token, model, count_per_page, page_index, search_field, search_value, order, _filter, data_type, id_field, name_field = param_list
- if not user_token:
- return self.res_err(601, u'无权操作:缺少 token')
- if not model:
- return self.res_err(600, u'缺少参数:缺少 要查询的档案model')
- if not id_field:
- id_field = 'id'
- else:
- search_field = id_field
- wx_user, info = self._query_wx_user(user_token)
- request.uid = wx_user.user_id.id
- if info:
- return info
- return self._query_dropdown_data(wx_user, model, count_per_page, page_index, search_field, search_value, order,
- _filter, data_type, id_field, name_field)
- def _get_params(self, param_list):
- if not param_list:
- return None
- param_values = []
- try:
- encrypt_type = request.params.get('encrypt_type', 'raw')
- if encrypt_type == 'raw':
- if request.httprequest.data:
- dic = json.loads(request.httprequest.data)
- for p in param_list:
- param_values.append(dic.get(p, None))
- else:
- for p in param_list:
- v = request.httprequest.values[p] if p in request.httprequest.values else None
- param_values.append(v)
- return param_values
- else:
- _logger.info(u'>>> ===error===未处理的请求类型')
- return None
- except Exception as e:
- _logger.info(u'>>> ===error===获取参数出错:' + str(e))
- return None
- def _query_wx_user(self, user_token): # 已保证微信用户与系统用户关联起来
- access_token = request.env(user=1)['wxapp.access_token'].search([
- ('token', '=', user_token),
- ])
- if not access_token:
- return None, self.res_err(10000, u'微信用户未注册,或登录信息过期')
- if not access_token.open_id:
- return None, self.res_err(9999, u'用户未登录')
- user = request.env(user=1)['wxapp.user'].search([
- ('open_id', '=', access_token.open_id),
- ])
- _logger.info(u'>>> open_id======' + access_token.open_id)
- _logger.info(u'>>> wx_user======' + user.name if user else u'无')
- if not user or not user.user_id.id or not user.user_id.active:
- return None, self.res_err(9999, u'请等待系统管理员授权: 当前微信用户,没有与系统用户关联')
- return user, None
- def _query_dropdown_data(self, wx_user, model, count_per_page, page_index, search_field, search_value, order,
- _filter, data_type, id_field, name_field):
- count_per_page = self._get_valid_count_per_page(count_per_page)
- page_index = self._get_valid_page_index(page_index)
- domain = self._get_domain(search_field, search_value)
- # self._add_organization(domain, model, data_type)
- # print('filter:', _filter)
- _filter = Dropdown._get_valid_filter(_filter)
- # print('filter after deal:', _filter)
- if _filter:
- domain += _filter
- # print '===>domain', domain, ',order:', order, ',limit:', count_per_page
- if order:
- data = request.env(user=wx_user.user_id.id)[model].search(domain, limit=count_per_page,
- offset=count_per_page * page_index, order=order)
- else:
- data = request.env(user=wx_user.user_id.id)[model].search(domain, limit=count_per_page,
- offset=count_per_page * page_index)
- if id_field == 'id':
- _name_list = [{'id': row.id, 'name': row[name_field] if name_field else row.name} for row in
- data] if data else []
- else:
- _name_list = [{'id': row[id_field].id, 'name': row[name_field] if name_field else row[id_field].name} for
- row in data if row[id_field]] if data else []
- data = {
- "_list": _name_list
- }
- # print 'data:', data
- # print 'result:', _name_list
- return self.res_ok(data)
- @staticmethod
- def _get_valid_filter(_filter):
- if not _filter:
- return None
- _filter = eval(_filter) if util.is_string(_filter) else _filter
- _filter = searchargs(_filter)
- if _filter and util.is_list(_filter):
- _need_replace = []
- for _tuple in _filter:
- if len(_tuple) > 2:
- if util.is_string(_tuple[2]):
- new_tuple = (_tuple[0], _tuple[1], _tuple[2])
- _need_replace.append((_tuple, new_tuple))
- else:
- new_tuple = (_tuple[0], _tuple[1], None)
- _need_replace.append((_tuple, new_tuple))
- if _need_replace:
- for old, _new in _need_replace:
- index = _filter.index(old)
- _filter.remove(old)
- _filter.insert(index, _new)
- return _filter
- return None
- def _get_valid_count_per_page(self, count_per_page):
- if not count_per_page:
- return 80
- try:
- count_per_page = int(count_per_page)
- except Exception:
- return 80
- if count_per_page < 10:
- count_per_page = 80
- return count_per_page
- def _get_valid_page_index(self, page_index):
- if not page_index:
- return 0
- try:
- page_index = int(page_index)
- except Exception:
- return 0
- if page_index < 0:
- page_index = 0
- return page_index
- def _get_domain(self, search_field, search_value):
- if not search_field or not search_value:
- return []
- return [(search_field, 'ilike', search_value)]
- @http.route('/<string:sub_domain>/drop-down-fault', auth='public', methods=['POST'], csrf=False)
- def query_fault(self, sub_domain, **kwargs): # 需要传递过来参数token
- param_list = self._get_params(
- ['token', 'model', 'count_per_page', 'page_index', 'search_field', 'search_value', 'order', 'filter',
- 'data_type', 'id_field', 'name_field']) # data_type:用于数据授权:当同一个档案要使用不同数据授权时,通过该字段区分
- if not param_list:
- return self.res_err(-1, u'未处理的请求类型,请联系开发者')
- # print('all param list:', param_list)
- user_token, model, count_per_page, page_index, search_field, search_value, order, _filter, data_type, id_field, name_field = param_list
- if not user_token:
- return self.res_err(601, u'无权操作:缺少 token')
- if not id_field:
- id_field = 'id'
- else:
- search_field = id_field
- wx_user, info = self._query_wx_user(user_token)
- request.uid = wx_user.user_id.id
- if info:
- return info
- return self._query_dropdown_data_fault(wx_user, count_per_page, page_index, search_field, search_value, _filter)
- def _query_dropdown_data_fault(self, wx_user, count_per_page, page_index, search_field, search_value, _filter):
- count_per_page = self._get_valid_count_per_page(count_per_page)
- page_index = self._get_valid_page_index(page_index)
- domain = self._get_domain(search_field, search_value)
- # self._add_organization(domain, model, data_type)
- _filter = Dropdown._get_valid_filter(_filter)
- has_valid_filter = _filter[0][2] if _filter else False
- where_exp, where_param = self._get_where_from(domain, _filter, has_valid_filter)
- limit_exp = count_per_page
- offset_exp = count_per_page * page_index
- where_param.append(limit_exp)
- where_param.append(offset_exp)
- if has_valid_filter:
- sql_format = "select f.id,f.name from archives_fault f " \
- "left join archives_equipment_fault_rel r on r.fault_id=f.id " \
- "{} limit %s offset %s"
- sql = sql_format.format(where_exp)
- else:
- sql_format = "select f.id,f.name from archives_fault f " \
- "{} limit %s offset %s"
- sql = sql_format.format(where_exp)
- # print('sql:', sql)
- # print('params:', where_param)
- cr = request.env(user=wx_user.user_id.id).cr
- cr.execute(sql, where_param)
- data = cr.fetchall()
- _name_list = [{'id': row[0], 'name': row[1]} for row in data] if data else []
- data = {
- "_list": _name_list
- }
- return self.res_ok(data)
- def _get_where_from(self, domain, _filter, has_valid_filter):
- _param_value_list = []
- if domain:
- _and_list_domain = []
- for field, operator, value in domain:
- self._add_condition_and_param(_and_list_domain, _param_value_list, field, operator, value)
- domain_condition = ' and '.join(_and_list_domain)
- else:
- domain_condition = ''
- if has_valid_filter:
- _filter_condition_list = []
- for field, operator, value in _filter:
- self._add_condition_and_param(_filter_condition_list, _param_value_list, field, operator, value)
- _filter_condition = ' and '.join(_filter_condition_list)
- _format = '(({}) or f.is_common=true)' if len(_filter_condition_list) > 1 else '({} or f.is_common=true)'
- _filter_condition = _format.format(_filter_condition)
- else:
- _filter_condition = ''
- if domain and has_valid_filter:
- condition = '{} and {}'.format(domain_condition, _filter_condition)
- else:
- condition = domain_condition or _filter_condition
- if condition:
- condition = 'where {}'.format(condition)
- return condition, _param_value_list
- @staticmethod
- def _add_condition_and_param(condition_list, param_ist, field, operator, value):
- # print('field:', field)
- # print('operator:', operator)
- # print('value:', value)
- has_prefix = '.' in field
- add_prefix = '' if has_prefix else 'f.'
- if operator == 'ilike':
- condition_list.append('{}{} ilike %s'.format(add_prefix, field))
- param_ist.append('%{}%'.format(value))
- return
- condition_list.append("{}{} {} %s".format(add_prefix, field, operator))
- param_ist.append(value)
- return
- @http.route('/<string:sub_domain>/drop-down-fault-reason', auth='public', methods=['POST'], csrf=False)
- def query_fault_reason(self, sub_domain, **kwargs): # 需要传递过来参数token
- param_list = self._get_params(
- ['token', 'model', 'count_per_page', 'page_index', 'search_field', 'search_value', 'order', 'filter',
- 'data_type', 'id_field', 'name_field']) # data_type:用于数据授权:当同一个档案要使用不同数据授权时,通过该字段区分
- if not param_list:
- return self.res_err(-1, u'未处理的请求类型,请联系开发者')
- # print('all param list:', param_list)
- user_token, model, count_per_page, page_index, search_field, search_value, order, _filter, data_type, id_field, name_field = param_list
- if not user_token:
- return self.res_err(601, u'无权操作:缺少 token')
- if not id_field:
- id_field = 'id'
- else:
- search_field = id_field
- wx_user, info = self._query_wx_user(user_token)
- request.uid = wx_user.user_id.id
- if info:
- return info
- return self._query_dropdown_data_fault_reason(wx_user, count_per_page, page_index, search_field, search_value,
- _filter, order)
- def _query_dropdown_data_fault_reason(self, wx_user, count_per_page, page_index, search_field, search_value,
- _filter, order):
- count_per_page = self._get_valid_count_per_page(count_per_page)
- page_index = self._get_valid_page_index(page_index)
- domain = self._get_domain(search_field, search_value)
- # self._add_organization(domain, model, data_type)
- _filter = Dropdown._get_valid_filter(_filter)
- has_valid_filter = _filter[0][2] if _filter else False
- where_exp, where_param = self._get_fault_reason_where_from(domain, _filter, has_valid_filter)
- limit_exp = count_per_page
- offset_exp = count_per_page * page_index
- where_param.append(limit_exp)
- where_param.append(offset_exp)
- if order:
- order = 'order by {}'.format(order)
- sql_format = "select id,name from archives_fault_reason " \
- "{} {} limit %s offset %s"
- sql = sql_format.format(where_exp, order)
- # print('sql:', sql)
- # print('params:', where_param)
- cr = request.env(user=wx_user.user_id.id).cr
- cr.execute(sql, where_param)
- data = cr.fetchall()
- _name_list = [{'id': row[0], 'name': row[1]} for row in data] if data else []
- data = {
- "_list": _name_list
- }
- return self.res_ok(data)
- def _get_fault_reason_where_from(self, domain, _filter, has_valid_filter):
- _param_value_list = []
- if domain:
- _and_list_domain = []
- for field, operator, value in domain:
- self._add_condition_and_param_4_fault_reason(_and_list_domain, _param_value_list, field, operator,
- value)
- domain_condition = ' and '.join(_and_list_domain)
- else:
- domain_condition = ''
- if has_valid_filter:
- _filter_condition_list = []
- for field, operator, value in _filter:
- self._add_condition_and_param_4_fault_reason(_filter_condition_list, _param_value_list, field, operator,
- value)
- _filter_condition = ' and '.join(_filter_condition_list)
- _format = '(({}) or fault_id is null)' if len(_filter_condition_list) > 1 else '({} or fault_id is null)'
- _filter_condition = _format.format(_filter_condition)
- else:
- _filter_condition = ''
- if domain and has_valid_filter:
- condition = '{} and {}'.format(domain_condition, _filter_condition)
- else:
- condition = domain_condition or _filter_condition
- if condition:
- condition = 'where {}'.format(condition)
- return condition, _param_value_list
- @staticmethod
- def _add_condition_and_param_4_fault_reason(condition_list, param_ist, field, operator, value):
- # print('field:', field)
- # print('operator:', operator)
- # print('value:', value)
- condition_list.append("{} {} %s".format(field, operator))
- if operator == 'ilike':
- value = '%{}%'.format(value)
- param_ist.append(value)
- return
|