| name | Applicable_Fee_IDs |
| description | Solve dabstep dataset questions about identifying applicable fee IDs from fees.json. Use this skill for any question asking which fee IDs apply to given conditions, a specific merchant on a specific day/month/year, or which merchants are affected by a specific fee ID.
|
Applicable Fee IDs Skill
Dataset Files
fees.json: 1000 fee rules with matching criteria
merchant_data.json: merchant account_type, capture_delay, MCC, acquirers (list of dicts)
payments.csv: transactions with columns: merchant, card_scheme, year, day_of_year, is_credit, eur_amount, issuing_country, acquirer_country, aci, has_fraudulent_dispute
acquirer_countries.csv: maps acquirer name to country_code (rarely needed—payments.csv already has acquirer_country)
Fee Rule Structure (fees.json)
Each fee has: ID, card_scheme, account_type (list), capture_delay, monthly_fraud_level, monthly_volume, merchant_category_code (list), is_credit, aci (list), fixed_amount, rate, intracountry
Critical matching rule: An empty list [] for account_type, aci, or merchant_category_code means "applies to all values"—same as null. There are NO null values for these list fields in fees.json; only empty lists and populated lists exist.
A fee rule applies when ALL of these match:
| Field | Match condition |
|---|
card_scheme | null → all; otherwise exact match |
account_type | [] or null → all; otherwise merchant's account_type in list |
capture_delay | null → all; otherwise exact string match |
monthly_fraud_level | null → all; otherwise computed monthly fraud category must match |
monthly_volume | null → all; otherwise computed monthly volume category must match |
merchant_category_code | [] or null → all; otherwise merchant's MCC in list |
is_credit | null → all; otherwise must match transaction's is_credit |
aci | [] or null → all; otherwise transaction's ACI in list |
intracountry | null → all; 0.0 → international (issuing≠acquirer); 1.0 → domestic (issuing==acquirer) |
Question Types & Approaches
Type 1: Simple Attribute Filter
Pattern: "What fee IDs apply to account_type = X and aci = Y?"
Filter fees.json directly—no payments data needed:
import json
with open('fees.json') as f:
fees = json.load(f)
account_type = 'F'
aci = 'A'
result = [
fee['ID'] for fee in fees
if (not fee['account_type'] or account_type in fee['account_type'])
and (not fee['aci'] or aci in fee['aci'])
]
print(', '.join(str(x) for x in sorted(result)))
Apply the same pattern for other simple field combinations (card_scheme, is_credit, etc.).
Type 2: Merchant + Date (Day/Month/Year) → Applicable Fee IDs
Pattern: "For the Nth day of 2023, what Fee IDs apply to [Merchant]?" or "What Fee IDs applied in [Month] 2023?"
Step 1: Get merchant characteristics
with open('merchant_data.json') as f:
merchants = json.load(f)
merchant = next(m for m in merchants if m['merchant'] == 'Belles_cookbook_store')
account_type = merchant['account_type']
mcc = merchant['merchant_category_code']
capture_delay_raw = merchant['capture_delay']
Step 2: Map capture_delay to fee rule format
def map_capture_delay(raw):
try:
days = int(raw)
if days < 3: return '<3'
elif days <= 5: return '3-5'
else: return '>5'
except ValueError:
return raw
capture_delay = map_capture_delay(capture_delay_raw)
Step 3: Determine the time window and filter payments
import pandas as pd, datetime
payments = pd.read_csv('payments.csv')
txns = payments[(payments['merchant']=='Belles_cookbook_store') &
(payments['year']==2023) & (payments['day_of_year']==200)]
oct_start = datetime.date(2023, 10, 1).timetuple().tm_yday
oct_end = datetime.date(2023, 10, 31).timetuple().tm_yday
txns = payments[(payments['merchant']=='Belles_cookbook_store') &
(payments['year']==2023) &
(payments['day_of_year'] >= oct_start) &
(payments['day_of_year'] <= oct_end)]
txns = payments[(payments['merchant']=='Belles_cookbook_store') & (payments['year']==2023)]
Step 4: Compute monthly volume & fraud categories for the relevant month(s)
Monthly stats must be computed for the calendar month(s) containing the transactions. For a specific day query, compute for the month that day falls in. For month-wide query, compute for that month. For year-wide query, compute per-month and union results.
def volume_category(eur):
if eur < 100_000: return '<100k'
elif eur < 1_000_000: return '100k-1m'
elif eur < 5_000_000: return '1m-5m'
else: return '>5m'
def fraud_category(rate_pct):
if rate_pct < 7.2: return '<7.2%'
elif rate_pct < 7.7: return '7.2%-7.7%'
elif rate_pct <= 8.3: return '7.7%-8.3%'
else: return '>8.3%'
total_vol = txns['eur_amount'].sum()
fraud_vol = txns[txns['has_fraudulent_dispute'] == True]['eur_amount'].sum()
fraud_rate = (fraud_vol / total_vol * 100) if total_vol > 0 else 0
vol_cat = volume_category(total_vol)
fraud_cat = fraud_category(fraud_rate)
Step 5: Identify applicable fee IDs
def fee_applies(fee, cs, is_credit, aci, intracountry, vol_cat, fraud_cat,
account_type, mcc, capture_delay):
if fee['card_scheme'] is not None and fee['card_scheme'] != cs:
return False
if fee['account_type'] and account_type not in fee['account_type']:
return False
if fee['capture_delay'] is not None and fee['capture_delay'] != capture_delay:
return False
if fee['monthly_fraud_level'] is not None and fee['monthly_fraud_level'] != fraud_cat:
return False
if fee['monthly_volume'] is not None and fee['monthly_volume'] != vol_cat:
return False
if fee['merchant_category_code'] and mcc not in fee[]:
fee[] fee[] != is_credit:
fee[] aci fee[]:
fee[] (fee[]) != intracountry:
() f:
fees = json.load(f)
applicable = ()
_, row txns.iterrows():
intracountry = (row[] == row[])
fee fees:
fee_applies(fee, row[], row[], row[],
intracountry, vol_cat, fraud_cat, account_type, mcc, capture_delay):
applicable.add(fee[])
(.join((x) x (applicable)))
For year-wide queries, loop over each month (1–12), compute monthly stats for that month's transactions, then union all applicable fee IDs:
applicable = set()
for month in range(1, 13):
m_start = datetime.date(2023, month, 1).timetuple().tm_yday
m_end = (datetime.date(2023, month+1, 1) - datetime.timedelta(days=1)).timetuple().tm_yday \
if month < 12 else 365
month_txns = txns[(txns['day_of_year'] >= m_start) & (txns['day_of_year'] <= m_end)]
if month_txns.empty:
continue
total_vol = month_txns['eur_amount'].sum()
fraud_vol = month_txns[month_txns['has_fraudulent_dispute']==True]['eur_amount'].sum()
fraud_rate = (fraud_vol / total_vol * 100) if total_vol > 0 else 0
v_cat = volume_category(total_vol)
f_cat = fraud_category(fraud_rate)
for _, row in month_txns.iterrows():
intracountry = (row['issuing_country'] == row['acquirer_country'])
for fee in fees:
if fee_applies(fee, row['card_scheme'], row['is_credit'], row['aci'],
intracountry, v_cat, f_cat, account_type, mcc, capture_delay):
applicable.add(fee['ID'])
Type 3: Reverse Lookup — Which Merchants Does Fee X Affect?
Pattern: "Which merchants were affected by Fee ID 709 in 2023?"
fee = next(f for f in fees if f['ID'] == 709)
subset = payments[payments['year'] == 2023].copy()
if fee['card_scheme']:
subset = subset[subset['card_scheme'] == fee['card_scheme']]
if fee['is_credit'] is not None:
subset = subset[subset['is_credit'] == fee['is_credit']]
if fee['aci']:
subset = subset[subset['aci'].isin(fee['aci'])]
if fee['intracountry'] is not None:
subset = subset[(subset['issuing_country'] == subset['acquirer_country']) == bool(fee['intracountry'])]
merchants_affected = sorted(subset['merchant'].unique())
print(', '.join(merchants_affected))
If the fee has account_type, mcc, or capture_delay constraints, also filter merchants from merchant_data before joining.
Output Format
- Applicable fee IDs: comma-separated integers in ascending order:
3, 4, 5, 7, ...
- Empty result: empty string
""
- If question is irrelevant:
Not Applicable
Common Pitfalls
- Empty list ≠ null for lists: In fees.json, empty
[] for account_type/aci/merchant_category_code means "all"—treat it the same as null
- capture_delay conversion: Merchant's numeric delay (e.g., "1", "7") must be mapped to fee rule strings ("<3", "3-5", ">5")
- Monthly stats are required: Fees with
monthly_fraud_level or monthly_volume constraints only apply when the merchant's actual monthly stats match—never skip this calculation
- intracountry is float in fees.json:
0.0 = international, 1.0 = domestic; compare with bool(fee['intracountry'])
- merchant_data.json is a list: Access with
next(m for m in merchants if m['merchant'] == name), not dict-style lookup
- payments.csv has
acquirer_country directly: No need to join acquirer_countries.csv for intracountry calculation