Example #1
0
def parse_mems_from_csv(file_path, mapping, **kwargs):
    """
    Returns membership dictionary and stats dictionary

    stats:
        all, added, skipped

    memberships:
        username, fn, ln, email,
        join dt, renew dt, expire dt,
        added, skipped, renewal
    """
    # initialize membership import settings
    membership_import = kwargs['membership_import']
    key = membership_import.key  # for determining duplicates
    override = membership_import.override  # override changed fields

    if override:
        update_override = 'override'
    else:
        update_override = 'update'

    csv_dicts = csv_to_dict(file_path, machine_name=True)

    # membership lists
    total = []
    added = []
    updated = []
    skipped = []

    for csv_dict in csv_dicts:  # field mapping

        # set up field mapping
        m = {}
        for app_field, csv_field in mapping.items():
            if csv_field:  # skip blank option
                # membership['username'] = '******'
                m[clean_field_name(app_field)] = csv_dict.get(csv_field, '')

        # remove empty keys
        m = dict([(k, v) for k, v in m.items() if len(v) > 0])

        if not m:  # empty row in imported file
            continue  # on to the next one

        user_keys = ['username', 'firstname', 'lastname', 'email']
        for user_key in user_keys:
            m[user_key] = m.get(user_key, '')
        null_date = datetime(1951, 1, 1)
        date_keys = ['joindate', 'renewdate', 'expiredate', 'joindt', 'renewdt', 'expiredt']
        for date_key in date_keys:
            m[date_key] = m.get(date_key)

        m['renewal'] = bool(m['renewdate'])
        m['status__action'] = 'add'

        # set up user kwargs from mapping
        keys = {}
        for i in key.split(','):
            keys[i] = m[i.replace('_', '')]

        if 'username' in kwargs:
            kwargs['username'] = kwargs['username'][:30]

        # remove empty keys
        keys = dict( [(k,v) for k,v in keys.items() if len(v)>0])

        user = None
        if 'member_number' in keys:
            membership = Membership.objects.first(**keys)
            user = membership.user
        elif keys:  # first name, last name, email
            user = get_user(**keys)

        if not user and m['username']:
            user = get_user(username=m['username'][:30])

        # if a user is found, determine if override or update
        if user:
            if override:
                m['status__action'] = update_override
                m['username'] = m['username'] or user.username
                m['firstname'] = m['firstname'] or user.first_name
                m['lastname'] = m['lastname'] or user.last_name
                m['email'] = m['email'] or user.email
            else:
                m['status__action'] = update_override
                m['username'] = user.username or m['username']
                m['firstname'] = user.first_name or m['firstname']
                m['lastname'] = user.last_name or m['lastname']
                m['email'] = user.email or m['email']

        # set up user's fullname
        m['fullname'] = "%s %s" % (m.get('firstname', ''), m.get('lastname', ''))
        m['fullname'] = m['fullname'].strip()

        # check if the membership type is valid
        try:
            membership_type = MembershipType.objects.get(name=m.get('membershiptype', ''))
        except MembershipType.DoesNotExist:
            # skip if it does not exist
            m['status__action'] = 'skip'
            m['status__reason'] = 'invalid membership type'
            membership_type = None

        # if it's not skipped yet
        if m['status__action'] != 'skip':
            # check if there is a corresponding user or an email
            if not user and not m['email']:  # email required to create user
                m['status__action'] = 'skip'

        # if it's still not skipped
        if m['status__action'] != 'skip':
            # check if membership already exists
            if membership_type and user:
                membership_exists = Membership.objects.active(
                    user=user, membership_type=membership_type).exists()
                # check if this is the first instance of the same key
                if is_duplicate(csv_dict, csv_dicts, key):
                    m['status__action'] = 'skip'
                    m['status__reason'] = 'duplicate'
                # consider as update if already exists and is not yet skipped
                if membership_exists and m['status__action'] != 'skip':
                    m['status__action'] = update_override

        if m['joindate']:
            dt = dt_parse(m['joindate'])
            if dt > null_date:
                m['joindt'] = dt

        if m['renewdate']:
            dt = dt_parse(m['renewdate'])
            if dt > null_date:
                m['renewdt'] = dt

        if m['expiredate']:
            m['expiredt'] = dt_parse(m['expiredate'])

        if not m['expiredt']:
            if membership_type:
                m['expiredt'] = membership_type.get_expiration_dt(
                    join_dt=m['joindt'],
                    renew_dt=m['renewdt'],
                    renewal=m['renewal']
                )

        m['subscribedt'] = m['joindt'] or datetime.now()

        # make lists of memberships
        total.append(m)
        if m['status__action'] == 'skip':
            skipped.append(m)
        elif m['status__action'] == 'add':
            added.append(m)
        elif m['status__action'] == update_override:
            updated.append(m)

    stats = {
        'all': len(total),
        'skipped': len(skipped),
        'added': len(added),
        'updated': len(updated),
    }

    # return "total" list of memberships & stats
    return total, stats
Example #2
0
    def __init__(self, *args, **kwargs):
        memport = kwargs.pop('memport')
        super(ImportMapForm, self).__init__(*args, **kwargs)

        app = memport.app
        file_path = str(memport.get_file().file.name)

        csv = csv_to_dict(file_path)

        # choices list
        choices = csv[0].keys()
        machine_choices = [slugify(c).replace('-', '') for c in choices]
        choice_tuples = zip(machine_choices, choices)

        choice_tuples.insert(0, ('', ''))  # insert blank option; top option
        choice_tuples = sorted(choice_tuples, key=lambda c: c[0].lower())

        app_fields = AppField.objects.filter(app=app)

        native_fields = [
            'User Name',
            'Membership Type',
            'Corp. Membership Name',
            'Member Number',
            'Payment Method',
            'Join Date',
            'Renew Date',
            'Expire Date',
            'Owner',
            'Creator',
            'Status',
            'Status Detail',
        ]

        for native_field in native_fields:
            native_field_machine = slugify(native_field).replace('-', '')

            self.fields[native_field_machine] = forms.ChoiceField(
                **{
                    'label': native_field,
                    'choices': choice_tuples,
                    'required': False,
                })

            # compare required field with choices
            # if they match; set initial
            if native_field_machine in machine_choices:
                self.fields[
                    native_field_machine].initial = native_field_machine

        self.fields['membershiptype'].required = True

        for app_field in app_fields:
            for csv_row in csv:

                app_field_machine = slugify(app_field.label).replace('-', '')

                if slugify(app_field_machine) == 'membershiptype':
                    continue  # skip membership type

                self.fields[app_field_machine] = forms.ChoiceField(
                    **{
                        'label': app_field.label,
                        'choices': choice_tuples,
                        'required': False,
                    })

                # compare label with choices
                # if label matches choice; set initial
                if app_field_machine in machine_choices:
                    self.fields[app_field_machine].initial = app_field_machine
Example #3
0
    def __init__(self, *args, **kwargs):
        memport = kwargs.pop("memport")
        super(ImportMapForm, self).__init__(*args, **kwargs)

        app = memport.app
        file_path = str(memport.get_file().file.name)

        csv = csv_to_dict(file_path)

        # choices list
        choices = csv[0].keys()
        machine_choices = [slugify(c).replace("-", "") for c in choices]
        choice_tuples = zip(machine_choices, choices)

        choice_tuples.insert(0, ("", ""))  # insert blank option; top option
        choice_tuples = sorted(choice_tuples, key=lambda c: c[0].lower())

        app_fields = AppField.objects.filter(app=app)

        native_fields = [
            "User Name",
            "Membership Type",
            "Corp. Membership Name",
            "Member Number",
            "Payment Method",
            "Join Date",
            "Renew Date",
            "Expire Date",
            "Owner",
            "Creator",
            "Status",
            "Status Detail",
        ]

        for native_field in native_fields:
            native_field_machine = slugify(native_field).replace("-", "")

            self.fields[native_field_machine] = forms.ChoiceField(
                **{"label": native_field, "choices": choice_tuples, "required": False}
            )

            # compare required field with choices
            # if they match; set initial
            if native_field_machine in machine_choices:
                self.fields[native_field_machine].initial = native_field_machine

        self.fields["membershiptype"].required = True

        for app_field in app_fields:
            for csv_row in csv:

                app_field_machine = slugify(app_field.label).replace("-", "")

                if slugify(app_field_machine) == "membershiptype":
                    continue  # skip membership type

                self.fields[app_field_machine] = forms.ChoiceField(
                    **{"label": app_field.label, "choices": choice_tuples, "required": False}
                )

                # compare label with choices
                # if label matches choice; set initial
                if app_field_machine in machine_choices:
                    self.fields[app_field_machine].initial = app_field_machine