ZH/Case-Study-01-Journal-21
From ADempiere
This Wiki is read-only for reference purposes to avoid broken links.
Contents
实施日志-21-普通报表
- 本文属于机械装备制造业进销存实施案例——ADempiere ERP案例研究之一。
- 本文记录ADempiere ERP项目实施的过程
2010-11-04
关联报表
- 今天主要测试了ADempiere的关联报表功能,这个报表的制作有点繁杂,想参照测试的新手建议从最简单的报表修改开始。
- 本测试参照HumanFlash的动画教程进行,见HumanFlash/Part8/D.Customizing Reports/4.Create New Reports(Document Lines)。
- 测试时遇到一个小问题,就是报表头与报表明细重迭了,后来发现是Print Format当中的Header Margin没有设置。设置为120后就不重迭了。
SQL语句
- SQL语句如下:
- MyProduct_V
CREATE OR REPLACE VIEW MyProduct_V AS SELECT p.M_Product_ID AS MyProduct_V_ID, p.AD_Client_ID, p.AD_Org_ID, p.isActive, p.created, p.createdby, p.updated, p.updatedby, 'en_US' AS AD_Language, p.M_Product_ID, p.value, p.name, p.M_Product_Category_ID, uom.UoMSymbol, tax.name AS TaxCategory, rl.name AS ProductType, p.volume, p.weight, p.upc, p.sku FROM M_Product p INNER JOIN C_UoM uom ON ( uom.C_UoM_ID = p.C_UoM_ID ) INNER JOIN C_TaxCategory tax on (tax.C_TaxCategory_ID = p.C_TaxCategory_ID) INNER JOIN AD_Ref_List rl ON ( rl.value = p.ProductType AND rl.AD_Reference_ID =270);
- MyProduct_VT
CREATE OR REPLACE VIEW MyProduct_VT AS SELECT p.M_Product_ID AS MyProduct_V_ID, p.AD_Client_ID, p.AD_Org_ID, p.isActive, p.created, p.createdby, p.updated, p.updatedby, pt.ad_language AS AD_Language, p.M_Product_ID, p.value, pt.name, p.M_Product_Category_ID, uomt.UoMSymbol, taxt.name AS TaxCategory, rlt.name AS ProductType, p.volume, p.weight, p.upc, p.sku FROM M_Product p INNER JOIN M_Product_Trl pt ON (pt.M_Product_ID = p.M_Product_ID ) INNER JOIN C_UoM uom ON ( uom.C_UoM_ID = p.C_UoM_ID ) INNER JOIN C_UoM_Trl uomt ON (uomt.c_uom_id = uom.c_uom_id) INNER JOIN C_TaxCategory tax ON (tax.C_TaxCategory_ID = p.C_TaxCategory_ID) INNER JOIN C_TaxCategory_Trl taxt ON (tax.C_TaxCategory_ID = taxt.C_TaxCategory_ID) INNER JOIN AD_Ref_List rl ON ( rl.value = p.ProductType AND rl.AD_Reference_ID =270) INNER JOIN AD_Ref_List_Trl rlt ON ( rlt.AD_Ref_List_ID = rl.AD_Ref_List_ID );
- MyProductLine_V
CREATE OR REPLACE VIEW MyProductLine_V AS SELECT pb.AD_Client_ID, pb.ad_org_id, pb.isactive, pb.created, pb.createdby, pb.updated, pb.updatedby, 'en_US' AS AD_Language, pb.M_Product_ID, pb.BomQty, pb.Line, pb.Description, p.value, p.name AS BOMProduct, uom.UoMSymbol, rl.name AS BomType FROM M_Product_BOM pb INNER JOIN M_Product p ON (pb.M_ProductBOM_ID = p.m_product_id) INNER JOIN c_uom uom ON ( uom.c_uom_id = p.c_uom_id ) INNER JOIN ad_ref_list rl ON ( rl.value = pb.bomtype AND rl.ad_reference_id =279);
- MyProductLine_VT
CREATE OR REPLACE VIEW MyProductLine_VT AS SELECT pb.AD_Client_ID, pb.ad_org_id, pb.isactive, pb.created, pb.createdby, pb.updated, pb.updatedby, pt.AD_Language AS AD_Language, pb.M_Product_ID, pb.BomQty, pb.Line, pb.Description, p.value, pt.name AS BOMProduct, uomt.UoMSymbol, rlt.name AS BomType FROM M_Product_BOM pb INNER JOIN M_Product p ON (pb.M_ProductBOM_ID = p.m_product_id) INNER JOIN M_Product_trl pt ON (pt.M_Product_ID = p.m_product_id) INNER JOIN c_uom uom ON ( uom.c_uom_id = p.c_uom_id ) INNER JOIN c_uom_trl uomt ON ( uomt.c_uom_id = uom.c_uom_id ) INNER JOIN ad_ref_list rl ON ( rl.value = pb.bomtype AND rl.ad_reference_id =279) INNER JOIN ad_ref_list_trl rlt ON ( rlt.ad_ref_list_id = rl.ad_ref_list_id);
讨论栏
一楼-不建议用View写报表
- 不建議一開始就偷懶用 View 來寫報表.
- 因為當資料是 : 萬筆*萬筆*萬筆 JOIN, 時資料庫會很慢很慢.
- 這是我們在大量資料的公司實際上線後的基本教條.嚴禁用 View 寫報表,除非他沒有 Join.
- 建議使用資料庫 StoredProcedure 傳入參屬限制 JOIN 範圍.
- ADempiere 近來的方向,將所有 StoredProcedure 幾乎都移除.請參考 Compiere 3.0之前的版本.
- ADempiere 近來的方向,並不是以中大型企業大量資料每日千筆交易以上交易量.因此沒人討論到速度問題.
- 我們的主要服務對象是在每日萬筆資料或千筆交易量的企業,我們大量使用 StoredProcedure.
- 我們可能是唯一將 ADempiere 用於中大型企業, 所以我們仿效 SAP ECC6.0 架構大量使用 StoredProcedure.
- --Albertachen
二楼
- 谢谢Albertachen的提醒!但是我有个疑问,写报表不用View的话用什么?我只找到这篇文章数据库 SQL千万级数据规模处理概要。--Peanut
2010-11-06
报表中文显示
- 今天在职员的计算机浏览器对销售订单的报表进行测试,报表是以PDF格式生成的,打开后发现中文都显示为一个个方框。于是对服务器进行设置。
1. 首先检查使用中的JVM版本。
$ java -version
2. 发现是OpenJDK。于是执行以下命令转为SunJDK。
# update-alternatives --config java
3. 安装中文字体
# aptitude install ttf-wqy-zenhei
4. 设置JVM中文字体
# cd /usr/lib/jvm/java-6-sun/jre/lib/ # mkdir fonts/fallback # ln -s /usr/share/fonts/truetype/wqy/wqy-zenhei.ttc fonts/fallback/wqy-zenhei.ttf
5. 系统退出帐户重新登录即可,重新启动JBOSS。
6. 在职员的计算机再次进行测试,中文正常显示!
讨论栏
2010-11-08
讨论-关于复杂报表
一楼-原有报表很垃圾
打印格式没有用过,我一直认为adempiere系列中的报表(除了财务报表)很垃圾,所以使用的都是jasperreports的扩展,建议你也不要使用打印格式。
--2010年11月08日 aoslee
二楼-布署JasperReports
谢谢aoslee的建议!我接下来会布署JasperReports。利用ADempiere自身Report功能来设置复杂报表的确比较费事。--Peanut
三楼-善用StoredProcedure
> 利用ADempiere自身Report功能来设置复杂报表的确比较费事。
其實如果你善用 StoredProcedure (Oracle/PostgresDB)
可以讓 Master/Detail(兩階或是三階/四階統計表)簡單串接.
以下簡單案例 :
-- Function: adempiere.t_rj_productbp(numeric) -- DROP FUNCTION adempiere.t_rj_productbp(numeric); CREATE OR REPLACE FUNCTION adempiere.t_rj_productbp(p_ad_pinstacne_id numeric) RETURNS numeric AS $BODY$ DECLARE cur_parameter record; cur_1 record; v_resultstr VARCHAR (2000); v_message VARCHAR (2000); v_result numeric := 1; v_record_id numeric; v_ad_user_id numeric; p_date date; p_date_to date; p_c_bpartner_id numeric; p_c_bpartner_id_to numeric; p_m_product_id numeric; p_m_product_id_to numeric; v_nextno numeric; p_pdvalue_x VARCHAR (40); p_pdvalue VARCHAR (40); p_pdvalue_to VARCHAR (40); p_bpvalue_x VARCHAR (40); p_bpvalue VARCHAR (40); p_bpvalue_to VARCHAR (40); BEGIN p_date := null; p_date_to := null; p_c_bpartner_id :=0; p_c_bpartner_id_to :=0; p_m_product_id :=0; p_m_product_id_to :=0; FOR cur_parameter IN SELECT i.record_, i.ad_user_id, i.parametername, p.p_string, p.p_string_to, p.p_number, p.p_number_to, p.p_date , p.p_date_to FROM adempiere.ad_pinstance i LEFT OUTER JOIN adempiere.ad_pinstance_para p ON( i.ad_pinstance_id = p.ad_pinstance_id) WHERE i.ad_pinstance_id = p_ad_pinstacne_id ORDER BY p.SeqNo LOOP v_record_id := cur_parameter.Record_id; v_ad_user_id := cur_parameter.ad_user_id; IF (cur_parameter.parametername = 'DateOrdered' ) THEN p_date := cur_parameter.p_date; p_date_to := cur_parameter.p_Date_TO; ELSIF (cur_parameter.parametername = 'C_BPartner_ID') THEN p_c_bpartner_id := cur_parameter.p_number; p_c_bpartner_id_to := cur_parameter.p_number_to; ELSIF (cur_parameter.parametername = 'M_Product_ID' ) THEN p_m_product_id := cur_parameter.p_number; p_m_product_id_to := cur_parameter.p_number_to; -- ELSE -- DBMS_OUTPUT.put_line ('*** Unknown Parameter=' || P.parametername); END IF; END LOOP; BEGIN--將客戶內碼(ID)改為:客戶編號(Value) IF (p_c_bpartner_id > 0) THEN SELECT value INTO p_bpvalue FROM c_bpartner WHERE c_bpartner_id=p_c_bpartner_id; ELSE p_bpvalue := ''; END IF; EXCEPTION WHEN OTHERS THEN p_bpvalue := ''; -- RAISE NOTICE '%',SQLERRM; END; BEGIN--將客戶內碼(ID)改為:客戶編號(Value) IF (p_c_bpartner_id_to > 0) THEN SELECT value INTO p_bpvalue_to FROM c_bpartner WHERE c_bpartner_id=p_c_bpartner_id_to; ELSE p_bpvalue_to := ''; END IF; EXCEPTION WHEN OTHERS THEN p_bpvalue_to := ''; -- RAISE NOTICE '%',SQLERRM; END; BEGIN --將產品內碼(ID)改為:產品編號(Value) IF (p_m_product_id > 0) THEN SELECT value INTO p_pdvalue FROM m_product WHERE m_product_id=p_m_product_id; ELSE p_pdvalue := ''; END IF; EXCEPTION WHEN OTHERS THEN p_pdvalue := ''; -- RAISE NOTICE '%',SQLERRM; END; BEGIN --將產品內碼(ID)改為:產品編號(Value) IF (p_m_product_id_to > 0) THEN SELECT value INTO p_pdvalue_to FROM m_product WHERE m_product_id=p_m_product_id_to; ELSE p_pdvalue_to := ''; END IF; EXCEPTION WHEN OTHERS THEN p_pdvalue_to := ''; -- RAISE NOTICE '%',SQLERRM; END; if p_bpvalue > b_bpvalue_to then p_bpvalue_x := p_bpvalue_to; p_bpvalue_to := p_bpvalue; p_bpvalue := b_bpvalue_x; end if; if p_pdvalue > b_pdvalue_to then p_pdvalue_x := p_pdvalue_to; p_pdvalue_to := p_pdvalue; p_pdvalue := p_pdvalue_x; end if; --要用客戶編號 Value 區間篩選客戶(註:用客戶內碼 ID 將引發區段錯亂) FOR cur_1 IN SELECT p.ad_client_id,p.ad_org_id, p.m_product_id, p.value AS pdvalue, p.name AS pdname, b.c_bpartner_id, b.value AS bpvalue, b.name AS bpname FROM adempiere.m_product p LEFT OUTER JOIN adempiere.c_orderline ol ON( p.m_product_id = ol.m_product_id) LEFT OUTER JOIN adempiere.c_order o ON( ol.c_order_id = o.c_order_id) LEFT OUTER JOIN adempiere.c_bpartner b ON( o.c_bpartner_id = bp.c_bpartner_id) WHERE 1=1 AND (p_pdvalue ='' OR p.value BETWEEN p_pdvalue AND p_pdvalue_to) AND (p_bpvalue ='' OR b.value BETWEEN p_bpvalue AND p_bpvalue_to) ORDER BY p.value,b.value LOOP v_nextno := adempiere.ad_sequence_next('T_RJ_ProductBP','Y'); INSERT INTO adempiere.t_rj_productbp (ad_pinstance_id ,-- numeric(10,0), t_rj_productbp_id ,-- numeric(10,0), ad_client_id ,-- numeric(10,0), ad_org_id ,-- numeric(10,0), isactive ,-- char(1), created ,-- date, createdby ,-- numeric(10,0), updated ,-- date, updatedby ,-- numeric(10,0), m_product_id ,-- numeric(10,0), pdvalue ,-- varchar(30), pdname ,-- varchar(60), c_bpartner_id ,-- numeric(10,0), bpvalue ,-- varchar(30), bpname -- varchar(60), )VALUES( p_ad_pinstance_id, v_nextno, cur_1.ad_client_id, cur_1.ad_org_id, 'Y',SYSDATE,0,SYSDATE,0, cur_1.m_product_id, cur_1.pdValue, cur_1.pdName, cur_1.bpartner_id, cur_1.bpvalue, cur_1.bpname ); END LOOP; RETURN 0; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION adempiere.t_rj_productbp(numeric) OWNER TO adempiere;
--Albert :: Skype: Adempiere/Compiere
四楼
谢谢Albertachen的详细补充!
JasperReports和iReport的优势是使报表设计的灵活、快捷、美观。还可以很方便地生成各种图表。
StoredProcedure看起来很强大,我将来会学习如何使用的。
--Peanut