A source declaration gives a raw relation a stable logical name. Your SQL calls source with that name and the table name, so moving the underlying relation doesn't require edits throughout the project.
The source still contains what the upstream system sent. A declaration doesn't make its records clean.
In a staging model, handle mechanical cleanup once: normalize codes, choose column names, and establish the record grain. Harbor Cart sometimes sends the same order more than once after a correction. Keep the latest updated_at for each order_id, and use a deterministic second ordering column when the timestamp ties.
Don't erase unknown amounts just to make an aggregate easier. Downstream models should be able to tell the difference between missing evidence and a recorded zero.
select order_id, customer_id, lower(trim(status)) as status, amount, ordered_at, updated_at, upper(trim(currency)) as currency from {{ source('shop', 'orders') }} where order_id is not null qualify row_number() over (partition by order_id order by updated_at desc, amount desc nulls last)=1
A worked pattern with fictional records. Adapt the model name and business rule to each task.