Skip to main content

Acceptance Criteria

Acceptance Criteria: Bilko{{PROJECT_NAME}}

Project: Bilko — Balkan Accounting SaaS{{PROJECT_NAME}} Version: 1.0{{VERSION}} Date: 2026-02-25{{DATE}} Author: John (AI Director){{AUTHOR}} Status: FinalDraft | In Review | Approved Reviewers: Alem Bašić (CEO){{REVIEWERS}}

Document History

Version Date Author Changes
0.1 2026-02-23{{DATE}} John (AI Director){{AUTHOR}} Initial draft — Phase 1 Serbia MVP
1.02026-02-25John (AI Director)Finalized for v1.0 release

1. Purpose & Methodology

1.1 What Are Acceptance Criteria?

Acceptance criteria are the conditions that the Bilkoa system must satisfy to be accepted asby workinga correctly.stakeholder. They answer:answer the question: "How will we know when this feature is done?"

For financial software, acceptance criteria are especially critical because errors have direct legal and financial consequences for users (SEF fines, incorrect PDV filings, balance sheet errors).

Good acceptance criteria are:

  • Testable — Can be verified with a specific test procedure
  • Clear — Unambiguous; no room for interpretation
  • Complete — Cover happy path, error paths, and edge cases
  • Financially accurateAgreedForSigned accountingoff features:by verifiedthe againstbusiness BalkanBEFORE GAAPdevelopment and tax lawbegins

1.2 Format: Given / When / Then (Gherkin-Style)

Given [an initial context / precondition that is true]
When  [an action or event occurs]
Then  [the expected outcome is observed]
And   [additional expected outcomes, chained]

Example — User Login:

Given a registered user with valid credentials
When the user submits the login form
Then the user is redirected to the dashboard
And a session token is created and stored in a secure cookie
And the last login timestamp is updated in the database

1.3 Categories of Acceptance Criteria

Category Description Example
Positive (Happy Path) System works as expected with valid inputs InvoiceSuccessful submitted to SEF successfullylogin
Negative (Sad Path) System handles invalid inputs gracefully SEFWrong rejects invoice —password error shown
Edge Case Boundary conditions and unusual but valid scenarios Zero-PDVLogin invoice;at zero-balanceexact periodsession timeout
Integration System works correctly with external services SEFPayment API,processed exchangevia rate API
Financial AccuracyCalculations correct per tax lawPDV = base × 0.20 exact to 4 decimal placesStripe
Non-Functional Performance, accessibility, security criteria InvoicePage creationloads in < 5s2 end-to-endseconds
DataCorrect data storage, retrieval, and validationFields saved with correct types

2. Feature Acceptance Criteria


Module: Authentication & User Management{{MODULE_1_NAME}}


Feature: User Registration{{FEATURE_1_NAME}} (FR-001){{XXX}})

Feature Description: New users register with email/password and automatically get an organization with Serbian Chart of Accounts.{{BRIEF_DESCRIPTION}} Business Requirement: BR-014{{XXX}} Linked User Stories: US-001{{XXX}}, US-{{XXX}}

Positive Scenarios:

# Scenario Given When Then
AC-001 Successful registration{{SCENARIO_NAME}} A new user with valid email "[email protected]" and strong password{{PRECONDITION}} User submits form with org name "Firma d.o.o."{{ACTION}} Account created; org created with Kontni Okvir pre-populated; verification email sent within 2 minutes{{EXPECTED_RESULT}}
AC-002 Email verification Account just created User clicks verification link (valid within 48h) Email confirmed; user redirected to organization dashboard
AC-003Chart of Accounts pre-populatedNew organization createdUser opens /settings/accountsAll 10 account classes (0-9) visible with standard Serbian accounts

Negative Scenarios:

# Scenario Given When Then
AC-004003 Duplicate email{{INVALID_INPUT_SCENARIO}} Account already exists for [email protected]{{PRECONDITION_WITH_BAD_DATA}} User submits registration with same email{{ACTION}} Error "Nalog sa ovim emailom već postoji"; no account created{{ERROR_MESSAGE_OR_BEHAVIOR}}
AC-005004 Weak password User is on registration form User submits password "abc123" (no uppercase/special) Inline error shown before form submission; form not submitted
AC-006Invalid email formatUser is on registration formUser submits "notanemail" as emailInline validation error shown

Edge Cases:

# Scenario Given When Then
AC-007005 Verification link expiry{{BOUNDARY_CONDITION}} Verification link generated 49+ hours ago{{EDGE_CONDITION}} User clicks expired link{{ACTION}} Error "Link je istekao"; option to resend verification shown
AC-008Double registration attemptUser submits form twice rapidlyTwo identical POST requests within 1 secondOnly one account created; second returns appropriate error{{EXPECTED_RESULT}}

Non-Functional Acceptance Criteria:

# Category Criterion
AC-009006 Performance Registration + org creation + CoA seedingFeature completes in < 3{{X}} seconds under normal load
AC-007AccessibilityFeature is fully operable by keyboard; ARIA labels present
AC-008Security{{SECURITY_CRITERION_IF_APPLICABLE}}

Feature: User Registration (FR-020)

Feature Description: New users can create accounts using email and password. Business Requirement: BR-{{XXX}} Linked User Stories: US-{{XXX}}

Positive Scenarios:

hash(cost12+);
#ScenarioGivenWhenThen
AC-010 SecuritySuccessful registration PasswordA storeduser visits /register with a valid, unregistered emailUser submits form with valid email, strong password, and required fieldsAccount is created; confirmation email sent; user redirected to email verification page
AC-011Email verification sentAccount was just createdSystem processes registrationVerification email arrives within 2 minutes with unique, expiring link
AC-012Verification link worksUser receives verification emailUser clicks verification linkEmail verified; user redirected to login; account marked as bcryptverified
never

Negative Scenarios:

#ScenarioGivenWhenThen
AC-013Duplicate emailAn account already exists with [email protected]User submits registration with [email protected]Error "An account with this email already exists" shown; no new account created
AC-014Weak passwordUser is on registration formUser submits password "abc123"Inline error shown: "Password must be at least 8 characters and include uppercase, number, and special character"
AC-015Invalid email formatUser is on registration formUser submits "notanemail" in plaintextemail logsfieldInline validation error shown before form submission
AC-016Empty required fieldUser is on registration formUser submits with required field emptyInline error shown; form not submitted

Edge Cases:

#ScenarioGivenWhenThen
AC-017Email with plus addressingUser submits [email protected]Registration submittedAccount created; treated as valid email
AC-018Verification link expiryVerification link generated 25+ hours agoUser clicks expired linkError "Verification link has expired"; option to resend verification email shown
AC-019Double registration attemptUser submits form; due to slow network submits twiceTwo identical POST requests sentOnly one account created; second request returns appropriate error

Feature: User Login (FR-002)021)

Feature Description: Authenticated users log in with email and password. Business Requirement: BR-014 Linked User Stories: US-002

Positive Scenarios:

# Scenario Given When Then
AC-020 Successful login VerifiedA verified user with valid credentials User submits login form Authenticated; access token (15min) + refresh token (30d) set; redirected to dashboarddashboard; session created
AC-021 SilentRemember token refreshme User'sA accessverified tokenuser expired;checks refresh"Remember token validMe" User makessubmits APIlogin callform NewSession accesspersists tokenfor issued30 silently;days; user notstays logged out;in originalafter requestbrowser succeedsclose

Negative Scenarios:

# Scenario Given When Then
AC-022 Wrong password RegisteredA registered user exists User submits wrongincorrect password Generic error "PogrešanInvalid email ilior lozinka"password" (no userenumeration); enumeration)login not granted
AC-023 Non-existent email No account for this email User submits login Same generic error "PogrešanInvalid email ilior lozinka"password" (prevent user enumeration)
AC-024 Account locked User has made 5 failed attempts within 15 minutes6th attemptError "Nalog zaključan. Pokušajte za 15 minuta."
AC-025Unverified accountAccount created but email not verified User attempts login again ErrorMessage: "MolimoAccount vastemporarily potvrditelocked. emailTry adresu"again within option15 to resendminutes."

Edge Cases:

# Scenario Given When Then
AC-026025 Session expiry User has been idle for 30+31 minutes; access token expired; refresh token also expiredminutes User attempts actionto navigate Redirected to login; messagesession cleared; unsaved work warning shown
AC-026Login on unverified accountAccount created but email not verifiedUser attempts to log inError "VašaPlease sesijaverify jeyour istekla"email before logging in" with option to resend

Module: Invoicing


Feature: Create Invoice with PDV{{NEXT_FEATURE_NAME}} (FR-010){{XXX}})

Feature Description: Create invoices with auto-PDV calculation. Financial accuracy is critical — NUMERIC(19,4) precision required. Business Requirement: BR-001, BR-002 Linked User Stories: US-010

Positive Scenarios:

# Scenario Given When Then
AC-030{{NEXT}} Invoice with 20% PDV Line item: 1000.0000 RSD base, 20% PDV rate Invoice created and viewed PDV amount = 200.0000 RSD; total = 1200.0000 RSD exactly (NUMERIC precision)
AC-031Invoice with 10% PDVLine item: 500.0000 RSD base, 10% PDV rateInvoice createdPDV = 50.0000 RSD; total = 550.0000 RSD
AC-032Multi-line invoice with mixed PDV rates3 line items: 1000 @ 20%, 500 @ 10%, 200 @ 0%Invoice createdPDV breakdown shown per rate; total PDV = 250.0000 RSD; grand total = 1950.0000 RSD
AC-033Invoice saved as DraftAll required fields filledUser clicks "Save Draft"Invoice in Draft status; not submitted to SEF; can be edited
AC-034Invoice number sequentialPrevious invoice number: INV-2026-001New invoice createdInvoice number: INV-2026-002 (no gaps)

Negative Scenarios:

# Scenario Given When Then
AC-035{{NEXT}} Missing required field Invoice wizard open User tries to advance without selecting client Inline error "Odaberite klijenta"; cannot advance to next step
AC-036Zero-amount invoiceUser enters 0 for all line item pricesUser tries to saveValidation error "Iznos fakture mora biti veći od 0"
AC-037Due date before invoice dateInvoice date: 2026-03-01, due date: 2026-02-28User saves invoiceValidation error "Rok plaćanja mora biti nakon datuma fakture"

Edge Cases:

# Scenario Given When Then
AC-038{{NEXT}} PDV rounding edge case Line item: 333.3333 RSD, 20% PDV Invoice calculated PDV = 66.6667 RSD (ROUND to 4 decimal places, not truncate); total = 400.0000 RSD
AC-039PDV-exempt invoice (0%)Business in PDV exemption regimeInvoice created with 0% PDVPDV amount = 0.0000; total = base amount; PDV field shows "PDV 0%" with exemption reason

Financial Accuracy Criteria:

#CategoryCriterion
AC-040NUMERIC precisionAll PDV and total amounts stored as NUMERIC(19,4) — verified in DB; no floating point
AC-041PDV law compliancePDV calculation matches Zakon o PDV Art. 17 — base × rate formula verified for 20 test cases

Feature: SEF E-Invoice Submission (FR-011)

Feature Description: Automatic submission of Serbian B2B invoices to efaktura.gov.rs. Business Requirement: BR-001 Linked User Stories: US-011

Positive Scenarios:

#ScenarioGivenWhenThen
AC-050Successful SEF submissionSerbian B2B invoice, organization has SEF credentialsUser clicks "Pošalji fakturu"UBL 2.1 XML generated and submitted to SEF within 10 seconds; SEF status = "Prihvaćeno"; SEF invoice ID stored
AC-051SEF status visibleInvoice submitted to SEFUser views invoice detailSEF status shown: "Prihvaćeno" + SEF invoice ID

Negative Scenarios:

#ScenarioGivenWhenThen
AC-052SEF rejects — missing buyer PIBInvoice created without buyer's PIB (tax ID)Submission attemptedSEF rejection error shown in Serbian: reason from SEF response; invoice status = "SEF Odbijeno"; user can edit and resubmit
AC-053SEF API unavailable (503)SEF platform returns 503Submission attemptedInvoice queued for retry; user notified "Faktura je u redu čekanja za SEF. Prosleđivanje za max 30 minuta."; max 3 retries

Edge Cases:

#ScenarioGivenWhenThen
AC-054Duplicate SEF submission attemptInvoice already submitted and AcceptedUser somehow triggers send againSystem detects SEF invoice ID exists; blocks resubmission; shows "Faktura je već prosleđena SEF-u"
AC-055B2C invoice (no SEF required)Invoice for individual (no PIB)User sendsPDF emailed; SEF submission skipped; no SEF status shown

Feature: Invoice Payment Tracking (FR-012)

Linked User Stories: US-012

Positive Scenarios:

#ScenarioGivenWhenThen
AC-060Mark invoice paidInvoice status = SentUser marks as paid with date 2026-03-15 and amount 1200 RSDStatus = Paid; double-entry: Debit 1200 (110 — tekući račun), Credit 1200 (200 — potraživanja); payment date recorded
AC-061Overdue detectionInvoice due 2026-03-14; today is 2026-03-15; status = SentSystem daily check runsStatus automatically changes to Overdue; in-app notification sent

Negative Scenarios:

#ScenarioGivenWhenThen
AC-062Mark paid with wrong amountInvoice total = 1200 RSDUser marks paid with amount 1000 RSDWarning: "Plaćeni iznos (1.000 RSD) je manji od iznosa fakture (1.200 RSD). Potvrdi parcijalno plaćanje."

Module: Expense Tracking


Feature: Create Expense (FR-020)

Feature Description: Record business expenses with double-entry auto-creation. Business Requirement: BR-009 Linked User Stories: US-020

Positive Scenarios:

#ScenarioGivenWhenThen
AC-070Record expense with double-entryExpense: 5000 RSD, category "Kirija" (account 480), paid from tekući račun (110)User submits expenseExpense saved; Transaction: Debit 5000 (480 — Expenses), Credit 5000 (110 — Bank); LoggedAction entry created
AC-071Receipt attachmentExpense savedUser attaches JPEG receipt (3MB)Receipt stored; accessible from expense record; thumbnail shown

Negative Scenarios:

#ScenarioGivenWhenThen
AC-072Receipt too largeUser attaches 15MB PDFUpload attemptedError "Dokument ne može biti veći od 10MB"
AC-073Future date expenseUser enters expense date 2027-01-01Form submittedWarning "Datum troška je u budućnosti. Potvrdi unos." — requires explicit confirmation

Module: VAT/PDV Management


Feature: PDV Report Generation (FR-050)

Feature Description: Monthly PDV report aggregating all sales and purchase PDV. Critical for legal compliance. Business Requirement: BR-002, BR-006 Linked User Stories: US-050

Positive Scenarios:

#ScenarioGivenWhenThen
AC-080January PDV reportJanuary 2026: 3 invoices (PDV 600+400+200=1200 RSD), 2 expenses (input PDV 240+120=360 RSD)User generates January PDV reportOutput PDV = 1200 RSD; Input PDV = 360 RSD; Net PDV payable = 840 RSD
AC-081PDV report PDF exportPDV report generatedUser clicks "Exportuj PDF"PDF with header "PDV Prijava — Januar 2026", org name, PIB, all amounts per official format
AC-082Zero PDV periodDecember: no PDV transactionsUser generates December PDV reportZero-value report generated with all fields = 0; exportable (still legally required)

Financial Accuracy Criteria:

#CategoryCriterion
AC-083PDV accuracyPDV report totals verified against sum of all invoice/expense PDV fields in DB — must match to 4 decimal places
AC-084PDV law complianceOutput PDV = sum of all 20% standard + sum of all 10% reduced PDV from outgoing invoices per Zakon o PDV

3. Integration Scenarios

rate
# Integration Scenario Expected Behavior Test Environment
INT-001 SEF API (efaktura.gov.rs){{EXTERNAL_SERVICE}} Valid invoice submission{{SCENARIO}} SEF returns invoice ID + "Accepted" status within 30s{{EXPECTED}} SEFSandbox sandbox/ Mock
INT-002 SEF APIInvalid invoice (missing buyer PIB)SEF returns rejection with specific reason codeSEF sandbox
INT-003SEF APISEF unavailable (503)Bilko queues submission; retries 3× with exponential backoff; user notifiedMocked 503
INT-004Email provider InvoiceTransactional PDFemail delivery RecipientEmail receives PDF invoicereceived within 2 minutes of send Mailtrap / staging
INT-005003 Exchange rate API (ECB){{PAYMENT_PROVIDER}} EUR/RSDSuccessful rate fetchpayment RateTransaction fetchedrecorded; andconfirmation cached;shown; usedwebhook for multi-currency invoicereceived ECBStripe test endpointmode
INT-006004 Exchange{{PAYMENT_PROVIDER}} Payment APIdeclinedUser sees friendly error; no order created; no double-chargeStripe test mode
INT-005{{THIRD_PARTY_API}} API unavailabletimeout CachedSystem rateshows (<user-friendly 24h)error; used;request iflogged; no cache,data user prompted for manual entrycorruption Mocked timeout
INT-007006 SEF API{{THIRD_PARTY_API}} SEFAPI credentials invalidunavailable ErrorSystem showndegrades togracefully; user:non-dependent "SEFfeatures akreditivistill su nevalidni. Proveri podešavanja."work SEFService sandboxunavailable mock

4. Non-Functional Acceptance Criteria

4.1 Performance

# Criterion Target Test Method
NF-AC-001 DashboardAll initialpages load within target time < 33s secondsinitial, (4G)< 1.5s subsequent Lighthouse on staging
NF-AC-002 DashboardAll subsequentAPI navigationendpoints respond within target < 1500ms secondat p95 under normal load Lighthousek6 warmload cachetest
NF-AC-003 InvoiceCore creationWeb (fullVitals wizard + API save)pass LCP < 52.5s, secondsCLS end-to-end< 0.1, FCP < 1.8s Manual timing + k6
NF-AC-004SEF submission (Bilko to SEF confirmation)< 30 secondsE2E test in SEF sandbox
NF-AC-005PDV report generation (1 year of data)< 5 secondsLoad test with synthetic dataLighthouse

4.2 Accessibility

# Criterion Target Test Method
NF-AC-010 No critical accessibility violations 0 critical violations axe-core onautomated all pagesscan
NF-AC-011 Invoice wizard keyboardKeyboard navigation complete CompleteAll wizardfeatures operable without mouse Manual keyboard test
NF-AC-012 Color contrast compliant ≥ 4.5:1 (normal text), ≥ 3:1 (large text)text/background Contrast checker — Bilko #00E5A0 on dark verified

4.3 Security

# Criterion Target Test Method
NF-AC-020 OrganizationNo dataOWASP isolationTop 10 vulnerabilities User0 fromcritical/high Org A cannot access Org B datafindings APIOWASP test:ZAP send request with Org A token for Org B resource — must return 403scan
NF-AC-021 NoAll financialuser datainputs in client-side logssanitized No amounts,XSS/injection invoices, or PII in browser consolevulnerabilities ManualSAST browser+ DevToolsmanual reviewtesting
NF-AC-022 InputNo injectionsensitive preventiondata in client-side code No SQL/XSSAPI injectionkeys, vulnerabilitiestokens in browser OWASPCode ZAPreview + Snykbrowser SAST
NF-AC-023SEF credentials encryptedSEF API keys not stored in plaintext in DBDB inspection + code review

4.4 Financial Accuracy

#CriterionTargetTest Method
NF-AC-030Debit = Credit invariantSum of all debits = sum of all credits across ALL transactionsAutomated DB check in CI: SELECT SUM(debit_amount) - SUM(credit_amount) FROM transactions must = 0
NF-AC-031NUMERIC precisionZero floating point errors in PDV and totals1000 PDV calculations with known expected values; compare to NUMERIC result
NF-AC-032Exchange rate immutabilityChanging today's rate does not affect historical transactionsCreate transaction, change rate, verify transaction amount unchangedDevTools

5. UAT Scenario Mapping

calculation
AC ID AC Description UAT Scenario ID UAT Tester Status
AC-001010 Successful registration UAT-001 Beta SMB owner{{TESTER}} Not Started
AC-030011 InvoiceEmail PDVverification 20%sent UAT-002
AC-020Successful loginUAT-003
INT-003Payment success UAT-010 Beta accountant Not Started
AC-050SEF submission successUAT-020Beta SMB ownerNot Started
AC-080PDV report generationUAT-030Beta accountantNot Started
NF-AC-030Debit = Credit invariantUAT-ACC-001Beta accountantNot Started
NF-AC-001 DashboardPage load < 3sperformance UAT-P01 Any beta user Not Started

6. Traceability to Requirements

AC ID Acceptance Criterion FR Reference BR Reference US Reference
AC-001 Successful registration{{CRITERION}} FR-001{{XXX}} BR-014{{XXX}} US-001{{XXX}}
AC-020010 Successful loginFR-002BR-014US-002
AC-030Invoice PDV 20%FR-010BR-002US-010
AC-050SEF submission successFR-011BR-001US-011
AC-060Mark invoice paidFR-012BR-001US-012
AC-070Record expenseregistration FR-020 BR-009{{XXX}} US-020
AC-080PDV report JanuaryFR-050BR-002, BR-006US-050{{XXX}}

Full traceability: RTM.md[requirements-traceability-matrix.md](requirements-traceability-matrix.md)


Approval

Role Name Date Signature
Author John (AI Director) 2026-02-23
Reviewer
Business Analyst John 2026-02-23
Product Owner John 2026-02-23
QA Engineer validator agent
AI Director (John) John 2026-02-23
CEOClient (Alem)Representative Alem Bašić