Prerequisites
- Operating system: Windows
- Java version 8
- SGB Auto Export application.
- Download: ...
- Altove MapForce
- Altova XmlSpy:
Reference Document
Working Process Export:
Installation Procedure
Sau khi đã download tập tin zip của ứng dụng SGB Auto Export về, hãy chép nó lên ổ đĩa bạn muốn lưu trữ và giải nén nó. Tôi sẽ lưu trữ ứng dụng tại thư mục "C:\Application" và sẽ sử dụng đường dẫn này để mô tả trong xuyên xuốt bài hướng dẫn.Tiếp theo mở tập tin "C:\Application\SGBAutoExport\application\Configuration" để cấu hình cho ứng dụng theo bảng thông số bên dưới:
Name | Example | Description |
---|---|---|
PostgreSQL.Url | jdbc:postgresql://localhost:5432/postgres | |
PostgreSQL.Schema | sgb_soft_mrp | |
PostgreSQL.Username | postgres | |
PostgreSQL.Password | 0123456789 | |
Export.Loop | 10 | |
Mail.SMTP.Send.Enable | true or false | |
Mail.SMTP.Send.When | error or any | |
Mail.SMTP.Host | smtp.gmail.com | |
Mail.SMTP.Port | 587 | |
Mail.SMTP.Auth | true or false | |
Mail.SMTP.Starttls.Enable | true or false | |
Mail.SMTP.Username | liaudio@gmail.com | |
Mail.SMTP.Password | test1986! | |
Mail.SMTP.From | liaudio@gmail.com | |
Mail.SMTP.To | bnson.1986@gmail.com | |
Mail.SMTP.Subject | [AutoExport][Project_Name] | |
Export.Type | Có 3 option: - image: hình nào xong thì xuất hình đó. - folder_import: folder import nào xong thì xuất folder đó. - folder_image: folder chứa các image đã làm xong thì xuất. |
Database
Chọn một dự án nằm trong hệ thống SGB Data Capture để cài đặt các function bên dưới. Trong bài hướng dẫn tôi sẽ chọn dự án "sgb_soft_mrp" để thực hiện hướng dẫn.Nhấn vào biểu tượng (SQL - Execute arbitray SQL queries), sau đó copy và run lần lượt các tập lệnh SQL của 3 function sql bên dưới.
1. Tạo bảng export_info
-- Table: bnson.export_info
-- DROP TABLE bnson.export_info;
CREATE TABLE sgb_soft_mrp.export_info
(
id serial NOT NULL,
export_time_start timestamp without time zone,
export_time_end timestamp without time zone,
export_content character varying NOT NULL,
export_folder_path character varying NOT NULL,
export_file_name character varying NOT NULL,
export_type_id integer NOT NULL,
export_type_name character varying NOT NULL,
export_by_index integer NOT NULL,
comment character varying(255),
CONSTRAINT export_info_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE bnson.export_info
OWNER TO ideas_bnson;
3. Tạo bảng export_column_by_query
Table này dùng để định nghĩa các column có dữ liệu chỉnh sửa, biến đổi mà trong Altova Mapforce khó định nghĩa. Ví dụ như cắt tên Folder Import hoặc tên của Folder chứa image.
CREATE TABLE sgb_soft_mrp.export_column_by_query
(
column_name character varying NOT NULL,
sql_query character varying NOT NULL,
CONSTRAINT prm_column_name PRIMARY KEY (column_name)
)
WITH (
OIDS=FALSE
);
ALTER TABLE sgb_soft_mrp.export_column_by_query
OWNER TO postgres;
Isert 2 định nghĩa để lấy tên Folder_Import và Folder_Image:
INSERT INTO sgb_soft_mrp.export_column_by_query(column_name, sql_query) VALUES ('folder_download', 'REVERSE(SUBSTRING(REVERSE(download_info.filename), POSITION('.' IN REVERSE(download_info.filename)) + 1)) AS "ecbq.folder_download"');
INSERT INTO sgb_soft_mrp.export_column_by_query(column_name, sql_query) VALUES ('folder_image', 'REVERSE(LEFT(REVERSE(management.filepath), POSITION(''/'' IN REVERSE(management.filepath)) - 1)) AS "ecbq.folder_image"');
4. Tạo bảng upload_info
-- Table: bnson.upload_info
-- DROP TABLE bnson.upload_info;
CREATE TABLE bnson.upload_info
(
id serial NOT NULL,
export_id serial NOT NULL,
upload_time_start timestamp without time zone,
upload_time_end timestamp without time zone,
upload_to character varying,
upload_status boolean,
zip_status boolean,
encrypt_status boolean,
comment character varying(255),
CONSTRAINT upload_pkey PRIMARY KEY (id)
)
WITH (
OIDS=TRUE
);
ALTER TABLE bnson.upload_info
OWNER TO ideas_bnson;
4. export_list() function
CREATE OR REPLACE FUNCTION sgb_soft_mrp.export_list(character varying)
RETURNS refcursor AS
$BODY$
DECLARE
exportType alias FOR $1;
result refcursor;
BEGIN
IF (exportType = 'image') THEN
OPEN result FOR
SELECT form_id, id::Text
FROM sgb_soft_mrp.management
WHERE input_status = 1
AND (export_status = 0 OR export_status IS NULL)
ORDER BY id
LIMIT 100;
ELSEIF (exportType = 'folder_import') THEN
OPEN result FOR
SELECT form_id, string_agg(id::Text,',')
FROM sgb_soft_mrp.management
GROUP BY download_id,form_id
HAVING SUM(CASE WHEN (input_status = 1 AND (export_status = 0 OR export_status IS NULL)) THEN 0 ELSE 1 END) < 1
ORDER BY download_id
LIMIT 1;
ELSE
OPEN result FOR
SELECT form_id, string_agg(id::Text,',')
FROM sgb_soft_mrp.management
GROUP BY filepath, form_id, download_id
HAVING SUM(CASE WHEN (input_status = 1 AND (export_status = 0 OR export_status IS NULL)) THEN 0 ELSE 1 END) < 1
ORDER BY download_id
LIMIT 1;
END IF;
RETURN result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION sgb_soft_mrp.export_list(character varying)
OWNER TO postgres;
5. export_data(character varying)
CREATE OR REPLACE FUNCTION sgb_soft_mrp.export_data(character varying)
RETURNS character varying AS
$BODY$
DECLARE
ids alias for $1;
dataColumnName varchar;
downloadInfoColumnName varchar;
managementColumnName varchar;
result varchar;
BEGIN
SELECT column_name from (
SELECT table_name,string_agg(table_name || '.' || column_name || ' AS "' || table_name || '.' || column_name || '"',',') as column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog = 'postgres'
AND table_schema = 'sgb_soft_mrp'
AND (table_name = 'data') GROUP BY 1 ORDER BY 1) AS tmpData INTO dataColumnName;
SELECT column_name from (
SELECT table_name,string_agg(table_name || '.' || column_name || ' AS "' || table_name || '.' || column_name || '"',',') as column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog = 'postgres'
AND table_schema = 'sgb_soft_mrp'
AND (table_name = 'management') GROUP BY 1 ORDER BY 1) AS tmpManagement INTO managementColumnName;
SELECT column_name from (
SELECT table_name,string_agg(table_name || '.' || column_name || ' AS "' || table_name || '.' || column_name || '"',',') as column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog = 'postgres'
AND table_schema = 'sgb_soft_mrp'
AND (table_name = 'download_info') GROUP BY 1 ORDER BY 1) AS tmpDownloadInfo INTO downloadInfoColumnName;
--SELECT * FROM query_to_xml('SELECT * FROM sgb_soft_mrp.data WHERE data.management_id in (' || ids || ')', true, false, '')
SELECT * FROM query_to_xml('SELECT ' || dataColumnName || ',' || managementColumnName || ',' || downloadInfoColumnName || ' FROM sgb_soft_mrp.data AS data
INNER JOIN sgb_soft_mrp.management AS management ON data.management_id = management.id
INNER JOIN sgb_soft_mrp.download_info AS download_info ON management.download_id = download_info.id
WHERE management.id IN (' || ids || ')', true, false, '')
AS exportData INTO result;
RAISE NOTICE '%', result;
RETURN result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION sgb_soft_mrp.export_data(character varying) SET search_path=sgb_soft_mrp;
ALTER FUNCTION sgb_soft_mrp.export_data(character varying)
OWNER TO rls_sgb_soft_mrp;
5. export_finish(character varying)
CREATE OR REPLACE FUNCTION sgb_soft_mrp.export_finish(character varying)
RETURNS void AS
$BODY$
DECLARE
ids alias for $1;
sqlQuery varchar;
BEGIN
sqlQuery := 'UPDATE sgb_soft_mrp.management SET export_status = 1 WHERE id IN (' || ids || ');';
RAISE info '%',sqlQuery;
EXECUTE(sqlQuery);
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION sgb_soft_mrp.export_finish(character varying) SET search_path=sgb_soft_mrp;
ALTER FUNCTION sgb_soft_mrp.export_finish(character varying)
OWNER TO rls_sgb_soft_mrp;
User Guides
1. Khởi tạo template:
Trong thư mục SGBAutoExport chạy tập tin "SGBAutoExport_Generate_Template.bat" để khởi tạo các tập tin cần thiết cho việc tạo template export. Sau khi chạy xong bạn sẽ nhận được các tập tin sau:- ...\SGBAutoExport\Configuration\Templates\generalXMLToText.xslt
- Tập tin hệ thống này hỗ trợ cho việc export các loại tập tin là dạng text, không cần quan tâm.
- ...\SGBAutoExport\Configuration\Templates\DataColumnStructure.xsd
- Tập tin này được tạo từ cấu trúc bảng Data của project, ta sẽ sử dụng nó để convert dữ liệu trong bảng data thành tập tin mong muốn.
- ...SGBAutoExport\Configuration\Templates\0
- Folder 0 là folder mặc định chứa tập tin template mẫu để hỗ trợ việc định nghĩa template export XSLT.
- ...SGBAutoExport\Configuration\Templates\0\TemplateExport_1.xsd
- Tâp tin XSD template export mẫu được tạo ra dựa trên các cột của bảng Data.
2. Thiết kế XSLT:
File XSLT là file quan trọng nó sẽ quyết định dữ liêu của dự án sẽ xuất như thế nào. Phần này sẽ hướng dẫn cách thiết kế XSLT cho một số trường hợp cơ bản.2.1. Trường hợp 1:
2.1.A. Yêu cầu:
Giả định có 1 dự án yêu cầu export khi 1 record (image) được nhập xong thì sẽ export ra 1 file txt và lấy "management_id" để làm tên tập tin export và các cột sẽ được phân cách theo dấu ";".Dự án chỉ có 1 Form nhập duy nhất.
Khi export nào ngày nào thì sẽ được bỏ trong thư mục của ngày đó, ví dụ ngày "01/01/2017" export ra 3 tập tin là "001.txt, 002.txt, 003.txt" thì thư mục export sẽ có dạng là:
- 01012017/001.txt
- 01012017/002.txt
- 01012017/003.txt
2.1.B. Thiết kế:
Để thực hiện yêu cầu trên, ta sẽ định nghĩa tập XSLT Template export cho Form ID 1, mở chương trình Altova MapForce. Chú ý trước bắt đầu design bạn hãy chọn chế độ thiết kế XSLT2 trên menu icon.Tiếp theo nhấn chọn "Insert → XML Schema/File..." để insert hai tập tin:
- "Templates\DataColumnStructure.xsd"
- "Templates\1\TemplateExport_1.xsd"
Tiếp theo ta sẽ định nghĩa tên export cho tập tin, trong bài hướng dẫn này tôi giả định tập tin export sẽ có cấu trúc sau:
- D:\tmp\test\export\001\[Ngày_Hiện_Tại (DDMMYYYY)]\management_id.txt
Đầu tiên ta sẽ chọn "Insert → Constant" trong hộp thoại Insert Constant chọn String và điền giá trị là "file:///D:/tmp/test/export/001/" (lưu ý nhớ thêm "file:///" vào trước và đổi dấu phân tách "\" thành "/") như hình bên dưới.
Ta làm tương tự để tạo thêm Constant String có nội dung là ".txt".Và như cấu trúc đường dẫn export trên ta có một thư mục là ngày hiện tại để tạo được nó ta tìm trong khu vực Libraries bên trái mục "context functions → current-date" và kéo nó vào khu vực thiết kế như hình bên dưới.
Trong trường hợp không tìm thấy "current-date" function, bạn chú bên thanh icon men đã chọn chế độ design XSLT2 chưa? nếu chưa thì chọn như hình bên dưới.
Để có thể xuất dúng định dạng "DDMMYYYY" như yêu cầu ta cẩn phải convert định dạng nó lại bằng cách chọn tiếp "conversion functions → format-dateTime" trong mục Libraries.
Insert tiếp thêm một "Constant" với nội dung là "[D,2-2][M,2-2][Y,4-4]/" để định nghĩa format cho ngày tháng hiện tại.
Ok việc còn lại chỉ kéo kết nối "current-date" và "fortmat date constant" vào "format-dateTime" bằng cách nhấn vào nút tam giác nhỏ bên phải và kéo tới mục tiêu như hình bên dưới là ta đã định nghĩa xong thư mục ngày hiện tại.
Tổng kết lại ta đã có đầy đủ thông tin cho việc định đường dẫn export và tên tập tin export, việc còn lại là nối các định nghĩa này lại với nhau bằng cách sửa dụng "string function → concat" trong Libraries.
Sau khi kéo "concat" và nhấn vào biểu tượng dấu cộng nho nhỏ để thêm giá trị kết nối, và nối các thành phần đã định nghĩa trước vào, sau đó kéo "result" và dòng "File: TemplateExport_1.xml" trong bảng "TemplateExport_1" như hình bên dưới (cẩn thận thứ tự kết hợp).
File txt cần phải có một ký tự để phân tách các cột dữ liệu với nhau vì vậy ta cần phải định thêm "separator" cho nó, trường hợp nếu là export là fiel XML hoặc EXCEL bạn cũng phải để mặc định một ký tự nào đó cho nó để tránh bị lỗi phát sinh.
Insert thêm một "contact" với nội dung là ký tự ";" và map vào dòng "separator" trong bảng TemplateExport_1 như hình bên dưới.
Vậy ta đã định nghĩa xong, Nhấn save và lưu tập tin định nghĩa này lại tại đường dẫn của tập tin "TemplateExport_1.xsd" và đặt cùng tên "TemplateExport_1.mfd" để dễ quản lý sau này.
Tiếp theo ta sẽ tạo tập tin quan trong nhất là XSLT template bằng cách nhấn chọn "File → Generate code in → XSLT 2.0" và lưu tập tin này chung thư mục với các template trên.
Và đây là kết quả cuối cùng ta nhận được sau khi thiết kế template export cho form id 1.
Việc tiếp theo là chạy Auto Export theo hướng dẫn tại mục số "3. Khởi động SGBAutoExport".
2.2. Trường hợp 2:
2.2.A. Yêu cầu:
Yêu cầu sẽ tương tự như trường hợp 1, tuy nhiên làn này sẽ export theo zip (package) và lấy tên zip để đặt tên cho tập export txt.2.2.B Thiết kế:
Có nhiều cách để xử lý yêu cầu trên, phần này sẽ hướng dẫn một số cách, thông qua đó ta sẽ hiểu thêm về cách dùng các function trong Altova MapForce.*Cách 1: Cắt tên folder từ "management.filepath". Cách này chỉ nên áp dụng khi đường dẫn image cố định về chiều dài.
Giả định điều kiện dầu vào đường dẫn "filepath" của dự án là:
- /project/demo/test/import/2017-05-04/F01/A001/Image001.tif
- /project/demo/test/import/2017-05-04/F02/A002/Image001.tif
- /project/demo/test/import/2017-05-04/F02/A003/Image001.tif
- ....
Đầu tiên ta sẽ insert function "sequence functions → item-at", đây là function cho phép ta lấy giá trị của một Node tại một vị trí chỉ định, ví dụ file export có 5 dòng ta chỉ muốn lấy giá trị của Node A tại dòng dòng số 5 thì ta dùng function này.
Như trong ví dụ ta cần lấy đường dẫn folder để đặt tên cho file export thì cần phải lấy 1 đường dẫn bất kỳ trong node "management.filepath" thì ta sẽ kết nối node này vào "item-at - nodes/rows", sau đó tạo thêm 1 constant number để xác định vị cần lấy và kết nối vào "iem-at - postion" như hình bên dưới.
Như vây thông qua bước trên ta đã lấy được "filepath" của record đầu tiên để định nghĩa tên file name export, tiếp theo ta chỉ cần insert "string function → substring" function để cắt đường dẫn lấy tên folder, theo giả định "filepath" đầu vào ở trên thì ta sẽ định nghĩa như sau:Như trong ví dụ ta cần lấy đường dẫn folder để đặt tên cho file export thì cần phải lấy 1 đường dẫn bất kỳ trong node "management.filepath" thì ta sẽ kết nối node này vào "item-at - nodes/rows", sau đó tạo thêm 1 constant number để xác định vị cần lấy và kết nối vào "iem-at - postion" như hình bên dưới.
Tới đây đã hoàn thành việc cắt lấy folder name để làm tên file export giờ ta chỉ việc kết hợp nó và "concat" function để định nghĩa file name là được, về tổng thể thì nó sẽ như hình bên dưới đây.
Công việc còn lại chỉ save design lại rùi tạo file XSLT (File → Generate code in → xslt 2) và chạy auto export.
*Cách 2: Tương tự như cách 1 ta cũng cắt một "filepath" để, tuy nhiên vấn đề là tên folder không cố định về chiều dài, như ví dụ bên dưới.
- /project/demo/test/import/2017-05-04/F01/A001/Image001.tif
- /project/demo/test/import/2017-05-04/F002/A002/Image001.tif
- /project/demo/test/import/2017-05-04/F0003/A003/Image001.tif
- ...
Tương tự như cách một ta dùng các function "item-at, substring" để lấy filepath của record đầu tiên, tiếp theo ta sẽ thay thế "substring" function bằng "string functions → tokenize" như hình bên dưới.
"tokenize" là function cho phép cắt 1 chuỗi thành 1 một mảng (array) dựa trên dấu phân tách (delimiter), ví dụ với "filepath" trên sau khi dùng tokenize với đấu phân tách thì nó sẽ cho ra kết quả là:
- [, project, demo, test, import, 2017-05-04, F01, A001, Image001.tif]
Vấn đề đặt ra là làm sao lấy được phần tử (element) "F01" để đặt tên cho tập tin export? Ta sử dụng tiếp "sequence functions → item-at", function này cho phép chỉ định lấy một phần tử trong mảng.
Như ví dụ thì phần tử ta cần lấy nằm ở vị trí số 7 nên ta insert thêm một "constant number" để định nghĩa vị trí cần lấy cho "item-at" function như hình bên dưới.
Kế tiếp ta chỉ việc kết nối các define lại với nhau như hình bên dưới.
Công việc còn lại chỉ save design lại rùi tạo file XSLT (File → Generate code in → xslt 2) và chạy auto export.
3. Khởi động SGBAutoExport:
Để chạy ứng dụng SGBAutoExport ta run tập tin "SGBAutoExport_Run.bat".Chương trình đầu tiên sẽ truy cập vào bảng Management của project lấy ID của các records có "export_status = 1" để export (điều kiện này có thể hợp hợp với các điều kiện khác để tạo ra điều kiện export phù hợp cho dự án.).
Dựa trên các IDs lấy được chương trình sẽ vào bảng data lấy dữ liệu export, dữ liệu này sẽ kếp hợp với template export (xslt) để xuất ra file export.
Cuối cùng sau khi export xong chương trình sẽ đánh dấu "export_status = 2" để xác định record đã export thành công.
0 comments:
Post a Comment