Here is a bug that is embarrassingly easy to write and remarkably hard to notice, and it is worth describing precisely because it is not hypothetical. It was found in our own code, by testing against a real signed agreement.

The setup

Seasonal property agreements commonly mix two kinds of line. Fixed annual items, such as a winterization or a spring opening, happen once. Monthly items recur, but usually only during part of the year: an off-season care fee for the closed months, an in-season support fee for the rental months.

To present an annual figure, software has to convert the monthly lines into a yearly amount. The obvious way to do that is to multiply by twelve.

Why twelve is wrong

Because the monthly lines are not twelve-month lines. An off-season fee that runs November to April is six months. An in-season fee running June to September is four. Multiplying either by twelve inflates it by a factor of two or three.

On a real agreement, that error turned a contracted annual total into roughly double the correct figure. Not a rounding discrepancy. A number that would have been visibly, embarrassingly wrong in front of a client.

Why nobody caught it sooner

This is the part worth dwelling on. There was a test. The test passed.

The test used invented rates chosen to sum to the correct contracted total, and the fixture happened not to set the seasonal windows. With no window, the code multiplied by twelve, and the invented numbers had been reverse-engineered to make that produce the right answer.

The test was validating that the arithmetic was self-consistent. It could not validate that the arithmetic was correct, because both the inputs and the expected output had been chosen by the same person to agree with each other.

The moment the real fee table was substituted, four assertions failed immediately.

The lesson for anyone building this

Test financial logic against a real signed document, not against numbers you invented to make the total work. Synthetic figures validate that your code agrees with itself. Only real figures validate that it agrees with the contract.

If you cannot get the real document, that is not a reason to proceed with invented numbers. It is a signal that the highest-value next step is obtaining it.

The fix, and what it implies for the data model

Each rate line now carries its own billing window, and the multiplier is derived from that window rather than assumed. A line with no window still means all year, which keeps simple agreements simple.

The windows also have to wrap the year boundary. November to April is start month eleven, end month four, and any implementation that subtracts one from the other produces a negative month count. Six months, not minus six.

What this means when you write an agreement

If you are drafting a seasonal service agreement, state the window for every recurring line explicitly, and state the count. "Ninety dollars monthly, November through April, six payments" leaves nothing to be inferred by a person or a system.

Ambiguity in a fee schedule does not stay ambiguous. It gets resolved by whichever piece of software reads it first, and that software will resolve it in whatever way its author found convenient.