diff --git a/doorUpdater.py b/doorUpdater.py index fd2fdef..c31c380 100755 --- a/doorUpdater.py +++ b/doorUpdater.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +import copy + from common import doors, membershipworks, memberLevels, doorSpecificSchedules from lib.hid.Credential import Credential from lib.hid.DoorController import ROOT, E @@ -155,76 +157,80 @@ def update_door(door, members): # TODO: can I combine requests? for membershipworksMember in members: member = membershipworksMember.to_DoorMember(door) - # cardholder exists, compare contents - if member.membershipWorksID in cardholders: - ch = cardholders.pop(member.membershipWorksID) - member.cardholderID = ch.cardholderID - if member.attribs() != ch.attribs(): # update cardholder attributes - print(f"- Updating profile for {member.forename} {member.surname}") - print(f" - Old: {ch.attribs()}") - print(f" - New: {member.attribs()}") - door.doXMLRequest(ROOT( - E.Cardholders( - {"action": "UD", "cardholderID": member.cardholderID}, - E.CardHolder(member.attribs())))) - - if member.credentials != ch.credentials: - print(f"- Updating card for {member.forename} {member.surname}") - print(f" - {ch.credentials} -> {member.credentials}") - - oldCards = ch.credentials - newCards = member.credentials - - allNewCards = set( - card for m in members if m != membershipworksMember - for card in m.credentials) - - # cards removed, and won't be reassigned to someone else - for card in (oldCards - newCards) - allNewCards: - door.doXMLRequest(ROOT(E.Credentials( - {"action": "UD", - "rawCardNumber": card.hex, - "isCard": "true"}, - E.Credential({"cardholderID": ""})))) - - if newCards - oldCards: # cards added - for card in newCards & allNewCards: # new card exists in another member - print([m for m in members - for card in m.credentials - if card in newCards]) - raise Exception(f"Duplicate Card in input data! {card}") - - # card existed in door, and needs to be reassigned - for card in newCards & allCredentials: - door.doXMLRequest(ROOT(E.Credentials( - {"action": "UD", - "rawCardNumber": card.hex, - "isCard": "true"}, - E.Credential({"cardholderID": member.cardholderID})))) - - # cards that never existed, and need to be created - if newCards - allCredentials: - door.doXMLRequest(ROOT(member.make_credentials( - newCards - allCredentials, cardFormats))) - - if member.schedules != ch.schedules: - print("- Updating schedule for" + - f" {member.forename} {member.surname}:" + - f" {ch.schedules} -> {member.schedules}") - door.doXMLRequest(ROOT( - member.make_schedules(schedulesMap))) - else: # cardholder did not exist, so add them - print(f"- Adding Member:") - print(member) + # cardholder did not exist, so add them + if member.membershipWorksID not in cardholders: + print("- Adding Member {member.forename} {member.surname}:") + print(f" - {member.attribs()}") resp = door.doXMLRequest(ROOT( E.Cardholders( {"action": "AD"}, E.Cardholder(member.attribs())))) member.cardholderID = resp.find('{*}Cardholders/{*}Cardholder') \ .attrib["cardholderID"] + + # create a dummy ch to force an update + # TODO: probably a cleaner way to do this + ch = copy.copy(member) + ch.schedules = [] + ch.credentials = set() + # cardholder exists, compare contents + else: + ch = cardholders.pop(member.membershipWorksID) + member.cardholderID = ch.cardholderID + + if member.attribs() != ch.attribs(): # update cardholder attributes + print(f"- Updating profile for {member.forename} {member.surname}") + print(f" - Old: {ch.attribs()}") + print(f" - New: {member.attribs()}") door.doXMLRequest(ROOT( - member.make_credentials(member.credentials, cardFormats), - member.make_schedules(schedulesMap))) + E.Cardholders( + {"action": "UD", "cardholderID": member.cardholderID}, + E.CardHolder(member.attribs())))) + + if member.credentials != ch.credentials: + print(f"- Updating card for {member.forename} {member.surname}") + print(f" - {ch.credentials} -> {member.credentials}") + + oldCards = ch.credentials + newCards = member.credentials + + allNewCards = set( + card for m in members if m != membershipworksMember + for card in m.credentials) + + # cards removed, and won't be reassigned to someone else + for card in (oldCards - newCards) - allNewCards: + door.doXMLRequest(ROOT(E.Credentials( + {"action": "UD", + "rawCardNumber": card.hex, + "isCard": "true"}, + E.Credential({"cardholderID": ""})))) + + if newCards - oldCards: # cards added + for card in newCards & allNewCards: # new card exists in another member + print([m for m in members + for card in m.credentials + if card in newCards]) + raise Exception(f"Duplicate Card in input data! {card}") + + # card existed in door, and needs to be reassigned + for card in newCards & allCredentials: + door.doXMLRequest(ROOT(E.Credentials( + {"action": "UD", + "rawCardNumber": card.hex, + "isCard": "true"}, + E.Credential({"cardholderID": member.cardholderID})))) + + # cards that never existed, and need to be created + if newCards - allCredentials: + door.doXMLRequest(ROOT(member.make_credentials( + newCards - allCredentials, cardFormats))) + + if member.schedules != ch.schedules: + print("- Updating schedule for" + + f" {member.forename} {member.surname}:" + + f" {ch.schedules} -> {member.schedules}") + door.doXMLRequest(ROOT(member.make_schedules(schedulesMap))) # TODO: delete cardholders that are no longer members?