You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
16 KiB

Excel Import/Export/Report (#1522) * [ADD] v12 excel_import_export * Change from eval() to safe_evel() * Change variable to format to style, as fomat is a common python function :100644 100644 00ee3d9f... e9e48d87... M excel_import_export/models/common.py :100644 100644 a215d29b... 5b4d1fb1... M excel_import_export/models/styles.py :100644 100644 ace11a32... 01e5b9f5... M excel_import_export/models/xlsx_export.py :100644 100644 881b814f... cadfb0f2... M excel_import_export/models/xlsx_import.py :100644 100644 58689ee5... 80490ce8... M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6... a363ad19... M excel_import_export/views/xlsx_template_view.xml :100644 100644 475b5187... 392fe6e5... M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 4af9c519... 45ee33c6... M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3... 17d3964d... M excel_import_export/__manifest__.py :100644 100644 00ee3d9f... 51c2572a... M excel_import_export/models/common.py :100644 100644 a215d29b... 5b4d1fb1... M excel_import_export/models/styles.py :100644 100644 ace11a32... 185a3330... M excel_import_export/models/xlsx_export.py :100644 100644 881b814f... cadfb0f2... M excel_import_export/models/xlsx_import.py :100644 100644 58689ee5... 80490ce8... M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6... a363ad19... M excel_import_export/views/xlsx_template_view.xml :100644 100644 475b5187... 392fe6e5... M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 4af9c519... 45ee33c6... M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3... 933ce0dc... M excel_import_export/__manifest__.py :100644 100644 00ee3d9f... 51c2572a... M excel_import_export/models/common.py :100644 100644 a215d29b... 5b4d1fb1... M excel_import_export/models/styles.py :100644 100644 ace11a32... 185a3330... M excel_import_export/models/xlsx_export.py :100644 100644 881b814f... cadfb0f2... M excel_import_export/models/xlsx_import.py :100644 100644 58689ee5... 80490ce8... M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6... a363ad19... M excel_import_export/views/xlsx_template_view.xml :100644 100644 475b5187... 392fe6e5... M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 4af9c519... 45ee33c6... M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 3b1217e8 M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 5b4d1fb1 M excel_import_export/models/styles.py :100644 100644 ace11a32 185a3330 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f cadfb0f2 M excel_import_export/models/xlsx_import.py :100644 100644 58689ee5 80490ce8 M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 5b4d1fb1 M excel_import_export/models/styles.py :100644 100644 ace11a32 185a3330 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f cadfb0f2 M excel_import_export/models/xlsx_import.py :100644 100644 58689ee5 80490ce8 M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 a7d6adc5 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 12f9ca99 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 578a1fd8 M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 c7db3f92 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 12f9ca99 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 578a1fd8 M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 c7db3f92 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 12f9ca99 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 e3826e08 M excel_import_export/models/xlsx_template.py :000000 100644 00000000 34aa53bf A excel_import_export/tests/__init__.py :000000 100644 00000000 18618688 A excel_import_export/tests/sale_order.xlsx :000000 100644 00000000 c8481487 A excel_import_export/tests/test_xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 c7db3f92 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 12f9ca99 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 ed8c9fc7 M excel_import_export/models/xlsx_template.py :000000 100644 00000000 34aa53bf A excel_import_export/tests/__init__.py :000000 100644 00000000 18618688 A excel_import_export/tests/sale_order.xlsx :000000 100644 00000000 69aa6ea0 A excel_import_export/tests/test_xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 475b5187 392fe6e5 M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 c7db3f92 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 933d8614 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 1460473a M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 a2d035ef 9463f279 M excel_import_export_demo/__manifest__.py :100644 100644 475b5187 e7f1255b M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :000000 100644 00000000 79db62f7 A excel_import_export_demo/tests/__init__.py :000000 100644 00000000 18618688 A excel_import_export_demo/tests/sale_order.xlsx :000000 100644 00000000 c9733b95 A excel_import_export_demo/tests/test_common.py :000000 100644 00000000 9c943768 A excel_import_export_demo/tests/test_xlsx_import_export.py :000000 100644 00000000 730605c1 A excel_import_export_demo/tests/test_xlsx_template.py :100644 100644 96157ea3 fee958bc M excel_import_export/__manifest__.py :100644 100644 00ee3d9f 51c2572a M excel_import_export/models/common.py :100644 100644 a215d29b 9738a3c8 M excel_import_export/models/styles.py :100644 100644 ace11a32 c7db3f92 M excel_import_export/models/xlsx_export.py :100644 100644 881b814f 933d8614 M excel_import_export/models/xlsx_import.py :100644 100644 70c37799 f123d2a6 M excel_import_export/models/xlsx_report.py :100644 100644 58689ee5 1460473a M excel_import_export/models/xlsx_template.py :100644 100644 5c9c09a6 a363ad19 M excel_import_export/views/xlsx_template_view.xml :100644 100644 800ea573 1807ea7e M excel_import_export/wizard/export_xlsx_wizard.py :100644 100644 febed8d0 750dc17e M excel_import_export/wizard/import_xlsx_wizard.py :100644 100644 a2d035ef 9463f279 M excel_import_export_demo/__manifest__.py :100644 100644 475b5187 e7f1255b M excel_import_export_demo/import_export_sale_order/templates.xml :100644 100644 8e40a2d0 21574896 M excel_import_export_demo/report_sale_order/report_sale_order.py :100644 100644 4af9c519 45ee33c6 M excel_import_export_demo/report_sale_order/templates.xml :000000 100644 00000000 79db62f7 A excel_import_export_demo/tests/__init__.py :000000 100644 00000000 18618688 A excel_import_export_demo/tests/sale_order.xlsx :000000 100644 00000000 bb3ea32e A excel_import_export_demo/tests/test_common.py :000000 100644 00000000 9c943768 A excel_import_export_demo/tests/test_xlsx_import_export.py :000000 100644 00000000 730605c1 A excel_import_export_demo/tests/test_xlsx_template.py
5 years ago
  1. # Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
  2. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
  3. import os
  4. import base64
  5. from ast import literal_eval
  6. from odoo import api, fields, models, _
  7. from odoo.modules.module import get_module_path
  8. from os.path import join as opj
  9. from . import common as co
  10. from odoo.exceptions import ValidationError
  11. class XLSXTemplate(models.Model):
  12. """ Master Data for XLSX Templates
  13. - Excel Template
  14. - Import/Export Meta Data (dict text)
  15. - Default values, etc.
  16. """
  17. _name = 'xlsx.template'
  18. _description = 'Excel template file and instruction'
  19. _order = 'name'
  20. name = fields.Char(
  21. string='Template Name',
  22. required=True,
  23. )
  24. res_model = fields.Char(
  25. string='Resource Model',
  26. help="The database object this attachment will be attached to.",
  27. )
  28. fname = fields.Char(
  29. string='File Name',
  30. )
  31. gname = fields.Char(
  32. string='Group Name',
  33. help="Multiple template of same model, can belong to same group,\n"
  34. "result in multiple template selection",
  35. )
  36. description = fields.Char(
  37. string='Description',
  38. )
  39. input_instruction = fields.Text(
  40. string='Instruction (Input)',
  41. help="This is used to construct instruction in tab Import/Export",
  42. )
  43. instruction = fields.Text(
  44. string='Instruction',
  45. compute='_compute_output_instruction',
  46. help="Instruction on how to import/export, prepared by system."
  47. )
  48. datas = fields.Binary(
  49. string='File Content',
  50. )
  51. to_csv = fields.Boolean(
  52. string='Convert to CSV?',
  53. default=False,
  54. )
  55. csv_delimiter = fields.Char(
  56. string='CSV Delimiter',
  57. size=1,
  58. default=',',
  59. required=True,
  60. help="Optional for CSV, default is comma.",
  61. )
  62. csv_extension = fields.Char(
  63. string='CSV File Extension',
  64. size=5,
  65. default='csv',
  66. required=True,
  67. help="Optional for CSV, default is .csv"
  68. )
  69. csv_quote = fields.Boolean(
  70. string='CSV Quoting',
  71. default=True,
  72. help="Optional for CSV, default is full quoting."
  73. )
  74. export_ids = fields.One2many(
  75. comodel_name='xlsx.template.export',
  76. inverse_name='template_id',
  77. )
  78. import_ids = fields.One2many(
  79. comodel_name='xlsx.template.import',
  80. inverse_name='template_id',
  81. )
  82. post_import_hook = fields.Char(
  83. string='Post Import Function Hook',
  84. help="Call a function after successful import, i.e.,\n"
  85. "${object.post_import_do_something()}",
  86. )
  87. show_instruction = fields.Boolean(
  88. string='Show Output',
  89. default=False,
  90. help="This is the computed instruction based on tab Import/Export,\n"
  91. "to be used by xlsx import/export engine",
  92. )
  93. redirect_action = fields.Many2one(
  94. comodel_name='ir.actions.act_window',
  95. string='Return Action',
  96. domain=[('type', '=', 'ir.actions.act_window')],
  97. help="Optional action, redirection after finish import operation",
  98. )
  99. @api.multi
  100. @api.constrains('redirect_action', 'res_model')
  101. def _check_action_model(self):
  102. for rec in self:
  103. if rec.res_model and rec.redirect_action and \
  104. rec.res_model != rec.redirect_action.res_model:
  105. raise ValidationError(_('The selected redirect action is '
  106. 'not for model %s') % rec.res_model)
  107. @api.model
  108. def load_xlsx_template(self, tempalte_ids, addon=False):
  109. for template in self.browse(tempalte_ids):
  110. if not addon:
  111. addon = list(template.get_external_id().
  112. values())[0].split('.')[0]
  113. addon_path = get_module_path(addon)
  114. file_path = False
  115. for root, dirs, files in os.walk(addon_path):
  116. for name in files:
  117. if name == template.fname:
  118. file_path = os.path.abspath(opj(root, name))
  119. if file_path:
  120. template.datas = base64.b64encode(open(file_path, 'rb').read())
  121. return True
  122. @api.model
  123. def create(self, vals):
  124. rec = super().create(vals)
  125. if vals.get('input_instruction'):
  126. rec._compute_input_export_instruction()
  127. rec._compute_input_import_instruction()
  128. rec._compute_input_post_import_hook()
  129. return rec
  130. @api.multi
  131. def write(self, vals):
  132. res = super().write(vals)
  133. if vals.get('input_instruction'):
  134. for rec in self:
  135. rec._compute_input_export_instruction()
  136. rec._compute_input_import_instruction()
  137. rec._compute_input_post_import_hook()
  138. return res
  139. @api.multi
  140. def _compute_input_export_instruction(self):
  141. self = self.with_context(compute_from_input=True)
  142. for rec in self:
  143. # Export Instruction
  144. input_dict = literal_eval(rec.input_instruction.strip())
  145. rec.export_ids.unlink()
  146. export_dict = input_dict.get('__EXPORT__')
  147. if not export_dict:
  148. continue
  149. export_lines = []
  150. sequence = 0
  151. # Sheet
  152. for sheet, rows in export_dict.items():
  153. sequence += 1
  154. vals = {'sequence': sequence,
  155. 'section_type': 'sheet',
  156. 'sheet': str(sheet),
  157. }
  158. export_lines.append((0, 0, vals))
  159. # Rows
  160. for row_field, lines in rows.items():
  161. sequence += 1
  162. is_cont = False
  163. if '_CONT_' in row_field:
  164. is_cont = True
  165. row_field = row_field.replace('_CONT_', '')
  166. vals = {'sequence': sequence,
  167. 'section_type': (row_field == '_HEAD_' and
  168. 'head' or 'row'),
  169. 'row_field': row_field,
  170. 'is_cont': is_cont,
  171. }
  172. export_lines.append((0, 0, vals))
  173. for excel_cell, field_name in lines.items():
  174. sequence += 1
  175. vals = {'sequence': sequence,
  176. 'section_type': 'data',
  177. 'excel_cell': excel_cell,
  178. 'field_name': field_name,
  179. }
  180. export_lines.append((0, 0, vals))
  181. rec.write({'export_ids': export_lines})
  182. @api.multi
  183. def _compute_input_import_instruction(self):
  184. self = self.with_context(compute_from_input=True)
  185. for rec in self:
  186. # Import Instruction
  187. input_dict = literal_eval(rec.input_instruction.strip())
  188. rec.import_ids.unlink()
  189. import_dict = input_dict.get('__IMPORT__')
  190. if not import_dict:
  191. continue
  192. import_lines = []
  193. sequence = 0
  194. # Sheet
  195. for sheet, rows in import_dict.items():
  196. sequence += 1
  197. vals = {'sequence': sequence,
  198. 'section_type': 'sheet',
  199. 'sheet': str(sheet),
  200. }
  201. import_lines.append((0, 0, vals))
  202. # Rows
  203. for row_field, lines in rows.items():
  204. sequence += 1
  205. no_delete = False
  206. if '_NODEL_' in row_field:
  207. no_delete = True
  208. row_field = row_field.replace('_NODEL_', '')
  209. vals = {'sequence': sequence,
  210. 'section_type': (row_field == '_HEAD_' and
  211. 'head' or 'row'),
  212. 'row_field': row_field,
  213. 'no_delete': no_delete,
  214. }
  215. import_lines.append((0, 0, vals))
  216. for excel_cell, field_name in lines.items():
  217. sequence += 1
  218. vals = {'sequence': sequence,
  219. 'section_type': 'data',
  220. 'excel_cell': excel_cell,
  221. 'field_name': field_name,
  222. }
  223. import_lines.append((0, 0, vals))
  224. rec.write({'import_ids': import_lines})
  225. @api.multi
  226. def _compute_input_post_import_hook(self):
  227. self = self.with_context(compute_from_input=True)
  228. for rec in self:
  229. # Import Instruction
  230. input_dict = literal_eval(rec.input_instruction.strip())
  231. rec.post_import_hook = input_dict.get('__POST_IMPORT__')
  232. @api.multi
  233. def _compute_output_instruction(self):
  234. """ From database, compute back to dictionary """
  235. for rec in self:
  236. inst_dict = {}
  237. prev_sheet = False
  238. prev_row = False
  239. # Export Instruction
  240. itype = '__EXPORT__'
  241. inst_dict[itype] = {}
  242. for line in rec.export_ids:
  243. if line.section_type == 'sheet':
  244. sheet = co.isinteger(line.sheet) and \
  245. int(line.sheet) or line.sheet
  246. sheet_dict = {sheet: {}}
  247. inst_dict[itype].update(sheet_dict)
  248. prev_sheet = sheet
  249. continue
  250. if line.section_type in ('head', 'row'):
  251. row_field = line.row_field
  252. if line.section_type == 'row' and line.is_cont:
  253. row_field = '_CONT_%s' % row_field
  254. row_dict = {row_field: {}}
  255. inst_dict[itype][prev_sheet].update(row_dict)
  256. prev_row = row_field
  257. continue
  258. if line.section_type == 'data':
  259. excel_cell = line.excel_cell
  260. field_name = line.field_name or ''
  261. field_name += line.field_cond or ''
  262. field_name += line.style or ''
  263. field_name += line.style_cond or ''
  264. if line.is_sum:
  265. field_name += '@{sum}'
  266. cell_dict = {excel_cell: field_name}
  267. inst_dict[itype][prev_sheet][prev_row].update(cell_dict)
  268. continue
  269. # Import Instruction
  270. itype = '__IMPORT__'
  271. inst_dict[itype] = {}
  272. for line in rec.import_ids:
  273. if line.section_type == 'sheet':
  274. sheet = co.isinteger(line.sheet) and \
  275. int(line.sheet) or line.sheet
  276. sheet_dict = {sheet: {}}
  277. inst_dict[itype].update(sheet_dict)
  278. prev_sheet = sheet
  279. continue
  280. if line.section_type in ('head', 'row'):
  281. row_field = line.row_field
  282. if line.section_type == 'row' and line.no_delete:
  283. row_field = '_NODEL_%s' % row_field
  284. row_dict = {row_field: {}}
  285. inst_dict[itype][prev_sheet].update(row_dict)
  286. prev_row = row_field
  287. continue
  288. if line.section_type == 'data':
  289. excel_cell = line.excel_cell
  290. field_name = line.field_name or ''
  291. field_name += line.field_cond or ''
  292. cell_dict = {excel_cell: field_name}
  293. inst_dict[itype][prev_sheet][prev_row].update(cell_dict)
  294. continue
  295. itype = '__POST_IMPORT__'
  296. inst_dict[itype] = False
  297. if rec.post_import_hook:
  298. inst_dict[itype] = rec.post_import_hook
  299. rec.instruction = inst_dict
  300. class XLSXTemplateImport(models.Model):
  301. _name = 'xlsx.template.import'
  302. _description = 'Detailed of how excel data will be imported'
  303. _order = 'sequence'
  304. template_id = fields.Many2one(
  305. comodel_name='xlsx.template',
  306. string='XLSX Template',
  307. index=True,
  308. ondelete='cascade',
  309. readonly=True,
  310. )
  311. sequence = fields.Integer(
  312. string='Sequence',
  313. default=10,
  314. )
  315. sheet = fields.Char(
  316. string='Sheet',
  317. )
  318. section_type = fields.Selection(
  319. [('sheet', 'Sheet'),
  320. ('head', 'Head'),
  321. ('row', 'Row'),
  322. ('data', 'Data')],
  323. string='Section Type',
  324. required=True,
  325. )
  326. row_field = fields.Char(
  327. string='Row Field',
  328. help="If section type is row, this field is required",
  329. )
  330. no_delete = fields.Boolean(
  331. string='No Delete',
  332. default=False,
  333. help="By default, all rows will be deleted before import.\n"
  334. "Select No Delete, otherwise"
  335. )
  336. excel_cell = fields.Char(
  337. string='Cell',
  338. )
  339. field_name = fields.Char(
  340. string='Field',
  341. )
  342. field_cond = fields.Char(
  343. string='Field Cond.',
  344. )
  345. @api.model
  346. def create(self, vals):
  347. new_vals = self._extract_field_name(vals)
  348. return super().create(new_vals)
  349. @api.model
  350. def _extract_field_name(self, vals):
  351. if self._context.get('compute_from_input') and vals.get('field_name'):
  352. field_name, field_cond = co.get_field_condition(vals['field_name'])
  353. field_cond = field_cond and '${%s}' % (field_cond or '') or False
  354. vals.update({'field_name': field_name,
  355. 'field_cond': field_cond,
  356. })
  357. return vals
  358. class XLSXTemplateExport(models.Model):
  359. _name = 'xlsx.template.export'
  360. _description = 'Detailed of how excel data will be exported'
  361. _order = 'sequence'
  362. template_id = fields.Many2one(
  363. comodel_name='xlsx.template',
  364. string='XLSX Template',
  365. index=True,
  366. ondelete='cascade',
  367. readonly=True,
  368. )
  369. sequence = fields.Integer(
  370. string='Sequence',
  371. default=10,
  372. )
  373. sheet = fields.Char(
  374. string='Sheet',
  375. )
  376. section_type = fields.Selection(
  377. [('sheet', 'Sheet'),
  378. ('head', 'Head'),
  379. ('row', 'Row'),
  380. ('data', 'Data')],
  381. string='Section Type',
  382. required=True,
  383. )
  384. row_field = fields.Char(
  385. string='Row Field',
  386. help="If section type is row, this field is required",
  387. )
  388. is_cont = fields.Boolean(
  389. string='Continue',
  390. default=False,
  391. help="Continue data rows after last data row",
  392. )
  393. excel_cell = fields.Char(
  394. string='Cell',
  395. )
  396. field_name = fields.Char(
  397. string='Field',
  398. )
  399. field_cond = fields.Char(
  400. string='Field Cond.',
  401. )
  402. is_sum = fields.Boolean(
  403. string='Sum',
  404. default=False,
  405. )
  406. style = fields.Char(
  407. string='Default Style',
  408. )
  409. style_cond = fields.Char(
  410. string='Style w/Cond.',
  411. )
  412. @api.model
  413. def create(self, vals):
  414. new_vals = self._extract_field_name(vals)
  415. return super().create(new_vals)
  416. @api.model
  417. def _extract_field_name(self, vals):
  418. if self._context.get('compute_from_input') and vals.get('field_name'):
  419. field_name, field_cond = co.get_field_condition(vals['field_name'])
  420. field_cond = field_cond or 'value or ""'
  421. field_name, style = co.get_field_style(field_name)
  422. field_name, style_cond = co.get_field_style_cond(field_name)
  423. field_name, func = co.get_field_aggregation(field_name)
  424. vals.update({'field_name': field_name,
  425. 'field_cond': '${%s}' % (field_cond or ''),
  426. 'style': '#{%s}' % (style or ''),
  427. 'style_cond': '#?%s?' % (style_cond or ''),
  428. 'is_sum': func == 'sum' and True or False,
  429. })
  430. return vals