@obs.api_call()
def upsert_merchant_info(
self, data: "TransferNotificationMerchantData"
) -> MerchantInfo | None:
"""
Upsert merchant info based on the incoming payment event data.
If an entry with the merchant ID already exists, update it with the incoming non-None data. Otherwise, create a new entry.
Log all non-None field changes. Unexpected changes (e.g. acquirer ID) are logged as warnings, expected changes (e.g. name) are logged as info.
"""
if not data.merchantId:
# Not much we can do without a merchantId
current_logger.error(
"No merchant ID found in incoming payment event data",
data=data,
)
return None
# Fetch existing data to log significant changes
merchant_info = MerchantInfoModelBroker.find_merchant_info_by_merchant_id(
current_session,
merchant_id=data.merchantId,
)
# Upsert the existing entry with all non-None fields from the incoming data
# What to do on existing non-None fields depends on the field type
params = {}
# First, fields that we don't expect to change => warning
if data.acquirerId:
params["acquirer_id"] = data.acquirerId
if (
merchant_info is not None
and merchant_info.acquirer_id is not None
and merchant_info.acquirer_id != data.acquirerId
):
current_logger.warn(
"Acquirer ID changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.acquirer_id,
data.acquirerId,
)
if data.mcc:
params["mcc"] = data.mcc
if (
merchant_info is not None
and merchant_info.mcc is not None
and merchant_info.mcc != data.mcc
):
current_logger.warn(
"MCC changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.mcc,
data.mcc,
)
# Then fields that we may change => info
if data.name:
params["name"] = data.name
if (
merchant_info is not None
and merchant_info.name is not None
and merchant_info.name != data.name
):
current_logger.info(
"Name changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.name,
data.name,
)
if data.postalCode:
params["postal_code"] = data.postalCode
if (
merchant_info is not None
and merchant_info.postal_code is not None
and merchant_info.postal_code != data.postalCode
):
current_logger.info(
"Postal code changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.postal_code,
data.postalCode,
)
if data.city:
params["city"] = data.city
if (
merchant_info is not None
and merchant_info.city is not None
and merchant_info.city != data.city
):
current_logger.info(
"City changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.city,
data.city,
)
if data.country:
params["country"] = data.country
if (
merchant_info is not None
and merchant_info.country is not None
and merchant_info.country != data.country
):
current_logger.info(
"Country changed for merchant %s: %s -> %s",
data.merchantId,
merchant_info.country,
data.country,
)
merchant_info = MerchantInfoModelBroker.upsert_merchant_info(
current_session,
merchant_id=data.merchantId,
**params,
)
return _to_merchant_info(merchant_info)