Skip to content

Conversation

@AleX83Xpert
Copy link
Member

@AleX83Xpert AleX83Xpert commented Jan 19, 2026

Summary by CodeRabbit

  • New Features

    • POS receipt column with a "View" download link and verification tooltip for test receipts
    • POS integration alert workflow with a full-page loading spinner while integration data loads
    • Automatic prioritization and orange highlight of the latest test receipt in payments tables
    • POS integration configuration added to B2B apps and GraphQL/API surface
    • Multi-language labels for the POS receipt flow (EN / ES / RU)
  • Tests

    • CRUD tests for POS integration config schema added
  • Chores

    • Database migration to support POS integration config and history

✏️ Tip: You can customize this high-level summary in your review settings.

@AleX83Xpert AleX83Xpert added the 🚨 Migrations We have a database migrations here! label Jan 19, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 19, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds POS integration end-to-end: DB schema, migration, GraphQL types/queries, access controls, server/test utilities, client IFrame alert and hooks, last-testing-receipt fetcher, table renderer/column, and UI flow to surface an alert/spinner, fetch/refetch the last testing receipt, and sort/highlight the matching payment row.

Changes

Cohort / File(s) Summary
Backend Schema & DB
apps/condo/schema.ts, apps/condo/schema.graphql, apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.js, apps/condo/domains/miniapp/schema/B2BApp.js, apps/condo/migrations/...20260123132524-0506_b2bappposintegrationconfighistoryrecord_and_more.js, apps/condo/domains/miniapp/schema/index.js
Add B2BAppPosIntegrationConfig list + history record; add posIntegrationConfig relation to B2BApp and history; migration creates tables/columns/indexes/FKs; exports updated.
Access Control & Utilities
apps/condo/domains/miniapp/access/B2BAppPosIntegrationConfig.js, apps/condo/domains/miniapp/utils/serverSchema/index.js, apps/condo/domains/miniapp/utils/testSchema/index.js
New read/manage access checks for POS config; server utilities and test factory helpers exported for B2BAppPosIntegrationConfig.
GraphQL Documents & Client Types
apps/condo/domains/acquiring/queries/B2BAppContextWithPosIntegrationConfig.graphql, apps/condo/gql/index.ts, apps/condo/gql/operation.types.ts
Add getB2BAppContextWithPosIntegrationConfig query to fetch POS URLs and generated hooks/types for client use.
Frontend Hooks & IFrame
apps/condo/domains/acquiring/hooks/usePosIntegrationAlert.tsx, apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts, apps/condo/domains/miniapp/components/IFrame.tsx
New usePosIntegrationAlert (IFrame render + loading flag) and usePosIntegrationLastTestingPosReceipt (fetch + refetch, skipUntilAuthenticated option); IFrame gains optional onLoad prop.
Payments UI & Renderers
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx, apps/condo/domains/acquiring/components/payments/getPosReceiptUrlRender.tsx, apps/condo/domains/acquiring/hooks/usePaymentsTableColumns.ts
Integrate PosIntegrationAlert and large Spin while loading; add posReceiptUrl column via getPosReceiptUrlRender; pass lastTestingPosReceipt into columns; combine loading flags; refetch logic; sort & highlight matching payment row; minor API additions (internal props/types).
Marketplace Payments
apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx, apps/condo/domains/marketplace/hooks/useMarketplacePaymentTableColumns.tsx
Add wrapper MarketplacePaymentsTable to render PosIntegrationAlert + spinner; fetch/refetch lastTestingPosReceipt and pass to columns; add posReceiptUrl column; reorder and style row matching lastTestingPosReceipt.
I18n
apps/condo/lang/en/en.json, apps/condo/lang/es/es.json, apps/condo/lang/ru/ru.json
Add translations for receipt column, view link, verify title and description (EN/ES/RU).
Tests
apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.test.js
New CRUD tests for B2BAppPosIntegrationConfig covering admin/support/user/anonymous roles and versioning checks.
Client types / operations
apps/condo/gql/operation.types.ts, apps/condo/gql/index.ts
Add generated types and exports for the new POS-context query and hooks.
Migrations
apps/condo/migrations/...20260123132524-0506_b2bappposintegrationconfighistoryrecord_and_more.js
Raw SQL migration to create config/history tables, add posIntegrationConfig columns and indexes, and set FK constraints; includes down migration.
Misc (icons / submodule)
packages/icons/src/components/OnOff.tsx, apps/pos-integration (submodule)
Removed white background path from OnOff icon; updated pos-integration submodule pointer.

Sequence Diagram(s)

sequenceDiagram
  participant UI as rgba(66,133,244,0.5)
  participant PosAlertHook as rgba(34,197,94,0.5)
  participant GQL as rgba(234,88,12,0.5)
  participant ReceiptHook as rgba(168,85,247,0.5)
  participant Table as rgba(14,165,233,0.5)

  UI->>PosAlertHook: mount (orgId)
  PosAlertHook->>GQL: query getB2BAppContextWithPosIntegrationConfig(orgId)
  GQL-->>PosAlertHook: return posIntegrationConfig URLs
  PosAlertHook->>UI: render PosIntegrationAlert (IFrame) + loading=true
  Note over PosAlertHook,UI: IFrame loads → onLoad fires
  PosAlertHook->>UI: set loading=false
  UI->>ReceiptHook: mount (skipUntilAuthenticated = alertLoading)
  ReceiptHook->>GQL: GET fetchLastPosReceiptUrl (credentials)
  GQL-->>ReceiptHook: return lastTestingPosReceipt|null
  ReceiptHook->>UI: provide lastTestingPosReceipt + loading
  UI->>Table: render columns (include posReceiptUrl), use sortedDataSource and highlight row
  Table->>UI: user interacts (Download / Tooltip)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 I peeked inside an iframe bright,
Spotted a test receipt glinting light,
Pulled it to the top with a joyful hop,
Painted its row orange — what a pop!
Now downloads and tooltips dance in sight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: implementing POS integration injection into Condo via B2BApp configuration, which is the core objective of this changeset.

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


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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9cbfa38b59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 23 to 25
status: B2BAppContextStatusType.Finished,
organization: { id: organization.id },
app: { posIntegrationConfig_is_null: false, deletedAt: null },

Choose a reason for hiding this comment

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

P1 Badge Guard organization before dereferencing in alert hook

On initial render, useOrganization() can return organization as undefined (e.g., while the org context is still loading or when the user has no org). This hook immediately dereferences organization.id inside the where clause, which will throw before the skip option is evaluated. The result is a runtime crash and the payments page never renders in those states. Consider guarding the access (e.g., organization?.id) or returning early until the org is available.

Useful? React with 👍 / 👎.

Comment on lines 34 to 36
where: {
status: B2BAppContextStatusType.Finished,
organization: { id: organization.id },

Choose a reason for hiding this comment

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

P1 Badge Guard organization before dereferencing in receipt hook

This hook has the same unsafe access pattern as the alert hook: it uses organization.id inside the query where before the skip flag can short‑circuit. If organization is still undefined during mount, the hook throws and prevents the payments table from rendering. Use organization?.id in the query or defer the query until the org is present.

Useful? React with 👍 / 👎.

Copy link
Contributor

@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

🤖 Fix all issues with AI agents
In `@apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx`:
- Around line 153-157: Remove the redundant useEffect that immediately calls
refetchLastTestingPosReceipt when areAlertLoading flips to false;
MarketplacePaymentsTableContent already mounts after areAlertLoading is false
and triggers the initial fetch, so delete the effect block referencing
useEffect, areAlertLoading and refetchLastTestingPosReceipt to avoid the
duplicate refetch on mount.

In `@apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.test.js`:
- Around line 119-121: The test currently expects an AccessDeniedError when an
anonymous user calls B2BAppPosIntegrationConfig.delete; change the assertion to
expect an AuthenticationError instead by replacing the
expectToThrowAccessDeniedErrorToObj usage with the corresponding
expectToThrowAuthenticationErrorToObj helper for the anonymous,
createdB2BAppPosIntegrationConfig.id deletion call (keep the same anonymous
variable and B2BAppPosIntegrationConfig.delete invocation).

In `@apps/condo/lang/es/es.json`:
- Around line 2427-2430: Update the Spanish strings to use informal "tú" tone:
change pages.condo.payments.posReceiptVerifyTitle from "Verifique la exactitud
del recibo" to an informal variant (e.g., "Verifica la exactitud del recibo")
and change pages.condo.payments.posReceiptVerifyDescription from the formal
phrasing to informal (e.g., "Si todos los datos son correctos, puedes activar la
fiscalización. Si hay errores, contacta al soporte técnico.") so the tone
matches other UI strings.
♻️ Duplicate comments (2)
apps/condo/domains/acquiring/hooks/usePosIntegrationAlert.tsx (1)

21-28: Guard against undefined organization before building the where filter.

On initial render, useOrganization() can yield organization as undefined, so organization.id throws before skip is evaluated (Line 24). This matches the prior review finding.

🛠️ Proposed fix
-            organization: { id: organization.id },
+            organization: { id: organization?.id },
apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (1)

34-40: Guard organization before dereferencing in query where clause.

The query's where clause accesses organization.id directly (line 36), but the skip option on line 40 uses optional chaining (organization?.id). If organization is undefined during mount, the where clause evaluation may throw before the skip condition can prevent the query. Use optional chaining consistently:

🐛 Proposed fix
     } = B2BAppContext.useObjects({
         where: {
             status: B2BAppContextStatusType.Finished,
-            organization: { id: organization.id },
+            organization: { id: organization?.id },
             app: { posIntegrationConfig_is_null: false, deletedAt: null },
             deletedAt: null,
         },
     }, { skip: !organization?.id })
🧹 Nitpick comments (5)
apps/condo/domains/acquiring/components/payments/getPosReceiptUrlRender.tsx (1)

9-14: Prefer interface over type for object shape definitions.

Per coding guidelines, use interface for defining object shapes in TypeScript.

♻️ Suggested refactor
-type GetPosReceiptUrlRenderParams = {
+interface GetPosReceiptUrlRenderParams {
     linkText: string
     verifyTitle: string
     verifyDescription: string
     lastTestingPosReceipt?: LastTestingPosReceiptData
 }
apps/condo/domains/acquiring/hooks/usePaymentsTableColumns.ts (1)

20-22: Prefer interface over type for object shape definitions.

Per coding guidelines, use interface for defining object shapes in TypeScript.

♻️ Suggested refactor
-type PaymentsTableColumnsOptions = {
+interface PaymentsTableColumnsOptions {
     lastTestingPosReceipt?: LastTestingPosReceiptData
 }
apps/condo/domains/marketplace/hooks/useMarketplacePaymentTableColumns.tsx (1)

20-22: Prefer interface over type for object shape definitions.

Per coding guidelines, use interface for defining object shapes in TypeScript.

♻️ Suggested refactor
-type MarketplacePaymentsTableColumnsOptions = {
+interface MarketplacePaymentsTableColumnsOptions {
     lastTestingPosReceipt?: LastTestingPosReceiptData
 }
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

297-301: Minor: Consider returning an empty object for consistency.

The onRow callback implicitly returns undefined when the condition doesn't match. While this works, returning an empty object explicitly improves readability and consistency:

♻️ Optional refactor
                         onRow={(record) => {
                             if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
                                 return { style: { backgroundColor: colors.orange[1] } }
                             }
+                            return {}
                         }}
apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.js (1)

11-12: Consider a more descriptive schemaDoc.

The current schemaDoc simply repeats the schema name. A more descriptive documentation would help developers understand the purpose of this configuration entity.

Suggested improvement
 const B2BAppPosIntegrationConfig = new GQLListSchema('B2BAppPosIntegrationConfig', {
-    schemaDoc: 'B2BAppPosIntegrationConfig',
+    schemaDoc: 'Configuration for B2B App POS (Point of Sale) integration, containing URLs for payment alerts and receipt fetching.',
     fields: {

Comment on lines +153 to +157
useEffect(() => {
if (!areAlertLoading) {
refetchLastTestingPosReceipt()
}
}, [areAlertLoading, refetchLastTestingPosReceipt])
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid the immediate duplicate refetch.

MarketplacePaymentsTableContent only mounts once areAlertLoading is false, so the hook already fetches on mount. This effect triggers a second, immediate refetch every time, which is redundant.

✅ Simplest fix: remove the effect
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
📝 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.

Suggested change
useEffect(() => {
if (!areAlertLoading) {
refetchLastTestingPosReceipt()
}
}, [areAlertLoading, refetchLastTestingPosReceipt])
🤖 Prompt for AI Agents
In `@apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx`
around lines 153 - 157, Remove the redundant useEffect that immediately calls
refetchLastTestingPosReceipt when areAlertLoading flips to false;
MarketplacePaymentsTableContent already mounts after areAlertLoading is false
and triggers the initial fetch, so delete the effect block referencing
useEffect, areAlertLoading and refetchLastTestingPosReceipt to avoid the
duplicate refetch on mount.

Comment on lines +119 to +121
await expectToThrowAccessDeniedErrorToObj(async () => {
await B2BAppPosIntegrationConfig.delete(anonymous, createdB2BAppPosIntegrationConfig.id)
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Anonymous user should throw AuthenticationError, not AccessDeniedError.

For consistency with other tests in this file (lines 57-61, 95-99, 165-170), anonymous users should receive an AuthenticationError rather than AccessDeniedError. The current expectation may pass if the access control returns AccessDenied before checking authentication, but this is inconsistent with the pattern used elsewhere in the test file.

Proposed fix
                 await expectToThrowAccessDeniedErrorToObj(async () => {
                     await B2BAppPosIntegrationConfig.delete(user, createdB2BAppPosIntegrationConfig.id)
                 })
-                await expectToThrowAccessDeniedErrorToObj(async () => {
+                await expectToThrowAuthenticationErrorToObj(async () => {
                     await B2BAppPosIntegrationConfig.delete(anonymous, createdB2BAppPosIntegrationConfig.id)
                 })
🤖 Prompt for AI Agents
In `@apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.test.js` around
lines 119 - 121, The test currently expects an AccessDeniedError when an
anonymous user calls B2BAppPosIntegrationConfig.delete; change the assertion to
expect an AuthenticationError instead by replacing the
expectToThrowAccessDeniedErrorToObj usage with the corresponding
expectToThrowAuthenticationErrorToObj helper for the anonymous,
createdB2BAppPosIntegrationConfig.id deletion call (keep the same anonymous
variable and B2BAppPosIntegrationConfig.delete invocation).

Comment on lines +2427 to +2430
"pages.condo.payments.posReceiptColumn": "Recibo",
"pages.condo.payments.posReceiptLink": "Ver",
"pages.condo.payments.posReceiptVerifyTitle": "Verifique la exactitud del recibo",
"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puede activar la fiscalización. Si hay errores, contacte al soporte técnico.",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align the tone with the rest of the Spanish UI (tú vs. usted).

These strings use formal address (“Verifique”, “puede”, “contacte”), while most of the UI uses informal “tú” (e.g., “Introduce…”, “No tienes…”). Consider switching to informal for consistency.

✏️ Proposed text update
-"pages.condo.payments.posReceiptVerifyTitle": "Verifique la exactitud del recibo",
-"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puede activar la fiscalización. Si hay errores, contacte al soporte técnico.",
+"pages.condo.payments.posReceiptVerifyTitle": "Verifica la exactitud del recibo",
+"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puedes activar la fiscalización. Si hay errores, contacta al soporte técnico.",
📝 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.

Suggested change
"pages.condo.payments.posReceiptColumn": "Recibo",
"pages.condo.payments.posReceiptLink": "Ver",
"pages.condo.payments.posReceiptVerifyTitle": "Verifique la exactitud del recibo",
"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puede activar la fiscalización. Si hay errores, contacte al soporte técnico.",
"pages.condo.payments.posReceiptColumn": "Recibo",
"pages.condo.payments.posReceiptLink": "Ver",
"pages.condo.payments.posReceiptVerifyTitle": "Verifica la exactitud del recibo",
"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puedes activar la fiscalización. Si hay errores, contacta al soporte técnico.",
🤖 Prompt for AI Agents
In `@apps/condo/lang/es/es.json` around lines 2427 - 2430, Update the Spanish
strings to use informal "tú" tone: change
pages.condo.payments.posReceiptVerifyTitle from "Verifique la exactitud del
recibo" to an informal variant (e.g., "Verifica la exactitud del recibo") and
change pages.condo.payments.posReceiptVerifyDescription from the formal phrasing
to informal (e.g., "Si todos los datos son correctos, puedes activar la
fiscalización. Si hay errores, contacta al soporte técnico.") so the tone
matches other UI strings.

@AleX83Xpert AleX83Xpert force-pushed the feat/pos-integration/doma-12621/inject-pos-integration-to-condo branch from fc2ee1d to 81c1bf9 Compare January 21, 2026 08:23
Copy link
Contributor

@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: 1

🤖 Fix all issues with AI agents
In `@apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx`:
- Around line 129-133: The useEffect in PaymentsTable.tsx that depends on
areAlertLoading and refetchLastTestingPosReceipt causes a redundant immediate
refetch because PaymentsTableContent already mounts after areAlertLoading is
false and fetches on mount; remove this useEffect block (the effect that calls
refetchLastTestingPosReceipt when !areAlertLoading) to avoid duplicate
refetches, keeping the initial mount fetch in PaymentsTableContent intact and
leaving refetchLastTestingPosReceipt usage elsewhere unchanged.
♻️ Duplicate comments (2)
apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (1)

33-40: Guard organization before dereferencing in query where.
The query uses organization.id before the skip can take effect, which can throw on initial render when organization is undefined. This was already flagged previously.

apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (1)

153-157: Avoid the immediate duplicate refetch.

MarketplacePaymentsTableContent only mounts once areAlertLoading is false, so the hook already fetches on mount. This effect triggers a second, immediate refetch every time, which is redundant.

✅ Simplest fix: remove the effect
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
🧹 Nitpick comments (7)
apps/condo/domains/miniapp/components/IFrame.tsx (1)

31-40: Use an interface for props shape.

Repo guidelines prefer interface over type for object-shaped props in TS/TSX. Please switch IFrameProps to an interface.

♻️ Proposed change
-export type IFrameProps = {
+export interface IFrameProps {
     src: string
     hidden?: boolean
     reloadScope: 'user' | 'organization' | null
     withLoader?: boolean
     withPrefetch?: boolean
     withResize?: boolean
     allowFullscreen?: boolean
     onLoad?: () => void
-}
+}

As per coding guidelines, please prefer interface for object shapes.

apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (1)

57-67: Use structured logger instead of console.error.

Per repo logging guidelines, prefer getLogger() with structured fields for error reporting.

♻️ Suggested update
+import { getLogger } from '@open-condo/keystone/logging'
+
+const logger = getLogger('usePosIntegrationLastTestingPosReceipt')
@@
-            if (!response.ok) {
-                console.error('Failed to fetch last receipt:', response.statusText)
+            if (!response.ok) {
+                logger.error({
+                    msg: 'Failed to fetch last receipt',
+                    status: response.status,
+                    data: { statusText: response.statusText },
+                })
                 setLastTestingPosReceipt(null)
                 return
             }
@@
-        } catch (error) {
-            console.error('Error fetching last receipt:', error)
+        } catch (error) {
+            logger.error({ msg: 'Error fetching last receipt', err: error })
             setLastTestingPosReceipt(null)
         } finally {
             setLoading(false)
         }

As per coding guidelines, prefer structured logging via getLogger().

apps/condo/domains/acquiring/hooks/usePaymentsTableColumns.ts (1)

20-22: Use interface instead of type for object shape.

Project TS guidelines prefer interface for object shapes.

♻️ Suggested update
-type PaymentsTableColumnsOptions = {
+interface PaymentsTableColumnsOptions {
     lastTestingPosReceipt?: LastTestingPosReceiptData
 }

As per coding guidelines, prefer interface for object shapes in TS.

apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

297-301: Minor: Clean up conditional logic and return value.

Two small improvements:

  1. The optional chaining lastTestingPosReceipt?.condoPaymentId is redundant after the truthy check lastTestingPosReceipt &&.
  2. onRow implicitly returns undefined when the condition is false; explicitly returning an empty object or {} is clearer and safer for potential future table implementations.
✨ Suggested improvement
 onRow={(record) => {
-    if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
+    if (lastTestingPosReceipt && lastTestingPosReceipt.condoPaymentId === record.id) {
         return { style: { backgroundColor: colors.orange[1] } }
     }
+    return {}
 }}
apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (3)

112-114: Consider using a type alias instead of interface.

Based on learnings, prefer type aliases over interfaces for object shapes in this repository.

✨ Suggested change
-interface MarketplacePaymentsTableContentProps {
-    areAlertLoading: boolean
-}
+type MarketplacePaymentsTableContentProps = {
+    areAlertLoading: boolean
+}

361-365: Minor: Clean up redundant optional chaining.

Same pattern as in PaymentsTable.tsx: the optional chaining is redundant after the truthy check, and returning an empty object explicitly is cleaner.

✨ Suggested improvement
 onRow={(record) => {
-    if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
+    if (lastTestingPosReceipt && lastTestingPosReceipt.condoPaymentId === record.id) {
         return { style: { backgroundColor: colors.orange[1] } }
     }
+    return {}
 }}

172-177: Missing dependency in useMemo.

searchPaymentsQuery depends on invoiceOrganizationQuery but the dependency array only includes orgId and showPaymentsOnlyInDoneStatus. While this works because invoiceOrganizationQuery is memoized with orgId, explicitly including it would be more maintainable.

✨ Suggested fix
-    }, [orgId, showPaymentsOnlyInDoneStatus])
+    }, [invoiceOrganizationQuery, showPaymentsOnlyInDoneStatus])

Comment on lines +129 to +133
useEffect(() => {
if (!areAlertLoading) {
refetchLastTestingPosReceipt()
}
}, [areAlertLoading, refetchLastTestingPosReceipt])
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid the immediate duplicate refetch.

PaymentsTableContent only mounts once areAlertLoading is false, so the hook already fetches on mount. This effect triggers a second, immediate refetch every time, which is redundant.

✅ Simplest fix: remove the effect
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
📝 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.

Suggested change
useEffect(() => {
if (!areAlertLoading) {
refetchLastTestingPosReceipt()
}
}, [areAlertLoading, refetchLastTestingPosReceipt])
🤖 Prompt for AI Agents
In `@apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx` around
lines 129 - 133, The useEffect in PaymentsTable.tsx that depends on
areAlertLoading and refetchLastTestingPosReceipt causes a redundant immediate
refetch because PaymentsTableContent already mounts after areAlertLoading is
false and fetches on mount; remove this useEffect block (the effect that calls
refetchLastTestingPosReceipt when !areAlertLoading) to avoid duplicate
refetches, keeping the initial mount fetch in PaymentsTableContent intact and
leaving refetchLastTestingPosReceipt usage elsewhere unchanged.

@AleX83Xpert AleX83Xpert force-pushed the feat/pos-integration/doma-12621/inject-pos-integration-to-condo branch from 81c1bf9 to 0fcaca9 Compare January 21, 2026 11:32
@AleX83Xpert AleX83Xpert added the ✋🙂 Review please Comments are resolved, take a look, please label Jan 22, 2026
Copy link
Member

@toplenboren toplenboren left a comment

Choose a reason for hiding this comment

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

Loooks ok, but note that you are downgrading next here

yarn.lock Outdated
lodash: ^4.17.21
mkdirp: ^3.0.1
next: ^15.5.7
next: ^15.4.6
Copy link
Member

Choose a reason for hiding this comment

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

^^

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm, I'll check it. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed. I've set the version to the same as the condo.

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
In
`@apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts`:
- Around line 57-67: In usePosIntegrationLastTestingPosReceipt, replace the two
console.error calls with the repo's structured logger: call
getLogger().error(...) instead and include structured fields (e.g., { error,
status: response?.status, statusText: response?.statusText }) so the failure
branch (when !response.ok) logs response.status and response.statusText
alongside a descriptive message and setLastTestingPosReceipt(null), and the
catch branch logs the thrown error object as a field (e.g., { error }) with a
clear message before calling setLastTestingPosReceipt(null); locate these
changes around the response handling and the catch in
usePosIntegrationLastTestingPosReceipt.

In `@apps/condo/domains/miniapp/access/B2BAppPosIntegrationConfig.js`:
- Around line 10-15: canReadB2BAppPosIntegrationConfigs currently returns {}
which grants all authenticated users global read access; restrict it to the same
scope as the manage rule. Change canReadB2BAppPosIntegrationConfigs to mirror
canManageB2BAppPosIntegrationConfigs (or the org-scoping logic you use
elsewhere): return true/{} only for global admins, otherwise return a filter
object that limits results to the user's organisation (e.g. return {
organization: { id: user.organizationId } }) or return false if the user lacks
that org relationship; ensure you reuse the same checks/utility used by
canManageB2BAppPosIntegrationConfigs to avoid divergence.
♻️ Duplicate comments (3)
apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (1)

33-40: Guard organization before dereference in the query filter.

Line 36 accesses organization.id before the skip guard can short‑circuit, which can throw during initial render.

🐛 Suggested fix
-            organization: { id: organization.id },
+            organization: { id: organization?.id },
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

129-133: Avoid the immediate duplicate refetch.

PaymentsTableContent only mounts once areAlertLoading is false, so the hook already fetches on mount. This effect triggers a second, immediate refetch every time, which is redundant.

✅ Simplest fix: remove the effect
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (1)

153-157: Remove the redundant refetch effect.

MarketplacePaymentsTableContent mounts only after areAlertLoading is false, and the hook already fetches on mount. This effect triggers a second, immediate fetch.

✅ Simplest fix
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
🧹 Nitpick comments (3)
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

297-301: Return empty object when condition is false to avoid undefined.

The onRow callback returns undefined when the condition doesn't match. While this may work, it's inconsistent and can cause subtle issues with type expectations.

🔧 Suggested fix
 onRow={(record) => {
     if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
         return { style: { backgroundColor: colors.orange[1] } }
     }
+    return {}
 }}
apps/condo/domains/miniapp/schema/B2BAppPosIntegrationConfig.js (1)

15-25: Consider adding URL validation for the URL fields.

Both paymentsAlertPageUrl and fetchLastPosReceiptUrl are plain Text fields accepting any string. Since these are used for iframe sources and fetch requests respectively (as documented in the schema), consider adding a validateInput hook to ensure valid URLs, following the validation patterns used in similar URL fields throughout the codebase (e.g., DEVELOPER_URL_FIELD, IFRAME_URL_FIELD in B2BApp.js).

apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (1)

4-4: Prefer @open-condo/ui for Space/Spin (if available).

These new UI elements should come from @open-condo/ui to stay consistent with the UI layer. If @open-condo/ui exports Space and Spin, consider switching the imports. As per coding guidelines, prefer @open-condo/ui components for GUI elements.

♻️ Suggested adjustment (if supported by `@open-condo/ui`)
-import { Col, Row, RowProps, Space, Spin } from 'antd'
+import { Col, Row, RowProps } from 'antd'
...
-import { Button, Modal, Checkbox, Typography } from '@open-condo/ui'
+import { Button, Modal, Checkbox, Space, Spin, Typography } from '@open-condo/ui'

Also applies to: 97-105

Comment on lines +57 to +66
if (!response.ok) {
console.error('Failed to fetch last receipt:', response.statusText)
setLastTestingPosReceipt(null)
return
}

const data: LastTestingPosReceiptData | null = await response.json()
setLastTestingPosReceipt(data)
} catch (error) {
console.error('Error fetching last receipt:', error)
setLastTestingPosReceipt(null)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace console.error with structured logger.

This repo’s JS/TS logging guideline requires getLogger() and structured fields.

🧭 Suggested fix
 import { useCallback, useEffect, useState } from 'react'
 
+import { getLogger } from '@open-condo/keystone/logging'
 import { useOrganization } from '@open-condo/next/organization'
 
 import { B2BAppContext } from '@condo/domains/miniapp/utils/clientSchema'
 
+const logger = getLogger('usePosIntegrationLastTestingPosReceipt')
+
@@
-            if (!response.ok) {
-                console.error('Failed to fetch last receipt:', response.statusText)
+            if (!response.ok) {
+                logger.error({ msg: 'Failed to fetch last receipt', data: { status: response.status, statusText: response.statusText } })
                 setLastTestingPosReceipt(null)
                 return
             }
@@
-        } catch (error) {
-            console.error('Error fetching last receipt:', error)
+        } catch (error) {
+            logger.error({ msg: 'Error fetching last receipt', err: error })
             setLastTestingPosReceipt(null)
         } finally {
🤖 Prompt for AI Agents
In `@apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts`
around lines 57 - 67, In usePosIntegrationLastTestingPosReceipt, replace the two
console.error calls with the repo's structured logger: call
getLogger().error(...) instead and include structured fields (e.g., { error,
status: response?.status, statusText: response?.statusText }) so the failure
branch (when !response.ok) logs response.status and response.statusText
alongside a descriptive message and setLastTestingPosReceipt(null), and the
catch branch logs the thrown error object as a field (e.g., { error }) with a
clear message before calling setLastTestingPosReceipt(null); locate these
changes around the response handling and the catch in
usePosIntegrationLastTestingPosReceipt.

Comment on lines +10 to +15
async function canReadB2BAppPosIntegrationConfigs ({ authentication: { item: user } }) {
if (!user) return throwAuthenticationError()
if (user.deletedAt) return false

return {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Scope read access; current rule exposes all configs to any authenticated user.

If global read isn’t intended, align read access with the manage rule to avoid cross‑org leakage of integration URLs.

🔐 Suggested adjustment
-async function canReadB2BAppPosIntegrationConfigs ({ authentication: { item: user } }) {
+async function canReadB2BAppPosIntegrationConfigs ({ authentication: { item: user }, listKey, originalInput, operation }) {
     if (!user) return throwAuthenticationError()
     if (user.deletedAt) return false
-
-    return {}
+    if (user.isSupport || user.isAdmin) return true
+    return await canDirectlyManageSchemaObjects(user, listKey, originalInput, operation)
 }
🤖 Prompt for AI Agents
In `@apps/condo/domains/miniapp/access/B2BAppPosIntegrationConfig.js` around lines
10 - 15, canReadB2BAppPosIntegrationConfigs currently returns {} which grants
all authenticated users global read access; restrict it to the same scope as the
manage rule. Change canReadB2BAppPosIntegrationConfigs to mirror
canManageB2BAppPosIntegrationConfigs (or the org-scoping logic you use
elsewhere): return true/{} only for global admins, otherwise return a filter
object that limits results to the user's organisation (e.g. return {
organization: { id: user.organizationId } }) or return false if the user lacks
that org relationship; ensure you reuse the same checks/utility used by
canManageB2BAppPosIntegrationConfigs to avoid divergence.

Copy link
Contributor

@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

🤖 Fix all issues with AI agents
In
`@apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts`:
- Around line 78-81: The hook usePosIntegrationLastTestingPosReceipt currently
returns a hardcoded stub for lastTestingPosReceipt; replace the stubbed object
(lastTestingPosReceipt: { id: 'test', condoPaymentId: '2' }) with the actual
fetched state from the query (e.g., the query response variable such as data or
lastTestingPosReceipt from your fetch), so callers receive the real receipt;
keep the existing loading and refetch values (loading: areB2bAppContextsLoading
|| loading and refetch: fetchLastTestingPosReceipt) and ensure you handle
null/undefined safely (return null or undefined when the fetch hasn’t produced a
receipt).
- Around line 31-34: The destructuring of the query result in
usePosIntegrationLastTestingPosReceipt assumes data is always defined; change
the destructure for useGetB2BAppContextWithPosIntegrationConfigQuery so it
safely handles undefined data (e.g., default data = {} or use optional chaining)
before accessing data.contexts, ensuring areB2bAppContextsLoading and
b2bAppContexts are assigned without throwing when the hook returns undefined
initially.

In
`@apps/condo/domains/acquiring/queries/B2BAppContextWithPosIntegrationConfig.graphql`:
- Around line 6-7: The query currently applies manual deletedAt filters (e.g.,
the nested filter "app: { posIntegrationConfig_is_null: false, deletedAt: null
}" and top-level "deletedAt: null"); remove these explicit deletedAt predicates
so the softDeleted plugin can handle soft-deletion automatically, leaving only
the necessary conditions like "posIntegrationConfig_is_null: false" on the app
field and deleting the two deletedAt checks in
B2BAppContextWithPosIntegrationConfig.graphql.
♻️ Duplicate comments (2)
apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (2)

35-37: Avoid dereferencing organization before it exists.

Line 36 can throw when organization is undefined. Use optional chaining (or delay variables) even if skip is set. This repeats a prior review point.

🛠️ Proposed fix
-    variables: { organizationId: organization.id },
+    variables: { organizationId: organization?.id },

56-66: Replace console.error with structured logger.

Use getLogger() and structured fields instead of console.error for both the non-OK response and the catch block. This repeats a prior review point. As per coding guidelines, use structured logging.

🛠️ Proposed fix
+import { getLogger } from '@open-condo/keystone/logging'
+
+const logger = getLogger('usePosIntegrationLastTestingPosReceipt')
+
             if (!response.ok) {
-                console.error('Failed to fetch last receipt:', response.statusText)
+                logger.error({ msg: 'Failed to fetch last receipt', data: { status: response.status, statusText: response.statusText } })
                 setLastTestingPosReceipt(null)
                 return
             }
@@
         } catch (error) {
-            console.error('Error fetching last receipt:', error)
+            logger.error({ msg: 'Error fetching last receipt', err: error })
             setLastTestingPosReceipt(null)
         } finally {

Comment on lines +6 to +7
app: { posIntegrationConfig_is_null: false, deletedAt: null },
deletedAt: null,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove manual deletedAt filters to preserve softDeleted behavior.

Manually filtering deletedAt disables the softDeleted plugin’s automatic handling and can unintentionally filter out nested entities. Please rely on the plugin instead. Based on learnings, do not add deletedAt filters in GraphQL queries.

🧹 Suggested fix
-            app: { posIntegrationConfig_is_null: false, deletedAt: null },
-            deletedAt: null,
+            app: { posIntegrationConfig_is_null: false },
📝 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.

Suggested change
app: { posIntegrationConfig_is_null: false, deletedAt: null },
deletedAt: null,
app: { posIntegrationConfig_is_null: false },
🤖 Prompt for AI Agents
In
`@apps/condo/domains/acquiring/queries/B2BAppContextWithPosIntegrationConfig.graphql`
around lines 6 - 7, The query currently applies manual deletedAt filters (e.g.,
the nested filter "app: { posIntegrationConfig_is_null: false, deletedAt: null
}" and top-level "deletedAt: null"); remove these explicit deletedAt predicates
so the softDeleted plugin can handle soft-deletion automatically, leaving only
the necessary conditions like "posIntegrationConfig_is_null: false" on the app
field and deleting the two deletedAt checks in
B2BAppContextWithPosIntegrationConfig.graphql.

…ma for POS integration

Added new B2BAppPosIntegrationConfig model to store POS integration configuration for B2BApps. The config includes paymentsAlertPageUrl field for displaying integration status alerts on billing and marketplace pages. Added relationship to B2BApp model, access rules, CRUD tests, and GQL queries. Only admins and support users can create/update configs, all authenticated users can read.
…ts page

Added usePosIntegrationAlert hook to display POS integration status alerts on payments page. The hook fetches B2BAppContext with posIntegrationConfig and renders an IFrame with paymentsAlertPageUrl if available. Added loading state handling and onLoad callback support to IFrame component. Updated PaymentsTable to show alert above table content with loading spinner. Changed lodash import to use specific function import.
…OnOff icon

Renamed variables in usePosIntegrationAlert hook for clarity: isPosIntegrationAppContextsLoading to areB2bAppContextsLoading, posIntegrationAppContexts to b2bAppContexts. Removed isIFrameHidden from loading state calculation. Fixed OnOff icon background path fill from white to none.
…pacing

Updated usePosIntegrationAlert hook to include isIFrameHidden in loading state calculation. Changed PaymentsTable Space component size to be 0 during loading to prevent extra spacing when spinner is shown.
…pPosIntegrationConfig and highlight payments with receipts

Added fetchLastPosReceiptUrl field to B2BAppPosIntegrationConfig schema for fetching last POS receipt data. Created usePosIntegrationLastPosReceipt hook to fetch receipt information from miniapp. Updated PaymentsTable to highlight rows with orange background when payment has associated receipt. Regenerated migration to include new field.
…grationConfig test fixtures

Added fetchLastPosReceiptUrl field to create and update test payloads in B2BAppPosIntegrationConfig.test.js. Updated createTestB2BAppPosIntegrationConfig helper to include fetchLastPosReceiptUrl with faker-generated URL.
…d yarn.lock

Add the @open-keystone/server-side-graphql-client package to dependencies
…phQL query for POS integration config

Created dedicated GraphQL query getB2BAppContextWithPosIntegrationConfig to fetch B2BAppContext with POS integration configuration. Replaced B2BAppContext.useObjects calls with useGetB2BAppContextWithPosIntegrationConfigQuery hook in usePosIntegrationAlert and usePosIntegrationLastTestingPosReceipt.
@AleX83Xpert AleX83Xpert force-pushed the feat/pos-integration/doma-12621/inject-pos-integration-to-condo branch from 4d20ace to 62e186a Compare January 23, 2026 08:26
Copy link
Contributor

@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: 1

🤖 Fix all issues with AI agents
In `@apps/condo/domains/acquiring/hooks/usePosIntegrationAlert.tsx`:
- Around line 18-26: The hook call to
useGetB2BAppContextWithPosIntegrationConfigQuery unsafe-destructures data and
references organization.id too early; change the call so variables are only
supplied when organization?.id exists (e.g., compute variables =
organization?.id ? { organizationId: organization.id } : undefined and pass
skip: !organization?.id), and stop destructuring directly from data — read
data?.contexts or provide a default like const b2bAppContexts = data?.contexts
?? []; update references to use b2bAppContexts and ensure organization?.id is
used where checked by skip.
♻️ Duplicate comments (9)
apps/condo/domains/miniapp/access/B2BAppPosIntegrationConfig.js (1)

10-15: Read access is overly permissive compared to manage access.

Returning {} grants any authenticated user global read access to all POS integration configs, while the manage function properly restricts access. This inconsistency could leak integration URLs across organizations.

Consider aligning read access with manage access by checking for support/admin or delegating to canDirectlyManageSchemaObjects.

apps/condo/lang/es/es.json (1)

2427-2430: Align tone with the rest of the Spanish UI (tú vs. usted).
These strings use formal address; most UI uses informal “tú”. Suggest switching to informal for consistency.

✏️ Proposed text update
-"pages.condo.payments.posReceiptVerifyTitle": "Verifique la exactitud del recibo",
-"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puede activar la fiscalización. Si hay errores, contacte al soporte técnico.",
+"pages.condo.payments.posReceiptVerifyTitle": "Verifica la exactitud del recibo",
+"pages.condo.payments.posReceiptVerifyDescription": "Si todos los datos son correctos, puedes activar la fiscalización. Si hay errores, contacta al soporte técnico.",
apps/condo/domains/acquiring/hooks/usePosIntegrationLastTestingPosReceipt.ts (4)

31-38: Guard organization access before building variables.

Line 36 dereferences organization.id even when organization may be undefined, which can throw before skip takes effect. Use optional chaining for the variables payload.

🛠️ Proposed fix
-            variables: { organizationId: organization.id },
+            variables: { organizationId: organization?.id },

31-34: Avoid deep destructuring of query data without a default.

Line 33 assumes data is always defined. Apollo can return data: undefined on initial render, which will throw when destructuring.

🛠️ Proposed fix
-        data: { contexts: b2bAppContexts },
+        data: { contexts: b2bAppContexts } = {},

56-66: Use structured logger instead of console.error.

Replace console.error with the repo logger and structured fields.

🧭 Suggested fix
 import { useCallback, useEffect, useState } from 'react'
 
+import { getLogger } from '@open-condo/keystone/logging'
 import { useOrganization } from '@open-condo/next/organization'
 
 import { B2BAppContext } from '@condo/domains/miniapp/utils/clientSchema'
 
+const logger = getLogger('usePosIntegrationLastTestingPosReceipt')
+
@@
-            if (!response.ok) {
-                console.error('Failed to fetch last receipt:', response.statusText)
+            if (!response.ok) {
+                logger.error({ msg: 'Failed to fetch last receipt', data: { status: response.status, statusText: response.statusText } })
                 setLastTestingPosReceipt(null)
                 return
             }
@@
-        } catch (error) {
-            console.error('Error fetching last receipt:', error)
+        } catch (error) {
+            logger.error({ msg: 'Error fetching last receipt', err: error })
             setLastTestingPosReceipt(null)
         } finally {

As per coding guidelines, use getLogger with structured fields.


78-81: Return the fetched receipt instead of a stub.

Line 79 hardcodes a test object, so callers never see the real receipt state.

🛠️ Proposed fix
 return {
-        lastTestingPosReceipt: { id: 'test', condoPaymentId: '2' },
+        lastTestingPosReceipt,
         loading: areB2bAppContextsLoading || loading,
         refetch: fetchLastTestingPosReceipt,
 }
apps/condo/domains/acquiring/queries/B2BAppContextWithPosIntegrationConfig.graphql (1)

6-7: Remove manual deletedAt filters to preserve softDeleted behavior.

The manual deletedAt: null filters on the nested app filter and at the context level disable the softDeleted plugin's automatic handling. Based on learnings, rely on the plugin instead and remove these explicit filters.

🧹 Suggested fix
-            app: { posIntegrationConfig_is_null: false, deletedAt: null },
-            deletedAt: null,
+            app: { posIntegrationConfig_is_null: false },
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

129-133: Redundant refetch on mount.

PaymentsTableContent only mounts once areAlertLoading is false, so the hook already fetches on mount. This effect triggers a second, immediate refetch which is unnecessary.

✅ Proposed fix: remove the effect
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (1)

153-157: Remove the redundant refetch effect.

Since MarketplacePaymentsTableContent only mounts after areAlertLoading becomes false, the usePosIntegrationLastTestingPosReceipt hook already fetches on mount. This effect immediately triggers a duplicate refetch.

✅ Proposed fix
-    useEffect(() => {
-        if (!areAlertLoading) {
-            refetchLastTestingPosReceipt()
-        }
-    }, [areAlertLoading, refetchLastTestingPosReceipt])
🧹 Nitpick comments (2)
apps/condo/domains/acquiring/components/payments/PaymentsTable.tsx (1)

297-301: onRow callback should return a value for all paths.

When the condition is false, the function implicitly returns undefined. While this works, it's cleaner to explicitly return an empty object for consistency.

♻️ Suggested improvement
                         onRow={(record) => {
                             if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
                                 return { style: { backgroundColor: colors.orange[1] } }
                             }
+                            return {}
                         }}
apps/condo/domains/marketplace/components/MarketplacePaymentsContent.tsx (1)

361-365: Remove redundant optional chaining.

After the truthy check lastTestingPosReceipt &&, the optional chaining ?. on lastTestingPosReceipt?.condoPaymentId is unnecessary.

✅ Proposed fix
                                onRow={(record) => {
-                                    if (lastTestingPosReceipt && lastTestingPosReceipt?.condoPaymentId === record.id) {
+                                    if (lastTestingPosReceipt && lastTestingPosReceipt.condoPaymentId === record.id) {
                                        return { style: { backgroundColor: colors.orange[1] } }
                                    }
                                }}

Icon imported from Figma by command:
```sh
yarn workspace @open-condo/icons import:figma
```
…ub in POS integration hooks

Added default empty object destructuring for data in useGetB2BAppContextWithPosIntegrationConfigQuery to prevent errors when data is undefined. Removed hardcoded test stub from usePosIntegrationLastTestingPosReceipt return value.
…integration hooks

Changed destructured `data: { contexts: b2bAppContexts }` to `data: b2bAppContextsResult` and updated property access to `b2bAppContextsResult?.contexts` in usePosIntegrationAlert and usePosIntegrationLastTestingPosReceipt hooks for better code clarity.
@AleX83Xpert
Copy link
Member Author

@coderabbitai help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
    • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
    • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@AleX83Xpert
Copy link
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

✅ Actions performed

Full review triggered.

@sonarqubecloud
Copy link

@AleX83Xpert AleX83Xpert merged commit df45a53 into main Jan 26, 2026
73 of 74 checks passed
@AleX83Xpert AleX83Xpert deleted the feat/pos-integration/doma-12621/inject-pos-integration-to-condo branch January 26, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚨 Migrations We have a database migrations here! ✋🙂 Review please Comments are resolved, take a look, please

Development

Successfully merging this pull request may close these issues.

4 participants