Skip to content

Fix IsResolved is not set to false despite associated Loan Return Preparations being deleted or unresolved#8077

Open
Iwantexpresso wants to merge 16 commits into
mainfrom
issue-4883
Open

Fix IsResolved is not set to false despite associated Loan Return Preparations being deleted or unresolved#8077
Iwantexpresso wants to merge 16 commits into
mainfrom
issue-4883

Conversation

@Iwantexpresso
Copy link
Copy Markdown
Contributor

@Iwantexpresso Iwantexpresso commented May 12, 2026

Fixes #4883 and #8076

Previously there was an inconsistency between the isResolved checkbox not being properly set to false when deleting loan return preps. during debugging for this issue, there was a new issue found specific to Firefox browsers that occurred while manually creating loan return preps due to how it handled JSON field parsing. both are addressed within this pr. and both features should be working as intended.

Checklist

  • Self-review the PR after opening it to make sure the changes look good and
    self-explanatory (or properly documented)
  • Add relevant issue to release milestone
  • Add pr to documentation list
  • Add automated tests

Testing instructions

For Firefox Specifically ( #8076) :

  • Create a CO with preparations, Note down the CO number.
  • Create a loan for that specific CO, then import the loan preparations for that CO.
  • Click on the Loan Return prep Subform, select quantity returned and quantity resolved to be any number less than or equal to the total quantity of loan preparations
  • Make sure there is no longer an error related to the manual creation of LoanReturnPreps
  • (optional) test these on a different browser to ensure functionality stayed the same between them

For any browser (#4883):

  • Create a CO with preparations, Save CO Number.
  • Create a loan for that specific CO, then import the loan preparations for that CO.
  • Click on return loan button and select all preps
  • make sure the isResolved box is checked
  • click on loanReturnPrep subForm and delete them, then save the loan
  • Make sure the isResolved box is unchecked
  • Using the subform manually add loan return preps, then save.
  • IsResolved checkbox remains unchecked until the amount of loan return preps is equivalent to the amount of loan preparations available

Summary by CodeRabbit

  • Bug Fixes

    • Fixed handling of loan return quantities submitted as strings so returned counts sum correctly.
  • New Features

    • Automatically marks loan preparations as "resolved" when returned quantity meets or exceeds the total.
  • Refactor

    • UI and code formatting cleanups across several components and tests for improved maintainability.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Warning

Rate limit exceeded

@Iwantexpresso has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 14 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1194c0d9-9038-4853-88ac-5099b0b81354

📥 Commits

Reviewing files that changed from the base of the PR and between e62a4dd and 2f054b1.

📒 Files selected for processing (1)
  • specifyweb/specify/api/calculated_fields.py
📝 Walkthrough

Walkthrough

Adds API logic to compute Loanpreparation.extra["isresolved"] from integerized quantities and casts posted quantity fields to int when summing loan return preparations; applies widespread non-functional frontend formatting and a localization key quoting change.

Changes

Loan Preparation IsResolved Resolution

Layer / File(s) Summary
IsResolved calculation and quantity parsing
specifyweb/specify/api/calculated_fields.py, specifyweb/backend/interactions/cog_preps.py
Adds Loanpreparation handling in calculate_extra_fields() to set extra["isresolved"] from integerized quantityresolved/quantity, and casts quantityreturned/quantityresolved to int when recomputing totals in loan return prep sync.

Code Formatting and Localization Alignment

Layer / File(s) Summary
ExpressSearchConfig UI and tests
specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/*, specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/*
Reformats ExpressSearchConfigDialog, ResultsOrderingTab, and related tests (multi-line destructuring, JSX reflow, assertion formatting) without behavioral changes.
Header, notifications, navigator, localization, schema visibility
specifyweb/frontend/js_src/lib/components/Header/*, specifyweb/frontend/js_src/lib/components/Notifications/*, specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx, specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts, specifyweb/frontend/js_src/lib/localization/*, specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts
Non-functional formatting changes across header hooks/tasks, notification renderers, FormTable, navigator EOF, localization entries; languageCodeMapper nb key unquoted.

Possibly related PRs

  • specify/specify7#7815: Overlapping ExpressSearchConfig/ResultsOrderingTab formatting and languageCodeMapper (nb key) changes from the same formatting effort.

Suggested reviewers

  • emenslin
  • CarolineDenis
🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Automatic Tests ⚠️ Warning PR lacks automatic tests for core fixes in cog_preps.py and calculated_fields.py; PR checklist explicitly states "automated tests still to be added." Add tests for the string-to-int quantity casting fix and new Loanpreparation isresolved calculation logic before merging.
Testing Instructions ⚠️ Warning The PR template "Testing instructions" section is empty (only HTML comments remain). PR objectives claim instructions were provided for Firefox and manual LRP creation, but none exist in the codebase. Fill the PR's "Testing instructions" section with clear step-by-step procedures for testing across Firefox and other browsers, covering loan prep imports, Return Loan, LRP deletion/addition, and IsResolved checkbox behavior.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: ensuring IsResolved is set to false when Loan Return Preparations are deleted or unresolved.
Linked Issues check ✅ Passed The PR addresses all key requirements from issue #4883: fixing IsResolved state during manual LRP creation/deletion and resolving Firefox JSON parsing errors.
Out of Scope Changes check ✅ Passed The changes are focused on fixing IsResolved calculations and include formatting improvements, all aligned with the linked issue objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-4883

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Iwantexpresso Iwantexpresso changed the title Fix IsResolved is not set to false despite Fix IsResolved is not set to false despite associated Loan Return Preparations being deleted or unresolved May 12, 2026
@Iwantexpresso Iwantexpresso marked this pull request as ready for review May 20, 2026 18:12
@Iwantexpresso Iwantexpresso requested review from a team May 20, 2026 18:13
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
specifyweb/frontend/js_src/lib/localization/utils/config.ts (1)

27-27: 💤 Low value

Inconsistent quote style for object key.

All other language code keys in languageCodeMapper (lines 19–26) use quoted string format ('en-us', 'ru-ru', etc.), but nb now uses an unquoted identifier. For consistency, consider using the same quote style as the other keys.

Suggested fix for consistency
- nb: 'nb_NO',
+ 'nb': 'nb_NO',
🤖 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 `@specifyweb/frontend/js_src/lib/localization/utils/config.ts` at line 27, The
languageCodeMapper object contains an inconsistent key style: the nb key is
unquoted while all other keys (e.g., 'en-us', 'ru-ru') are quoted; update the nb
entry in languageCodeMapper to use the same quoted string format ('nb') to match
the surrounding keys and maintain consistent style across the object.
🤖 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 `@specifyweb/backend/businessrules/rules/Loanprep_rules.py`:
- Around line 33-35: The registration code currently swallows failures and only
logs them; change those paths so that when a signal lookup yields None (e.g.,
the check using the variable signal and signal_name) you raise a ValueError (or
re-raise the original exception) instead of continuing, and for other unexpected
registration exceptions catch them only to log context then re-raise; also
replace silent missing-model logs with at least logger.warning or raise a clear
error so misconfiguration is visible. Locate the three registration blocks
around the signal/signal_name checks (the branch that currently logs when signal
is None and the two similar blocks later) and update them to raise on missing
signals, and to re-raise any unexpected exceptions after logging contextual
information.

In `@specifyweb/backend/interactions/cog_preps.py`:
- Around line 550-553: The sum comprehensions for total_quantity_returned and
total_quantity_resolved use raw int(...) which will raise on None/empty strings;
update the list comprehensions in cog_preps.py (the expressions that compute
total_quantity_returned and total_quantity_resolved) to coerce each item safely,
e.g. use int(loan_return.get("quantityreturned") or 0) and
int(loan_return.get("quantityresolved") or 0) (or int((loan_return["..."] if
loan_return.get("...") else 0))) so empty/nullable payload fields become 0
instead of throwing.

In `@specifyweb/specify/api/calculated_fields.py`:
- Around line 118-121: Coerce incoming quantity fields to integers before
comparing: convert the values assigned to quantity_resolved and total_quantity
(from data.get('quantityresolved') and data.get('quantity')) to int with safe
defaults (e.g., 0) to avoid string comparisons or type errors, then compute
is_resolved = (quantity_resolved >= total_quantity) and set extra['isresolved']
accordingly in calculated_fields.py so the variables quantity_resolved,
total_quantity, is_resolved and extra['isresolved'] are always based on integer
values.

---

Nitpick comments:
In `@specifyweb/frontend/js_src/lib/localization/utils/config.ts`:
- Line 27: The languageCodeMapper object contains an inconsistent key style: the
nb key is unquoted while all other keys (e.g., 'en-us', 'ru-ru') are quoted;
update the nb entry in languageCodeMapper to use the same quoted string format
('nb') to match the surrounding keys and maintain consistent style across the
object.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2f9558d1-52c8-4bf5-a74d-1db0de260cb5

📥 Commits

Reviewing files that changed from the base of the PR and between b3a6255 and 6acc134.

📒 Files selected for processing (16)
  • specifyweb/backend/businessrules/rules/Loanprep_rules.py
  • specifyweb/backend/interactions/cog_preps.py
  • specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ExpressSearchConfigDialog.tsx
  • specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ResultsOrderingTab.tsx
  • specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ExpressSearchConfigEditor.test.tsx
  • specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/RelatedTablesTab.test.tsx
  • specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ResultsOrderingTab.test.tsx
  • specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx
  • specifyweb/frontend/js_src/lib/components/Header/ExpressSearchHooks.tsx
  • specifyweb/frontend/js_src/lib/components/Header/ExpressSearchTask.tsx
  • specifyweb/frontend/js_src/lib/components/Notifications/NotificationRenderers.tsx
  • specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts
  • specifyweb/frontend/js_src/lib/localization/common.ts
  • specifyweb/frontend/js_src/lib/localization/utils/config.ts
  • specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts
  • specifyweb/specify/api/calculated_fields.py

Comment thread specifyweb/backend/businessrules/rules/Loanprep_rules.py Outdated
Comment thread specifyweb/backend/interactions/cog_preps.py Outdated
Comment thread specifyweb/specify/api/calculated_fields.py Outdated
@github-project-automation github-project-automation Bot moved this from 📋Back Log to Dev Attention Needed in General Tester Board May 20, 2026
@CarolineDenis CarolineDenis removed request for a team May 20, 2026 19:41
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
specifyweb/backend/interactions/cog_preps.py (1)

550-553: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Edge case handling remains incomplete despite Firefox fix.

While the int() casting resolves the Firefox string-to-int issue, the code still doesn't guard against loan_return being None or the dictionary keys being absent—both would raise exceptions and break the update flow.

Recommended fix (from previous review)
 total_quantity_returned = sum(
-    [int(loan_return["quantityreturned"] or 0) for loan_return in loan_return_data])
+    int((loan_return or {}).get("quantityreturned") or 0)
+    for loan_return in loan_return_data
+ )
 total_quantity_resolved = sum(
-    [int(loan_return["quantityresolved"] or 0) for loan_return in loan_return_data])
+    int((loan_return or {}).get("quantityresolved") or 0)
+    for loan_return in loan_return_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 `@specifyweb/backend/interactions/cog_preps.py` around lines 550 - 553, The
summation lines for total_quantity_returned and total_quantity_resolved assume
every loan_return in loan_return_data is a dict with the keys "quantityreturned"
and "quantityresolved" and that values are numeric/parseable; update them to
defensively handle None entries and missing keys by skipping None loan_return
objects and using dict.get with a 0 default, then safely coerce the value to int
(fallback to 0 on empty/invalid strings) before summing. Modify the
comprehensions that reference loan_return_data / loan_return to first check
loan_return is truthy and use loan_return.get("quantityreturned", 0) and
loan_return.get("quantityresolved", 0) with a safe int conversion fallback for
both total_quantity_returned and total_quantity_resolved.
🤖 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.

Duplicate comments:
In `@specifyweb/backend/interactions/cog_preps.py`:
- Around line 550-553: The summation lines for total_quantity_returned and
total_quantity_resolved assume every loan_return in loan_return_data is a dict
with the keys "quantityreturned" and "quantityresolved" and that values are
numeric/parseable; update them to defensively handle None entries and missing
keys by skipping None loan_return objects and using dict.get with a 0 default,
then safely coerce the value to int (fallback to 0 on empty/invalid strings)
before summing. Modify the comprehensions that reference loan_return_data /
loan_return to first check loan_return is truthy and use
loan_return.get("quantityreturned", 0) and loan_return.get("quantityresolved",
0) with a safe int conversion fallback for both total_quantity_returned and
total_quantity_resolved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b0c6a52-d62b-4877-8b8d-dc97131d1e64

📥 Commits

Reviewing files that changed from the base of the PR and between 6acc134 and ead5630.

📒 Files selected for processing (1)
  • specifyweb/backend/interactions/cog_preps.py

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
specifyweb/specify/api/calculated_fields.py (1)

118-119: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Harden integer parsing to avoid runtime errors on empty/null payloads.

int(data.get(...)) can raise before fallback is applied (e.g., None, ''), which can still break the Firefox/manual-create path and skip isresolved calculation.

Suggested minimal fix
-            quantity_resolved = int(data.get('quantityresolved')) or 0
-            total_quantity = int(data.get('quantity')) or 0
+            quantity_resolved = int(data.get('quantityresolved') or 0)
+            total_quantity = int(data.get('quantity') or 0)
🤖 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 `@specifyweb/specify/api/calculated_fields.py` around lines 118 - 119, The
integer parsing for quantity_resolved and total_quantity is unsafe:
int(data.get(...)) can raise on None or empty string and prevent downstream
isresolved logic; update the parsing in specify/api/calculated_fields.py so you
first retrieve the raw values (e.g., raw_quantity_resolved =
data.get('quantityresolved') and raw_total_quantity = data.get('quantity')),
then convert using a safe pattern (treat None/'' as 0) before calling int (or
wrap int(...) in a small try/except that falls back to 0). Ensure you replace
the current assignments to quantity_resolved and total_quantity with this safe
parsing approach and keep the rest of isresolved calculation intact.
🤖 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.

Duplicate comments:
In `@specifyweb/specify/api/calculated_fields.py`:
- Around line 118-119: The integer parsing for quantity_resolved and
total_quantity is unsafe: int(data.get(...)) can raise on None or empty string
and prevent downstream isresolved logic; update the parsing in
specify/api/calculated_fields.py so you first retrieve the raw values (e.g.,
raw_quantity_resolved = data.get('quantityresolved') and raw_total_quantity =
data.get('quantity')), then convert using a safe pattern (treat None/'' as 0)
before calling int (or wrap int(...) in a small try/except that falls back to
0). Ensure you replace the current assignments to quantity_resolved and
total_quantity with this safe parsing approach and keep the rest of isresolved
calculation intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8120b7f-7f7d-43e3-bfa1-206f184cd121

📥 Commits

Reviewing files that changed from the base of the PR and between ead5630 and e62a4dd.

📒 Files selected for processing (1)
  • specifyweb/specify/api/calculated_fields.py

@Iwantexpresso Iwantexpresso requested review from a team and Copilot and removed request for Copilot May 21, 2026 15:40
Copy link
Copy Markdown
Collaborator

@bhumikaguptaa bhumikaguptaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Firefox Specifically ( #8076) :

  • Make sure there is no longer an error related to the manual creation of LoanReturnPreps
  • (optional) test these on a different browser to ensure functionality stayed the same between them

For any browser (#4883):

  • make sure the isResolved box is checked
  • Make sure the isResolved box is unchecked
  • IsResolved checkbox remains unchecked until the amount of loan return preps is equivalent to the amount of loan preparations available

Everything works perfectly. I did not run into any error messages. I also tested it on Safari.

@Iwantexpresso Iwantexpresso requested a review from a team May 21, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Dev Attention Needed

Development

Successfully merging this pull request may close these issues.

IsResolved is not set to false despite associated Loan Return Preparations being deleted or unresolved

2 participants