- 首先定義菜單然后是菜單動(dòng)作 然后初始化一個(gè)報(bào)表動(dòng)作
<!-- 菜單視圖 出庫憑證單據(jù)報(bào)表-->
<record id="action_stock_out_voucher_report" model="ir.actions.act_window">
<field name="name">Stock Out Voucher Report</field>
<field name="res_model">kthrp.chanyi.stock.out.voucher.report</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<!-- 菜單視圖 出庫憑證單據(jù)報(bào)表-->
<menuitem name="Stock Out Voucher Report"
action="action_stock_out_voucher_report"
id="chanyi_menu_stock_out_voucher_report"
parent="kthrp_stock.menu_stock_out_in_query_report"
sequence="40"/>
<!-- 報(bào)表-->
<record id="kthrp_chanyi_stock_out_voucher_report_xlsx" model="ir.actions.report.xml">
<field name="name">Chanyi Stock Out Voucher Report</field>
<field name="model">kthrp.chanyi.stock.out.voucher.report</field>
<field name="type">ir.actions.report.xml</field>
<field name="report_name">kthrp.chanyi.stock.out.voucher.report.xlsx</field>
<field name="report_type">xlsx</field>
<field name="auto" eval="False"/>
</record>
2.首先定義瞬時(shí)模型和需要的字段
class KthrpChanyiStockOutVoucher(models.TransientModel):
_name = "kthrp.chanyi.stock.out.voucher.report"
_description = "chanyi Kthrp Stock Out Voucher Report"
# 客戶
customer_id = fields.Many2one(string="Customer", comodel_name="kthrp.base.global.partner", domain="[('customer','=',True)]")
# 公司
company_id = fields.Many2one(string='Company', comodel_name="res.company", default=lambda self: self.env.user.company_id.id)
# 處理日期自
date_from = fields.Datetime('Processing Date from')
# 處理日期至
date_to = fields.Datetime('Processing Date to')
# 輸出格式
output_format = fields.Selection([('excel', 'EXCEL')], 'Output Format', default='excel', readonly=True)
# 產(chǎn)品類別
product_category_ids = fields.Many2many(comodel_name='product.category', string='Product Category')
3.定義頁面參數(shù)獲取方法
@api.model
def get_datas(self):
tmp_from = datetime.strptime(self.date_from, "%Y-%m-%d %H:%M:%S")
date_from = (tmp_from + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S")
tmp_to = datetime.strptime(self.date_from, "%Y-%m-%d %H:%M:%S")
date_to = (tmp_to + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S")
form = {
'lang': self.env.context['lang'],
'customer_id': self.customer_id,
'company_id': self.company_id,
'product_category_ids': self.product_category_ids,
'date_from': date_from,
'date_to': date_to,
'output_format': self.output_format
}
datas = {
'form': form,
}
return datas
4.獲取到參數(shù)之后再通過參數(shù)過濾得到需要的數(shù)據(jù)
@api.model
def get_lines(self, datas):
customer_id = datas['form']['customer_id']
company_id = datas['form']['company_id']
product_category_ids = datas['form']['product_category_ids']
date_from = datas['form']['date_from']
date_to = datas['form']['date_to']
# 以銷售出庫的產(chǎn)品為維度
# self.env['stock.move'].search([('state', '=', 'done')])
stock_move_obj = self.env['stock.move']
code_list = []
for rec in stock_move_obj.search([]):
code_list.append(rec.supplier_id.company_code)
convert = self.env['kthrp.stock.unit.convert']
# 客戶=庫存移動(dòng)對(duì)應(yīng)業(yè)務(wù)伙伴 庫存移動(dòng)狀態(tài)完成 事務(wù)處理類型=庫房出庫
domain = [('supplier_id.company_code', '=', customer_id.partner_number), ('state', '=', 'done'), ('transaction_type_id.code', '=', 'Stock Shipment')]
# domain = [('transaction_type_id.code', '=', 'Stock Shipment'), ('state', '=', 'done')]
if company_id:
domain += [('company_id', '=', company_id.id)]
if product_category_ids:
centralized_cls_ids = []
for rec in product_category_ids:
centralized_cls_ids.append(rec.centralized_cls_id.id)
domain += [('centralized_cls_id', 'in', centralized_cls_ids)]
if date_from:
domain += [('date', '>=', date_from)]
if date_to:
domain += [('date', '<=', date_to)]
lines = stock_move_obj.search(domain)
field_dict = {}
for line in lines:
ratio = convert.convert_unit_ratio(line.product_id.id, line.product_id.uom_id.id,
line.actual_unit_id.id)
product_number = line.product_id.product_number
# 如果產(chǎn)品編號(hào)不在字典中 添加到字典中
if product_number not in field_dict.keys():
field_dict[product_number] = line.actual_qty * ratio
else:
field_dict[product_number] += line.actual_qty * ratio
datalist = []
field_list = []
# 序號(hào)
number = 1
for line in lines:
record = {}
product_number = line.product_id.product_number
# 如果該產(chǎn)品不在產(chǎn)品編碼列表中
if product_number not in field_list:
record['origin'] = number
record['product_number'] = line.product_id.product_number
record['product_id'] = line.product_id.name
record['specification'] = line.specification or ''
record['actual_qty'] = round(field_dict[product_number], 2)
record['actual_unit_id'] = line.actual_unit_id.name
datalist.append(record)
number += 1
field_list.append(product_number)
# 分頁
datalist = [datalist[i:i + 10] for i in range(0, len(datalist), 10)]
return datalist
- 還有兩個(gè)關(guān)鍵方法 查看方法 和 下載方法走趋,第一個(gè)是查看第二個(gè)是下載
@api.multi
def report_view(self):
datas = self.get_datas()
lines = self.get_lines(datas)
# 上下文攜帶數(shù)據(jù)
context = {}
context['customer_id'] = self.customer_id.name
context['date_from'] = datas['form']['date_from']
context['date_to'] = datas['form']['date_to']
context['name'] = _('Stock Out Voucher Report')
context['lines'] = lines
return {
'name': _('Stock Out Voucher Report'),
'type': 'ir.actions.client',
'tag': 'stock_out_voucher_report',
'context': context,
}
@api.multi
def report_print(self):
name = _('Stock Out Voucher Report')
report_name = 'kthrp.chanyi.stock.out.voucher.report.xlsx'
return {
'name': name,
'type': 'ir.actions.report.xml',
'report_name': report_name,
}
6.定義解析類和打印數(shù)據(jù)的類
_ir_translation_name = 'stock.out.voucher.report.xlsx'
class KthrpChanyiStockOutVoucherReportParse(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(KthrpChanyiStockOutVoucherReportParse, self).__init__(cr, uid, name, context=context)
self.context = context
template_changes = {}
self.localcontext.update({
'datetime': datetime,
'wanted_list': [],
'template_changes': template_changes,
'_': self._,
})
def _(self, src):
lang = self.context.get('lang', 'en_US')
return translate(self.cr, _ir_translation_name, 'report', lang, src) or src
class KthrpChanyiStockOutVoucherReportXLSX(ReportXlsxDevelop):
def generate_xlsx_report(self, wb, data, objs):
# 獲取數(shù)據(jù)
data_para = objs.get_datas()
lines_list = objs.get_lines(data_para)
def get_lang_value(values):
lang = self.env.user.lang
if lang == 'zh_CN':
return values[1]
else:
return values[0]
# 獲取樣式(詳見_get_format方法)
general_formats = self._get_format(wb)
# 列標(biāo)題 general_formats['rh_header_format']
other_head_left_format = wb.add_format(self.union(self.font_style, {'align': 'left', 'bold': True}))
other_head_right_format = wb.add_format(self.union(self.font_style, {'align': 'right', 'bold': True}))
# 文本格式
font_format_left = {'align': 'left', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
'border_color': 'black', }
font_format_left = wb.add_format(font_format_left)
font_format_right = {'align': 'right', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
'border_color': 'black', }
font_format_right = wb.add_format(font_format_right)
font_format_center = {'align': 'center', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
'border_color': 'black', }
font_format_center = wb.add_format(font_format_center)
# 設(shè)置頁簽
ws = wb.add_worksheet(get_lang_value([u'Stock Out Voucher Report', u'出庫憑證']))
blue_fields = [['Origin', u'序號(hào)'], ['Product Number', u'產(chǎn)品編碼'],
['Product', u'產(chǎn)品'], ['Specification', u'規(guī)格'],
['Qty', u'數(shù)量'], ['Unit', u'單位']]
# fields = ['origin', 'product_number', 'product_id', 'specification', 'actual_qty', 'actual_unit_id']
# 設(shè)置列寬
colums_size = [30, 30, 20, 30, 30, 20]
length = len(colums_size)
for col in range(length):
ws.set_column(col, col, colums_size[col])
row_pos = 0
col_pos = 0
if lines_list:
# 打印數(shù)據(jù)(數(shù)據(jù)格式為列表嵌套字典)
for index, lines in enumerate(lines_list):
# 打印標(biāo)題
row_pos += 1
ws.merge_range(row_pos, col_pos, row_pos, length - 1,
get_lang_value(
[u'Stock Out Voucher Report', u'%s出庫憑證' % data_para['form']['company_id'].name]),
general_formats['title_format'])
row_pos += 1
# 打印表頭
# merge_range寫入蝙搔,參數(shù)(行號(hào), 合并起列號(hào), 行號(hào), 合并至列號(hào), 打印數(shù)據(jù), 格式)
# ws.merge_range(row_pos, 0, row_pos, 1, get_lang_value([u'Customer:', u'客戶:']) + data_para['form']['customer_id'].name,
# other_head_left_format)
ws.write_rich_string(row_pos, col_pos,
general_formats['font_bold_format'],
get_lang_value([u'Customer:', u'客戶:']),
general_formats['font_format'],
data_para['form']['customer_id'].name,
wb.add_format({'align': 'left'}))
value = u'第%d頁/共%d頁' % (index + 1, len(lines_list))
ws.write(row_pos, 5, get_lang_value([u'Number', value]), general_formats['font_format'])
# ws.merge_range(row_pos, col_pos, general_formats['font_format'])
row_pos += 1
ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'],
get_lang_value([u'Date From:', u'處理日期自:']),
general_formats['font_format'], data_para['form']['date_from'],
wb.add_format({'align': 'left'}))
ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_format'],
get_lang_value([u'Date To::', u'處理日期至:']),
general_formats['font_right_format'], data_para['form']['date_to'],
wb.add_format({'align': 'right'}))
row_pos += 1
# 設(shè)置標(biāo)題欄名稱,寬度
columns = []
for field in blue_fields:
columns.append((field[1], 20))
# 打印標(biāo)題欄
for i, column in enumerate(columns):
ws.set_column(col_pos + i, col_pos + i, column[1])
ws.write(row_pos, col_pos + i, column[0], general_formats['rh_header_format'])
row_pos += 1
# 固定標(biāo)題
ws.freeze_panes(row_pos, 0)
for line in lines:
ws.write(row_pos, 0, line['origin'], font_format_center)
ws.write(row_pos, 1, line['product_number'], font_format_left)
ws.write(row_pos, 2, line['product_id'], font_format_left)
ws.write(row_pos, 3, line['specification'], font_format_left)
ws.write(row_pos, 4, line['actual_qty'], font_format_right)
ws.write(row_pos, 5, line['actual_unit_id'], font_format_left)
row_pos += 1
# 打印報(bào)表信息(表尾)(固定打有襞:打印人辛燥,打印時(shí)間)
ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'], _('Printer:'),
general_formats['font_format'], objs.env.user.related_employee_id.name_get()[0][1])
ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_right_format'], _('Print Time:')
, general_formats['font_right_format'], get_context_datetime(objs, fields.Datetime.now()),
wb.add_format({'align': 'right'}))
# 首行留空
row_pos += 1
else:
# 打印標(biāo)題
row_pos += 1
ws.merge_range(row_pos, col_pos, row_pos, length - 1,
get_lang_value(
[u'Stock Out Voucher Report', u'%s出庫憑證' % data_para['form']['company_id'].name]),
general_formats['title_format'])
row_pos += 1
# 打印表頭
# merge_range寫入磷瘤,參數(shù)(行號(hào), 合并起列號(hào), 行號(hào), 合并至列號(hào), 打印數(shù)據(jù), 格式)
# ws.merge_range(row_pos, 0, row_pos, 1, get_lang_value([u'Customer:', u'客戶:']) + data_para['form']['customer_id'].name,
# other_head_left_format)
ws.write_rich_string(row_pos, col_pos,
general_formats['font_bold_format'],
get_lang_value([u'Customer:', u'客戶:']),
general_formats['font_format'],
data_para['form']['customer_id'].name,
wb.add_format({'align': 'left'}))
ws.write(row_pos, 5, get_lang_value([u'Number', u'第1頁/共1頁']), general_formats['font_format'])
# ws.merge_range(row_pos, col_pos, general_formats['font_format'])
row_pos += 1
ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'],
get_lang_value([u'Date From:', u'處理日期自:']),
general_formats['font_format'], data_para['form']['date_from'],
wb.add_format({'align': 'left'}))
ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_format'],
get_lang_value([u'Date To::', u'處理日期至:']),
general_formats['font_right_format'], data_para['form']['date_to'],
wb.add_format({'align': 'right'}))
row_pos += 1
# 設(shè)置標(biāo)題欄名稱敏晤,寬度
columns = []
for field in blue_fields:
columns.append((field[1], 20))
# 打印標(biāo)題欄
for i, column in enumerate(columns):
ws.set_column(col_pos + i, col_pos + i, column[1])
ws.write(row_pos, col_pos + i, column[0], general_formats['rh_header_format'])
row_pos += 1
# 固定標(biāo)題
ws.freeze_panes(row_pos, 0)
# 打印報(bào)表信息(表尾)(固定打咏暗酢:打印人威根,打印時(shí)間)
ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'], _('Printer:'),
general_formats['font_format'], objs.env.user.related_employee_id.name_get()[0][1])
ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_right_format'],
_('Print Time:')
, general_formats['font_right_format'],
get_context_datetime(objs, fields.Datetime.now()),
wb.add_format({'align': 'right'}))
KthrpChanyiStockOutVoucherReportXLSX('report.kthrp.chanyi.stock.out.voucher.report.xlsx', 'kthrp.chanyi.stock.out.voucher.report',
parser=KthrpChanyiStockOutVoucherReportParse)
解析類是固定格式,只用修改類名即可屏积,固定格式
7.上面是下載邏輯医窿,接下來所示查看的邏輯,在上述定義了查看方法之后炊林,對(duì)應(yīng)的會(huì)有一個(gè)js動(dòng)作
odoo.define('kthrp_chanyi_ext.stock_out_voucher_report', function (require) {
"use strict";
var core = require('web.core');
var Widget = require('web.Widget');
var Model = require('web.Model');
var data = require('web.data');
var QWeb = core.qweb;
var StockOutVoucherReport = Widget.extend({
init: function (parent, context) {
this._super(parent);
if (context.context.active_id) {
this.report_id = context.context.active_id;
sessionStorage.setItem("report_id", this.report_id);
}
else {
this.report_id = parseInt(sessionStorage.getItem("report_id"));
}
this.context = context.context;
},
start:function () {
var self = this;
var context = self.context;
this.$el.append(QWeb.render("StockOutVoucherReport",{
widget: this,
name: context.name,
customer_id: context.customer_id,
date_from: context.date_from,
date_to: context.date_to,
lines: context.lines,
}
));
this.$("button").click(function () {
var model_name = "kthrp.chanyi.stock.out.voucher.report";
var report_model = new Model(model_name);
report_model.call("report_print",[self.report_id])
.then(function (action) {
action.context = {
'active_id': self.report_id,
'active_model': 'kthrp.chanyi.stock.out.voucher.report',
'active_ids': [self.report_id]
};
self.do_action(action);
});
});
},
});
core.action_registry.add('stock_out_voucher_report', StockOutVoucherReport);
})
通過js動(dòng)作打開對(duì)應(yīng)的模板文件姥卢,然后渲染出來
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="StockOutVoucherReport">
<div style="margin-left:8px;font-size:20px;border-bottom: 1px solid #cacaca;color:gray;margin-top:2.2px;height:35px;margin-right:8px">
<span t-esc="name"/>
<button type="button" style="float:right;display: inline-block;margin-right:5%;margin-bottom:2.2px;" class="btn btn-primary btn-sm payable-supplier-aging-download">Download</button>
</div>
<t>
<div style="line-height:40px;">
<span style="margin-left: 20px;">Customer:</span>
<span style="margin-left:8px;display: inline-block;"><t t-esc="customer_id"/></span>
</div>
<div style="line-height:40px;">
<span style="margin-left: 20px;">Date From:</span>
<span style="margin-left:8px;display: inline-block;"><t t-esc="date_from"/></span>
<span style="float:right;margin-right: 20px;">
<span>Date To:</span>
<span style="margin-left:8px;display: inline-block;"><t t-esc="date_to"/></span>
</span>
</div>
<div style="height: 100%;position: absolute;width:100%;padding-bottom:80px">
<div class="account_report_table_wrapper" style="overflow:auto;height: 100%;position:relative;margin-left:5px">
<table class="o_list_view table table-condensed table-striped table-expandable-wang" style="margin-left: 1px;width: 99.9%;">
<thead style="background:#D9D9D9;width:100%">
<tr>
<th>Origin</th>
<th>Product Number</th>
<th>Product</th>
<th>Specification</th>
<th>Qty</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
<t t-if="lines">
<t t-foreach="lines" t-as="line">
<t t-foreach="line" t-as="rec">
<tr>
<td align="center" style="border: 1px solid;"><span t-esc="rec['origin']"/></td>
<td align="left" style="border: 1px solid;"><span t-esc="rec['product_number']"/></td>
<td align="left" style="border: 1px solid;"><span t-esc="rec['product_id']"/></td>
<td align="left" style="border: 1px solid;"><span t-esc="rec['specification']"/></td>
<td align="right" style="border: 1px solid;"><span t-esc="rec['actual_qty']"/></td>
<td align="left" style="border: 1px solid;"><span t-esc="rec['actual_unit_id']"/></td>
</tr>
</t>
</t>
</t>
</tbody>
</table>
</div>
</div>
</t>
</t>
</templates>
記住,這兩個(gè)文件都是定義在static文件目錄下的
js文件需要引用聲明渣聚, 類似于以下方式
<script type="text/javascript"
src="/kthrp_base/static/lib/Resources/dynamsoft.webtwain.config.js"/>