vinhngba2704 commited on
Commit
5654237
·
1 Parent(s): 6a73dca

First commit application to vinhngba2704/multimodal-image-audio

Browse files
.env ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ MODEL_NAME=gemini-1.5-flash
2
+ MERCHANT_JSON_PATH=resources/merchant.json
3
+ PRODUCT_JSON_PATH=resources/product.json
4
+ UNIT_JSON_PATH=resources/unit.json
5
+ EMPLOYEE_JSON_PATH=resources/employee.json
6
+ NORMALIZATION_RULE_PATH=resources/normalization_rule.json
app.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import json
4
+ from zipfile import ZipFile
5
+ from io import BytesIO
6
+
7
+ # Initialized Modules
8
+ from modules.image_process import image_process
9
+ from modules.audio_process import audio_process
10
+ from modules.transformation import json_to_dms_excel
11
+ # from modules.saving import saving_json, saving_excel
12
+
13
+
14
+ # Streamlit app
15
+ st.title("TOOL NHẬP ĐƠN HÀNG TỰ ĐỘNG")
16
+
17
+ # Add a text input for employee code
18
+ employee_code = st.text_input("Nhập mã nhân viên của bạn:", placeholder="Administrator", max_chars=20)
19
+
20
+ # Add a button to confirm the input
21
+ if st.button("Xác nhận mã nhân viên"):
22
+ if employee_code == "":
23
+ st.error("Vui lòng nhập mã nhân viên trước khi xác nhận.")
24
+ else:
25
+ st.success(f"Mã nhân viên của bạn là: {employee_code}")
26
+
27
+ st.write("Tải lên folder chứa hình ảnh đơn hàng (dưới dạng file Zip).")
28
+
29
+ # File uploader for ZIP file
30
+ uploaded_file = st.file_uploader("Tải file Zip chứa hình ảnh đơn hàng", type=["zip"])
31
+
32
+ if uploaded_file is not None:
33
+ # Extract ZIP file
34
+ with ZipFile(uploaded_file) as zip_file:
35
+ zip_file.extractall("temp_invoices")
36
+
37
+ # Collect image and audio files
38
+ all_files = zip_file.namelist()
39
+ # Image files
40
+ image_files = [os.path.join("temp_invoices", file) for file in all_files if file.lower().endswith((".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".webp"))]
41
+ # Audio files
42
+ audio_files = [os.path.join("temp_invoices", file) for file in all_files if file.lower().endswith((".mp3", ".wav", ".m4a", ".flac"))]
43
+
44
+ if not image_files and not audio_files:
45
+ st.error("Không có file hình ảnh và/hoặc file âm thanh hợp lệ trong thư mục file Zip.")
46
+ else:
47
+ st.write(f"Tìm thấy file {len(image_files)} ảnh và {len(audio_files)} file âm thanh trong thư mục.")
48
+
49
+ order_counter = 1 # Initialize the order ID counter
50
+ results = {}
51
+
52
+ # Process image files
53
+ for i, image_path in enumerate(image_files, start=1):
54
+ st.write(f"Processing image{i}/{len(image_files)}: {os.path.basename(image_path)}")
55
+ try:
56
+ content = image_process(image_path= image_path, order_id= order_counter)
57
+ results[f"image_file_{i}"] = content
58
+ order_counter += 1
59
+ except Exception as e:
60
+ st.error(f"Error processing {image_path}: {e}")
61
+
62
+ # Process audio files
63
+ for i, audio_path in enumerate(audio_files, start=1):
64
+ st.write(f"Processing audio{i}/{len(audio_files)}: {os.path.basename(audio_path)}")
65
+ try:
66
+ content = audio_process(audio_path= audio_path, order_id= order_counter)
67
+ results[f"audio_file_{i}"] = content
68
+ order_counter += 1
69
+ except Exception as e:
70
+ st.error(f"Error processing {audio_path}: {e}")
71
+
72
+ # Display the results
73
+ st.write("OCR Results:")
74
+ st.json(results)
75
+
76
+ # Allow user to download the results as a JSON file
77
+ json_data = json.dumps(results, indent=4)
78
+ st.download_button(
79
+ label="Tải file kết quả ở dạng JSON",
80
+ data=json_data,
81
+ file_name="invoice_results.json",
82
+ mime="application/json"
83
+ )
84
+ # Allow user to download the results as Excel file
85
+ # Convert results to Excel format
86
+ df = json_to_dms_excel(results, employee_code)
87
+
88
+ # Allow user to preview excel file before downloading
89
+ st.subheader("Xem trước dữ liệu Excel:")
90
+ st.dataframe(df.head())
91
+
92
+ excel_buffer = BytesIO()
93
+ df.to_excel(excel_buffer, index=False)
94
+ excel_buffer.seek(0)
95
+ st.download_button(
96
+ label="Tải file theo template Excel từ DMS",
97
+ data=excel_buffer,
98
+ file_name="invoice_results.xlsx",
99
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
100
+ )
modules/audio_process.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import whisper
2
+ from dotenv import load_dotenv
3
+ import os
4
+ from rapidfuzz import process, fuzz
5
+ import pandas as pd
6
+ import json
7
+ import google.generativeai as genai
8
+ import re
9
+
10
+ # Initialized Modules
11
+ from modules.mapping import mapping_employee, mapping_merchant, mapping_product, mapping_unit
12
+
13
+ load_dotenv()
14
+ # Trancribe Model: Whisper
15
+ transcribe_model = whisper.load_model("turbo")
16
+ # Load the Gemini model
17
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
18
+ MODEL_NAME = os.getenv("MODEL_NAME")
19
+ genai.configure(api_key=GEMINI_API_KEY)
20
+ # Gemini Model
21
+ LLM_model = genai.GenerativeModel(MODEL_NAME)
22
+
23
+ # Line Split Function
24
+ def line():
25
+ print("=" * 30)
26
+
27
+ # Audio to raw text
28
+ def process_audio(audio_path, transcribe_model):
29
+ try:
30
+ transcript = transcribe_model.transcribe(audio_path)
31
+ return transcript["text"]
32
+ except Exception as e:
33
+ print(f"Trancribe failed: {e}")
34
+ return ""
35
+
36
+ # Parsing audio-text
37
+ def parse_audio_text(text, extract_model):
38
+ prompt = f"""
39
+ Dưới đây là nội dung hóa đơn bằng tiếng Việt. Hãy trích xuất tên đại lý mua (seller), tên đại lý bán (buyer), tên sản phẩm (product_name), đơn vị tính (unit), số lượng theo từng đơn hàng (quantity), ngày đặt hàng (order_date).
40
+
41
+ Văn bản:
42
+ {text}
43
+
44
+ Trả về kết quả dạng JSON:
45
+ {{
46
+ "order_1": {{
47
+ "seller": "...",
48
+ "buyer": "...",
49
+ "product_name": "...",
50
+ "unit": "...",
51
+ "quantity": "...",
52
+ "order_date": "..."
53
+ }},
54
+ ...
55
+ }}
56
+ """
57
+ response = extract_model.generate_content(prompt)
58
+
59
+ try:
60
+ content = response.text
61
+ # Use regex to extract the JSON part
62
+ match = re.search(r"\{[\s\S]*\}", content)
63
+ if match:
64
+ json_str = match.group(0)
65
+ extracted_json = json.loads(json_str)
66
+ return list(extracted_json.values()) # List of orders
67
+ else:
68
+ raise ValueError("No valid JSON found in Gemini output")
69
+
70
+ except Exception as e:
71
+ print("Failed to parse JSON from LLM response:", e)
72
+ return []
73
+
74
+ # Audio Handling Function
75
+ def audio_process(audio_path, order_id):
76
+ print(f"Start process audio file: {os.path.basename(audio_path)}")
77
+ line()
78
+
79
+ # Audio to Text
80
+ raw_text = process_audio(
81
+ audio_path=audio_path,
82
+ transcribe_model=transcribe_model
83
+ )
84
+ print(f"Transcript is done. Transcription: {raw_text}")
85
+ line()
86
+
87
+ # Text to JSON
88
+ extracted_information = parse_audio_text(
89
+ text=raw_text,
90
+ extract_model=LLM_model
91
+ )
92
+ print(f"Extracted Information.")
93
+ line()
94
+
95
+ # Mapping
96
+ merchant_mapped_data = mapping_merchant(
97
+ information=extracted_information,
98
+ json_path=os.getenv("MERCHANT_JSON_PATH"),
99
+ normalization_rule=os.getenv("NORMALIZATION_RULE_PATH")
100
+ )
101
+
102
+ unit_merchant_mapped_data = mapping_unit(
103
+ information=merchant_mapped_data,
104
+ json_path=os.getenv("UNIT_JSON_PATH"),
105
+ normalization_rule=os.getenv("NORMALIZATION_RULE_PATH")
106
+ )
107
+
108
+ # Skipping employee and product mapping
109
+ processed_data = unit_merchant_mapped_data
110
+
111
+ # Assign order id
112
+ for item in processed_data:
113
+ item["order_id"] = order_id
114
+
115
+ print(f"Successfully mapped data (merchant + unit).")
116
+ line()
117
+
118
+ return processed_data
modules/image_process.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ import os
3
+ import pandas as pd
4
+ import json
5
+ from google.cloud import vision
6
+ import google.generativeai as genai
7
+ from google.oauth2 import service_account
8
+ import re
9
+
10
+ # Initialized Modules
11
+ from modules.mapping import mapping_employee, mapping_merchant, mapping_product, mapping_unit
12
+
13
+ load_dotenv()
14
+ # Load the credential for Cloud-Vision-API model
15
+ service_account_info_str = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
16
+ service_account_info = json.loads(service_account_info_str)
17
+ CREDENTIALS = service_account.Credentials.from_service_account_info(service_account_info)
18
+ # Load the Gemini model
19
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
20
+ MODEL_NAME = os.getenv("MODEL_NAME")
21
+ genai.configure(api_key=GEMINI_API_KEY)
22
+
23
+ # Gemini Model
24
+ LLM_model = genai.GenerativeModel(MODEL_NAME)
25
+
26
+ # Line Split Function
27
+ def line():
28
+ print("=" * 30)
29
+
30
+ # Image to raw text
31
+ def process_ocr(image_path):
32
+ try:
33
+ client = vision.ImageAnnotatorClient(credentials=CREDENTIALS)
34
+
35
+ with open(image_path, "rb") as image_file:
36
+ content = image_file.read()
37
+
38
+ image = vision.Image(content=content)
39
+ response = client.document_text_detection(image=image)
40
+
41
+ # Extract detected text
42
+ texts = response.text_annotations
43
+ return texts[0].description if texts else ""
44
+ except Exception as e:
45
+ print(f"OCR failed: {e}")
46
+ return ""
47
+
48
+ # Parsing image-text
49
+ def parse_image_text(text, extract_model):
50
+ prompt = f"""
51
+ Dưới đây là nội dung hóa đơn bằng tiếng Việt. Hãy trích xuất tên đại lý mua (seller), tên đại lý bán (buyer), tên sản phẩm (product_name), đơn vị tính (unit), số lượng theo từng đơn hàng (quantity), ngày đặt hàng (order_date).
52
+
53
+ Văn bản:
54
+ {text}
55
+
56
+ Trả về kết quả dạng JSON:
57
+ {{
58
+ "order_1": {{
59
+ "seller": "...",
60
+ "buyer": "...",
61
+ "product_name": "...",
62
+ "unit": "...",
63
+ "quantity": "...",
64
+ "order_date": "..."
65
+ }},
66
+ ...
67
+ }}
68
+ """
69
+ response = extract_model.generate_content(prompt)
70
+
71
+ try:
72
+ content = response.text
73
+ # Use regex to extract the JSON part
74
+ match = re.search(r"\{[\s\S]*\}", content)
75
+ if match:
76
+ json_str = match.group(0)
77
+ extracted_json = json.loads(json_str)
78
+ return list(extracted_json.values()) # List of orders
79
+ else:
80
+ raise ValueError("No valid JSON found in Gemini output")
81
+
82
+ except Exception as e:
83
+ print("Failed to parse JSON from LLM response:", e)
84
+ return []
85
+
86
+ # Image Handling Function
87
+ def image_process(image_path, order_id):
88
+ print(f"Start process image file: {os.path.basename(image_path)}")
89
+ line()
90
+
91
+ # Image to Text
92
+ raw_text = process_ocr(image_path=image_path)
93
+ print(f"Successfully extract raw text. Text: {raw_text}")
94
+ line()
95
+
96
+ # Text to JSON
97
+ extracted_information = parse_image_text(
98
+ text=raw_text,
99
+ extract_model=LLM_model
100
+ )
101
+ print(f"Extracted Information.")
102
+ line()
103
+
104
+ # Mapping
105
+ merchant_mapped_data = mapping_merchant(
106
+ information=extracted_information,
107
+ json_path=os.getenv("MERCHANT_JSON_PATH"),
108
+ normalization_rule=os.getenv("NORMALIZATION_RULE_PATH")
109
+ )
110
+
111
+ unit_merchant_mapped_data = mapping_unit(
112
+ information=merchant_mapped_data,
113
+ json_path=os.getenv("UNIT_JSON_PATH"),
114
+ normalization_rule=os.getenv("NORMALIZATION_RULE_PATH")
115
+ )
116
+
117
+ # Skipping employee and product mapping
118
+ processed_data = unit_merchant_mapped_data
119
+
120
+ # Assign order id
121
+ for item in processed_data:
122
+ item["order_id"] = order_id
123
+
124
+ print(f"Successfully mapped data (merchant + unit).")
125
+ line()
126
+
127
+ return processed_data
128
+
modules/mapping.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from rapidfuzz import process, fuzz
3
+
4
+ # Initialized Modules
5
+ from modules.normalization import normalization
6
+
7
+ # Mapping merchant
8
+ def mapping_merchant(information, json_path, normalization_rule):
9
+ # Load from merchant JSON file
10
+ with open(json_path, "r", encoding="utf-8") as f:
11
+ name_id_dict = json.load(f)
12
+
13
+ # Create cached normalized dictionary
14
+ normalized_cached_map = {normalization(text= k, normalization_rule= normalization_rule): v for k, v in name_id_dict.items()}
15
+ name_list = list(normalized_cached_map.keys())
16
+
17
+ for item in information:
18
+ # Match seller
19
+ seller_name = normalization(text= item["seller"], normalization_rule= normalization_rule)
20
+ seller_match, seller_score, _ = process.extractOne(seller_name, name_list, scorer= fuzz.token_sort_ratio)
21
+ if seller_score >= 80:
22
+ item["seller_id"] = normalized_cached_map[seller_match]
23
+ else:
24
+ item["seller_id"] = None
25
+
26
+ # Match buyer
27
+ buyer_name = normalization(text= item["buyer"], normalization_rule= normalization_rule)
28
+ buyer_match, buyer_score, _ = process.extractOne(buyer_name, name_list, scorer= fuzz.token_sort_ratio)
29
+ if buyer_score >= 80:
30
+ item["buyer_id"] = normalized_cached_map[buyer_match]
31
+ else:
32
+ item["buyer_id"] = None
33
+
34
+ return information
35
+
36
+ # Mapping unit
37
+ def mapping_unit(information, json_path, normalization_rule):
38
+ # Load from unit JSON file
39
+ with open(json_path, "r", encoding="utf-8") as f:
40
+ unit_id_dict = json.load(f)
41
+
42
+ # Create cached normalized dictionary
43
+ normalized_cached_map = {normalization(text= k, normalization_rule= normalization_rule): v for k, v in unit_id_dict.items()}
44
+ unit_list = list(normalized_cached_map.keys())
45
+
46
+ for item in information:
47
+ # Match unit
48
+ unit = normalization(text= item["unit"], normalization_rule= normalization_rule)
49
+ unit_match, unit_score, _ = process.extractOne(unit, unit_list, scorer= fuzz.token_sort_ratio)
50
+ if unit_score >= 80:
51
+ item["unit_id"] = normalized_cached_map[unit_match]
52
+ else:
53
+ item["unit_id"] = None
54
+
55
+ return information
56
+
57
+ # Mapping employee
58
+ def mapping_employee(information, json_path, normalization_rule):
59
+ # Load from employee JSON file
60
+ with open(json_path, "r", encoding="utf-8") as f:
61
+ employee_id_dict = json.load(f)
62
+
63
+ # Mapping product
64
+ def mapping_product(information, json_path, normalization_rule):
65
+ # Load from product JSON file
66
+ with open(json_path, "r", encoding="utf-8") as f:
67
+ product_id_dict = json.load(f)
modules/normalization.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ # Normalize the key before mapping
4
+ def normalization(text, normalization_rule):
5
+ # Load normalization rule:
6
+ with open(normalization_rule, "r", encoding="utf-8") as f:
7
+ replace_dict = json.load(f)
8
+
9
+ # Lowercase the text
10
+ text = text.lower()
11
+ # Replace the words
12
+ for old, new in replace_dict.items():
13
+ text = text.replace(old.lower(), new.lower())
14
+ # # Remove diacritics
15
+ # text = unicodedata.normalize('NFD', text)
16
+ # text = ''.join(c for c in text if unicodedata.category(c) != 'Mn')
17
+
18
+ return text.strip()
modules/saving.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import pandas as pd
4
+
5
+ # Write the json result
6
+ def saving_json(data, json_path: str):
7
+ try:
8
+ # Ensure the directory exists
9
+ os.makedirs(os.path.dirname(json_path), exist_ok=True)
10
+
11
+ # Write the data to the JSON file
12
+ with open(json_path, "w", encoding="utf-8") as f:
13
+ json.dump(data, f, ensure_ascii=False, indent=4)
14
+
15
+ print(f"Data successfully saved to: {json_path}")
16
+ except Exception as e:
17
+ print(f"Failed to save JSON file. Error: {e}")
18
+
19
+ def saving_excel(data: pd.DataFrame, excel_path: str):
20
+ try:
21
+ # Ensure the directory exists
22
+ os.makedirs(os.path.dirname(excel_path), exist_ok=True)
23
+
24
+ # Save DataFrame to Excel file
25
+ data.to_excel(excel_path, index=False)
26
+
27
+ print(f"Data successfully saved to: {excel_path}")
28
+ except Exception as e:
29
+ print(f"Failed to save Excel file. Error: {e}")
modules/transformation.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+
3
+ # JSON to Excel Template
4
+ def json_to_dms_excel(res, employee_code=""):
5
+ columns = [
6
+ "STT *",
7
+ "Số thứ tự đơn hàng *",
8
+ "Mã nhân viên kinh doanh *",
9
+ "Tên nhân viên kinh doanh",
10
+ "Mã tự sinh đại lý mua *",
11
+ "Tên đại lý mua",
12
+ "Mã tự sinh đại lý bán *",
13
+ "Tên đại lý bán",
14
+ "Ngày đặt hàng *",
15
+ "Ngày giao hàng",
16
+ "Ghi chú",
17
+ "Sửa giá bán *",
18
+ "Chiết khấu tổng đơn hàng (%)",
19
+ "Mã sản phẩm *",
20
+ "Tên sản phẩm",
21
+ "Mã đơn vị tính *",
22
+ "Là sản phẩm? *",
23
+ "Số lượng *",
24
+ "Giá bán (bao gồm VAT)"
25
+ ]
26
+
27
+ rows = []
28
+ idx = 1
29
+
30
+ for _, orders in res.items():
31
+ for order in orders:
32
+ row = {col: '' for col in columns} # Initialize all columns with empty string
33
+
34
+ row["STT *"] = idx
35
+ row["Số thứ tự đơn hàng *"] = order.get("order_id", idx)
36
+ row["Mã nhân viên kinh doanh *"] = employee_code
37
+ row["Tên nhân viên kinh doanh"] = order.get("saler", "")
38
+ row["Mã tự sinh đại lý mua *"] = order.get("buyer_id", "")
39
+ row["Tên đại lý mua"] = order.get("buyer", "")
40
+ row["Mã tự sinh đại lý bán *"] = order.get("seller_id", "")
41
+ row["Tên đại lý bán"] = order.get("seller", "")
42
+ row["Ngày đặt hàng *"] = order.get("order_date", "")
43
+ row["Ngày giao hàng"] = order.get("delivery_date", "")
44
+ row["Ghi chú"] = order.get("note", "")
45
+ row["Sửa giá bán *"] = order.get("change_price", "")
46
+ row["Chiết khấu tổng đơn hàng (%)"] = order.get("discount", "")
47
+ row["Mã sản phẩm *"] = order.get("product_id", "")
48
+ row["Tên sản phẩm"] = order.get("product_name", "")
49
+ row["Mã đơn vị tính *"] = order.get("unit_id", "")
50
+ row["Là sản phẩm? *"] = "Sản phẩm bán"
51
+ row["Số lượng *"] = order.get("quantity", "")
52
+ rows.append(row)
53
+ idx += 1
54
+
55
+ df = pd.DataFrame(rows, columns=columns)
56
+
57
+ # Create "End" row, first column is "End", other is blank like in the excel template
58
+ end_row = pd.DataFrame([["End"] + [""] * df.shape[1] - 1], columns= df.columns)
59
+
60
+ df = pd.concat([df, end_row], ignore_index= True)
61
+
62
+ return df
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ git+https://github.com/openai/whisper.git
2
+ ffmpeg
3
+ transformers
4
+ accelerate
5
+ python-dotenv
6
+ rapidfuzz
7
+ openpyxl
8
+ python-dotenv
9
+ huggingface_hub
10
+ google-generativeai
11
+ pandas
12
+ google-cloud-vision
13
+ google-auth
14
+ streamlit
resources/cloud_vision_ai_key.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "gen-lang-client-0680794503",
4
+ "private_key_id": "3f1d0c6b365a57afc5f11e5627d8cd00a5436c23",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBKbnDskM5Ht1w\ngKUZsMvlkSFWI3INBHntrY1sTvBZnVBs0xq2NIIAnhamMAtIqBt0bYk1qNzZd/y3\nlCo59Ogla4edbZ6XaLn7lBj0qHi2j9m2IleFfRXvtSIkFueOHmbG3qUYQpSoIQMI\ngu376o5YasuBiIPvQbHiG58/30UB8DSzM+aTPfGBKv52hVRsP9U4stZ6X8H+AKoy\nH0PQyrhMBozBGdeqQO3x3LBRmWL8AM/f7Nc9yUcpO/H9C/roTWrTMH4tSAufC0Qj\nnojDSatQZQ3SEXI6R5C8K8y0VnyhGD92++2BrjK8BkQrMtSTF6g7LomFkF6sJuv5\nvY6cxMhRAgMBAAECggEAEx1jRKUKAfJhTMDDlcc+ZiP2feUEDvBidc1hhquecpUe\ntaYuU9mJA9v2YdEJ93wAkNpGDwlRfDO4znHbETaAbTOMOAf2VFqzYjHwRkW7Aas6\nisuF3a/Ye+AbgMwYyKI5iXR+4ee0zkPLXmGWgKy1aV/Sw6lpZO5wq+9lKEJFPJZc\nbf8I5QI91W+fG9qYE15H5AOO+XGsgKv+gHFh2xfmZ4eJI1d1/VJWrCpmHHa4WtJZ\nYxBDOY9qqYICSTR7wYwYRhSdX3vrErfppJDIVzQlHDseV80Bc6YoIX7QSzygWrR0\nV6Ob/meSYhuH+RQXaoCyZ59pF8pR+w4mENu6OuLQAQKBgQDz0za9DMQnn/HMSZrb\n+lNFBZFV2G63FiEE3yJTSFSC3MCDPSd1dNPEDJ9Oh0AfhWv/ieyHVmGS7VuqwMMD\n7ANQFlhkS5xXc9qN+Liq1SytCFpEZEzVbeaCYNNBvuJbeAI8yiB/qCk6+Zocflbs\n9Sj1Aa7oXbl1ZYyckNi8r8Tz+wKBgQDKzueghglBXb6zaByhk/0r5gwfERLpwrI0\naYTZTcLH+8akdFge3K03bZ5YQaG0dHl9YqxGQMZGMoinootLlu1LtFXcCRfrK35U\nM4n9MZ7SsAh5himCqtDNNnCuxcklSsp4F7N/CIlbloE7EnzwF+2PG1JWjjsoOLPz\nPQiXxR23IwKBgEDB8iHXyCk2A8RcMDMIkyEbz3PbXdxmljJzCOzRoxB2jPLORTKe\n6reBGraCmXdFul9ORHHVcWjSfawmMiVSg7a7mJJaupVHgd5/FpzYrVrvgvnzIaz1\n2Wj7SmCF0By3DPEURflhskGllVbH/1JD8rLP1aKFcgJKDERw+/9xN4ANAoGBAJrJ\nbalrg3bbOKgvBuMfUvQFQS0Y1+mHyoEMI/PCUK5XcFWl4nezj5SlWlwbw3I6D1tu\nSvPXjjyXZwsimNPZXkUQXxNv8Uxwxps3NtMC4ygEaINvrRDolDJ7oWcS16FZwswD\nsuB6wHMhnIJcavTIHmzBuocLSQU6ucUkyQEk1bgnAoGATz+x4X9FLz6e/tVHnBJ5\nXG1EfenUJMLQCVsDq6ine/n5Mz+2ngsOu2b8W6PGNabisfCE0e/xJM/TYw5jJ9vf\nYHf0+4h4BWKom4vlQHb/FgZXzS85oPJ7kY9IGzpWa2A0IKFBHabD9roT3tDYv9Qq\nBfT1Cl41UTsqYre+nDGNX/c=\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "vision-api-sa@gen-lang-client-0680794503.iam.gserviceaccount.com",
7
+ "client_id": "104243194869318851804",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/vision-api-sa%40gen-lang-client-0680794503.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
resources/employee.json ADDED
@@ -0,0 +1,566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ " Nguyễn Tuấn Vũ": "TG.VuNT",
3
+ "Ngô Sỹ Kiên": "TV01.KienNS",
4
+ "Huỳnh Hiếu Nghĩa": "TG.NghiaHH",
5
+ "Cao Hoàng Hải": "HCM.HaiCH",
6
+ "Phạm Ngọc Đệ": "HCM.DePN",
7
+ "Dương Quốc Hưng": "PN.HungDQ",
8
+ "Trần Bảo Ngân": "HCM.NganTB",
9
+ "Trần Việt Hoàng": "NT.HoangTV",
10
+ "Hồ Xuân Thuận": "TV01.ThuanHX",
11
+ "Trần Xuân Mạnh": "TV01.ManhTX",
12
+ "La Mạnh Toàn": "TV02.ToanLM",
13
+ "Ngô Tiến Thành": "TV02.ThanhNT",
14
+ "Trần Mạnh Hùng": "TV01.HungTM",
15
+ "Lê Vũ Duy": "TT2.DuyLV",
16
+ "Nguyễn Đức Tuấn": "TT2.TuanND",
17
+ "Phan Thanh Tâm": "TG.TamPT",
18
+ "Ngô Minh Đẳng": "TG.DangNM",
19
+ "Nguyễn Văn Giám": "RD.GiamNV",
20
+ "Nguyễn Ngọc Nghĩa": "RD.NghiaNN",
21
+ "Đinh Hồng Dương": "TV02.DuongDH",
22
+ "Đoàn Nguyễn Huy Hoàng": "TN.HoangDNH",
23
+ "Ngô Thanh Bình": "DN.BinhNT",
24
+ "Đặng Huỳnh Nam Anh": "DN.AnhDHN",
25
+ "Lưu Liên Thảo": "TMDT.ThaoLL",
26
+ "Bùi Thị Anh Thư": "BH.ThuBTA",
27
+ "Đỗ Nam Anh": "TV01.AnhDN",
28
+ "Châu Hoài Duy": "TG.DuyCH",
29
+ "Nguyễn Diệu Linh": "TV03.LinhND",
30
+ "Bùi Thị Linh Chi": "TMDT.ChiBTL",
31
+ "Nguyễn Thị Bích Ngọc": "TMDT.NgocNTB",
32
+ "Lê Việt Hòa": "PR.HoaLV",
33
+ "Nguyễn Văn Hùng": "CT.HungNV",
34
+ "Dương Văn Phúc": "DN.PhucDV",
35
+ "Đào Ngô Bích Hồng": "RD.hongDNB",
36
+ "Lê Văn Thành": "RD.thanhlv",
37
+ "Đào Văn Phú": "Xled.phudv",
38
+ "Nguyễn Xuân Dũng": "TN.DungNX",
39
+ "Trần Bình Minh": "TMDT.MinhTB",
40
+ "Võ Thành Long": "HCM.LongVT",
41
+ "Nguyễn Tuấn Dũng": "TV02.DungNT",
42
+ "Trang GS": "Tv01.TrangtestGS",
43
+ "Nguyễn Minh Tâm": "TG.TamNM",
44
+ "Thái Phi Châu": "NT.ChauTP",
45
+ "Đào Khắc Khương": "TV02.KhuongDK",
46
+ "Nguyễn Viết Luận": "NT.LuanNV",
47
+ "Phạm Minh Đức": "TMDT.Ducpm",
48
+ "DLUQ_CN_TN_GiaBao": "DLUQ_CN_TN_GiaBao",
49
+ "DLUQ_CN_NT_Khangan": "DLUQ_CN_NT_Khangan",
50
+ "DLUQ_V2_SHome": "DLUQ_V2_SHome",
51
+ "DLUQ_V2_HN_A Hoàng": "DLUQ_V2_HN_TBD15",
52
+ "Cập nhật SP 1": "TMDT.SanPham1",
53
+ "Vũ Văn Quang": "TV03.QuangVV",
54
+ "Đỗ Thị Lý": "QLHT.LyDT",
55
+ "Trần Đăng Khoa": "HCM.KhoaTD",
56
+ "Huỳnh Công Hải": "TN.HaiHC",
57
+ "Đặng Hồng Phúc": "HCM.PhucDH",
58
+ "Dương Lý Đức": "CT.DucDL",
59
+ "Phan Đăng Phú": "TN.PhuPD",
60
+ "DLUQ_CN_HCM_ACT": "DLUQ_CN_HCM_ACT",
61
+ "DLUQ_CN_BH_BRVT": "DLUQ_CN_BH_BRVT",
62
+ "DLUQ_CN_BH_BT_HienHau": "DLUQ_CN_BH_BT_HienHau",
63
+ "DLUQ_CN_BH_BP_DuongHa": "DLUQ_CN_BH_BP_DuongHa",
64
+ "DLUQ_CN_BH_BD_SongThang": "DLUQ_CN_BH_BD_SongThang",
65
+ "DLUQ_CN_BH_DN_VinhQuang": "DLUQ_CN_BH_DN_VinhQuang",
66
+ "DLUQ_CN_TG_TruongXuan": "DLUQ_CN_TG_TruongXuan",
67
+ "DLUQ_CN_TN_ThanhMai": "DLUQ_CN_TN_ThanhMai",
68
+ "DLUQ_CN_DN_NhatBich": "DLUQ_CN_DN_NhatBich",
69
+ "DLUQ_V3_HN": "DLUQ_V3_HN",
70
+ "DLUQ_V3_PT_Saka": "DLUQ_V3_PT_Saka",
71
+ "DLUQ_V2_HN_Smartree": "DLUQ_V2_HN_Smartree",
72
+ "DLUQ_V2_HN_QuangTuan": "DLUQ_V2_HN_QuangTuan",
73
+ "DLUQ_V2_HN_Kingsway": "DLUQ_V2_HN_Kingsway",
74
+ "DLUQ_V1_TH_NgaSang": "DLUQ_V1_TH_NgaSang",
75
+ "DLUQ_V1_TH_NhatThinh": "DLUQ_V1_TH_NhatThinh",
76
+ "DLUQ_V1_TH_LuongThuy": "DLUQ_V1_TH_LuongThuy",
77
+ "Phạm Anh Thơ": "TV01.ThoPA",
78
+ "Nguyễn Kim Long": "TV02.LongNK",
79
+ "Bùi Quang Tiến": "BH.TienBQ",
80
+ "Đồng Văn Quảng": "BH.QuangDV",
81
+ "Nguyễn Thị Thu Phong": "HCM.PhongNTT",
82
+ "Phạm Mạnh Tùng": "BH.TungPM",
83
+ "Nguyễn Thị Ngọc Châm": "CT.ChamNTN",
84
+ "Trần Thị Thu Hiền": "TN.HienTTT",
85
+ "Nguyễn Thị Thu Phương": "NT.PhuongNTT",
86
+ "Lê Thị Thạo": "DN.ThaoLT",
87
+ "Nguyễn Ngọc Bảo Thiện": "TG.ThienNNB",
88
+ "Nguyễn Văn Phong (V3)": "TV03.PhongNV",
89
+ "App Dịch vụ": "appdv",
90
+ "Nguyễn Đình Quốc Trung": "TN.TrungNDQ",
91
+ "Đoàn Thị Thanh Thảo": "NCTT.ThaoDT",
92
+ "Đỗ Hải Triều": "NCTT.TrieuDH",
93
+ "Nguyễn Trọng Nghĩa": "CT.NghiaNT",
94
+ "Nguyễn Văn Huy": "TV03.HuyNV",
95
+ "Admin Test": "Admintest",
96
+ "TMDT.TrangDT": "TMDT.trangdt",
97
+ "Vũ Đức Cường": "TMDT.Cuongvd",
98
+ "Tài khoản giám sát test app đại lý 02": "TK.GS.TESTAPPDAILY02",
99
+ "Tài khoản giám sát test app đại lý 01": "TK.GS.TESTAPPDAILY01",
100
+ "Tài khoản test app đại lý 02": "TK.TESTAPPDAILY02",
101
+ "Tài khoản test app đại lý 01": "TK.TESTAPPDAILY01",
102
+ "Hoàng Phú Thừa": "TN.ThuaHP",
103
+ "Vũ Nguyễn Quỳnh Nga": "PR.NgaLVQ",
104
+ "Nguyễn Đình Thiện": "TN.ThienND",
105
+ "SangDV": "C4LED.SangDV1",
106
+ "Dien97": "C4LED.Dien97",
107
+ "HuyND": "C4LED.HuyND",
108
+ "HoangND": "C4LED.HoangND",
109
+ "HungTM": "C4LED.HungTM",
110
+ "Lê Anh Dũng": "FPT.dungla15",
111
+ "Lê Ngọc Tú": "TMDT.tunl",
112
+ "Phạm Hồng Nhung": "TMDT.nhungph",
113
+ "ThauTho_Admin_CN_BH": "ThauTho_Admin_CN_BH",
114
+ "ThauTho_Admin_CN_TG": "ThauTho_Admin_CN_TG",
115
+ "ThauTho_Admin_CN_CT": "ThauTho_Admin_CN_CT",
116
+ "ThauTho_Admin_CN_HCM": "ThauTho_Admin_CN_HCM",
117
+ "ThauTho_Admin_V3": "ThauTho_Admin_V3",
118
+ "ThauTho_Admin_V2": "ThauTho_Admin_V2",
119
+ "ThauTho_Admin_V1": "ThauTho_Admin_V1",
120
+ "Bùi Thị Mỹ Tiên": "CT.TienBTM",
121
+ "Hà Đình Thi": "TV03.ThiHD",
122
+ "Lã Mạnh Toán": "TV01.ToanLM",
123
+ "Nguyễn Thị Hoa": "RD.HoaNT",
124
+ "Nguyệt VTS": "vts.nguyetta",
125
+ "ThauTho_Call": "ThauTho_Call",
126
+ "ThauTho_CV": "ThauTho_CV",
127
+ "ThauTho_Admin": "ThauTho_Admin",
128
+ "Chu Thị Khuyên": "KT.KhuyenCT",
129
+ "Lê Văn Từ": "HCM.TuLV",
130
+ "Nguyễn Hà Nhật Thanh": "NT.ThanhNHN",
131
+ "Nguyễn Văn Bi": "NT.BiNV",
132
+ "Nguyễn Thành Long": "TV01.LongNT",
133
+ "Nguyễn Thành Nhân": "TG.NhanNT",
134
+ "Đỗ Văn Thuận": "TV02.ThuanDV",
135
+ "Bùi Tứ Trực": "BH.TrucBT",
136
+ "Đặng Hồng Kiên": "TV03.KienDH",
137
+ "Huỳnh Kinh Kha": "CT.KhaHK",
138
+ "Hoàng Trọng Công": "BH.CongHT",
139
+ "Lê Thu Hà": "xk.halt",
140
+ "Hoàng Trung Kiên": "TV02.KienHT",
141
+ "Ngô Văn Cương": "TV01.CuongNV",
142
+ "Nguyễn Huy Phúc Đạt": "datnhp",
143
+ "Hoàng Ngọc Minh Huy": "HCM.HuyHNM",
144
+ "Support": "support.it",
145
+ "Nguyễn Phương Lâm": "BH.LamNP",
146
+ "Nguyễn Trọng Hiếu": "hieunt.pntt",
147
+ "Trần Vinh Quy": "C4LED.QuyTV",
148
+ "Đinh Văn Sáng": "C4LED.SangDV",
149
+ "report": "report.ecom",
150
+ "Ralli Smart IOT": "RalliSmart",
151
+ "Nguyễn Khắc Quý": "TV03.QuyNK",
152
+ "Bùi Quang Thái": "HCM.ThaiBQ",
153
+ "Võ Nhật Hào": "NCTT.HaoVN",
154
+ "Mạc Kế Minh": "TT2.MinhMK",
155
+ "Võ Văn Duy": "TT2.DuyVV",
156
+ "Mai Bảo Linh": "RD.LinhMB",
157
+ "Bùi Trần Bảo Linh": "RD.LinhBTB",
158
+ "Nguyễn Lê Lâm": "TT2.LamNL",
159
+ "Trần Nghiệp Đoàn": "RD.DoanTN",
160
+ "Đặng Hồ Đắc Trung": "TT2.TrungDHD",
161
+ "Lê Nam Thành": "PPMN.ThanhLN",
162
+ "Nguyễn Thị Hồng Liên": "RD.LienNTH",
163
+ "NCTT.QT": "NCTT",
164
+ "Trần Thị Loan": "KH.LoanTT",
165
+ "Nguyễn Duy Ngọc": "BH.NgocND",
166
+ "Hà Minh Khang": "TN.KhangHM",
167
+ "Nguyễn Thắng Lợi": "TN.LoiNT",
168
+ "K Văn Diu": "TN.DiuKV",
169
+ "Nguyễn Thanh Thiện": "TT4.ThienNT",
170
+ "Dư Chấn Hưng": "TT4.HungDC",
171
+ "Trần Phạm Diệu Linh": "RD.LinhTPD",
172
+ "Nguyễn Hoàng Hà": "NCTT.HaNH",
173
+ "Hoàng Thị Hường": "PTT.HuongHT",
174
+ "HienHT": "HienHT",
175
+ "Nguyễn Hoàng Gia": "HCM.GiaNH",
176
+ "Phan Tuấn Vũ": "CT.VuPT",
177
+ "Nguyễn Hải": "DN.HaiN",
178
+ "Quách Tiến Đạt": "CT.DatQT",
179
+ "Trần Văn Cường": "TV03.CuongTV",
180
+ "Phạm Đức Long": "TV03.LongPD",
181
+ "Nguyễn Ngọc Tuấn Minh": "NCTT.MinhNNT",
182
+ "Lại Phi Hùng": "NT.HungLP",
183
+ "Dương Văn Trung (TMDT)": "TMDT.TrungDV",
184
+ "Ngô Hải Đường": "CT.DuongNH",
185
+ "Vũ Thị Tuyết": "gdv.tuyetvt",
186
+ "Nguyễn Tiến Thành": "NT.ThanhNT",
187
+ "Phùng Quốc Khánh": "TMDT.khanhpq",
188
+ "Kiều Thanh Dương": "C4LED.duongkt",
189
+ "Vũ Thế Song": "TV02.SongVT",
190
+ "Nguyễn Quang Long": "TV02.LongNQ",
191
+ "Nguyễn Văn Phong": "Tv01.PhongNV",
192
+ "Giảng Công Tràng": "CT.TrangGC",
193
+ "Trần Ngọc Minh": "TV01.MinhTN",
194
+ "Test05": "test05",
195
+ "Hà Văn Quy": "TV01.QuyHV",
196
+ "Nguyễn Quang Huy": "TV03.HuyNQ",
197
+ "Lâm Minh Phúc": "BH.PhucLM",
198
+ "Mai Tiến Huy": "BH.HuyMT",
199
+ "KIM VĂN VINH": "RD.VinhKV",
200
+ "Nguyễn Văn Trường": "DN.TruongNV",
201
+ "Huỳnh Thắng Lợi": "TN.LoiHT",
202
+ "Lê Bá Sơn": "TN.SonLB",
203
+ "Vũ Quang Trung": "TV03.TrungVQ",
204
+ "Nguyễn Văn Sang": "TV03.SangNV",
205
+ "Nguyễn Hoài Nam": "TV02.NamNH",
206
+ "Tạ Quang Dướng": "HCM.DuongTQ",
207
+ "Nguyễn Hoài Thương": "CT.ThuongNH",
208
+ "Nguyễn Xuân Vinh": "TG.VinhNX",
209
+ "Đặng Văn Ninh": "HCM.NinhDV",
210
+ "Trần Nhân Kha": "HCM.KhaTN",
211
+ "Lê Thanh Thảo": "TN.ThaoLT",
212
+ "Hiệp": "hiep",
213
+ "nule": "nule",
214
+ "Nguyễn Thanh Đông": "BH.DongNT",
215
+ "Vũ Mai Phương": "xk.phuongmv",
216
+ "Quách Ngọc Ánh": "xk.anhqn",
217
+ "Phạm Yến Ngọc": "xk.ngocpy",
218
+ "Lê Kim Thành": "TV02.ThanhLK",
219
+ "Bùi Gia Thế": "TV03.TheBG",
220
+ "Nguyễn Hải Đăng (CT)": "TV02.DangNH1",
221
+ "Hoàng Trung Kiên TT1": "TT1.KienHT",
222
+ "Nguyễn Trung Hiếu": "TT1.HieuNT",
223
+ "Lê Chí Bảo": "TG.BaoLC",
224
+ "Đinh Xuân Đạo": "DN.DaoDX",
225
+ "Nguyễn Hải Ninh": "DN.NinhNH",
226
+ "Nguyễn Trọng Tuấn": "RD.TuanNT",
227
+ "Trần Đình Hinh": "RD.HinhTD",
228
+ "Phạm Anh Dũng": "RD.DungPA",
229
+ "Nguyễn Văn Trinh": "RD.TrinhNV",
230
+ "Trần Đức Thắng": "RD.ThangTD",
231
+ "Đặng Văn Ba": "RD.BaDV",
232
+ "Nguyễn Thị Thu Hương": "RD.HuongNTT",
233
+ "Nguyễn Đăng Chuyên": "TV02.ChuyenND",
234
+ "Trần Tùng Lâm": "TV02.LamTT",
235
+ "Lê Văn Nam Trường": "NCTT.TruongLVN",
236
+ "Phạm Duy Đức": "NCTT.DucPD",
237
+ "Trần Thị Diễm": "CT.diemtt",
238
+ "Nguyễn Minh Thư": "MN.thumn",
239
+ "Phạm Thị Thu": "tn.thupt",
240
+ "Đỗ Phượng": "BH1.phuongdo",
241
+ "Nguyễn Bá Huy": "tmdt.huynb",
242
+ "Sầm Mạnh Sơn": "TV03.SonSM",
243
+ "Nguyễn Hoàng Long (CT)": "TV03.LongNH",
244
+ "Hoàng Văn Tiến": "BH.TienHV",
245
+ "Huỳnh Đức Toàn": "BH.ToanHD",
246
+ "Phòng Kế hoạch - Xem đơn": "kh.xem",
247
+ "Phòng Kế hoạch - Xử lý đơn": "kh.xuly",
248
+ "Truyền thống V3 - Xem đơn OH": "tv03.xemdon",
249
+ "Truyền thống V3 - Tạo đơn OH": "tv03.taodon",
250
+ "Truyền thống V2 - Xem đơn OH": "tv02.xemdon",
251
+ "Truyền thống V2 - Tạo đơn OH": "tv02.taodon",
252
+ "Truyền thống V1 - Xem đơn OH": "tv01.xemdon",
253
+ "Truyền thống V1 - Tạo đơn OH": "tv01.taodon",
254
+ "Tây Nguyên - Xem đơn OH": "tn.xemdon",
255
+ "Tây Nguyên - Tạo đơn OH": "tn.taodon",
256
+ "Tiền Giang - Xem đơn OH": "tg.xemdon",
257
+ "Tiền Giang - Tạo đơn OH": "tg.taodon",
258
+ "Nha Trang - Xem đơn OH": "nt.xemdon",
259
+ "Nha Trang - Tạo đơn OH": "nt.taodon",
260
+ "Đà Nẵng - Xem đơn OH": "dn.xemdon",
261
+ "Đà Nẵng - Tạo đơn OH": "dn.taodon",
262
+ "Biên Hòa - Xem đơn OH": "bh.xemdon",
263
+ "Biên Hòa - Tạo đơn OH": "bh.taodon",
264
+ "Cần Thơ - Xem đơn OH": "ct.xemdon",
265
+ "Cần Thơ - Tạo đơn OH": "ct.taodon",
266
+ "Hồ Chí Minh - Xem đơn OH": "hcm.xemdon",
267
+ "Hồ Chí Minh - Tạo đơn OH": "hcm.taodon",
268
+ "Nguyễn Văn Vũ": "TV02.VuNV",
269
+ "Phan Văn Đạt": "TV02.DatPV",
270
+ "Phạm Hải": "TT4.HaiP",
271
+ "Khuất Thị Sâm": "QLHT.SamKT",
272
+ "Nguyễn Hoàng Kiên": "XLED.kiennh",
273
+ "Nguyễn Xuân Tùng": "TV03.TungNX",
274
+ "Nguyễn Hồng Sơn": "HCM.SonNH",
275
+ "Hoàng Quốc Việt": "TV03.VietHQ",
276
+ "Đào Thị Nhung": "TV02.NhungDT",
277
+ "Vũ Tuấn Dũng": "TV01.DungVT",
278
+ "Nguyễn Anh Quang": "TV01.QuangNA",
279
+ "Ngô Đức Hoài": "TT1.HoaiND",
280
+ "Huỳnh Tống": "DN.TongH",
281
+ "Trần Tuấn Dương": "tmdt.duongtt",
282
+ "Lê Thị Trang": "rd.tranglt",
283
+ "Vũ Duy Hải": "rd.haivd",
284
+ "Trần Thị Hiền": "HCM.HienTT",
285
+ "Nguyễn Mai Anh": "xk.anhnm",
286
+ "Nguyễn Thanh Hóa": "TG.HoaNT",
287
+ "Trần Việt Dũng": "TV03.DungTV",
288
+ "R&D_NV1": "R&D.NV1",
289
+ "Kiều Thanh Ly": "C4LED.lykt",
290
+ "Đào Phú Hội": "DN.HoiDP",
291
+ "Lê Tuấn Anh": "GDV_anhlt",
292
+ "Phạm Hải Nam": "BH.NamPH",
293
+ "Bùi Hưng": "TV02.HungB",
294
+ "Đoàn Giang Nam": "TV03.NamDG",
295
+ "Nguyễn Đình Quý": "TV03.QuyND",
296
+ "Nguyễn Văn Duy": "TV03.DuyNV",
297
+ "Hoàng Văn Tín": "BH.TinHV",
298
+ "Trần Anh Quân": "HCM.QuanTA",
299
+ "Nguyễn Quyết Chiến": "CT.ChienNQ",
300
+ "Nguyễn Ngọc Hải": "NT.HaiNN",
301
+ "Hoàng Văn Huân": "bh.huanhv",
302
+ "Sơn Đại": "CT.DaiS",
303
+ "Chu Thị Ngọc Diệp": "c4led.diepctn",
304
+ "Nguyễn Thị Thanh": "c4led.thanhnt",
305
+ "Kiều Hoài Trung (CTDA)": "CT.TrungKH",
306
+ "Trần Viết Hùng": "TV01.HungTV",
307
+ "Đõ Thị Hồng Nhung": "TMDT.Nhungdth",
308
+ "Phạm Quang Tiến": "TMDT.Tienpq",
309
+ "Lê Hồng Ánh": "TMDT.Anhlh",
310
+ "Đinh Thị Yến": "TMDT.Yendt",
311
+ "Phan Thanh Tâm (TMĐT)": "TMDT.Tampt",
312
+ "trangnt": "TTKDCS.trangnt",
313
+ "Trang nguyễn": "TN.trangnt",
314
+ "trang nguyễn": "QTHT.trangnt",
315
+ "trangnt175": "TV02.trang",
316
+ "nguyễn Trang V1": "TV01.trangnt",
317
+ "Nguyễn Trang": "CT.Trangnt",
318
+ "nguyễn Trang": "TT3.Trangnt",
319
+ "trang nguỹen": "HCM.trangnt",
320
+ "Nguyễn Trang QLBH2": "QLBH2.trangnt",
321
+ "Nguyễn Trang QLBH": "QLBH1.trangnt",
322
+ "Nguyễn Thu Trang": "gdv.trangthunt",
323
+ "Hằng TMĐT": "tmdt.hangntt",
324
+ "Hà Đức Trung": "DN.TrungHD",
325
+ "Nguyễn Ngọc Hiền": "TG.Hiennn",
326
+ "Nguyễn Tấn Thành": "TG.Thanhnt",
327
+ "Lê Văn Duy": "TN.Duylv",
328
+ "Khúc Minh Thu": "qlht.thukm",
329
+ "Nguyễn Hữu Thắng": "KST.Thangnh",
330
+ "Lê Hùng Quân": "KST.Quanlh",
331
+ "Phạm Tuấn Thành": "TT1.Thanhpt",
332
+ "Trần Thu Trang": "xk.trangtt",
333
+ "Nguyễn Thị Thu Trà": "xk.trantt",
334
+ "Lê Thúy Hạnh": "xk.hanhlt",
335
+ "Lê Hà My": "xk.mylh",
336
+ "Chu Thị Trang": "xk.trangct",
337
+ "Đỗ Đức Đại": "xk.daidd",
338
+ "Đỗ Huyền Trang": "xk.trangdh",
339
+ "Vũ Thị Nguyên": "xk.nguyenvt",
340
+ "Nguyễn Thùy Dung": "xk.dungnt",
341
+ "Trần Trung Hiếu": "xk.hieutt",
342
+ "Đinh Thị Vân": "xk.vandt",
343
+ "Đỗ Việt Tùng": "xk.tungdv",
344
+ "Phạm Đức Tuấn": "xk.tuanpd",
345
+ "Nguyễn Thanh Xuân": "xk.xuannt",
346
+ "Nguyễn Đoàn Thanh": "xk.thanhnd",
347
+ "Hoàng Ngọc Anh": "TV01.Anhhn",
348
+ "Nguyễn Tiến Dũng": "NCTT.Dungnt",
349
+ "Đào Xuân Dũng": "TT2.DungDX",
350
+ "Nguyễn Thế Kỳ Nam": "dn.namntk",
351
+ "Nguyễn Đắc Hùng": "TT1.hungnd",
352
+ "Biên tập nội dung SAMS": "SAMS",
353
+ "Lê Tấn Phát": "TV02.PhatLT",
354
+ "Trần Văn Tiến": "gdv_tientv",
355
+ "Nguyễn Tuấn Tân": "TMDT.Tannt",
356
+ "Kiều Thanh Loan": "gdv_loankt",
357
+ "Bùi Ngọc Thu": "gdv_thubn",
358
+ "Nguyễn Thuỳ Trang": "gdv_trangnt",
359
+ "Lê Thị Thuý Hiền": "C4LED.HienLTT",
360
+ "Nguyễn Văn Diễn": "gdv_diennv",
361
+ "Đặng Quỳnh Trang": "hoasao02",
362
+ "Nguyễn Thị Minh Hoa": "hoasao01",
363
+ "Nguyễn Văn Tỉnh": "TN.TinhNV",
364
+ "Đặng Thanh Hải": "BH.HaiDT",
365
+ "Ngô Thị kim Oanh": "NT.OanhNTK",
366
+ "Võ Thị Kim Anh": "TG.AnhVTK",
367
+ "Phạm Vũ Thiện": "TT1.ThienPV",
368
+ "Chu Minh Quân": "TT1.QuanCM",
369
+ "Lê Việt Hùng": "TT1.HungLV",
370
+ "Lã Thị Hải Yến": "PPMB.YenLTH",
371
+ "Nguyễn Lê Thăng": "PPMB.ThangNL",
372
+ "Tôn Nữ Thanh Thiện": "PPMN.ThienTNT",
373
+ "Lê Minh Tuấn": "PPMN.TuanLM",
374
+ "Đào Thị Ngát": "QLHT.NgatDT",
375
+ "Nguyễn thị Kim Ngân": "KH.NganNTK",
376
+ "Khúc Chí Tùng": "KH.TungKC",
377
+ "Quách Thành Chương": "KH.ChuongQT",
378
+ "Nguyễn Văn Thảo": "C4LED.ThaoNV",
379
+ "Lê Ngọc Lâm": "C4LED.LamLN",
380
+ "Lê Đức Anh": "C4LED.AnhLD",
381
+ "Nguyễn Triệu Sơn": "C4LED.SonNT",
382
+ "Trần Thanh Hải": "TV03.HaiTT",
383
+ "Lương Phước Tạo": "CT.TaoLP",
384
+ "Mai Việt Bình": "TV03.BinhMV",
385
+ "Xuong": "Xuong",
386
+ "C4LED": "C4LED",
387
+ "Trangnt": "CRM.Trangnt",
388
+ "Nguyễn Phi Long": "TV03.LongNP",
389
+ "Võ Tòng Bá": "CT.BaVT",
390
+ "Trần Nhật Tuấn": "tv03.tuantn",
391
+ "Nguyễn Văn Thiện": "dn.thiennv",
392
+ "Mai Phúc Huy": "HCM.HuyMP",
393
+ "Huỳnh Thị Bích Thúy": "TMDT.ThuyHTB",
394
+ "Nguyễn Ngọc Thiện": "TT3.ThienNN",
395
+ "Nguyễn Trọng Phan": "TV02.PhanNT",
396
+ "Phạm Đắc Quyết": "TV02.QuyetPD",
397
+ "Bùi Văn Minh": "HCM.MinhBV",
398
+ "Vũ Thế Hiếu": "TMDT.hieuvt",
399
+ "Võ Trần Chánh": "BH.ChanhVT",
400
+ "test02": "test02",
401
+ "Nguyễn Văn Minh": "TV03.MinhNV",
402
+ "Lê Tuấn Anh (TMDT)": "TMDT.AnhLT",
403
+ "Phạm Minh Thảo": "TG.ThaoPM",
404
+ "Trần Viết Bình": "TT3.BinhTV",
405
+ "Lượng Phú Thấp": "NT.ThapLP",
406
+ "Đỗ Trường Giang": "TV03.GiangDT",
407
+ "Hà Quân Hiệu": "TV03.HieuHQ",
408
+ "Lương Quang Thắng": "TV02.ThangLQ",
409
+ "Nguyễn Thế Công": "TV02.CongNT",
410
+ "Vũ Đức Khoa": "TV02.KhoaVD",
411
+ "Đào Văn Thảo": "TV02.ThaoDV",
412
+ "Ngô Huy Xuân": "TV02.XuanNH",
413
+ "Hồ Sỹ Dũng": "TV01.DungHS",
414
+ "Lê Văn Linh": "TV01.LinhLV",
415
+ "Trần Bá Tăng": "TV01.TangTB",
416
+ "Trần Tiến Dương": "TV01.DuongTT",
417
+ "Phạm Văn Anh": "TV02.Anhpv",
418
+ "Nguyễn Quốc Dũng": "TT2.DungNQ",
419
+ "Võ Quang Thiện": "TT2.ThienVQ",
420
+ "Nguyễn Hoàng Nam": "TG.NamNH",
421
+ "Nguyễn Hồng Đăng": "TG.DangNH",
422
+ "Nguyễn Thành Khương": "NT.KhuongNT",
423
+ "Ngô Quốc Huy": "NT.HuyNQ",
424
+ "Phan Tấn Linh": "NT.LinhPT",
425
+ "Bùi Vĩnh Nguyên": "HCM.NguyenBV",
426
+ "Trần Phú Cường": "HCM.CuongTP",
427
+ "Trần Ngọc Trọng": "HCM.TrongTN",
428
+ "Nguyễn Thụy Hồng Đô": "HCM.DoNTH",
429
+ "Vũ Hồng Vân": "DN.VanVH",
430
+ "Tống Phước Anh Duy": "DN.DuyTPA",
431
+ "Thái Thành Trung": "DN.TrungTT",
432
+ "Lê Trúc": "DN.TrucLe",
433
+ "Nguyễn Trọng Nguyễn": "CT.NguyenNT",
434
+ "Nguyễn Đức Phục": "CT.PhucND",
435
+ "Lý Văn Bình": "CT.BinhLV",
436
+ "Đào Thị Thu Hường": "BH.HuongDTT",
437
+ "Lưu văn Tuấn": "BH.TuanLV",
438
+ "Vũ Thanh Tuấn": "BH.TuanVT",
439
+ "Nguyễn Hữu Duyên": "BH.DuyenNH",
440
+ "Nguyễn Văn Quyết": "TV02.QuyetNV",
441
+ "Nguyễn Hải Đăng": "TV02.DangNH",
442
+ "Nguyễn Duy Quang": "HCM.QuangND",
443
+ "Trần Phước Huy": "DN.HuyTP",
444
+ "Nguyễn Long Thái": "rd.thainl",
445
+ "App Reviewer": "app.reviewer",
446
+ "Nguyễn Anh Đức": "rd.ducna",
447
+ "Hoàng Thanh Thủy": "ppmb.thuyht",
448
+ "Trần Mạnh Dũng": "TV02.DungTM",
449
+ "Nguyễn Duy Hải": "tv02.haind",
450
+ "Trần Văn Nhân": "TV03.NhanTV",
451
+ "Trần Lê Mạnh": "TV03.ManhTL",
452
+ "Hà Tùng Lâm": "TV03.LamHT",
453
+ "Nguyễn Hồng Hoàng": "TV03.HoangNH",
454
+ "Trần Thanh Hiếu": "TV03.HieuTT",
455
+ "Lê Chính Cương": "TV03.CuongLC",
456
+ "Ngô Pháp Anh": "TV03.AnhNP",
457
+ "Trần Minh Việt": "TV02.VietTM",
458
+ "Ngô Quang Vấn": "TV02.VanNQ",
459
+ "Đinh Trọng Uẩn": "TV02.UanDT",
460
+ "Phạm Tiến Tùy": "TV02.TuyPT",
461
+ "Đỗ Văn Tùng": "TV02.TungDV",
462
+ "Dương Quốc Trung": "TV02.TrungDQ",
463
+ "Nguyễn Văn Thế": "TV02.TheNV",
464
+ "Ngô Ngọc Thanh": "TV02.ThanhNN",
465
+ "Nguyễn Văn Rinh": "TV02.RinhNV",
466
+ "Nguyễn Văn Quynh": "TV02.QuynhNV",
467
+ "Đinh Văn Quyết": "TV02.QuyetDV",
468
+ "Trần Văn Long": "TV02.LongTV",
469
+ "Văn Tiến Lợi": "TV02.LoiVT",
470
+ "Vũ Văn Khởi": "TV02.KhoiVV",
471
+ "Trần Văn Đồng": "TV02.DongTV",
472
+ "Nguyễn Văn Cương": "TV02.CuongNV",
473
+ "Nguyễn Ngọc Anh": "TV02.AnhNN",
474
+ "Đỗ Tuấn Anh": "TV02.AnhDT",
475
+ "Nguyễn Minh Toàn": "TV01.ToanNM",
476
+ "Bùi Văn Thọ": "TV01.ThoBV",
477
+ "Bùi Tất Thành": "TV01.ThanhBT",
478
+ "Nguyễn Hồng Lĩnh": "TV01.LinhNH",
479
+ "Đoàn Văn Liêu": "TV01.LieuDV",
480
+ "Nguyễn Văn Lập": "TV01.LapNV",
481
+ "Đỗ Văn Khởi": "TV01.KhoiDV",
482
+ "Đỗ Hưng Hà": "TV01.HaDH",
483
+ "Bùi Văn Hùng": "TV01.HungBV",
484
+ "Lê Minh Hiếu": "TV01.HieuLM",
485
+ "Tạ Văn Dương": "TV01.DuongTV",
486
+ "Dương Quốc Chung": "TV01.ChungDQ",
487
+ "Vũ Thái Bình": "TV01.BinhVT",
488
+ "Nguyễn Anh Toàn": "TN.ToanNA",
489
+ "Nguyễn Lương Sự": "TN.SuNL",
490
+ "Đàm Nguyễn Vi Nhân": "TN.NhanDV",
491
+ "Nguyễn Anh Minh": "TN.MinhNA",
492
+ "Nguyễn Văn Hoàng": "TN.HoangNV",
493
+ "Đinh Song Hào": "TN.HaoDS",
494
+ "Bùi Hồ Vũ": "TG.VuBH",
495
+ "Nguyễn Ngọc Tú": "TG.TuNN",
496
+ "Phạm Minh Tuấn": "TG.TuanPM",
497
+ "Nguyễn Anh Tuấn": "TG.TuanNA",
498
+ "Võ Minh Trường": "TG.TruongVM",
499
+ "Phan Minh Trí": "TG.TriPM",
500
+ "Huỳnh Kim Phát": "TG.PhatHK",
501
+ "Phan Văn Hiếu": "TG.HieuPV",
502
+ "Nguyễn Văn Đồi": "TG.DoiNV",
503
+ "Võ Trường An": "TG.AnVT",
504
+ "Quản lý BH1": "PPMB.QLBH1",
505
+ "Nguyễn Ngọc Anh Tú": "NT.TuNNA",
506
+ "Trần Ngọc Sơn": "NT.SonTN",
507
+ "Nguyễn Thái Huy": "NT.HuyNT",
508
+ "Lê Hoài Bảo": "NT.BaoLH",
509
+ "Lương Minh Tuyển": "NCTT.TuyenLM",
510
+ "Trần Xuân Tùng": "NCTT.TungTX",
511
+ "Phạm Đoàn Thắng": "NCTT.ThangPD",
512
+ "Trần Quốc Phong": "NCTT.PhongTQ",
513
+ "Trần Xuân Chính": "NCTT.ChinhTX",
514
+ "Nguyễn Văn Quí": "CT.QuiNV",
515
+ "Trần Trung Liệt": "CT.LietTT",
516
+ "Nguyễn Văn Bé Hai": "CT.HaiNVB",
517
+ "Quản Minh Hoàng Việt": "HCM.VietQMH",
518
+ "Đặng Mạnh Vĩ": "HCM.ViDM",
519
+ "Phan Thanh Tú": "HCM.TuPT",
520
+ "Nguyễn Hoàng Tú": "HCM.TuNH",
521
+ "Nguyễn Trọng Minh Trường": "HCM.TruongNTM",
522
+ "Trần Đức Trọng": "HCM.TrongTD",
523
+ "Nguyễn Hoàng Thiện": "HCM.ThienNH",
524
+ "Huỳnh Ngọc Thành": "HCM.ThanhHN",
525
+ "Đỗ Tiến Quang": "HCM.QuangDT",
526
+ "Phạm Hoàng Minh": "HCM.MinhPH",
527
+ "Nguyễn Văn Luận": "HCM.LuanNV",
528
+ "Nguyễn Sĩ Long": "HCM.LongNS",
529
+ "Nguyễn Minh Đạt": "HCM.DatNM",
530
+ "Nguyễn Văn Binh": "HCM.BinhNV",
531
+ "Ngô Quang Vinh": "DN.VinhNQ",
532
+ "Dương Trung": "DN.TrungDuong",
533
+ "Trần Hồ Bảo Toàn": "DN.ToanTHB",
534
+ "Lê Minh Toàn": "DN.ToanLM",
535
+ "Nguyễn Quý": "DN.QuyN",
536
+ "Phan Thế Phú": "TT2.PhuPT",
537
+ "Nguyễn Thành Nam (TT2)": "TT2.NamNT",
538
+ "Lê Đình Nam": "DN.NamLD",
539
+ "Vương Văn Linh": "DN.LinhVV",
540
+ "Trần Như Lành": "DN.LanhTN",
541
+ "Nguyễn Văn Lâm": "DN.LamNV",
542
+ "Nguyễn Đức Khánh": "DN.KhanhND",
543
+ "Nguyễn Văn Cả": "DN.CaNV",
544
+ "Nguyễn Văn Bình": "DN.BinhNV",
545
+ "Đặng Phạm Minh Trung": "CT.TrungDPM",
546
+ "Nguyễn Trung Thảo": "CT.ThaoNT",
547
+ "Huỳnh Vỉnh Nông": "CT.NongHV",
548
+ "Nguyễn Tuấn Anh": "CT.AnhNT",
549
+ "Nguyễn Xuân Thương": "BH.ThuongNX",
550
+ "Dương Quốc Nguyên": "BH.NguyenDQ",
551
+ "Đinh Xuân Ngọc": "BH.NgocDX",
552
+ "Đặng Hải Nam": "BH.NamDH",
553
+ "Phạm Thành Minh": "BH.MinhPT",
554
+ "Phạm Anh Linh": "BH.LinhPA",
555
+ "Nguyễn Quốc Hậu": "BH.HauNQ",
556
+ "Bùi Đức Hạo": "BH.HaoBD",
557
+ "Nguyễn Phạm Duy": "BH.DuyNP",
558
+ "Bùi Nguyên Dũng": "BH.DungBN",
559
+ "Nguyễn Thế Đoàn": "BH.DoanNT",
560
+ "Vũ Thái An": "BH.AnVT",
561
+ "Đặng Ngọc Anh": "BH.AnhDN",
562
+ "Nguyễn Xuân Trường": "CT.TruongNX",
563
+ "Mai Văn An": "CT.AnMV",
564
+ "Test 01": "Test01",
565
+ "Administrator": "Administrator"
566
+ }
resources/merchant.json ADDED
The diff for this file is too large to render. See raw diff
 
resources/normalization_rule.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "cửa hàng": "ch"
3
+ }
resources/product.json ADDED
The diff for this file is too large to render. See raw diff
 
resources/unit.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Mét": "M",
3
+ "Bộ": "Bo",
4
+ "Cuộn": "Cuon",
5
+ "Chiếc": "Chiec",
6
+ "Thùng 10": "Thung10",
7
+ "Cái": "Cai"
8
+ }