label-sorter 0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- label_sorter-0.1/LICENSE +21 -0
- label_sorter-0.1/PKG-INFO +58 -0
- label_sorter-0.1/README.md +34 -0
- label_sorter-0.1/label_sorter/__init__.py +1 -0
- label_sorter-0.1/label_sorter/core.py +162 -0
- label_sorter-0.1/label_sorter.egg-info/PKG-INFO +58 -0
- label_sorter-0.1/label_sorter.egg-info/SOURCES.txt +11 -0
- label_sorter-0.1/label_sorter.egg-info/dependency_links.txt +1 -0
- label_sorter-0.1/label_sorter.egg-info/top_level.txt +1 -0
- label_sorter-0.1/pyproject.toml +0 -0
- label_sorter-0.1/setup.cfg +4 -0
- label_sorter-0.1/setup.py +26 -0
- label_sorter-0.1/tests/test_core.py +26 -0
label_sorter-0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Harilal Sunil
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: label_sorter
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: Library to sort Amazon and Shopify shipping labels
|
|
5
|
+
Home-page: https://github.com/harilal766/Ecommerce-label-sorter
|
|
6
|
+
Author: Harry19967
|
|
7
|
+
Author-email: harilalsunil2@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# Ecom-label-sorter
|
|
26
|
+
|
|
27
|
+
## Description:
|
|
28
|
+
1. A python program to sort Amazon and Shopify pdf shipping labels.
|
|
29
|
+
2. Each sorted group of orders will be stored in a dedicated pdf file which is named after the product name and quantity.
|
|
30
|
+
3. On Miscellaneous orders these pdf file will be named "Mixed".
|
|
31
|
+
4. All of these files will be stored inside a folder which is named after the input pdf file.
|
|
32
|
+
|
|
33
|
+
## Reason to develop this project
|
|
34
|
+
Manually sorting a large PDF containing multiple orders is time-consuming and prone to human error.
|
|
35
|
+
|
|
36
|
+
# Installation
|
|
37
|
+
```
|
|
38
|
+
pip install ecom_label_sorter
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
# Usage
|
|
42
|
+
```
|
|
43
|
+
from label_sorter import Label_sorter
|
|
44
|
+
|
|
45
|
+
sorter_instance = Label(pdf_path = <path to the pdf file>)
|
|
46
|
+
|
|
47
|
+
# Creating sorted pdf files
|
|
48
|
+
# this will create a folder named after the pdf file and will be containig sorted pdf files and summary json fle.
|
|
49
|
+
sorter_instance.created_sorted_pdf_files()
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Classes and their descriptions
|
|
57
|
+
|
|
58
|
+
[ Label Sorter](docs/Label_Sorter.md)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Ecom-label-sorter
|
|
2
|
+
|
|
3
|
+
## Description:
|
|
4
|
+
1. A python program to sort Amazon and Shopify pdf shipping labels.
|
|
5
|
+
2. Each sorted group of orders will be stored in a dedicated pdf file which is named after the product name and quantity.
|
|
6
|
+
3. On Miscellaneous orders these pdf file will be named "Mixed".
|
|
7
|
+
4. All of these files will be stored inside a folder which is named after the input pdf file.
|
|
8
|
+
|
|
9
|
+
## Reason to develop this project
|
|
10
|
+
Manually sorting a large PDF containing multiple orders is time-consuming and prone to human error.
|
|
11
|
+
|
|
12
|
+
# Installation
|
|
13
|
+
```
|
|
14
|
+
pip install ecom_label_sorter
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
# Usage
|
|
18
|
+
```
|
|
19
|
+
from label_sorter import Label_sorter
|
|
20
|
+
|
|
21
|
+
sorter_instance = Label(pdf_path = <path to the pdf file>)
|
|
22
|
+
|
|
23
|
+
# Creating sorted pdf files
|
|
24
|
+
# this will create a folder named after the pdf file and will be containig sorted pdf files and summary json fle.
|
|
25
|
+
sorter_instance.created_sorted_pdf_files()
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Classes and their descriptions
|
|
33
|
+
|
|
34
|
+
[ Label Sorter](docs/Label_Sorter.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .core import LabelSorter
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import pdfplumber, re, os,sys, logging, json
|
|
2
|
+
from pypdf import PdfReader, PdfWriter
|
|
3
|
+
from pprint import pprint
|
|
4
|
+
from label_sorter.platforms.ecommerce.base_label import BaseLabel
|
|
5
|
+
from label_sorter.platforms.ecommerce.shopify import ShopifyLabel
|
|
6
|
+
from label_sorter.platforms.ecommerce.amazon import AmazonLabel
|
|
7
|
+
|
|
8
|
+
logging.getLogger('pdfminer').setLevel(logging.ERROR)
|
|
9
|
+
|
|
10
|
+
class LabelSorter:
|
|
11
|
+
def __init__(self, pdf_path):
|
|
12
|
+
self.sorted_dict = {}
|
|
13
|
+
self.label_filepath = pdf_path
|
|
14
|
+
self.output_folder = self.label_filepath.replace(".pdf","")
|
|
15
|
+
self.platform = self.find_platform()
|
|
16
|
+
|
|
17
|
+
def find_platform(self) -> str:
|
|
18
|
+
platform = None
|
|
19
|
+
try:
|
|
20
|
+
with pdfplumber.open(self.label_filepath) as pdf_file:
|
|
21
|
+
total_pages = 0; amazon_count = 0
|
|
22
|
+
|
|
23
|
+
shopify_order_id_count, amazon_order_id_count = 0, 0
|
|
24
|
+
|
|
25
|
+
for page_index, page in enumerate(pdf_file.pages):
|
|
26
|
+
total_pages += 1
|
|
27
|
+
page_text = page.extract_text(); page_tables = page.extract_tables()
|
|
28
|
+
|
|
29
|
+
# Shopify Initializations
|
|
30
|
+
sh = ShopifyLabel(page_text=page_text, page_table=page_tables,page_num=0)
|
|
31
|
+
am = AmazonLabel(page_text=page_text, page_table=page_tables,page_num=0)
|
|
32
|
+
|
|
33
|
+
if re.findall(sh.shopify_order_id_pattern, page_text):
|
|
34
|
+
shopify_order_id_count += 1
|
|
35
|
+
elif re.findall(am.amazon_order_id_pattern, page_text):
|
|
36
|
+
amazon_order_id_count += 1
|
|
37
|
+
|
|
38
|
+
if total_pages == shopify_order_id_count:
|
|
39
|
+
platform = "Shopify"
|
|
40
|
+
# this condition is not complete, need to add overlap page detection
|
|
41
|
+
elif amazon_order_id_count > 0:
|
|
42
|
+
platform = "Amazon"
|
|
43
|
+
|
|
44
|
+
except FileNotFoundError:
|
|
45
|
+
print(f"The file {self.label_filepath} does not exist.")
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print(e)
|
|
48
|
+
else:
|
|
49
|
+
return platform
|
|
50
|
+
|
|
51
|
+
def create_sorted_summary(self):
|
|
52
|
+
if not self.platform:
|
|
53
|
+
sys.exit("Unsupported Platform, exiting....")
|
|
54
|
+
page_debrief = None
|
|
55
|
+
try:
|
|
56
|
+
print(f"Platform : {self.platform}")
|
|
57
|
+
with pdfplumber.open(self.label_filepath) as pdf_file:
|
|
58
|
+
for page_index, page in enumerate(pdf_file.pages):
|
|
59
|
+
page_text = page.extract_text(); page_table = page.extract_tables()
|
|
60
|
+
page_number = page_index+1
|
|
61
|
+
|
|
62
|
+
#Label_instance = BaseLabel(page_text=page_text, page_table=page_table,page_num=page_number)
|
|
63
|
+
debriefs = {
|
|
64
|
+
"Shopify" : ShopifyLabel(page_text=page_text, page_table=page_table,page_num=page_number).analyze_shpy_page(),
|
|
65
|
+
"Amazon" : AmazonLabel(page_text=page_text, page_table=page_table,page_num=page_number).analyze_amzn_page(),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
page_debrief = debriefs[self.platform]
|
|
69
|
+
|
|
70
|
+
print(f"{page_number} : {page_debrief}")
|
|
71
|
+
|
|
72
|
+
is_page_debrief_populated = page_debrief["order_id"] != None
|
|
73
|
+
# sorting summary
|
|
74
|
+
if self.platform and is_page_debrief_populated:
|
|
75
|
+
self.populate_shipment_summary(
|
|
76
|
+
sorting_key=page_debrief["sorting_key"], qty=page_debrief["qty"],
|
|
77
|
+
page_nums=[page_number - 1, page_number] if self.platform == "Amazon" else [page_number]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
except FileNotFoundError as fe:
|
|
81
|
+
print(fe)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(e)
|
|
84
|
+
else:
|
|
85
|
+
return self.sorted_dict
|
|
86
|
+
|
|
87
|
+
def populate_shipment_summary(self, sorting_key:str, page_nums:list, qty : str) -> None:
|
|
88
|
+
try:
|
|
89
|
+
# different conditions for mixed and single items
|
|
90
|
+
# sorting key initialization
|
|
91
|
+
numbers_list = None
|
|
92
|
+
# Adding sorting key if not present
|
|
93
|
+
if sorting_key not in self.sorted_dict.keys():
|
|
94
|
+
self.sorted_dict[sorting_key] = [] if sorting_key == "Mixed" else {}
|
|
95
|
+
|
|
96
|
+
if sorting_key == "Mixed":
|
|
97
|
+
numbers_list = self.sorted_dict[sorting_key]
|
|
98
|
+
else:
|
|
99
|
+
if qty not in self.sorted_dict[sorting_key].keys():
|
|
100
|
+
self.sorted_dict[sorting_key][qty] = []
|
|
101
|
+
numbers_list = self.sorted_dict[sorting_key][qty]
|
|
102
|
+
numbers_list += page_nums
|
|
103
|
+
|
|
104
|
+
except Exception as e:
|
|
105
|
+
print(e)
|
|
106
|
+
|
|
107
|
+
def create_single_pdf_file(self, pdf_name, page_numbers):
|
|
108
|
+
try:
|
|
109
|
+
reader = PdfReader(self.label_filepath); writer = PdfWriter()
|
|
110
|
+
print(pdf_name, page_numbers)
|
|
111
|
+
# adding pages to the writer
|
|
112
|
+
for page in page_numbers:
|
|
113
|
+
writer.add_page(reader.pages[page-1])
|
|
114
|
+
|
|
115
|
+
page_count = len(page_numbers)
|
|
116
|
+
order_count = int(page_count/2) if self.platform == "Amazon" else page_count
|
|
117
|
+
|
|
118
|
+
sorted_pdf_file = f"{re.sub(r"[\|\.]*",r"",pdf_name)} - {order_count} order{"s" if order_count > 1 else ""}.pdf"
|
|
119
|
+
except Exception as e:
|
|
120
|
+
print(e)
|
|
121
|
+
else:
|
|
122
|
+
if writer:
|
|
123
|
+
if sorted_pdf_file:
|
|
124
|
+
out_filepath = os.path.join(self.output_folder, sorted_pdf_file)
|
|
125
|
+
with open(out_filepath, "wb") as out_pdf:
|
|
126
|
+
writer.write(out_pdf)
|
|
127
|
+
|
|
128
|
+
def create_sorted_pdf_files(self):
|
|
129
|
+
summary_dict = self.create_sorted_summary()
|
|
130
|
+
|
|
131
|
+
#pprint(summary_dict.keys())
|
|
132
|
+
|
|
133
|
+
if len(summary_dict.keys()) == 0:
|
|
134
|
+
sys.exit("Cannot sort with empty summary...")
|
|
135
|
+
|
|
136
|
+
order_count = None; page_numbers = None
|
|
137
|
+
output_file = None
|
|
138
|
+
|
|
139
|
+
# Create output folder if not created already.
|
|
140
|
+
if not os.path.exists(self.output_folder):
|
|
141
|
+
os.makedirs(self.output_folder)
|
|
142
|
+
print(f"Created output folder : {self.output_folder}")
|
|
143
|
+
|
|
144
|
+
# save the summary as a json file to the output folder
|
|
145
|
+
with open(f"{self.output_folder}/summary.json","w") as summary_json:
|
|
146
|
+
json.dump(summary_dict, summary_json)
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
print(f"Sorted Summary :")
|
|
150
|
+
for sorting_key, value in summary_dict.items():
|
|
151
|
+
# Assigning output file name and its pages according to order type
|
|
152
|
+
# Mixed orders
|
|
153
|
+
if type(value) == list:
|
|
154
|
+
self.create_single_pdf_file(pdf_name=sorting_key, page_numbers=value)
|
|
155
|
+
# single item orders
|
|
156
|
+
elif type(value) == dict:
|
|
157
|
+
#print(f"Writing Single item order",end=", ")
|
|
158
|
+
for qty,page_list in value.items():
|
|
159
|
+
#print(f"Detected more than one qty.")
|
|
160
|
+
self.create_single_pdf_file(pdf_name=f"{sorting_key} - {qty}", page_numbers=page_list)
|
|
161
|
+
except Exception as e:
|
|
162
|
+
print(f"Err : {e}")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: label_sorter
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: Library to sort Amazon and Shopify shipping labels
|
|
5
|
+
Home-page: https://github.com/harilal766/Ecommerce-label-sorter
|
|
6
|
+
Author: Harry19967
|
|
7
|
+
Author-email: harilalsunil2@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# Ecom-label-sorter
|
|
26
|
+
|
|
27
|
+
## Description:
|
|
28
|
+
1. A python program to sort Amazon and Shopify pdf shipping labels.
|
|
29
|
+
2. Each sorted group of orders will be stored in a dedicated pdf file which is named after the product name and quantity.
|
|
30
|
+
3. On Miscellaneous orders these pdf file will be named "Mixed".
|
|
31
|
+
4. All of these files will be stored inside a folder which is named after the input pdf file.
|
|
32
|
+
|
|
33
|
+
## Reason to develop this project
|
|
34
|
+
Manually sorting a large PDF containing multiple orders is time-consuming and prone to human error.
|
|
35
|
+
|
|
36
|
+
# Installation
|
|
37
|
+
```
|
|
38
|
+
pip install ecom_label_sorter
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
# Usage
|
|
42
|
+
```
|
|
43
|
+
from label_sorter import Label_sorter
|
|
44
|
+
|
|
45
|
+
sorter_instance = Label(pdf_path = <path to the pdf file>)
|
|
46
|
+
|
|
47
|
+
# Creating sorted pdf files
|
|
48
|
+
# this will create a folder named after the pdf file and will be containig sorted pdf files and summary json fle.
|
|
49
|
+
sorter_instance.created_sorted_pdf_files()
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Classes and their descriptions
|
|
57
|
+
|
|
58
|
+
[ Label Sorter](docs/Label_Sorter.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
label_sorter/__init__.py
|
|
6
|
+
label_sorter/core.py
|
|
7
|
+
label_sorter.egg-info/PKG-INFO
|
|
8
|
+
label_sorter.egg-info/SOURCES.txt
|
|
9
|
+
label_sorter.egg-info/dependency_links.txt
|
|
10
|
+
label_sorter.egg-info/top_level.txt
|
|
11
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
label_sorter
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
this_directory = Path(__file__).parent
|
|
5
|
+
long_description = (this_directory / "README.md").read_text()
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name="label_sorter",
|
|
9
|
+
version="0.1",
|
|
10
|
+
packages=["label_sorter"],
|
|
11
|
+
install_requires = [
|
|
12
|
+
|
|
13
|
+
],
|
|
14
|
+
author = "Harry19967",
|
|
15
|
+
author_email="harilalsunil2@gmail.com",
|
|
16
|
+
description = "Library to sort Amazon and Shopify shipping labels",
|
|
17
|
+
url= "https://github.com/harilal766/Ecommerce-label-sorter",
|
|
18
|
+
license = "MIT",
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Operating System :: OS Independent"
|
|
22
|
+
],
|
|
23
|
+
python_requires = ">=3.9",
|
|
24
|
+
long_description=long_description,
|
|
25
|
+
long_description_content_type='text/markdown'
|
|
26
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import sys, os, pytest
|
|
2
|
+
|
|
3
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
4
|
+
|
|
5
|
+
from filepaths import amazon_pdf, shopify_pdf
|
|
6
|
+
from label_sorter.core import LabelSorter
|
|
7
|
+
|
|
8
|
+
class Test_LabelSorter:
|
|
9
|
+
label_inst = LabelSorter(pdf_path=shopify_pdf)
|
|
10
|
+
|
|
11
|
+
files = {
|
|
12
|
+
"Shopify" : shopify_pdf,
|
|
13
|
+
"Amazon" : amazon_pdf
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def test_find_platfrom(self):
|
|
17
|
+
for key,value in self.files.items():
|
|
18
|
+
inst = LabelSorter(pdf_path=value)
|
|
19
|
+
assert inst.find_platform() == key
|
|
20
|
+
|
|
21
|
+
def test_sort_label(self):
|
|
22
|
+
assert len(self.label_inst.create_sorted_summary().keys()) > 0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# need more tests for mixed orders and amazon qr page
|
|
26
|
+
|