1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
from django.db import transaction

from registration.django_utils import switch_language
from registration.models import User, Contact, Product, Sale

import csv, collections, itertools, decimal, re, datetime

def run():
    data = [[col.decode('utf8') for col in row]
            for row in csv.reader(file('liste_sylvain.csv'))]

    EntryBase = collections.namedtuple(
        'EntryBase', ['raw_%s' % c for c in data[0]])
    
    class Entry(EntryBase):
        def __getattr__(self, attrname):
            # Generic cleanup
            raw_attrname = 'raw_%s' % attrname
            if raw_attrname in EntryBase.__dict__:
                raw = getattr(self, raw_attrname)
                if '$' in raw:
                    return decimal.Decimal(re.sub('[^0-9\.]','', raw))
                elif raw.strip() in ('oui', 'non'):
                    return raw.strip() == 'oui'
                elif len(raw.strip()) == 0:
                    return None
                else:
                    return raw.strip()

        @property
        def street_address(self):
            return self.raw_street_address.strip(' ,')

        @property
        def postal_code(self):
            return self.__getattr__('postal_code') or u'HOH OHO'
            
        @property
        def emails(self):
            return [email.strip() for email in self.email.split(';')]

        @property
        def drop_off_name(self):
            # "Stich" to db values
            do = self.drop_off
            return {u'Douglas': u'Verdun, H\xf4pital Douglas',
                    u'PWC1': u'PWC',
                    u'Loto': u'Loto-Qu\xe9bec'}.get(do, do)

        @property
        def product(self):
            if self.drop_off == u'PWC1':
                product_id = 7 # PWC1
            elif self.extra_greens:
                product_id = 2 # Veggies basket with greens option
            else:
                product_id = 1 # Veggies basket
            return Product.objects.get(pk = product_id)

        @property
        def qty_label(self):
            fmt = self.format
            if isinstance(fmt, decimal.Decimal):
                if self.raw_drop_off != 'PWC1':
                    raise ValueError('impossible value')
                if fmt <= 300:
                    return u'1 carte pr\xe9pay\xe9e'
                else:
                    return u'2 carte pr\xe9pay\xe9es'
            else:
                return {'aux deux semaines': 'Aux deux semaines',
                        'Hebdo': 'Hebdomadaire'}[fmt]

        def _parse_phone_number(self, number):
            if '#' in number:
                base, ext = [c.strip() for c in number.split('#')]
                ext = re.sub('-', '', ext)
            else:
                base = number.strip()
                ext = None
            if re.match('^[0-9]{3}-[0-9]{3}-[0-9]{4}$', base) is None:
                base = None
                ext = None
            return base, ext
        
        @property
        def phone_numbers(self):
            return [(base, ext) for base, ext in (
                self._parse_phone_number(num)
                for num in (getattr(
                    self, 'phone_number_%d' % idx) for idx in (1, 2))
                if num is not None)]

        def _names(self):
            yield self.first_name, self.last_name
            other = self.other_contact
            if other is not None:
                other = other.split(None, 1)
                if len(other) == 2:
                    yield other

        @property
        def names(self):
            return list(self._names())

        def inject(self):
            # First, compute the various sale parameters
            # (see registration.views.buy())
            product = self.product
            sched = product.productdeliveryschedule
            drop_off_name = self.drop_off_name
            qty_label = self.qty_label

            now = datetime.datetime.today()
            schedules, warnings = sched.compute_all_schedules(now = now)

            sold_qty, sold_label, first_date, deliveries = \
                      schedules[qty_label][drop_off_name]

            # Then, create the user and primary contact, as needed.
            emails = self.emails
            contacts = Contact.objects.filter(email__in = emails)
            phone_numbers = self.phone_numbers
            if len(contacts) == 0:
                contact, created = Contact.get_or_create(email = emails[0])
            else:
                contact, created = (contacts[0], False)

            contact.first_name = self.first_name
            contact.last_name = self.last_name
            contact.phone_number = phone_numbers[0][0]
            contact.phone_number_ext = phone_numbers[0][1]
            contact.save()
            
            user = contact.user
            profile = user.get_profile()

            profile.street_address = self.street_address
            profile.city = self.city
            profile.postal_code = self.postal_code
            profile.phone_number = phone_numbers[0][0]
            profile.phone_number_ext = phone_numbers[0][1]
            profile.save()

            # Then, reconcile the additional bits and piece
            names = self.names
            if any(len(seq) > 1 for seq in (names, phone_numbers, emails)):
                #if len(emails) < len(names):
                #    print '%s %s' % tuple(names[1])
                for ((first_name, last_name),
                     (phone_number, phone_number_ext),
                     email) in zip(
                    names, itertools.repeat(phone_numbers[-1]), emails):
                    try:
                        cur_contact = Contact.objects.get(email = email)
                    except Contact.DoesNotExist:
                        cur_contact = Contact(user = user)

                    cur_contact.first_name = first_name
                    cur_contact.last_name = last_name
                    cur_contact.phone_number = phone_number
                    cur_contact.phone_number_ext = phone_number_ext
                    cur_contact.email = email
                    cur_contact.save()

                    #print cur_contact

            # Finally, create the sale
            sale = Sale.create(
                'fr',
                sched,
                user,
                qty_label,
                drop_off_name,
                sold_qty, sold_label, deliveries,
                'cheque', [(now, self.total_amount)], 0, None,
                None,
                self.equiterre)

            p = sale.payments.all()[0]
            p.received = self.payed
            p.save()

            print sale
                        
    # Fire in the hole!        
    entries = [Entry(*row) for row in data[1:]]
    with switch_language('fr'):
        with transaction.commit_on_success():
            for entry in entries:
                entry.inject()

        print 'Done.'
            #raise RuntimeError('full stop')

run()