Are they fundamentally different? Based on your description, it doesn't sound like it. Yes, logically the way you and I might think about credit and debit cards, they are fundamentally different.
But you need to differentiate between what you think is different in your mind and how you physically use it and what you need to model as different for your program to be able to process, because these are two different things. Sometimes the ideas that represent both how you use it and how your program will use it are the same, but not always.
In your case, you describe two things which may have different names, but are literally the same thing. If they have all the same attributes, and the function definitions are exactly identical, then it's the same class - why write it twice? Minimize your codebase.
That said, creating a separate class for both isn't a bad thing either. It helps you scale your code later.
abstract class Card {
UUID id;
BigDecimal limit;
BigDecimal currentAmount;
...
public void charge(BigDecimal amount) {
currentAmount = currentAmount.add(amount);
}
...
}
class DebitCard extends Card {}
class CreditCard extends Card{}
So your Card class contains all the logic, and DebitCard and CreditCard are both completely empty classes, inheriting all their fields and logic from the parent class, Card. The advantage here, again, is scaling. If later on, you determine that CreditCard needs to figure out some way to make monthly payments (not in your original description), then you can add that later without negatively impacting DebitCard in any way.
ICardReportand/or an Abstract classAbstractCardReportwhere you put the methods/fields that both classes share. This way you would not have any duplicate code but still have 2 seperate classes to represent that those 2 are representing different use cases.