Recued
Menu
← Back to recipes

Import payments

by recued-core v5 8 views

Use “Import payments” in Recued. Reads the collection sheet back and records one receipt per row that carries an amount and the date it arrived. Re-uploading the same sheet records nothing twice, and a row it cannot record is named rather than dropped.

Complete workflow

Rental Book 19 pinned recipes

Use Rental Book in Recued for property, landlord, ledger, and records. It includes 24 built-in actions and 18 ready-to-run workflows.

You are viewing one recipe in this workflow. Installing it opens the complete pack so its other recipes and background automations arrive together.

Import payments
This recipe

Use “Import payments” in Recued. Reads the collection sheet back and records one receipt per row that carries an amount and the date it arrived. Re-uploading the same sheet records nothing twice, and a row it cannot record is named rather than dropped.

pack:rental-bookreceiptpaymentimport
by recued-core pinned v5

Use “Add a building” in Recued. Records one building or complex. Units hang off it.

pack:rental-bookbuildingsetup
by recued-core pinned v2

Use “Add a unit” in Recued. Records one rentable unit against a building. It uses the connections and settings you choose when you run it.

pack:rental-bookunitsetup
by recued-core pinned v2

Use “Add a tenant” in Recued. Records one tenant and how they pay: cash, autopay, or stripe.

pack:rental-bookcustomertenantsetup
by recued-core pinned v3

Use “Open a rental contract” in Recued. Binds a tenant to a unit at a monthly rent. The contract is what a period charge is raised against.

pack:rental-bookcontractsetup
by recued-core pinned v4

Use “Raise the period's rent charges” in Recued. Raises one rent charge per live contract for a billing period. Safe to run unattended on a monthly schedule and safe to run twice — the charge id is the (contract, period, kind) tuple, so a repeat is a no-op rather than a second bill.

pack:rental-bookbillingchargescheduled
by recued-core pinned v4
Show all 19 recipes

Use “Record a rent payment” in Recued. Records what a tenant actually paid, against their account rather than against an invoice. A partial payment is one receipt for the part; an overpayment is one receipt for the whole, and the credit carries.

pack:rental-bookreceiptpaymentmanual
by recued-core pinned v3

Use “Collection sheet” in Recued. The month's collection list as a table and as CSV, one row per active contract, each carrying the contract id the import matches on.

pack:rental-bookreportexportcsv
by recued-core pinned v2

Use “Tenant statement” in Recued. One tenant's account: everything charged, everything received, and the balance derived from the two. Not read off any invoice, because no invoice knows about the payment that arrived against a different month.

pack:rental-bookstatementreportledger
by recued-core pinned v5

Use “Buildings” in Recued. Every building you hold, with a way into each one's units.

pack:rental-booklistbuildingnavigation
by recued-core pinned v5

Use “Building” in Recued. One building: what it is, and every unit in it. It uses the connections and settings you choose when you run it.

pack:rental-bookdetailbuildingnavigation
by recued-core pinned v5

Use “Unit” in Recued. One unit: who is in it now, and every tenancy it has had. It uses the connections and settings you choose when you run it.

pack:rental-bookdetailunittenancy
by recued-core pinned v4

Use “Contracts” in Recued. Live tenancies by default; expired ones only when you ask.

pack:rental-booklistcontractfilter
by recued-core pinned v5

Use “Customers” in Recued. Everyone on the book, most recent first — and the way to start a tenancy for one.

pack:rental-booklistcustomerpicker
by recued-core pinned v5

Use “Retire or restore a customer” in Recued. Takes a customer off the working list without deleting anything they are attached to, or puts them back.

pack:rental-bookcustomerhousekeeping
by recued-core pinned v5

Use “End a tenancy” in Recued. Closes a contract on a date. The ledger it produced stays exactly as it is — ending a tenancy is not settling it.

pack:rental-bookcontractterminationlifecycle
by recued-core pinned v5

Use “Change the rent” in Recued. Sets a contract's rent. Periods already raised keep the amount they were raised at.

pack:rental-bookcontractrentlifecycle
by recued-core pinned v5

Use “Collect the rent” in Recued. Type what each tenant paid, straight into a grid — one row per live tenancy, one save.

pack:rental-bookreceiptpaymentbatch
by recued-core pinned v5
View pack details, dependencies, and permissions →

The round trip

Export the collection sheet, fill in amount_received and received_on as payments arrive, upload it here. One receipt per row that has both; rows missing either are set aside before anything is recorded, because a blank amount is a tenant who has not paid, not a payment of zero — and a payment with no date cannot be told apart from the next one. Those rows are counted, not refused: an unpaid tenant is the normal state of most of the sheet.

A row that cannot be recorded now SAYS SO

This is the part that changed. The whole sheet is handed over as one file and recorded inside your warehouse, and the summary reports what landed AND what did not — recorded, already held, refused, with the reason for each refusal.

Before, it could not. Each row was written on its own in a loop, and a loop reports the run as a success even when every single write was rejected. A sheet with a mistyped amount in it looked exactly like a sheet that worked; the only sign was rent that never appeared in the balance. Money going quietly missing is the worst thing a rent book can do, and the loop had no way to tell you.

The line number in the refusal table counts PAYMENTS, not sheet rows. The empty rows are set aside first, so “3” means the third row you actually filled in, counting down the sheet. It is not the third line of your file, and it is not guessed at.

Amounts must be plain digits

1200 and 1200.50 are recorded. 1,200.00 is refused — that row alone, named in the summary, with the rest of the sheet recorded normally. Nothing here guesses whether a comma is a thousands mark or a decimal point, because guessing wrong turns twelve hundred into one point two.

Re-uploading is safe

A collection sheet gets filled in over a month, not in one sitting, so uploading it more than once is the normal way to use it. Each receipt's id is derived from the tenancy, the date you entered and the amount, inside the same call that records it — so a row you already imported is recognised and skipped. The summary says how many you already held.

Sheets you imported before this version will import once more. The identity is derived the same way from the same four things, but by the store rather than by this recipe, and the two produce different ids for the same payment. That is a one-off: the first upload after the update re-records what you already had, and every upload after it behaves normally. If you would rather not, hold the sheet back until the period closes.

This replaces the older ADDITIVE behaviour, and the reason it changed is worth knowing. Before, importing the same sheet twice recorded every payment twice — a deliberate choice, on the argument that two genuine payments of the same amount on the same day are two payments and a store that merged them would be wrong in a worse way. That argument is right, and the received_on column is what answers it: two payments on different days are two receipts. What remains is narrow — two payments, same contract, same amount, same day. The sheet has one row per contract, so it cannot express that, and the old behaviour paid for the rare case by doubling every ordinary re-upload.

The sheet and the grid are one book

Collect the rent records payments straight into a grid, and it derives each receipt's id exactly the way this does — from the tenancy, the day and the amount. So a payment typed on the screen and then listed on a sheet you upload is ONE receipt, not two. The summary counts it under already held.

The amount has to match as WRITTEN. 1200 in the grid and 1200.00 on the sheet are two different strings and therefore two different receipts. Nothing between the cell and the row is allowed to decide they are the same number — the same reason a comma is refused rather than interpreted.

If “How these arrived” disagrees with what you typed on the screen, the row is reported as refused instead of already held. It is recognised as the same payment but described two ways, and nothing here picks a winner. You keep one receipt — the one entered first — and nothing doubles. Collect the rent now offers the same five methods and starts on the same one, so this only happens if you deliberately say two different things about one payment.

If a tenant does pay twice in one day for the same amount, record the second with Record rent payment. Entering it by hand is the way to say "this is a different payment" — the sheet has no way to.

Check first

Turn on Check first and the whole sheet is read, put through exactly the checks a real import would run against your real data, and then thrown away. Nothing is recorded. Worth doing the first time you use a sheet from a new spreadsheet, or after editing one by hand.

Nothing is matched on a NAME. The contract_id column is the join. A row without one is set aside and counted, so the total tells you when the sheet was edited badly.

Set the delimiter your spreadsheet used. A European export writes ; and would otherwise parse as one column per row. A short row is not dropped in silence — it is set aside and counted like any other.

How it works 24 steps

Inspect the data fetches, transforms, gates, and output this recipe runs.

Process (24 steps)
sheet_id trim
Trim whitespace from setting sheet
has_sheet compare
Check if sheet id has data
sheet_guard guard
Stop if has sheet equals
file_read ?
csv_text decode_base64
Apply decode_base64
parsed csv_parse
Apply csv_parse
parsed_count count
Count items in parsed
with_id filter
Filter by condition
with_amount filter
Filter by condition
payable filter
Filter by condition
payable_count count
Count items in payable
skipped math
Calculate parsed count minus payable count
has_payable compare
Check if payable has data
payable_guard guard
Stop if has payable equals
referenced map
Extract from each item
payments_csv to_csv
Serialize rows as a CSV string
imported ?
any_refused compare
Check if imported failed is greater than 0
stopped default
Apply default
was_check compare
Check if imported dry run equals
mode ternary
Apply ternary
refused to_table
Format results as a data table
skip: step.any_refused equal false
table to_table
Format results as a data table
card to_summary
Format results as a summary card
Settings 5 configurable

Configurable at install. Defaults shown — change them anytime in Recued.

sheet setting = [object Object]
method setting = autopay
period setting =
delimiter setting = ,
check first setting = false

About

Tags

pack:rental-bookreceiptpaymentimportcsvbatch

Details

24 steps 5 configurable settings recipe_id: import-payments