feat(eet): report the cash received, reverse refunds and report from the settling device - #102
Merged
Merged
Conversation
An online event clears every backoff and queues a delivery pass. When it arrived while an attempt was in flight, that attempt then failed and started a new backoff, so the queued pass skipped the sale, and the sale waited out the backoff although the device was online again.
The test waits for exactly one sandbox request before switching to production, but the retry came 10 ms later. Under the full unit run the retry could land before the poll saw the first request, so the poll saw two and failed. A 250 ms retry keeps the retry after the switch, which is the case the test is about.
EET records what the business actually received, not what it charged. A 78.90 CZK bill paid in cash is 79 CZK after rounding to whole crowns, or 80 CZK when the customer leaves the change, and that is the amount the sale has to carry. Marking a payment paid in cash now shows the cash received, prefilled with the charge rounded to the nearest crown, halves up, and refuses anything lower. Staff can raise it and sees the difference before confirming. The received amount lives on the payment's cash detail, not on the cash register transaction, so rounding never shows the bill as overpaid. It is written in the settlement's own batch because the EET sale freezes its amount from the first settlement it sees. A cash payment without one, as settled by an older version, still reports its charge.
Money returned to a customer for a reported sale has to reach EET as a new sale with a negative amount, the time of the refund and a new message identifier, with no link to the original. Returning a reported sale in cash has to be reported. Payky had no refund at all: a paid payment could not be canceled and nothing deleted one, so a returned sale stayed reported in full. Staff can now refund a paid payment from its detail: the remainder, any amount, or chosen items while the payment is the only one claimed for its bill, since only then are the bill's lines its own. Refunding the rest of a line returns the rest of its amount, so rounding leaves nothing behind. The money leaves the cash register, as a transaction no payment claims, or is marked as returned outside Payky. A refund is its own record, not a negative payment, so the payment stays paid, its bill stays closed and covered, and the detail, the bill rows and the history show it as partly or fully refunded. The device that recorded a refund turns it into an EET reversal. The amount is capped at what the sale reported and earlier reversals left, so a refunded tip that belongs to employees is never reversed. A reversal waits for its sale's POK, then is delivered, retried and flagged overdue like a sale. It lives in its own table because an older version would deliver a reversal row in the sale table as a positive sale.
|
@i-am-fatik is attempting to deploy a commit to the Josef K's projects Team on Vercel. A member of the Team first needs to authorize it. |
i-am-fatik
marked this pull request as draft
September 29, 2026 13:49
prvni_zaslani marks the first attempt to send a sale, and the tax administrator counts any attempt without a POK. Payky recorded an attempt only once its answer arrived, so an app closed mid-request sent the next attempt as the first again, and Retry could still rewrite the EIČ of a sale EET may already hold. The attempt is now written before the message leaves. An attempt that finds an earlier one without an answer marks the record as possibly recorded by EET.
The payment screen never passed its device to a cash, bank or card settlement, and neither did a card result restored after Android killed the app, so no settlement staff made carried a device. EET reporting needs it to know the cash register a sale happened on.
A sale belongs to the cash register where the money was received, but Payky reported it from the device that created the payment, and only that device ever sent it on its own. A payment created on a phone and paid in cash at the counter reached EET with the phone's register, and a sale whose device broke or stayed off was never delivered unless someone tapped Retry on another device. The recording device is now the device on the payment's first settlement, or the device that created the payment when Payky matched the settlement on its own. For a reversal it is the device that recorded the refund. It creates and sends the record first. After 10 minutes any device of the account creates a missing record and delivers an unconfirmed one, still with the recording device's register, so EET sees a resend of the same sale. Retry on another device waits the same 10 minutes unless the record already has an attempt. Only the recording device's first attempt within 5 minutes is marked as the first sending, and every takeover is a repeat. The 5 minutes before anyone may take over absorb device clocks that disagree and a request still in flight.
i-am-fatik
marked this pull request as ready for review
September 29, 2026 15:35
A payment's sale reported the payment amount at its first settlement, whatever that settlement brought. Money the business keeps is a sale at the moment it arrives, and EET records the amount actually received, so this went wrong three ways. A payment settled twice, or by a transfer larger than its amount, left the rest unreported, a sale nobody reported once the business kept it. Returning that duplicate went through the payment's refund, whose reversal was capped at the sale, so EET ended at zero for goods that were sold. And a first settlement that paid only part reported money that had not arrived, for good if the rest never came. The sale now reports what the first settlement brought, capped at the payment amount, and cash still reports the cash received. Everything later settlements bring beyond that, the rest of a split or money above the amount, is reported as an extra money sale when it arrives, with the method, time and recording device of the claim that brought it. Each increase adds one more extra money sale keyed by the extra money already reported, so a device that missed a claim reports the rest once it syncs. Extra money brought before EET was enabled is never reported, as for sales. A reversal is capped at everything the payment reported, waits while extra money is still unreported, and is sent only once every sale of its payment is confirmed. Returning the duplicate leaves the real sale reported. Holding the extra money back until staff decides was rejected: it is lawful only if a mistaken payment is not a sale, which nothing we hold confirms, while reporting on arrival and reversing on return is lawful either way.
A refund was capped at the payment amount, or the cash received, so money a payment received above it, a second settlement or a transfer larger than the payment, could not be returned through Payky, and its extra money sale could never be reversed. The limit now adds what the payment's claims brought beyond its amount, and when there is such money the refund dialog offers it first, as it is what the business did not charge for. The payment detail, the payment history and the bill's payment rows measure the refund state against the same limit, so returning only the duplicate shows the payment partly refunded while its real sale stands, and returning everything leaves nothing reported in EET.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
3 of 5 tasks
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follows #99 and closes known gaps 1 (for refunds), 3 (for cash) and 5 of
docs/eet.md.79.00reported, or80.00with the change left), because EET wants the money actually taken. The payment, its claim and the cash register keep the charge, so no coverage moves. The payment detail shows the received amount when it differs.id_pokl, so EET sees a resend of the same sale. Retry on another device waits the same 10 minutes unless the record already has an attempt.prvni_zaslaniis true only for the recording device's first attempt within 5 minutes. An attempt is written before its message leaves, so an app closed mid-request makes the next attempt a repeat and keeps Retry from rewriting the EIČ of a sale EET may hold.onlineevent that arrived while an attempt was in flight was lost, and the sale waited out its backoff. It now retries at once. The sandbox test ineet-reporting-job.test.tsfailed 3 of 16 parallel runs before its fix, because its 10 ms retry could land before the poll saw the first request. It now retries after 250 ms.docs/eet.mdanddocs/bill-payment-states.mddescribe the received amount, refunds and reversals.Test plan
bun run checkpasses on every commit (915 tests on the last). With both job fixes,eet-reporting-job.test.tspassed 8 of 8 parallel runs, and so did the new takeover tests.e2e/eet.spec.tsagainst the fake responder: 78.90 CZK in cash confirmed as prefilled reports79.00, raised to 80 reports80.00, and refunding one beer of a paid bill and then the rest sends-50.00and-200.00while the bill stays closed.--workers=2on the takeover, and the 62 tests through the payment screen pass after the settlement-device fix. A new e2e test seeds another device's sale: 3 minutes old it waits without Retry, 11 minutes old it is sent from here as a repeat.79.00for 78.90 in cash,80.00with the change left,250.00for a bill then-50.00and-200.00for its refunds, and a resend after a failed attempt marked as repeated. Every message got a POK and no warning.id_poklas the first sending, and a refund recorded on B is reversed by B. A sale and a reversal A could not send are taken over by B 60.1 s after the sale or refund, marked as repeated, with A'sid_pokl, and confirmed.🤖 Generated with Claude Code