WEB-657: Working Capital Loan - Write-Off - #3798
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Note
|
| Layer / File(s) | Summary |
|---|---|
Request contracts and template data src/app/loans/models/working-capital/..., src/app/loans/loans.service.ts |
Added request interfaces and loading of WriteOffReasons options. |
Write-off form src/app/loans/loans-view/working-capital/loan-account-actions/write-off/* |
Added validated write-off fields, payload construction, submission, error handling, and navigation. |
Undo write-off form src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/* |
Added reversal fields, validation, submission, error handling, and navigation. |
Loan action routing and status actions src/app/loans/common-resolvers/..., src/app/loans/loans-view/loan-accounts-button-config.ts, src/app/loans/loans-view/loan-account-actions/*, src/app/loans/loans-view/general-tab/* |
Working-capital loans now select dedicated components and expose write-off or undo-write-off actions by state and permission. |
Loan status and write-off display src/app/loans/loans-view/loans-view.component.* |
Added written-off metadata and status badge styling. |
Write-off translations src/assets/translations/*.json |
Added labels for reversal external ID, written-off dates, write-off actions, and written-off statuses across supported locales. |
Estimated code review effort: 3 (Moderate) | ~25 minutes
Possibly related PRs
- openMF/web-app#3740: Shares loan-view service and translation changes but targets the loans list.
- openMF/web-app#3790: Uses similar working-capital loan action patterns for charge-off flows.
Suggested reviewers: adamsaghy
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title clearly and concisely identifies the main change: adding write-off support for working-capital loans. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
bd4ff1b to
44b0eb9
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.html (1)
14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the 8px spacing scale.
m-b-20andgap-5pxencode 20px and 5px spacing. Replace them with existing 8px-grid utilities or shared theme variables.As per coding guidelines,
src/**/*.{scss,html}must use the 8px grid and shared styling variables instead of explicit pixel spacing.Also applies to: 35-35
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.html` at line 14, Replace the m-b-20 and gap-5px spacing utilities in the undo-write-off template with existing 8px-grid utilities or shared theme variables, preserving the current layout spacing without explicit non-grid pixel values.Source: Coding guidelines
src/app/loans/loans.service.ts (1)
681-694: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winType the write-off template response.
getWorkingCapitalWriteOffTemplate()returnsObservable<any>and theWriteOffReasonscode/codevalue responses useany[]. MoveWriteOffReasonOption, the code record, the code value shape used here, and{ writeOffReasonOptions }out ofWorkingCapitalWriteOffComponentintosrc/app/loans/models/working-capital/working-capital-loan-account.model.tsso the service can return a typed shareable response.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/loans/loans.service.ts` around lines 681 - 694, Move the write-off-related interfaces currently defined in WorkingCapitalWriteOffComponent into working-capital-loan-account.model.ts, including WriteOffReasonOption, the code record, the code value shape, and the { writeOffReasonOptions } response. Update getWorkingCapitalWriteOffTemplate() to use these shared types instead of any/any[], and update the component imports and references to consume the relocated models.Sources: Coding guidelines, Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/loans/loans-view/general-tab/general-tab.component.html`:
- Around line 114-117: Update the translation key in the write-off reason label
within the general-tab template from “labels.inputs.Write-off Reason” to
“labels.inputs.WriteOff Reason”; leave the surrounding
loanDetails.writeOffReason rendering unchanged.
---
Nitpick comments:
In
`@src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.html`:
- Line 14: Replace the m-b-20 and gap-5px spacing utilities in the
undo-write-off template with existing 8px-grid utilities or shared theme
variables, preserving the current layout spacing without explicit non-grid pixel
values.
In `@src/app/loans/loans.service.ts`:
- Around line 681-694: Move the write-off-related interfaces currently defined
in WorkingCapitalWriteOffComponent into working-capital-loan-account.model.ts,
including WriteOffReasonOption, the code record, the code value shape, and the {
writeOffReasonOptions } response. Update getWorkingCapitalWriteOffTemplate() to
use these shared types instead of any/any[], and update the component imports
and references to consume the relocated models.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 06613eb3-de9e-4266-af81-504a67c6be2e
📒 Files selected for processing (26)
src/app/loans/common-resolvers/loan-action-button.resolver.tssrc/app/loans/loans-view/general-tab/general-tab.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.tssrc/app/loans/loans-view/loan-accounts-button-config.tssrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.htmlsrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.scsssrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.tssrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.htmlsrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.scsssrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.tssrc/app/loans/loans.service.tssrc/app/loans/models/working-capital/working-capital-loan-account.model.tssrc/assets/translations/cs-CS.jsonsrc/assets/translations/de-DE.jsonsrc/assets/translations/en-US.jsonsrc/assets/translations/es-CL.jsonsrc/assets/translations/es-MX.jsonsrc/assets/translations/fr-FR.jsonsrc/assets/translations/it-IT.jsonsrc/assets/translations/ko-KO.jsonsrc/assets/translations/lt-LT.jsonsrc/assets/translations/lv-LV.jsonsrc/assets/translations/ne-NE.jsonsrc/assets/translations/pt-PT.jsonsrc/assets/translations/sw-SW.json
44b0eb9 to
137d69f
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/loans/loans-view/loans-view.component.scss`:
- Around line 34-80: Update the working-capital status mapping used by
iconLoanStatusColor so loanStatusType.closed.written.off resolves to the
status-writtenoff pill modifier instead of status-unknown. Add the corresponding
status-writtenoff styling under account-status-pill using the dedicated error
colour.
In `@src/assets/translations/fr-FR.json`:
- Line 3157: Update the French translations for “Written Off On” at all three
occurrences to use the file’s existing “radiation” terminology instead of “passé
en perte”, while preserving the intended date-label meaning.
In `@src/assets/translations/ko-KO.json`:
- Around line 3425-3426: Update the "Withdrawn" translation in the Korean locale
to "철회됨", matching the existing "Withdrawn by Client" wording and expressing it
as a status.
In `@src/assets/translations/lt-LT.json`:
- Line 3153: Update the lt-LT translation for the “Written Off On” key to use
the date-specific label “Nurašymo data”, matching the existing “Write Off Date”
translation rather than the status wording.
In `@src/assets/translations/lv-LV.json`:
- Around line 3296-3297: Update the Latvian translation entries for Charge-Off
and Write-Off so they use distinct descriptive labels, preserving the existing
translation for one action and replacing the duplicate Norakstīšana value for
the other.
In `@src/assets/translations/sw-SW.json`:
- Line 3294: Update the “Write-Off” and “Written Off” translation entries in the
Swahili locale, including the related entry near line 3423, to use the same
approved Swahili write-off term consistently with the other same-meaning keys.
Remove the inconsistent “Ufutaji” value and preserve the surrounding translation
structure.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 038a7081-0680-4a8c-bd4d-646a73115386
📒 Files selected for processing (29)
src/app/loans/common-resolvers/loan-action-button.resolver.tssrc/app/loans/loans-view/general-tab/general-tab.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.tssrc/app/loans/loans-view/loan-accounts-button-config.tssrc/app/loans/loans-view/loans-view.component.htmlsrc/app/loans/loans-view/loans-view.component.scsssrc/app/loans/loans-view/loans-view.component.tssrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.htmlsrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.scsssrc/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.tssrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.htmlsrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.scsssrc/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.tssrc/app/loans/loans.service.tssrc/app/loans/models/working-capital/working-capital-loan-account.model.tssrc/assets/translations/cs-CS.jsonsrc/assets/translations/de-DE.jsonsrc/assets/translations/en-US.jsonsrc/assets/translations/es-CL.jsonsrc/assets/translations/es-MX.jsonsrc/assets/translations/fr-FR.jsonsrc/assets/translations/it-IT.jsonsrc/assets/translations/ko-KO.jsonsrc/assets/translations/lt-LT.jsonsrc/assets/translations/lv-LV.jsonsrc/assets/translations/ne-NE.jsonsrc/assets/translations/pt-PT.jsonsrc/assets/translations/sw-SW.json
🚧 Files skipped from review as they are similar to previous changes (14)
- src/app/loans/common-resolvers/loan-action-button.resolver.ts
- src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts
- src/app/loans/loans-view/loan-accounts-button-config.ts
- src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.scss
- src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html
- src/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.scss
- src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.html
- src/app/loans/loans-view/working-capital/loan-account-actions/undo-write-off/undo-write-off.component.ts
- src/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.ts
- src/app/loans/loans-view/working-capital/loan-account-actions/write-off/write-off.component.html
- src/app/loans/models/working-capital/working-capital-loan-account.model.ts
- src/assets/translations/en-US.json
- src/app/loans/loans.service.ts
- src/assets/translations/es-MX.json
| .account-status-pill { | ||
| display: inline-block; | ||
| margin-left: 12px; | ||
| padding: 2px 10px; | ||
| border-radius: 12px; | ||
| font-size: 0.72rem; | ||
| font-weight: 600; | ||
| line-height: 1.6; | ||
| letter-spacing: 0.04em; | ||
| text-transform: uppercase; | ||
| vertical-align: middle; | ||
| color: #fff; | ||
| background-color: $status-inactive; | ||
|
|
||
| &.status-active { | ||
| background-color: $status-active; | ||
| } | ||
|
|
||
| &.status-active-overdue, | ||
| &.status-block { | ||
| background-color: $status-active-overdue; | ||
| } | ||
|
|
||
| &.status-pending { | ||
| background-color: $status-pending; | ||
| } | ||
|
|
||
| &.status-approved { | ||
| background-color: $status-approved; | ||
| } | ||
|
|
||
| &.status-overpaid { | ||
| background-color: $status-overpaid; | ||
| } | ||
|
|
||
| &.status-chargeoff { | ||
| background-color: $status-chargeoff; | ||
| } | ||
|
|
||
| &.status-matured { | ||
| background-color: $status-matured; | ||
| } | ||
|
|
||
| &.subStatus-contract-termination { | ||
| background-color: $subStatus-contract-termination; | ||
| } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the statusLookup pipe implementation
fd -i 'status-lookup' --type f
# Inspect its mapping logic
fd -i 'status-lookup.pipe.ts' --type f -x cat -n {}Repository: openMF/web-app
Length of output: 3559
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
fd -i 'translations|loans-view|status-lookup|written' --type f | sed -n '1,120p'
echo
echo "== written off references =="
rg -n "Written Off|written[- ]?off|writtenoff|loanStatusType" src/app -g '!**/*.map' | sed -n '1,220p'
echo
echo "== loans-view scss relevant section =="
fd -i '^loans-view\.component\.scss$' --type f -x sh -c 'echo "--- $1"; wc -l "$1"; sed -n "1,140p" "$1"' sh {}
echo
echo "== loans-view ts relevant section =="
fd -i '^loans-view\.component\.ts$' --type f -x sh -c 'echo "--- $1"; wc -l "$1"; rg -n "accountStatus|statusLookup|written|class|template" "$1" -A4 -B4; sed -n "1,220p" "$1"' sh {}Repository: openMF/web-app
Length of output: 18297
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '520,625p' src/app/loans/loans-view/loans-view.component.ts
echo
sed -n '55,105p' src/app/loans/loans-view/loans-view.component.html
echo
sed -n '1,35p' src/app/loans/loans-view/loans-view.component.scss
echo
python3 - <<'PY'
from pathlib import Path
import re
lookup = {}
for m in re.finditer(r"['\"].*?['\"]:\s['\"](.*)['\"]", Path('src/app/pipes/status-lookup.pipe.ts').read_text()):
key, value = m.groups()
if value in ('status-unknown',):
lookup[key] = 'status-unknown'
else:
lookup[key] = value.split("'")[0]
pill_classes = re.findall(r"&\.([A-Za-z0-9_-]+)", Path('src/app/loans/loans-view/loans-view.component.scss').read_text())
print('unknown keys:', sorted([k for k in lookup if 'written' in k.lower() or 'close' in k.lower() or 'with' in k.lower()]))
print('status-unknown pipeline:', sorted([k for k,v in lookup.items() if 'unknown' in v]))
print('pill modifiers:', pill_classes)
PYRepository: openMF/web-app
Length of output: 6863
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
scm = Path('src/app/pipes/status-lookup.pipe.ts').read_text()
lookup = {}
for key, value in re.findall(r"['\"]([^'\"]+)['\"]\\s*:\\s*['\"]([^'\"]+)['\"]", scm):
lookup.setdefault(key, value)
# Extract exact .class-name selectors from .account-status-pill block.
scss = Path('src/app/loans/loans-view/loans-view.component.scss').read_text()
block = re.search(r'\\.account-status-pill\\s*\\{(?P<body>[^}]*(?:\\{[^}]*\\}[^}]*)*)\\}\\s*\\n', scss)
modifiers = []
if block:
modifiers = re.findall(r'^[[:space:]]*\\&\\.([A-Za-z0-9_-]+)', block.group('body'), re.M)
print("pipe mapping keys containing written/off/charge/close/with or status unknown:")
for key in sorted(lookup):
if any(token in key.lower() for token in ['written', 'off', 'charge', 'close', 'with', 'withdraw']) or lookup[key] == 'status-unknown':
print(f"{key!r} => {lookup[key]!r}")
print("\naccount-status-pill modifiers:")
print(", ".join(modifiers))
# Find computed status code for a written-off working-capital loan by inspecting code paths.
ts = Path('src/app/loans/loans-view/loans-view.component.ts').read_text()
m = re.search(r'iconLoanStatusColor\\([\\s\\S]*?return this\\.loanDetailsData\\.status\\?\\.code;', ts)
print("\niconLoanStatusColor tail containing return:", bool(m))
if m:
print(m.group(0)[-500:])
PYRepository: openMF/web-app
Length of output: 1087
Map the written-off working-capital status to a pill modifier.
iconLoanStatusColor() returns loanDetailsData.status?.code for working-capital loans, and the missing lookup key falls back to status-unknown; account-status-pill then uses the inactive colour instead of the dedicated error-coloured written-off badge. Add a mapped loanStatusType.closed.written.off → .status-writtenoff path for the pill.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/loans/loans-view/loans-view.component.scss` around lines 34 - 80,
Update the working-capital status mapping used by iconLoanStatusColor so
loanStatusType.closed.written.off resolves to the status-writtenoff pill
modifier instead of status-unknown. Add the corresponding status-writtenoff
styling under account-status-pill using the dedicated error colour.
Source: Coding guidelines
| "Write-off": "Radier", | ||
| "WriteOff Reason": "Motif de radiation", | ||
| "Written Off": "Radié", | ||
| "Written Off On": "Passé en perte le", |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use consistent French terminology for write-off states.
Lines 3157, 3301, and 3430 use “passé en perte”, while this file already uses “radiation” and “radié” for the same concept. Use the existing terminology.
Proposed change
- "Written Off On": "Passé en perte le",
+ "Written Off On": "Radié le",
- "Write-Off": "Passer en perte",
+ "Write-Off": "Radier",
- "Written Off": "Passé en perte"
+ "Written Off": "Radié"Also applies to: 3301-3301, 3430-3430
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/fr-FR.json` at line 3157, Update the French
translations for “Written Off On” at all three occurrences to use the file’s
existing “radiation” terminology instead of “passé en perte”, while preserving
the intended date-label meaning.
| "Withdrawn": "빼는", | ||
| "Written Off": "상각됨" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use a status-form translation for Withdrawn.
"빼는" means “taking out” and does not read as a loan status. Use "철회됨" to match the existing Withdrawn by Client translation and the status context.
Proposed fix
- "Withdrawn": "빼는",
+ "Withdrawn": "철회됨",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Withdrawn": "빼는", | |
| "Written Off": "상각됨" | |
| "Withdrawn": "철회됨", | |
| "Written Off": "상각됨" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/ko-KO.json` around lines 3425 - 3426, Update the
"Withdrawn" translation in the Korean locale to "철회됨", matching the existing
"Withdrawn by Client" wording and expressing it as a status.
| "Write-off": "Nusirašinėti", | ||
| "WriteOff Reason": "Nurašymo priežastis", | ||
| "Written Off": "Nurašytas", | ||
| "Written Off On": "Nurašyta", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use a date label for Written Off On.
Nurašyta describes the status and does not identify a date. Use Nurašymo data, which matches the existing Write Off Date translation.
Based on the PR objective, this label displays the written-off date in the General tab.
Proposed fix
- "Written Off On": "Nurašyta",
+ "Written Off On": "Nurašymo data",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Written Off On": "Nurašyta", | |
| "Written Off On": "Nurašymo data", |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/lt-LT.json` at line 3153, Update the lt-LT
translation for the “Written Off On” key to use the date-specific label
“Nurašymo data”, matching the existing “Write Off Date” translation rather than
the status wording.
| "Charge-Off": "Norakstīšana", | ||
| "Write-Off": "Norakstīšana", |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
What is the standard Latvian financial term to distinguish "charge-off" from "write-off" in loan management systems?
💡 Result:
In Latvian financial and accounting contexts, the term "norakstīšana" (write-off) is the standard terminology used to describe the process of removing an uncollectible asset or debt from the balance sheet [1][2][3]. Latvian financial systems and regulatory documents, such as those issued by Latvijas Banka (the central bank), consistently refer to the accounting of loan losses and asset removals using the term "norakstīšana" or "zaudējumu norakstīšana" (write-off/write-down) [4][5][6]. While English terminology distinguishes between "charge-off" (a status often used in consumer credit to signal a formal declaration of uncollectibility and an accounting write-off) [7][8] and "write-off" (the broader accounting action) [7][8][9], Latvian financial terminology typically does not utilize a separate, distinct technical term equivalent to the English "charge-off." Instead, both concepts are generally subsumed under "norakstīšana." If a distinction is necessary in a loan management system to reflect the specific nature of a charge-off (e.g., as a regulatory milestone for non-performing loans), institutions typically use descriptive phrasing rather than a single specialized noun. Commonly used descriptive terms include: 1. Zaudējumu norakstīšana: Used to specify that the write-off is explicitly recognized as a financial loss [1][3]. 2. Bezcerīgā parāda norakstīšana: Used to denote the writing off of "hopeless" or bad debt that is deemed uncollectible [2][3]. For technical implementation in loan management systems, "norakstīšana" serves as the primary functional term, often qualified by context (e.g., status flags or category labels) to differentiate between internal administrative actions and formal loss recognition.
Citations:
- 1: https://lv.know-base.net/7578038-write-off
- 2: https://lv.periodicalfinance.com/10919418-how-to-write-off-debt-for-losses
- 3: https://www.d-k.lv/lat/documents/help/14533/19148/print/
- 4: https://datnes.latvijasbanka.lv/files/statistika/2026%20Statistical%20Programme%20of%20Latvijas%20Banka.pdf
- 5: https://datnes.latvijasbanka.lv/files/statistika/Statistical%20Programme_Latvijas%20Banka_2024.pdf
- 6: https://www.bank.lv/images/stories/pielikumi/statistika/2022_Bank_of_Latvia_Statistical_Programme.pdf
- 7: https://accountinginsights.org/the-difference-between-a-charge-off-and-a-write-off/
- 8: https://economyr.com/managing-debt/charge-off-vs-write-off
- 9: https://en.wikipedia.org/wiki/charge-off
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file excerpt around keys =="
sed -n '3288,3302p' src/assets/translations/lv-L V.json 2>/dev/null || sed -n '3288,3302p' src/assets/translations/lv-LV.json
echo
echo "== exact key occurrences in lv translation =="
python3 - <<'PY'
from pathlib import Path
import json
p = Path("src/assets/translations/lv-LV.json")
data = json.load(p.open(encoding="utf-8"))
def walk(o, path=None):
for k,v in o.items() if isinstance(o, dict) else []:
yield path + [k], k, v
yield from walk(v, path+[k])
for i,v in enumerate(o) if isinstance(o, list) else []:
yield path + [str(i)], str(i), v
yield from walk(v, path+[str(i)])
for k,v in walk(data):
if k in ("Charge-Off","Write-Off","Norakstīšana"):
continue
if k == "Charge-Off" or k == "Write-Off":
print(f"{path_to_json(k, k)} {v}")
PY
echo
echo "== keys containing Charge or Write in all translation files =="
rg -n '"(Charge-Off|Write-Off)"' src/assets/translations || true
echo
echo "== local term occurrences =="
rg -n '"Norakstīšana"' src/assets/translations || trueRepository: openMF/web-app
Length of output: 1111
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json
from pathlib import Path
p = Path("src/assets/translations/lv-LV.json")
data = json.load(p.open(encoding="utf-8"))
def walk(o, path=None):
for k, v in ((k, v) for k, v in o.items()) if isinstance(o, dict) else []:
yield "+".join(path) + ":" + str(k), k, v
yield from walk(v, path + [k])
for i, v in enumerate(o) if isinstance(o, list) else []:
yield "+".join(path) + ":" + str(i), str(i), v
yield from walk(v, path + [str(i)])
print("lv-LV entries:")
for path_key, key, value in walk(data):
if key in ("Charge-Off", "Write-Off"):
print(f"{path_key}: {value}")
print()
print("all translation files Charge-Off / Write-Off:")
for trans in sorted(Path("src/assets/translations").glob("*.json")):
jd = json.load(trans.open(encoding="utf-8"))
# simple recursive traversal without dependency libraries
def scan(o, spath=""):
hits = []
if isinstance(o, dict):
for k,v in o.items():
if k in ("Charge-Off", "Write-Off"):
hits.append((trans.name, f"{spath}:{k}", v))
hits.extend(scan(v, f"{spath}:{k}" if spath else str(k)))
elif isinstance(o, list):
for i,v in enumerate(o):
hits.extend(scan(v, f"{spath}:{i}" if spath else str(i)))
return hits
for h in scan(jd):
print(" ".join(h))
PYRepository: openMF/web-app
Length of output: 312
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== exact key occurrences in lv-LV.json =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path("src/assets/translations/lv-LV.json")
data = json.load(p.open(encoding="utf-8"))
def walk(o, path=None):
if path is None:
path = []
for k, v in ((k, v) for k, v in o.items()) if isinstance(o, dict) else []:
yield path + [k], k, v
yield from walk(v, path + [k])
for i, v in enumerate(o) if isinstance(o, list) else []:
yield path + [str(i)], str(i), v
yield from walk(v, path + [str(i)])
for path, key, value in walk(data):
if key in ("Charge-Off", "Write-Off"):
print(f"{':' .join(str(x) for x in path)}: {value}")
PY
echo
echo "== keys containing Charge or Write in all translation files =="
rg -n '"(Charge-Off|Write-Off)"' src/assets/translations || true
echo
echo "== local term occurrences =="
rg -n '"Norakstīšana"' src/assets/translations || trueRepository: openMF/web-app
Length of output: 2468
Use separate Latvian labels for Charge-Off and Write-Off.
Charge-Off and Write-Off both translate to Norakstīšana in src/assets/translations/lv-LV.json, so Latvian users cannot distinguish these separate menu actions. Use one term for Charge-Off and a different descriptive term for Write-Off.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/lv-LV.json` around lines 3296 - 3297, Update the
Latvian translation entries for Charge-Off and Write-Off so they use distinct
descriptive labels, preserving the existing translation for one action and
replacing the duplicate Norakstīšana value for the other.
| "Centers": "Vituo", | ||
| "Change Loan Officer": "Badilisha Afisa Mikopo", | ||
| "Charge-Off": "Chaji-Zima", | ||
| "Write-Off": "Ufutaji", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate translation file and relevant keys"
if [ -f src/assets/translations/sw-SW.json ]; then
python3 - <<'PY'
import json, re
from pathlib import Path
path = Path("src/assets/translations/sw-SW.json")
data = json.loads(path.read_text(encoding="utf-8"))
def walk(obj, prefix=""):
if isinstance(obj, dict):
for k, v in obj.items():
if isinstance(v, dict):
yield from walk(v, f"{prefix}.{k}" if prefix else k)
else:
yield f"{prefix}.{k}" if prefix else k, v
elif isinstance(obj, list):
for i, v in enumerate(obj):
yield from walk(v, f"{prefix}[{i}]")
matches = {}
for key, val in walk(data):
if isinstance(val, str) and re.search(r'Write-?Off|Written Off|Kufuta|futa|Andika|Imeandikwa|Ufutaji|Imefutwa', val, re.I):
matches[key] = val
print("Relevant matches:")
for key, val in sorted(matches.items()):
print(f"{key}: {val}")
# Print a numeric-ish range around the reported line by locating newline count in raw JSON approximation for nested keys is hard; use textual search in raw.
text = path.read_text(encoding="utf-8").splitlines()
print("\nRaw context around lines 3280-3435:")
for n in range(3280, min(3436, len(text)) + 1):
if n <= len(text):
line = text[n-1]
if "Write-Off" in line or "Written Off" in line or "Andika" in line or "Ufutaji" in line or "Imeandikwa" in line or "Kufuta" in line:
print(f"{n}: {line}")
else:
print("No translation file or context found.")
PY
else
echo "src/assets/translations/sw-SW.json not found"
fiRepository: openMF/web-app
Length of output: 8464
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Neighborhood of write-off/write-off status translations"
python3 - <<'PY'
from pathlib import Path
path = Path("src/assets/translations/sw-SW.json")
lines = path.read_text(encoding="utf-8").splitlines()
for n in range(3284, min(3428, len(lines)) + 1):
print(f"{n}: {lines[n-1]}")
PY
echo
echo "Compare related label keys"
python3 - <<'PY'
from pathlib import Path
import json
path = Path("src/assets/translations/sw-SW.json")
data = json.loads(path.read_text(encoding="utf-8"))
def walk(obj, prefix=""):
if isinstance(obj, dict):
for k, v in obj.items():
if isinstance(v, dict):
yield from walk(v, f"{prefix}.{k}" if prefix else k)
else:
yield f"{prefix}.{k}" if prefix else k, v
elif isinstance(obj, list):
for i, v in enumerate(obj):
yield from walk(v, f"{prefix}[{i}]")
terms = ["Write Off", "Write-Off", "Written Off", "Closed (written off)", "Write off on", "Writeoff", "Writtenoff", "Reason for Write-Off", "WriteOff", "Undo Write-off"]
print("Target/related term translations:")
for key, val in walk(data):
if val in terms or any(s in key for s in ["Write Off", "Write-Off", "Written Off", "writeoff", "Writtenoff", "Write off", "Undo Write-off"]):
print(f"{key}: {val}")
# Also show nearby JSON key names by raw text scan for exact English keys.
for i, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if "Write" in line or "Write-Off" in line or "Write-off" in line or "Written Off" in line or "writeoff" in line or "Writtenoff" in line:
print(f"raw {i}: {line}")
PYRepository: openMF/web-app
Length of output: 9140
Use one Swahili term for write-off everywhere.
Write-Off is translated as Ufutaji, while same-meaning keys use Andika, Kuandika-mbali, or Imeandikwa Mbali. Apply the same approved term to Write-Off and Written Off consistently in this file.
Also applies to line 3423.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/sw-SW.json` at line 3294, Update the “Write-Off” and
“Written Off” translation entries in the Swahili locale, including the related
entry near line 3423, to use the same approved Swahili write-off term
consistently with the other same-meaning keys. Remove the inconsistent “Ufutaji”
value and preserve the surrounding translation structure.
137d69f to
83396ff
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
83396ff to
3770c43
Compare
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
src/assets/translations/de-DE.json (1)
829-829: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReplace the loan charge-off translations with a financial charge-off term.
Abladenmeans unloading and conflicts with the existingWrite-OffAbschreibung. Use a consistent charge-off/charged-off term such asAusbuchung/Ausgebuchtfor these labels, for example atcatalogs,labels.menus, andlabels.dialogContext.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/de-DE.json` at line 829, Update the German charge-off translations in catalogs, labels.menus, and labels.dialogContext to use the financial terms Ausbuchung/Ausgebucht instead of Abladen, while preserving the existing Write-Off translation Abschreibung.src/assets/translations/pt-PT.json (1)
827-827: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse accounting terminology for
Charge-Off.These entries translate
Charge-OffasCobrançaorCobrado. These terms describe collection or charging. They do not describe an accounting write-off. Use terminology consistent withWrite-Off:Baixa,Montante da baixa,Data da baixa,Baixado em, anddesfazer a baixa.Proposed terminology fixes
- "Charge-off": "Cobrança", + "Charge-off": "Baixa", - "Charge-Off Amount": "Montante da cobrança", + "Charge-Off Amount": "Montante da baixa", - "Charge-Off Date": "Data da cobrança", + "Charge-Off Date": "Data da baixa", - "Charged Off On": "Cobrado em", + "Charged Off On": "Baixado em", - "Charged Off": "Cobrado", + "Charged Off": "Baixado", - "Are you sure you want to undo the charge-off": "Tem a certeza de que pretende desfazer a cobrança?", + "Are you sure you want to undo the charge-off": "Tem a certeza de que pretende desfazer a baixa?",Also applies to: 1836-1837, 1841-1841, 3430-3430, 3486-3486
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/pt-PT.json` at line 827, Update the Portuguese translations for all `Charge-Off` entries, including the referenced entries, to use accounting write-off terminology consistent with the existing `Write-Off` translations, replacing collection-related terms such as “Cobrança” and “Cobrado” with the appropriate “Baixa” forms while preserving each string’s grammatical context.src/assets/translations/fr-FR.json (2)
1147-1147: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCorrect the French grammar for
Mark as Fraud.
Marquer comme fraudeis not a valid action label. UseMarquer comme frauduleuxandMarquer ce prêt comme frauduleux ?.Also applies to: 3283-3283, 3468-3468
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/fr-FR.json` at line 1147, Update the French translations for the `Mark as Fraud` action and its related confirmation prompt to use “Marquer comme frauduleux” and “Marquer ce prêt comme frauduleux ?” respectively, including all occurrences identified in the translation file.
827-827: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse the established French terminology for charge-off.
The changed values use
amortir,amortissement, andAmorti. These terms mean amortization. This file usesradiationandradiéfor charge-off states. Use consistent charge-off terminology for the action, amount, date, status, and undo confirmation.Also applies to: 1840-1841, 1845-1845, 3434-3434, 3490-3490
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/fr-FR.json` at line 827, Update the French charge-off translation entries, including “Charge-off” and the referenced action, amount, date, status, and undo-confirmation keys, to use the established “radiation”/“radié” terminology instead of “amortir”, “amortissement”, or “Amorti”.src/assets/translations/it-IT.json (1)
3434-3434: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCorrect the written-off status translation.
"Chiuso (scritto)"means “closed (written)”, not “closed (written off)”. Use the existing write-off terminology from this file.Proposed fix
- "Closed (written off)": "Chiuso (scritto)", + "Closed (written off)": "Chiuso (stralciato)",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/it-IT.json` at line 3434, Update the “Closed (written off)” entry in the Italian translations to use the file’s existing write-off terminology, replacing “Chiuso (scritto)” while preserving the key and JSON structure.src/assets/translations/lt-LT.json (1)
827-827: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReplace the incorrect Lithuanian
Charge-Offtranslations.
Atsakingas užmeans “responsible for”. It does not describe a charge-off. Use charge-off terminology for the action and status. Use date-specific text forCharge-Off DateandCharged Off On. Use amount-specific text forCharge-Off Amount.Proposed fix
- "Charge-off": "Atsakingas už", + "Charge-off": "Nurašymas", - "Charge-Off Amount": "Atsakingas už suma", + "Charge-Off Amount": "Nurašymo suma", - "Charge-Off Date": "Atsakingas už data", + "Charge-Off Date": "Nurašymo data", - "Charged Off On": "Atsakingas už", + "Charged Off On": "Nurašymo data", - "Charged Off": "Atsakingas už", + "Charged Off": "Nurašyta", - "Are you sure you want to undo the charge-off": "Ar tikrai norite anuliuoti Atsakingas už?", + "Are you sure you want to undo the charge-off": "Ar tikrai norite anuliuoti nurašymą?",Also applies to: 1836-1837, 1841-1841, 3430-3430, 3486-3486
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lt-LT.json` at line 827, Replace the Lithuanian translations for “Charge-off” and all referenced variants with accurate charge-off terminology: use action/status wording for “Charge-Off,” date-specific wording for “Charge-Off Date” and “Charged Off On,” and amount-specific wording for “Charge-Off Amount.” Update every occurrence identified by the comment, including the entries near the existing “Charge-off” translation.src/assets/translations/lv-LV.json (1)
1839-1841: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse “norakstīšana” for these charge-off labels.
"Charge-off reason"and"ChargeOff Expense"currently useIzmaksas, which means costs/expenses and not charge-offs."ChargeOff Fraud Expense"is also translated as “leave fraud expenses”. Use the existing Latvian charge-off termNorakstīšanafor consistency, e.g. reason asNorakstīšanas iemesls.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lv-LV.json` around lines 1839 - 1841, Update the three charge-off translation entries in the Latvian locale: use “Norakstīšanas iemesls” for “Charge-off reason” and apply the existing “Norakstīšana” terminology to both “ChargeOff Expense” and “ChargeOff Fraud Expense”, replacing the incorrect expense and fraud wording.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/assets/translations/cs-CS.json`:
- Line 2154: Remove the duplicate “Reversal External Id” entry from the
translation object, keeping the existing definition already present in inputs
and preserving its translation value.
In `@src/assets/translations/de-DE.json`:
- Line 2156: Remove the duplicate "Reversal External Id" entry from the later
declaration in the inputs object, while retaining the existing entry near the
earlier translation declaration.
In `@src/assets/translations/en-US.json`:
- Line 2182: Remove the duplicate “Reversal External Id” entry from the
translation object near the shown declaration, retaining the existing
declaration in the inputs object and preserving its value.
In `@src/assets/translations/es-CL.json`:
- Line 2154: Remove the duplicate “Reversal External Id” entry from the inputs
object, keeping the existing entry at the later location around line 2871 and
preserving its translation value.
In `@src/assets/translations/es-MX.json`:
- Line 2161: Remove the duplicate “Reversal External Id” entry from the inputs
object, retaining the existing entry near the earlier declaration and deleting
only the later duplicate.
In `@src/assets/translations/fr-FR.json`:
- Line 2157: Remove the duplicate “Reversal External Id” entry from the
labels.inputs translations, keeping a single declaration with the canonical
French translation.
In `@src/assets/translations/it-IT.json`:
- Line 2154: Remove one of the duplicate "Reversal External Id" entries from the
translation JSON, preserving a single declaration with its existing Italian
value so the inputs object remains valid and deterministic.
In `@src/assets/translations/ko-KO.json`:
- Line 2155: Remove one of the duplicate "Reversal External Id" entries in the
translation object, keeping a single definition with its existing value so the
object has no repeated keys.
In `@src/assets/translations/lt-LT.json`:
- Line 2153: Remove one duplicate “Reversal External Id” entry from the
translations JSON, keeping a single declaration and its existing Lithuanian
translation so the later value no longer overrides the earlier one.
In `@src/assets/translations/lv-LV.json`:
- Line 2154: Remove one of the duplicate “Reversal External Id” entries in the
translations inputs object, retaining a single declaration and its intended
value so JSON parsing and Biome no longer encounter duplicate keys.
In `@src/assets/translations/ne-NE.json`:
- Line 2153: Remove the duplicate "Reversal External Id" entry from the
translation object at the earlier declaration, keeping the existing declaration
later in the object unchanged so noDuplicateObjectKeys is satisfied.
In `@src/assets/translations/pt-PT.json`:
- Line 2153: Remove one of the duplicate “Reversal External Id” entries from the
labels.inputs translation object in pt-PT.json, keeping exactly one declaration
with the existing translation value.
In `@src/assets/translations/sw-SW.json`:
- Line 2151: Remove the duplicate “Reversal External Id” entry from the
labels.inputs translations, keeping one canonical key and its existing value so
the object contains no repeated key.
---
Outside diff comments:
In `@src/assets/translations/de-DE.json`:
- Line 829: Update the German charge-off translations in catalogs, labels.menus,
and labels.dialogContext to use the financial terms Ausbuchung/Ausgebucht
instead of Abladen, while preserving the existing Write-Off translation
Abschreibung.
In `@src/assets/translations/fr-FR.json`:
- Line 1147: Update the French translations for the `Mark as Fraud` action and
its related confirmation prompt to use “Marquer comme frauduleux” and “Marquer
ce prêt comme frauduleux ?” respectively, including all occurrences identified
in the translation file.
- Line 827: Update the French charge-off translation entries, including
“Charge-off” and the referenced action, amount, date, status, and
undo-confirmation keys, to use the established “radiation”/“radié” terminology
instead of “amortir”, “amortissement”, or “Amorti”.
In `@src/assets/translations/it-IT.json`:
- Line 3434: Update the “Closed (written off)” entry in the Italian translations
to use the file’s existing write-off terminology, replacing “Chiuso (scritto)”
while preserving the key and JSON structure.
In `@src/assets/translations/lt-LT.json`:
- Line 827: Replace the Lithuanian translations for “Charge-off” and all
referenced variants with accurate charge-off terminology: use action/status
wording for “Charge-Off,” date-specific wording for “Charge-Off Date” and
“Charged Off On,” and amount-specific wording for “Charge-Off Amount.” Update
every occurrence identified by the comment, including the entries near the
existing “Charge-off” translation.
In `@src/assets/translations/lv-LV.json`:
- Around line 1839-1841: Update the three charge-off translation entries in the
Latvian locale: use “Norakstīšanas iemesls” for “Charge-off reason” and apply
the existing “Norakstīšana” terminology to both “ChargeOff Expense” and
“ChargeOff Fraud Expense”, replacing the incorrect expense and fraud wording.
In `@src/assets/translations/pt-PT.json`:
- Line 827: Update the Portuguese translations for all `Charge-Off` entries,
including the referenced entries, to use accounting write-off terminology
consistent with the existing `Write-Off` translations, replacing
collection-related terms such as “Cobrança” and “Cobrado” with the appropriate
“Baixa” forms while preserving each string’s grammatical context.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1a6452de-591f-46fd-9810-1aba51b7f3aa
📒 Files selected for processing (21)
src/app/loans/common-resolvers/loan-action-button.resolver.tssrc/app/loans/loans-view/general-tab/general-tab.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.htmlsrc/app/loans/loans-view/loan-account-actions/loan-account-actions.component.tssrc/app/loans/loans-view/loans-view.component.htmlsrc/app/loans/loans-view/loans-view.component.scsssrc/app/loans/loans.service.tssrc/app/loans/models/working-capital/working-capital-loan-account.model.tssrc/assets/translations/cs-CS.jsonsrc/assets/translations/de-DE.jsonsrc/assets/translations/en-US.jsonsrc/assets/translations/es-CL.jsonsrc/assets/translations/es-MX.jsonsrc/assets/translations/fr-FR.jsonsrc/assets/translations/it-IT.jsonsrc/assets/translations/ko-KO.jsonsrc/assets/translations/lt-LT.jsonsrc/assets/translations/lv-LV.jsonsrc/assets/translations/ne-NE.jsonsrc/assets/translations/pt-PT.jsonsrc/assets/translations/sw-SW.json
🚧 Files skipped from review as they are similar to previous changes (8)
- src/app/loans/common-resolvers/loan-action-button.resolver.ts
- src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html
- src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts
- src/app/loans/loans-view/loans-view.component.html
- src/app/loans/loans-view/general-tab/general-tab.component.html
- src/app/loans/loans-view/loans-view.component.scss
- src/app/loans/models/working-capital/working-capital-loan-account.model.ts
- src/app/loans/loans.service.ts
| "External ID not found": "Externí ID nenalezeno", | ||
| "External ID verified successfully": "Externí ID úspěšně ověřeno", | ||
| "External Id": "Externí id", | ||
| "Reversal External Id": "Externí ID storna", |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Remove the duplicate translation key.
inputs already defines Reversal External Id at Line [2868]. The duplicate at Line [2154] triggers Biome noDuplicateObjectKeys and can fail the lint check.
Proposed fix
- "Reversal External Id": "Externí ID storna",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Reversal External Id": "Externí ID storna", |
🧰 Tools
🪛 Biome (2.5.6)
[error] 2154-2154: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/cs-CS.json` at line 2154, Remove the duplicate
“Reversal External Id” entry from the translation object, keeping the existing
definition already present in inputs and preserving its translation value.
Source: Linters/SAST tools
| "External ID not found": "Externe ID nicht gefunden", | ||
| "External ID verified successfully": "Externe ID erfolgreich verifiziert", | ||
| "External Id": "Externe ID", | ||
| "Reversal External Id": "Externe Storno-ID", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object declares this key at Line 2156 and again at Line 2870. Biome reports lint/suspicious/noDuplicateObjectKeys. Keep the declaration near Line 2156 and remove the duplicate at Line 2870.
Proposed fix
- "Reversal External Id": "Externe Storno-ID",
"Reversed": "Umgedreht",Also applies to: 2870-2870
🧰 Tools
🪛 Biome (2.5.6)
[error] 2156-2156: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/de-DE.json` at line 2156, Remove the duplicate
"Reversal External Id" entry from the later declaration in the inputs object,
while retaining the existing entry near the earlier translation declaration.
Source: Linters/SAST tools
| "External ID not found": "External ID not found", | ||
| "External ID verified successfully": "External ID verified successfully", | ||
| "External Id": "External Id", | ||
| "Reversal External Id": "Reversal External Id", |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object already defines this key at Line 2914. Keep one declaration, preferably the existing declaration, and remove the new declaration at Line 2182. Biome reports this duplicate key as an error.
Proposed fix
- "Reversal External Id": "Reversal External Id",Also applies to: 2914-2914
🧰 Tools
🪛 Biome (2.5.6)
[error] 2182-2182: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/en-US.json` at line 2182, Remove the duplicate
“Reversal External Id” entry from the translation object near the shown
declaration, retaining the existing declaration in the inputs object and
preserving its value.
Source: Linters/SAST tools
| "External ID not found": "Id externo no encontrado", | ||
| "External ID verified successfully": "Id externo verificado exitosamente", | ||
| "External Id": "Id externo", | ||
| "Reversal External Id": "Id externo de reversión", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object declares this key at Line 2154 and Line 2871. Biome reports Line 2154 as a duplicate. Keep one entry, preferably the existing entry at Line 2871. Duplicate keys can fail linting and produce last-key-wins behavior in JSON consumers.
Proposed fix
- "Reversal External Id": "Id externo de reversión",Also applies to: 2871-2871
🧰 Tools
🪛 Biome (2.5.6)
[error] 2154-2154: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/es-CL.json` at line 2154, Remove the duplicate
“Reversal External Id” entry from the inputs object, keeping the existing entry
at the later location around line 2871 and preserving its translation value.
Source: Linters/SAST tools
| "External ID not found": "Id externo no encontrado", | ||
| "External ID verified successfully": "Id externo verificado exitosamente", | ||
| "External Id": "Id externo", | ||
| "Reversal External Id": "Id externo de reversión", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object declares this key at Line 2161 and again at Line 2877. Biome reports lint/suspicious/noDuplicateObjectKeys. JSON parsers can silently retain only one duplicate value, and the lint gate can fail.
Keep the entry at Line 2161 and delete the duplicate at Line 2877.
Proposed fix
"Results": "Resultados",
- "Reversal External Id": "Id externo de reversión",
"Reversed": "invertido",Also applies to: 2877-2877
🧰 Tools
🪛 Biome (2.5.6)
[error] 2161-2161: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/es-MX.json` at line 2161, Remove the duplicate
“Reversal External Id” entry from the inputs object, retaining the existing
entry near the earlier declaration and deleting only the later duplicate.
Source: Linters/SAST tools
| "External ID not found": "Išorinis ID nerastas", | ||
| "External ID verified successfully": "Išorinis ID sėkmingai patvirtintas", | ||
| "External Id": "Išorinis ID", | ||
| "Reversal External Id": "Atšaukimo išorinis ID", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object declares this key at Line 2153 and Line 2867. The later JSON value overrides the earlier value, so one translation is unreachable. Biome also reports this duplicate key. Keep one declaration.
Also applies to: 2867-2867
🧰 Tools
🪛 Biome (2.5.6)
[error] 2153-2153: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/lt-LT.json` at line 2153, Remove one duplicate
“Reversal External Id” entry from the translations JSON, keeping a single
declaration and its existing Lithuanian translation so the later value no longer
overrides the earlier one.
Source: Linters/SAST tools
| "External ID not found": "Ārējais ID nav atrasts", | ||
| "External ID verified successfully": "Ārējais ID veiksmīgi verificēts", | ||
| "External Id": "Ārējais ID", | ||
| "Reversal External Id": "Storno ārējais ID", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
The inputs object declares this key at Lines 2154 and 2868 with different values. The later value overwrites the earlier value during JSON parsing. Biome also reports noDuplicateObjectKeys. Keep one declaration.
Also applies to: 2868-2868
🧰 Tools
🪛 Biome (2.5.6)
[error] 2154-2154: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/lv-LV.json` at line 2154, Remove one of the duplicate
“Reversal External Id” entries in the translations inputs object, retaining a
single declaration and its intended value so JSON parsing and Biome no longer
encounter duplicate keys.
Source: Linters/SAST tools
| "External ID not found": "बाह्य आईडी फेला परेन", | ||
| "External ID verified successfully": "बाह्य आईडी सफलतापूर्वक प्रमाणित भयो", | ||
| "External Id": "बाह्य आईडी", | ||
| "Reversal External Id": "उल्टाउने बाह्य आईडी", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate translation key before merge.
The inputs object declares "Reversal External Id" at Line 2153 and Line 2867. Biome reports this as lint/suspicious/noDuplicateObjectKeys. Keep the existing declaration at Line 2867 and remove the added declaration at Line 2153.
Proposed fix
- "Reversal External Id": "उल्टाउने बाह्य आईडी",Also applies to: 2867-2867
🧰 Tools
🪛 Biome (2.5.6)
[error] 2153-2153: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/ne-NE.json` at line 2153, Remove the duplicate
"Reversal External Id" entry from the translation object at the earlier
declaration, keeping the existing declaration later in the object unchanged so
noDuplicateObjectKeys is satisfied.
Source: Linters/SAST tools
| "External ID not found": "ID externo não encontrado", | ||
| "External ID verified successfully": "ID externo verificado com sucesso", | ||
| "External Id": "ID externo", | ||
| "Reversal External Id": "ID externo de estorno", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
labels.inputs declares this key at Lines 2153 and 2867. Biome reports lint/suspicious/noDuplicateObjectKeys. Keep one declaration to avoid lint failure and parser-dependent key resolution.
Proposed fix
"Retry": "Tentar novamente",
- "Reversal External Id": "ID externo de estorno",
"Reversed": "Invertido",Also applies to: 2867-2867
🧰 Tools
🪛 Biome (2.5.6)
[error] 2153-2153: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/pt-PT.json` at line 2153, Remove one of the duplicate
“Reversal External Id” entries from the labels.inputs translation object in
pt-PT.json, keeping exactly one declaration with the existing translation value.
Source: Linters/SAST tools
| "External ID not found": "Kitambulisho cha Nje hakijapatikana", | ||
| "External ID verified successfully": "Kitambulisho cha Nje kimethibitishwa kwa mafanikio", | ||
| "External Id": "Kitambulisho cha Nje", | ||
| "Reversal External Id": "Kitambulisho cha nje cha ubatilishaji", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the duplicate Reversal External Id key.
labels.inputs declares this key at Line 2151 and again at Line 2865. Biome reports lint/suspicious/noDuplicateObjectKeys. Keep one canonical entry and remove the duplicate to prevent silent value overriding.
🧰 Tools
🪛 Biome (2.5.6)
[error] 2151-2151: The key Reversal External Id was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/sw-SW.json` at line 2151, Remove the duplicate
“Reversal External Id” entry from the labels.inputs translations, keeping one
canonical key and its existing value so the object contains no repeated key.
Source: Linters/SAST tools
3770c43 to
e002e94
Compare
Description
Adds Write-Off and Undo Write-Off actions for Working Capital loans, mirroring the term-loan flow with dedicated typed components wired into the shared loan action switch. Write-Off posts to
POST /working-capital-loans/{id}/transactions?command=writeOff(reason dropdown sourced from the "WriteOffReasons" code values, since WC has no write-off template) and Undo Write-Off tocommand=undoWriteOff; both gated by theWRITEOFF_WORKINGCAPITALLOAN/UNDOWRITEOFF_WORKINGCAPITALLOANpermissions and the loan status. Includes the terminal-state button config, the written-off date/reason display in the general tab, and theReversal External IdRelated issues and discussion
WEB-657
Screenshots, if any
Screen.Recording.2026-08-04.at.2.26.33.PM.mov
Checklist
Please make sure these boxes are checked before submitting your pull request - thanks!
If you have multiple commits please combine them into one commit by squashing them.
Read and understood the contribution guidelines at
web-app/.github/CONTRIBUTING.md.Summary by CodeRabbit
New Features
Enhancements