models.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. # -*- coding: utf-8 -*-
  2. from odoo import api, models, tools
  3. from odoo.utils.model_util import const_model
  4. from odoo.utils.model_util.query_model_helper import QueryModelHelper
  5. from odoo.utils.model_util.const import get_digit_capacity_4_save_setting, DATE_LIST, get_database_value_from_value, \
  6. get_date_range_string, DEFAULT_COUNT_PER_PAGE
  7. from .report_sources.source_base import SourceBase, GROUP_FIELD, SUM_FIELD, EXPRESSION_FIELD
  8. from odoo.utils.constant import REPORT_TYPE, ANALYSE, ER_WEI, CHART, SINGLE_HEAD, DOUBLE_HEAD, TABLE_HEAD_TYPE, \
  9. CHART_TYPE, LINE, BAR
  10. from ..utils.chart import Chart, ChartType
  11. bi_result_dic = {} # 缓存。导出Excel、翻页时,就不用再查询一遍
  12. class Base(models.AbstractModel):
  13. _inherit = 'base'
  14. _module = 'jc_bi'
  15. def _get_bi_helper(self, detail_field, reference_field):
  16. # print('_get_bi_helper')
  17. model = self._get_model_from(detail_field, reference_field,self.env)
  18. helper = QueryModelHelper(self.env, model)
  19. # lock_column_count = 0
  20. # setting_list = [lock_column_count, DEFAULT_COUNT_PER_PAGE]
  21. # helper.set_setting(self, [], setting_list, [])
  22. return helper
  23. @api.model
  24. def super_query_dropdown(self, comodel):
  25. # todo: 是否需要权限管起来?在bi中调用这个方法
  26. return self.super_query_dropdown2(comodel, ['id', 'name'])
  27. @api.model
  28. def super_query_dropdown2(self, comodel, field_list):
  29. # todo: 是否需要权限管起来?在bi中调用这个方法
  30. res = self.env[comodel].sudo().search_read([], field_list)
  31. return res
  32. @api.model
  33. def get_source_info(self, source_name, report_style_id, report_type):
  34. # print('source_name:', source_name)
  35. # print('report_style_id:', report_style_id)
  36. # print('report_type:', report_type)
  37. exist_source = SourceBase.get_source(source_name)
  38. if not exist_source:
  39. return ''
  40. model = exist_source.model
  41. if report_type == ANALYSE:
  42. res = self.env[model].sudo().get_show_field(exist_source, report_style_id)
  43. # print('ANALYSE:', res)
  44. return res
  45. if report_type == ER_WEI:
  46. return self.env[model].sudo().get_er_wei(exist_source, report_style_id)
  47. if report_type == CHART:
  48. return self.env[model].sudo().get_chart(exist_source, report_style_id)
  49. return ''
  50. def get_show_field(self, source, report_style_id):
  51. style = self._query_style(report_style_id)
  52. _setting = style.detail if style else []
  53. helper = self._get_bi_helper(source.detail_field, source.reference_field)
  54. setting_list = [style.lock_column_count, style.count_per_page] if style else [0, DEFAULT_COUNT_PER_PAGE]
  55. helper.set_setting(_setting, [], setting_list, None)
  56. show_field_setting = helper.get_show_field_setting()
  57. # print('show_field_setting:', show_field_setting)
  58. return show_field_setting
  59. def get_er_wei(self, source, report_style_id):
  60. style = self._query_style(report_style_id)
  61. helper = self._get_bi_helper(source.detail_field, source.reference_field)
  62. all_fields = helper.get_all_chart_fields()
  63. # print('all_fields:', all_fields)
  64. indicator_list, er_wei_info = Base._get_er_wei_setting(style)
  65. return all_fields, indicator_list, er_wei_info
  66. def get_chart(self, source, report_style_id):
  67. style = self._query_style(report_style_id)
  68. helper = self._get_bi_helper(source.detail_field, source.reference_field)
  69. all_fields = helper.get_all_chart_fields()
  70. # print('all_fields:', all_fields)
  71. indicator_list, chart_info = Base._get_chart_setting(style)
  72. return all_fields, indicator_list, chart_info, CHART_TYPE
  73. def _query_style(self, report_style_id):
  74. if report_style_id:
  75. report_style_id = int(report_style_id)
  76. style = self.env['jc_bi.report_style'].browse(report_style_id)
  77. else:
  78. style = None
  79. return style
  80. @staticmethod
  81. def _get_er_wei_setting(style):
  82. indicator_list = [(detail.indicator_field, detail.indicator_name, detail.indicator_show_name) for detail in
  83. style.indication_detail]
  84. er_wei_info = [style.row_name, style.row_name_show, style.first_column_width,
  85. style.column_name, style.column_name_show, style.other_column_width]
  86. return indicator_list, er_wei_info
  87. @staticmethod
  88. def _get_chart_setting(style):
  89. indicator_list = [(detail.indicator_field, detail.indicator_name, detail.indicator_show_name) for detail in
  90. style.chart_detail]
  91. chart_info = [style.unit_name, style.unit_name_show, style.x_name, style.x_name_show, style.chart_type]
  92. return indicator_list, chart_info
  93. @api.model
  94. def query_condition_setting(self, report_set_id, condition_id):
  95. res = []
  96. bill = self.env[self._name].sudo().browse(int(report_set_id))
  97. if not bill:
  98. return []
  99. condition = self.env['jc_bi.report_label_condition'].sudo().browse(int(condition_id))
  100. for d in bill.detail:
  101. if not d.report_style_id:
  102. continue
  103. style_id = d.report_style_id.id
  104. style = self.env['jc_bi.report_style'].sudo().browse(style_id)
  105. source_name = style.source
  106. # print('style_id,source:', style_id, source_name)
  107. exist_source = SourceBase.get_source(source_name)
  108. if not exist_source:
  109. res.append([style_id, []])
  110. continue
  111. model = exist_source.model
  112. condition_list = self.env[model].sudo().get_style_condition(style, exist_source, condition)
  113. common_condition_field = Base._get_style_common_condition_field(style.id, condition)
  114. res.append([style_id, style.name, condition_list, common_condition_field])
  115. # condition_list = helper.get_pre_query_setting_condition(setting.pre_query_condition_detail)
  116. return res
  117. def get_style_condition(self, style, source, condition):
  118. detail = [x for x in condition.detail if x.report_style_id.id == style.id]
  119. helper = self._get_bi_helper(source.detail_field, source.reference_field)
  120. setting_list = [style.lock_column_count, style.count_per_page] if style else [0, DEFAULT_COUNT_PER_PAGE]
  121. _setting = style.detail if style else []
  122. helper.set_setting([], _setting, setting_list, None)
  123. condition_list = helper.get_setting_condition(detail)
  124. # print('style_id, condition_list:', style.id, condition_list)
  125. return condition_list
  126. @staticmethod
  127. def _get_style_common_condition_field(style_id, condition):
  128. detail = [x for x in condition.common_condition_detail if x.report_style_id.id == style_id]
  129. if not detail:
  130. return ''
  131. return detail[0].field
  132. @api.model
  133. def search_bi(self, label_id, style_id, page_no, date_range_condition):
  134. """
  135. BI的每一个报表的查询方法
  136. :param label_id: 标签ID
  137. :param style_id: 样式ID
  138. :param page_no: 第几页,用于分析
  139. :param date_range_condition: 右上角的日期通用条件
  140. :return: 查询结果
  141. """
  142. label_id = int(label_id)
  143. style_id = int(style_id)
  144. if page_no == -1: # 点击了查询按钮,或者点击了预定义查询按钮
  145. self._query_search_and_set_cache_bi(label_id, style_id, date_range_condition)
  146. return self._get_page_data_bi(label_id, style_id, page_no)
  147. def _query_search_and_set_cache_bi(self, label_id, style_id, date_range_condition):
  148. style = self.env['jc_bi.report_style'].sudo().browse(style_id)
  149. if not style:
  150. return
  151. label = self.env['jc_bi.report_label'].sudo().browse(int(label_id))
  152. condition_id = label.report_label_condition_id.id
  153. condition = self.env['jc_bi.report_label_condition'].sudo().browse(condition_id) if condition_id else None
  154. helper, count_per_page = self._get_helper_bi_query(style)
  155. condition_list = Base._get_condition(helper, condition, style_id)
  156. condition_list = Base._change_to_condition_format(condition_list)
  157. date_condition_list = Base._get_date_condition_list(date_range_condition, condition, style_id)
  158. if date_condition_list:
  159. condition_list += date_condition_list
  160. # print('condition_list:', condition_list)
  161. helper.set_condition_list(condition_list)
  162. if style.report_type == ANALYSE:
  163. self._query_analyse(helper, style, label_id, count_per_page)
  164. return
  165. if style.report_type == ER_WEI:
  166. self._query_er_wei(helper, style, label_id)
  167. return
  168. if style.report_type == CHART:
  169. self._query_chart(helper, style, label_id)
  170. return
  171. return
  172. def _query_analyse(self, helper, style, label_id, count_per_page):
  173. show_field_list = self._get_show_field_list(style)
  174. # print('show_field_list:', show_field_list)
  175. helper.set_query_fields_list(show_field_list)
  176. # # print('condition_list:', condition_list)
  177. # helper.set_condition_list(condition_list)
  178. res = helper.execute_query()
  179. column_name_list, rows, sum_row = res
  180. bi_result_dic[(label_id, style.id)] = (ANALYSE, (column_name_list, rows, sum_row, count_per_page))
  181. return
  182. def _query_er_wei(self, helper, style, label_id):
  183. column_list = helper.query_column(style.column_name)
  184. indicator_list = Base._get_indicator_list(style.indication_detail)
  185. # print('indicator_list:', indicator_list)
  186. field_expression_list, all_fields, heads_list = Base._get_indicator_expression(column_list, indicator_list,
  187. style.row_name,
  188. style.row_name_show,
  189. style.column_name)
  190. # print('start er wei:')
  191. # print('all fields:', all_fields)
  192. er_wei_data = helper.query_chart(field_expression_list, all_fields, heads_list, False)
  193. if er_wei_data:
  194. width_pair = style.get_er_wei_column_width()
  195. er_wei_data = er_wei_data[0], er_wei_data[1:], width_pair
  196. # print('er_wei_data:', er_wei_data)
  197. bi_result_dic[(label_id, style.id)] = (ER_WEI, er_wei_data)
  198. return
  199. def _query_chart(self, helper, style, label_id):
  200. column_list = helper.query_column(style.unit_name)
  201. indicator_list = Base._get_indicator_list(style.chart_detail)
  202. # print('indicator_list:', indicator_list)
  203. field_expression_list, all_fields, heads_list = Base._get_indicator_expression(column_list, indicator_list,
  204. style.x_name, style.x_name_show,
  205. style.unit_name)
  206. chart_data = helper.query_chart(field_expression_list, all_fields, heads_list)
  207. # print('chart_data:', chart_data)
  208. res = Base._get_chart(style.chart_type, chart_data)
  209. # print('chart:', res)
  210. bi_result_dic[(label_id, style.id)] = (CHART, res)
  211. return
  212. @staticmethod
  213. def _get_chart(chart_type, chart_data):
  214. helper = Chart(None)
  215. helper.set_data(chart_data)
  216. # helper.set_zoom(0, 100)
  217. helper.set_chart_type(Base._get_chart_type(chart_type))
  218. # helper.set_change_xy()
  219. return helper.get()
  220. @staticmethod
  221. def _get_chart_type(chart_type):
  222. if chart_type == LINE:
  223. return ChartType().line
  224. if chart_type == BAR:
  225. return ChartType().bar
  226. return ChartType().line
  227. @staticmethod
  228. def _get_indicator_list(style_detail):
  229. indicator_list = []
  230. for detail in style_detail:
  231. name = detail.indicator_show_name if detail.indicator_show_name else detail.indicator_name
  232. indicator_list.append((detail.indicator_field, name))
  233. return indicator_list
  234. @staticmethod
  235. def _get_indicator_expression(column_value_list, indicator_list, field_x_or_first, show_x_or_first,
  236. field_unit_or_other):
  237. all_fields = [field_x_or_first]
  238. selected_exp_list = [field_x_or_first]
  239. heads_list = [show_x_or_first]
  240. _format = "sum(case when {}={} then {} end) as {}"
  241. _format_none = "sum(case when {} is null then {} end) as {}"
  242. for name, _id in column_value_list:
  243. for table_field, show in indicator_list:
  244. all_fields.append(table_field)
  245. if not _id:
  246. name = '=无='
  247. selected_exp_list.append(_format_none.format(field_unit_or_other, table_field, show))
  248. else:
  249. selected_exp_list.append(_format.format(field_unit_or_other, _id, table_field, show))
  250. heads_list.append("{}/{}".format(name, show))
  251. # return ','.join(selected_exp_list), ','.join(heads_list)
  252. return selected_exp_list, all_fields, heads_list
  253. @staticmethod
  254. def _get_condition(helper, condition, style_id):
  255. if not condition:
  256. return []
  257. detail = [d for d in condition.detail if d.report_style_id.id == style_id]
  258. condition_list = helper.get_setting_condition(detail)
  259. # print('condition_list, before:', condition_list)
  260. condition_list = Base._clear_empty_vale_and_reset_date_value(condition_list)
  261. # print('condition_list, after:', condition_list)
  262. return condition_list
  263. @staticmethod
  264. def _get_date_condition_list(date_range_condition, condition, style_id):
  265. if not date_range_condition:
  266. return None
  267. if not date_range_condition[0] and not date_range_condition[1]:
  268. return None
  269. if not condition:
  270. return None
  271. common_condition_field = Base._get_style_common_condition_field(style_id, condition)
  272. if not common_condition_field:
  273. return None
  274. res = []
  275. if date_range_condition[0]:
  276. start = [common_condition_field, 'date', [date_range_condition[0], True]]
  277. res.append(start)
  278. if date_range_condition[1]:
  279. end = [common_condition_field, 'date', [date_range_condition[1], False]]
  280. res.append(end)
  281. return res
  282. @staticmethod
  283. def _clear_empty_vale_and_reset_date_value(condition_list):
  284. res = []
  285. for i, item in enumerate(condition_list):
  286. field, name, _type, value = item
  287. if not value:
  288. continue
  289. if _type in ('selection', 'many2one') and not value[0]:
  290. continue
  291. if _type != 'date':
  292. res.append((field, _type, value))
  293. continue
  294. start_date_define_pair, end_date_define_pair = value
  295. start_date_range = get_date_range_string(start_date_define_pair[0])
  296. end_date_range = get_date_range_string(end_date_define_pair[0])
  297. res.append((field, _type, [start_date_range[0], end_date_range[1]]))
  298. return res
  299. @staticmethod
  300. def _change_to_condition_format(condition_list):
  301. res = []
  302. for table_field, _type, value in condition_list:
  303. if _type == 'many2one':
  304. res.append([table_field, _type, value[0][0]])
  305. continue
  306. if _type == 'date':
  307. start, end = value
  308. if start:
  309. res.append([table_field, _type, [start, True]])
  310. if end:
  311. res.append([table_field, _type, [end, False]])
  312. continue
  313. res.append([table_field, _type, value])
  314. return res
  315. def _get_show_field_list(self, style):
  316. # res = []
  317. _list = [d for d in style.detail if d.sequence]
  318. # print('_list:', _list)
  319. _list.sort(key=lambda b: b.sequence)
  320. # print('style list order by sequence:', _list)
  321. return [d.field for d in _list if not d.field.endswith('.number_type') and not d.field.endswith('.bill_show')]
  322. def _get_helper_bi_query(self, style):
  323. model = self._get_model_from_bi(style)
  324. helper = QueryModelHelper(self.env, model)
  325. count_per_page = style.count_per_page
  326. if count_per_page <= 0:
  327. count_per_page = DEFAULT_COUNT_PER_PAGE
  328. setting_list = [style.lock_column_count, count_per_page]
  329. helper.set_setting(style.detail, [], setting_list, [])
  330. return helper, count_per_page
  331. def _get_model_from_bi(self, style):
  332. exist_source = SourceBase.get_source(style.source)
  333. if not exist_source:
  334. return ''
  335. model = exist_source.model
  336. table = exist_source.sql_table
  337. detail_field = exist_source.detail_field
  338. reference_field = exist_source.reference_field
  339. # print(' [获取 model 信息, do:', model, table)
  340. return const_model.get_model_from2(self, model, table, detail_field, reference_field, self._get_rec_name,
  341. self._get_field_info, self._get_table,self.env)
  342. def _get_page_data_bi(self, label_id, style_id, page_no):
  343. report_type, data = self.get_result_bi(label_id, style_id)
  344. if report_type == ANALYSE:
  345. return ANALYSE, self._get_analyse_result(data, page_no, label_id, style_id)
  346. if report_type == ER_WEI:
  347. return ER_WEI, (label_id, style_id, data)
  348. if report_type == CHART:
  349. return CHART, (label_id, style_id, data)
  350. return '', []
  351. def _get_analyse_result(self, data, page_no, label_id, style_id):
  352. column_name_list, rows, sum_row, count_per_page = data
  353. page_count = self._get_page_count(rows, count_per_page)
  354. if page_no == '全部':
  355. return column_name_list, rows, sum_row, page_count, len(rows), label_id, style_id
  356. page_no = self._get_page_no(page_no, page_count)
  357. start = (page_no - 1) * count_per_page
  358. end = page_no * count_per_page
  359. page_rows = rows if page_count == 1 else rows[start:end]
  360. return column_name_list, page_rows, sum_row, page_count, len(rows), label_id, style_id
  361. def get_result_bi(self, label_id, style_id):
  362. if (label_id, style_id) not in bi_result_dic:
  363. return ANALYSE, ([], [], [], DEFAULT_COUNT_PER_PAGE)
  364. return bi_result_dic[(label_id, style_id)]