Browse Source

support for banggood

Fabian Peter Hammerle 8 years ago
parent
commit
936f0c602b

+ 32 - 14
dingguo/__init__.py

@@ -112,8 +112,10 @@ class Sum(ScalarFigure):
     def set_unit(self, currency):
         if currency == u'€':
             currency = u'EUR'
+        if currency == u'US$':
+            currency = u'USD'
         assert type(currency) is unicode
-        assert currency in [u'EUR']
+        assert currency in [u'EUR', u'USD']
         super(Sum, self).set_unit(currency)
 
     """ use property() instead of decorator to enable overriding """
@@ -175,6 +177,8 @@ class Order(_YamlUnicodeConstruct):
             ):
         assert type(platform) is unicode
         self.platform = platform
+        if type(order_id) in [int]:
+            order_id = unicode(order_id)
         assert type(order_id) is unicode
         self.order_id = order_id
         if type(order_date) is datetime.datetime:
@@ -279,8 +283,10 @@ class Article(Item):
 
     def __init__(
             self,
-            authors = [],
+            authors = None,
             delivery_date = None,
+            option = None,
+            product_id = None,
             quantity = None,
             reseller = None,
             shipper = None,
@@ -290,14 +296,26 @@ class Article(Item):
         super(Article, self).__init__(**kwargs)
         assert type(quantity) is int
         self.quantity = quantity
-        assert type(authors) is list
-        self.authors = authors
-        assert state is None or type(state) is unicode
-        self.state = state
-        assert reseller is None or type(reseller) is unicode
-        self.reseller = reseller
-        assert shipper is None or type(shipper) is unicode
-        self.shipper = shipper
+        if authors is not None:
+            assert type(authors) is list
+            self.authors = authors
+        if state is not None:
+            assert type(state) is unicode
+            self.state = state
+        if reseller is not None:
+            assert type(reseller) is unicode
+            self.reseller = reseller
+        if shipper is not None:
+            assert type(shipper) is unicode
+            self.shipper = shipper
+        if product_id is not None:
+            if type(product_id) in [int]:
+                product_id = unicode(product_id)
+            assert type(product_id) is unicode
+            self.product_id = product_id
+        if option is not None:
+            assert type(option) is unicode
+            self.option = option
         assert delivery_date is None or type(delivery_date) is datetime.date
         self.delivery_date = delivery_date
 
@@ -306,11 +324,11 @@ class Article(Item):
         attr.update({
             'delivery_date': self.delivery_date,
             'quantity': self.quantity,
-            'reseller': self.reseller,
-            'shipper': self.shipper,
-            'state': self.state,
+            'reseller': self.reseller if hasattr(self, 'reseller') else None,
+            'shipper': self.shipper if hasattr(self, 'shipper') else None,
+            'state': self.state if hasattr(self, 'state') else None,
             })
-        if len(self.authors) > 0:
+        if hasattr(self, 'authors') and len(self.authors) > 0:
             attr['authors'] = self.authors
         return attr
 

+ 54 - 0
dingguo/parser/banggood.py

@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+import BeautifulSoup
+import datetime
+import dingguo
+import email.message
+import ioex
+import re
+
+def parse_order_confirmation_mail(mail):
+
+    assert isinstance(mail, email.message.Message)
+
+    html = mail.get_payload()[1].get_payload(decode = True).decode('utf-8')
+    doc = BeautifulSoup.BeautifulSoup(html)
+
+    """ Your Order#13998883(placed on Saturday 16 April, 2016)"""
+    order_attr = re.search(
+            ur'Your Order#(?P<id>\d+)\(placed on (?P<date>.*)\)',
+            doc.find(text = re.compile(r'placed on')).parent.text,
+            re.UNICODE,
+            ).groupdict()
+
+    with ioex.setlocale('en_US.UTF-8'):
+        order = dingguo.Order(
+                platform = u'banggood',
+                order_id = order_attr['id'],
+                order_date = datetime.datetime.strptime(order_attr['date'], '%A %d %B, %Y'),
+                customer_id = None,
+                )
+
+    """ 1 x 10X E27 LED Bulb 7W Warm White 36 SMD 5730 AC 220V Corn Light (10xPOA162664)€23.431 x 5X E14 7W Warm White 36 SMD 5730 LED Corn Light Lamp Bulbs AC 220V (5xPOA162668)€12.31 """
+    articles_text = doc.find(text = re.compile(r'Subtotal of Items')) \
+            .parent.parent.text.replace('&nbsp;', ' ') \
+            .split('Subtotal of Items:')[1].split('IMPORTANT NOTICE')[0]
+    for article_match in re.finditer(
+            ur'(?P<quantity>\d+) x (?P<name>[^\(]*) \((\d+x)?(?P<id>[^\)]+)\)'
+                + ur'(?P<currency>[^\d]+)(?P<price>\d+.\d\d)(?P<option>((?!\d+ x).)+)?',
+            articles_text,
+            re.UNICODE,
+            ):
+        attr = article_match.groupdict()
+        order.items.append(dingguo.Article(
+            name = attr['name'],
+            option = attr['option'],
+            price_brutto = dingguo.Sum(
+                float(attr['price']) / float(attr['quantity']),
+                attr['currency'],
+                ),
+            product_id = attr['id'],
+            quantity = int(attr['quantity']),
+            ))
+
+    return [order]

+ 6 - 0
scripts/order-confirmation-mail-parser

@@ -3,6 +3,7 @@
 # PYTHON_ARGCOMPLETE_OK
 
 import dingguo
+import dingguo.parser.banggood
 
 import re
 import os
@@ -474,6 +475,11 @@ def parse(msg):
     except:
         tracebacks['amazon'] = traceback.format_exc()
 
+    try:
+        return dingguo.parser.banggood.parse_order_confirmation_mail(msg)
+    except:
+        tracebacks['banggood'] = traceback.format_exc()
+
     try:
         return parse_oebb(msg)
     except:

+ 4 - 1
tests/test_.py

@@ -7,8 +7,11 @@ import dingguo
 import yaml
 import os
 
-def test_sum_init():
+def test_sum_init_eur():
     assert dingguo.Sum(1.23, u'EUR') == dingguo.Sum(1.23, u'€')
 
+def test_sum_init_usd():
+    assert dingguo.Sum(1.23, u'USD') == dingguo.Sum(1.23, u'US$')
+
 def test_distance_metres():
     assert int(dingguo.Distance(1.23, u'km').metres) == 1230

+ 24 - 0
tests/test_parser_banggood.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+import pytest
+
+import dingguo.parser.banggood
+import email
+import glob
+import os
+import test_yaml
+import yaml
+
+project_root_path = os.path.realpath(os.path.join(__file__, '..', '..'))
+test_data_path = os.path.join(project_root_path, 'tests', 'data', 'banggood')
+
+@pytest.mark.parametrize('mail_path', glob.glob(os.path.join(test_data_path, '*.eml')))
+def test_parse_confirmation_mail(mail_path):
+    with open(mail_path) as mail:
+        parsed_orders = dingguo.parser.banggood.parse_order_confirmation_mail(
+                email.message_from_file(mail)
+                )
+    with open(mail_path.replace('.eml', '.yml')) as yaml_file:
+        expected_orders = yaml.load(yaml_file.read())
+    assert expected_orders == parsed_orders, \
+            test_yaml.yaml_diff(expected_orders, parsed_orders)

+ 4 - 1
tests/test_yaml.py

@@ -37,6 +37,7 @@ def get_article():
             authors = ['a', 'b'],
             name = u'article name',
             price_brutto = get_sum_a(),
+            product_id = u'0815',
             quantity = 1,
             reseller = u'seller',
             shipper = u'shipper',
@@ -254,13 +255,14 @@ authors:
 delivery_date: null
 name: article name
 price_brutto: !sum '1.23 EUR'
+product_id: 0815
 quantity: 1
 reseller: seller
 shipper: shipper
 state: goood
 """
 
-def test_article_to_yaml():
+def test_article_from_yaml():
     assert get_article() == yaml.load(u"""!article
 authors:
 - a
@@ -268,6 +270,7 @@ authors:
 delivery_date: null
 name: article name
 price_brutto: !sum '1.23 EUR'
+product_id: 0815
 quantity: 1
 reseller: seller
 shipper: shipper