10 Commits 397aaa3337 ... a9e24b4aaf

Author SHA1 Message Date
  Jocelyn Delalande a9e24b4aaf Merge remote-tracking branch 'ARN/fix-misc-stuff-in-csv-import_' 6 years ago
  ljf 571df323fe Merge branch 'fix-requirements' of FFDN/coin into master 6 years ago
  ljf 5b37a3fbe5 [fix] Fix loalize issue due to missing requirements 6 years ago
  Jocelyn Delalande aa02805c73 Merge remote-tracking branch 'ARN/enh-disable-invoice-comment_' 6 years ago
  Alexandre Aubin a6e9e7ed4d Specify unidecode version 7 years ago
  Alexandre Aubin f652fb8de9 Document INVOICES_INCLUDE_CONFIG_COMMENTS in README 7 years ago
  Alexandre Aubin f2a4464f89 Change setting name to be more explicit 7 years ago
  ljf 413b1138a6 [enh] Disable invoice comment 7 years ago
  ljf 3d36136d63 [enh] Convert iso to utf8 csv file 7 years ago
  Alexandre Aubin 1192b2c094 Misc fixes/improvements in CSV import from bank and matching 7 years ago

+ 1 - 0
README.md

@@ -343,6 +343,7 @@ List of available settings in your `settings_local.py` file.
 - `PAYMENT_DELAY`: Payment delay in days for issued invoices ( default is 30 days which is the default in french law)
 - `MEMBER_CAN_EDIT_PROFILE`: Allow members to edit their profiles
 - `HANDLE_BALANCE`: Allows to handle money balances for members (False default)
+- `INVOICES_INCLUDE_CONFIG_COMMENTS`: Add comment related to a subscription configuration when generating invoices
 
 Accounting logs
 ---------------

+ 3 - 2
coin/billing/create_subscriptions_invoices.py

@@ -11,7 +11,7 @@ from django.core.exceptions import ObjectDoesNotExist
 from coin.offers.models import Offer, OfferSubscription
 from coin.members.models import Member
 from coin.billing.models import Invoice, InvoiceDetail
-
+from django.conf import settings
 
 def create_all_members_invoices_for_a_period(date=None):
     """
@@ -140,7 +140,8 @@ def create_member_invoice_for_a_period(member, date):
                 # à la facture
                 label = offer.name
                 try:
-                    if (offer_subscription.configuration.comment):
+                    if settings.INVOICES_INCLUDE_CONFIG_COMMENTS and \
+                    (offer_subscription.configuration.comment):
                         label += " (%s)" % offer_subscription.configuration.comment
                 except ObjectDoesNotExist:
                     pass

+ 28 - 11
coin/billing/management/commands/import_payments_from_csv.py

@@ -27,6 +27,8 @@ import logging
 import os
 import re
 
+import unidecode
+
 # Django specific imports
 from argparse import RawTextHelpFormatter
 from django.core.management.base import BaseCommand, CommandError
@@ -45,7 +47,7 @@ DATE_FORMAT="%d/%m/%Y"
 ID_REGEX=r"(?i)(\b|_)ID[\s\-\_\/]*(\d+)(\b|_)"
 # If the label of the payment contains one of these, the payment won't be
 # matched to a member when importing it.
-KEYWORDS_TO_NOTMATCH=[ "DON", "MECENAT", "REM CHQ" ]
+KEYWORDS_TO_NOTMATCH=[ "REM CHQ" ]
 
 class Command(BaseCommand):
 
@@ -76,9 +78,10 @@ class Command(BaseCommand):
     def handle(self, *args, **options):
 
         assert options["filename"] != ""
-
         if not os.path.isfile(options["filename"]):
             raise CommandError("This file does not exists.")
+        os.system("iconv -f ISO-8859-1 -t UTF-8 %s > %s.utf8.csv" % (options["filename"], options["filename"]))
+        options["filename"] = options["filename"] + '.utf8.csv'
 
         payments = self.convert_csv_to_dicts(self.clean_csv(self.load_csv(options["filename"])))
 
@@ -189,13 +192,14 @@ class Command(BaseCommand):
 
     def try_to_match_payment_with_members(self, payments):
 
-        members = Member.objects.filter(status="member")
+        #members = Member.objects.filter(status="member")
+        members = Member.objects.all()
 
         idregex = re.compile(ID_REGEX)
 
         for payment in payments:
 
-            payment_label = payment["label"]
+            payment_label = payment["label"].upper()
 
             # First, attempt to match the member ID
             idmatches = idregex.findall(payment_label)
@@ -211,11 +215,14 @@ class Command(BaseCommand):
             # Second, attempt to find the username
             usernamematch = None
             for member in members:
-                matches = re.compile(r"(?i)(\b|_)"+re.escape(member.username)+r"(\b|_)") \
+                username = self.flatten(member.username)
+                matches = re.compile(r"(?i)(\b|_)"+re.escape(username)+r"(\b|_)") \
                             .findall(payment_label)
+
                 # If not found, try next
                 if len(matches) == 0:
                     continue
+
                 # If we already had a match, abort the whole search because we
                 # have multiple usernames matched !
                 if usernamematch != None:
@@ -236,23 +243,31 @@ class Command(BaseCommand):
                 if member.last_name == "":
                     continue
 
-                matches = re.compile(r"(?i)(\b|_)"+re.escape(str(member.last_name))+r"(\b|_)") \
+                # "Flatten" accents in the last name... (probably the CSV
+                # don't contain 'special' chars like accents
+                member_last_name = self.flatten(member.last_name)
+
+                matches = re.compile(r"(?i)(\b|_)"+re.escape(member_last_name)+r"(\b|_)") \
                             .findall(payment_label)
+
                 # If not found, try next
                 if len(matches) == 0:
                     continue
+
                 # If this familyname was matched several time, abort the whole search
-                if len(matches) > 1:
-                    familynamematch = None
-                    break
+                #if len(matches) > 1:
+                #    print("Several matches ! Aborting !")
+                #    familynamematch = None
+                #    break
+
                 # If we already had a match, abort the whole search because we
                 # have multiple familynames matched !
                 if familynamematch != None:
                     familynamematch = None
                     break
 
-                familynamematch = str(member.last_name)
-                usernamematch = str(member.username)
+                familynamematch = member_last_name
+                usernamematch = member.username
 
             if familynamematch != None:
                 payment["member_matched"] = usernamematch
@@ -336,3 +351,5 @@ class Command(BaseCommand):
                                              date=new_payment["date"],
                                              member=member)
 
+    def flatten(self, some_string):
+        return unidecode.unidecode(some_string).upper()

+ 3 - 0
coin/settings_base.py

@@ -275,3 +275,6 @@ MEMBER_CAN_EDIT_PROFILE = False
 
 # Allows to deactivate displays and calculations of balances.
 HANDLE_BALANCE = False
+
+# Add subscription comments in invoice items
+INVOICES_INCLUDE_CONFIG_COMMENTS = True

+ 3 - 1
requirements.txt

@@ -1,5 +1,5 @@
 Django>=1.8.17,<1.9
-psycopg2==2.5.2
+psycopg2==2.5.4
 python-ldap==2.4.15
 wsgiref==0.1.2
 python-dateutil==2.2
@@ -16,3 +16,5 @@ feedparser
 six==1.10.0
 WeasyPrint==0.31
 freezegun==0.3.8
+pytz>=2018.5
+unidecode>=1.0,<1.1