Skip to content
Snippets Groups Projects
import_nk15.py 9.21 KiB
Newer Older
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
#!/usr/env/bin python3

from django.core.management.base import BaseCommand
from django.core.management import call_command
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
from django.utils import timezone
import psycopg2 as  pg
import psycopg2.extras as pge
from django.db import transaction

import json
import datetime
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
import collections

from django.core.exceptions import ValidationError
from django.utils.timezone import make_aware

Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
from django.db import IntegrityError
from django.contrib.auth.models import User
from note.models import Note, NoteSpecial, NoteUser, NoteClub
from note.models import Alias
from note.models import Transaction, TransactionTemplate,\
    TemplateCategory, RecurrentTransaction, MembershipTransaction
from member.models import Profile, Club, Membership
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed

"""
Script d'import de la nk15:
TODO: import transactions
TODO: import adhesion
TODO: import activite
M_DURATION = 396
M_START = datetime.date(2019,8,31)
M_END = datetime.date(2020,9,30)
MAP_IDBDE={
    -4: 2, # Carte Bancaire
    -3: 4, # Virement
    -2: 1, # Especes
    -1: 3, # Chèque
     0: 5, # BDE
}
def update_line(n,N, content):
    n = str(n)
    N = str(N)
    n.rjust(len(N))
    content.ljust(41)
    content = content[:40]
    print(f"({n}/{N}) {content}", end="\r")
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed

@transaction.atomic
def import_comptes(cur):
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
    cur.execute("SELECT * FROM comptes WHERE idbde > 0 ORDER BY idbde;")
    pkclub = 3
    N = cur.rowcount
    for idx, row in enumerate(cur):
        update_line(idx,N,row["pseudo"])
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        if row["type"] == "personne":
            #sanitize password
            if row["passwd"] != "*|*":
                passwd_nk15 = "$".join(["custom_nk15","1",row["passwd"]])
            else:
                passwd_nk15 = ''
            try:
                obj_dict = {
                    "username": row["pseudo"],
                    "password": passwd_nk15,
                    "first_name": row["nom"],
                    "last_name": row["prenom"],
                    "email":  row["mail"],
                    "is_active" : True, # temporary
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
                }
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
                user = User.objects.create(**obj_dict)
                profile = user.profile
                profile.phone_number = row['tel']
                profile.address = row['adresse']
                profile.paid = row['normalien']
                profile.registration_valid = True
                profile.email_confirmed = True
                user.save()
                profile.save()
                # sanitize duplicate aliases (nk12)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            except ValidationError as e:
                if e.code == 'same_alias':
                    user.username = row["pseudo"]+str(row["idbde"])
                    user.save()
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
                else:
                    raise(e)
            # profile  and note created via signal.
            
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            note = user.note
            date = row.get("last_negatif",None)
            if date != None:
                note.last_negative = make_aware(date)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            note.balance = row["solde"]
            obj_list =[user, profile, note]
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        else: # club
            obj_dict = {
                "pk":pkclub,
                "name": row["pseudo"],
                "email": row["mail"],
                "membership_duration": M_DURATION,
                "membership_start": M_START,
                "membership_end": M_END,
                "membership_fee_paid": 0,
                "membership_fee_unpaid":0,
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            }
            club,c = Club.objects.get_or_create(**obj_dict)
            pkclub +=1
            note = club.note
            note.balance = row["solde"]
            club.save()
            note.save()
            
        MAP_IDBDE[row["idbde"]] = note.pk
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed

@transaction.atomic
def import_boutons(cur):
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
    cur.execute("SELECT * FROM boutons;")
    N = cur.rowcount
    for idx, row in enumerate(cur):
        update_line(idx,N,row["label"])
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        cat, created = TemplateCategory.objects.get_or_create(name=row["categorie"])
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        obj_dict = {
            "pk": row["id"],
            "name": row["label"],
            "amount": row["montant"],
            "destination_id": MAP_IDBDE[row["destinataire"]],
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            "category": cat,
            "display" : row["affiche"],
            "description": row["description"],
        }
        try:
            with transaction.atomic(): # required for error management
                button = TransactionTemplate.objects.create(**obj_dict)
        except IntegrityError as e:
            # button with the same name is not possible in NK20.
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            if "unique" in e.args[0]:
                qs = Club.objects.filter(note__id=MAP_IDBDE[row["destinataire"]]).values('name')
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
                note_name = qs[0]["name"]
                #rename button name
                obj_dict["name"] ="{} {}".format(obj_dict["name"],note_name)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
                button = TransactionTemplate.objects.create(**obj_dict)
            else:
                raise(e)
        button.save()

@transaction.atomic
def import_transaction(cur):
    cur.execute("SELECT * FROM transactions LEFT JOIN adhesions ON transactions.id = adhesions.idtransaction ORDER BY -id;")
    N = cur.rowcount
    for idx, row in enumerate(cur):
        update_line(idx,N,row["label"])
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        obj_dict = {
            "destination_id" : MAP_IDBDE[row["destinataire"]],
            "source_id": MAP_IDBDE[row["emetteur"]],
            "created_at":make_aware(row["date"]),
            "amount":row["montant"],
            "quantity":row["quantite"],
            "reason":row["description"],
            "valid":row["valide"],
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        }
        if row["type"] == "bouton":
            cat_name = row["categorie"]
            if cat_name == None:
                cat_name = 'None'
            cat, created = TemplateCategory.objects.get_or_create(name=cat_name)
            if created:
                cat.save()
            obj_dict["category"] = cat
            transac = RecurrentTransaction.objects.create(**obj_dict)
            transac.save()
        elif row["type"] == "adhésion":
            print("adhesion not supported yet")
           print("other type not supported yet")
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
@transaction.atomic
def import_aliases(cur):
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
    cur.execute("SELECT * FROM aliases ORDER by id")
    N = cur.rowcount
    for idx, row in enumerate(cur):
        update_line(idx,N,row["alias"])
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        alias_name = row["alias"]
        alias_name_good = (alias_name[:252]+'...') if len(alias_name) > 255 else alias_name
        obj_dict = {
            "note_id":MAP_IDBDE[row["idbde"]],
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
            "name":alias_name_good,
            "normalized_name":Alias.normalize(alias_name_good)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        }
        try:
            with transaction.atomic():
                alias, created =  Alias.objects.get_or_create(**obj_dict)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        except IntegrityError as e:
            if "unique" in e.args[0]:
                continue
            else:
                raise(e)
        alias.save()


class Command(BaseCommand):
    """
    Command for importing the database of NK15.
    Need to be run by a user with a registered role in postgres for the database nk15. 
    """
    def print_success(self,to_print):
        return self.stdout.write(self.style.SUCCESS(to_print))
    
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
    def add_arguments(self,parser):
        parser.add_argument('-c', '--comptes', action = 'store_true', help="import accounts")
        parser.add_argument('-b', '--boutons', action = 'store_true', help="import boutons")
        parser.add_argument('-t', '--transactions', action = 'store_true',help="import transaction")
        parser.add_argument('-a', '--aliases', action = 'store_true',help="import aliases")
        parser.add_argument('-s', '--save', action='store', help="save mapping of idbde")
        parser.add_argument('-m', '--map', action='store', help="import mapping of idbde")
        parser.add_argument('-d', '--nk15db', action='store', default='nk15', help='NK15 database name')
        parser.add_argument('-u', '--nk15user', action='store', default='nk15_user', help='NK15 database owner')
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
    def handle(self, *args, **kwargs):
        nk15db, nk15user = kwargs['nk15db'], kwargs['nk15user']
        #reset database.
        call_command("migrate")
        call_command("loaddata","initial")
        self.print_success("reset  nk20 database")
        # connecting to nk15 database
        conn = pg.connect(database=nk15db,user=nk15user)
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        cur = conn.cursor(cursor_factory = pge.DictCursor)

        if kwargs["comptes"]:
            self.print_success("comptes table imported")
        elif kwargs["map"]:
            filename = kwargs["map"]
            with open(filename,'w') as fp:
                MAP_IDBDE = json.load(fp)
        if kwargs["save"]:
            filename = kwargs["save"]
            with open(filename,'w') as fp:
                json.dump(MAP_IDBDE,fp,sort_keys=True, indent=2)
                
        # /!\ need a prober MAP_IDBDE
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        if kwargs["boutons"]:
            self.print_success("boutons table imported")
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        if kwargs["transactions"]:
            import_transaction(cur)
            self.print_success("transaction imported")
Pierre-antoine Comby's avatar
Pierre-antoine Comby committed
        if kwargs["aliases"]:
            self.print_success("aliases imported")