changes
This commit is contained in:
240
fusion_poynt/graphify-out/GRAPH_REPORT.md
Normal file
240
fusion_poynt/graphify-out/GRAPH_REPORT.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Graph Report - /Users/gurpreet/Github/Odoo-Modules/fusion_poynt (2026-04-22)
|
||||
|
||||
## Corpus Check
|
||||
- 22 files · ~20,386 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 316 nodes · 492 edges · 30 communities detected
|
||||
- Extraction: 82% EXTRACTED · 18% INFERRED · 0% AMBIGUOUS · INFERRED: 87 edges (avg confidence: 0.72)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
- [[_COMMUNITY_Community 0|Community 0]]
|
||||
- [[_COMMUNITY_Community 1|Community 1]]
|
||||
- [[_COMMUNITY_Community 2|Community 2]]
|
||||
- [[_COMMUNITY_Community 3|Community 3]]
|
||||
- [[_COMMUNITY_Community 4|Community 4]]
|
||||
- [[_COMMUNITY_Community 5|Community 5]]
|
||||
- [[_COMMUNITY_Community 6|Community 6]]
|
||||
- [[_COMMUNITY_Community 7|Community 7]]
|
||||
- [[_COMMUNITY_Community 8|Community 8]]
|
||||
- [[_COMMUNITY_Community 9|Community 9]]
|
||||
- [[_COMMUNITY_Community 10|Community 10]]
|
||||
- [[_COMMUNITY_Community 11|Community 11]]
|
||||
- [[_COMMUNITY_Community 12|Community 12]]
|
||||
- [[_COMMUNITY_Community 13|Community 13]]
|
||||
- [[_COMMUNITY_Community 14|Community 14]]
|
||||
- [[_COMMUNITY_Community 15|Community 15]]
|
||||
- [[_COMMUNITY_Community 16|Community 16]]
|
||||
- [[_COMMUNITY_Community 17|Community 17]]
|
||||
- [[_COMMUNITY_Community 18|Community 18]]
|
||||
- [[_COMMUNITY_Community 19|Community 19]]
|
||||
- [[_COMMUNITY_Community 20|Community 20]]
|
||||
- [[_COMMUNITY_Community 21|Community 21]]
|
||||
- [[_COMMUNITY_Community 22|Community 22]]
|
||||
- [[_COMMUNITY_Community 23|Community 23]]
|
||||
- [[_COMMUNITY_Community 24|Community 24]]
|
||||
- [[_COMMUNITY_Community 25|Community 25]]
|
||||
- [[_COMMUNITY_Community 26|Community 26]]
|
||||
- [[_COMMUNITY_Community 27|Community 27]]
|
||||
- [[_COMMUNITY_Community 28|Community 28]]
|
||||
- [[_COMMUNITY_Community 29|Community 29]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
1. `PoyntController` - 29 edges
|
||||
2. `PaymentTransaction` - 24 edges
|
||||
3. `PoyntPaymentWizard` - 20 edges
|
||||
4. `PaymentProvider` - 14 edges
|
||||
5. `format_poynt_amount()` - 13 edges
|
||||
6. `PoyntRefundWizard` - 11 edges
|
||||
7. `AccountMove` - 10 edges
|
||||
8. `create()` - 10 edges
|
||||
9. `PoyntSettlementBatch` - 8 edges
|
||||
10. `build_order_payload()` - 7 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `poynt_process_card()` --calls--> `format_poynt_amount()` [INFERRED]
|
||||
/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/main.py → /Users/gurpreet/Github/Odoo-Modules/fusion_poynt/utils.py
|
||||
- `Override of payment to return Poynt-specific processing values. For dir` --uses--> `PoyntController` [INFERRED]
|
||||
/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/payment_transaction.py → /Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/main.py
|
||||
- `Override of `payment` to send a payment request to Poynt.` --uses--> `PoyntController` [INFERRED]
|
||||
/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/payment_transaction.py → /Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/main.py
|
||||
- `Create a Poynt order without a transaction. Used by the portal payment` --uses--> `PoyntController` [INFERRED]
|
||||
/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/payment_transaction.py → /Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/main.py
|
||||
- `Create a Poynt order and authorize the transaction. :return: Dict with` --uses--> `PoyntController` [INFERRED]
|
||||
/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/payment_transaction.py → /Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/main.py
|
||||
|
||||
## Communities
|
||||
|
||||
### Community 0 - "Community 0"
|
||||
Cohesion: 0.07
|
||||
Nodes (33): PoyntController, _detect_card_brand_from_details(), PaymentTransaction, Parse the stored receipt JSON for use in QWeb templates. For refund tra, Return receipt values from the original sale transaction. Used by the r, Create a Poynt order without a transaction. Used by the portal payment, Create a Poynt order and authorize the transaction. :return: Dict with, Detect card brand from the payment_details string on a token. Tokens st (+25 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.06
|
||||
Nodes (32): poynt_return(), poynt_terminal_callback(), Process a transaction-related webhook event. :param str event_type: The, PaymentProvider, Make an authenticated API request to the Poynt REST API. :param str met, Exchange a Poynt Collect nonce for a long-lived payment token JWT. :par, Charge a stored payment token JWT via the tokenize/charge endpoint. :pa, Test the connection to Poynt by authenticating and fetching business info. (+24 more)
|
||||
|
||||
### Community 2 - "Community 2"
|
||||
Cohesion: 0.08
|
||||
Nodes (22): _detect_card_brand(), _onchange_card_number(), _onchange_card_type(), _onchange_provider_id(), PoyntPaymentWizard, Add the surcharge invoice line if surcharge is enabled and not yet applied., Remove the surcharge line from the invoice if it was applied., Dispatch to the appropriate payment method. (+14 more)
|
||||
|
||||
### Community 3 - "Community 3"
|
||||
Cohesion: 0.1
|
||||
Nodes (13): Fetch all transactions from Poynt API for a date range. Paginates throu, _cron_daily_settlement_sync(), PoyntSettlementBatch, PoyntSettlementLine, Open linked payments in a list view., Open linked invoices in a list view., Fetch Poynt transactions for this batch's transaction date., Match this batch to an Elavon bank statement line. (+5 more)
|
||||
|
||||
### Community 4 - "Community 4"
|
||||
Cohesion: 0.1
|
||||
Nodes (14): _detect_card_brand(), poynt_process_card(), poynt_send_to_terminal(), poynt_terminal_status(), poynt_webhook(), Process an order-related webhook event. :param str event_type: The Poyn, Detect the card brand from the card number using BIN prefixes., Verify the webhook notification signature. :param dict event: The webho (+6 more)
|
||||
|
||||
### Community 5 - "Community 5"
|
||||
Cohesion: 0.14
|
||||
Nodes (12): Return a serialized JSON of values needed to render the inline payment form., PoyntRefundWizard, Dispatch to referenced refund or non-referenced credit., Check on Poynt that the transaction and all linked children have not bee, Raise if the given Poynt transaction has been voided or refunded., Send a referenced REFUND using the original transaction's parentId., Send a non-referenced credit via cloud message to the terminal. Require, Process the Poynt API response for a referenced refund. (+4 more)
|
||||
|
||||
### Community 6 - "Community 6"
|
||||
Cohesion: 0.1
|
||||
Nodes (9): AccountMove, Resend the Poynt payment/refund receipt email to the customer., Open the Poynt payment collection wizard for this invoice., Open the Poynt refund wizard for this credit note., Find the Poynt payment transaction from the reversed invoice. For credi, Open payment transactions linked to this invoice/credit note., Open the credit notes linked to this invoice that were refunded via Poynt., Find the Poynt transaction linked to this invoice or credit note. (+1 more)
|
||||
|
||||
### Community 7 - "Community 7"
|
||||
Cohesion: 0.17
|
||||
Nodes (17): _getSelectedCardType(), _hideProcessingOverlay(), _initiatePaymentFlow(), _pollTerminalStatus(), _prefillBillingAddress(), _prepareInlineForm(), _processCardPayment(), _processDirectFlow() (+9 more)
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.38
|
||||
Nodes (1): TerminalPaymentWidget
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.43
|
||||
Nodes (1): PoyntPollAction
|
||||
|
||||
### Community 10 - "Community 10"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): Create an invoice (if needed) and open the Poynt payment wizard. This s, SaleOrder
|
||||
|
||||
### Community 11 - "Community 11"
|
||||
Cohesion: 0.33
|
||||
Nodes (1): ResConfigSettings
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.4
|
||||
Nodes (2): AccountPayment, Open the settlement batch linked to this payment.
|
||||
|
||||
### Community 13 - "Community 13"
|
||||
Cohesion: 0.5
|
||||
Nodes (2): CustomerPortal, PoyntCustomerPortal
|
||||
|
||||
### Community 14 - "Community 14"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 15 - "Community 15"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 18 - "Community 18"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 1.0
|
||||
Nodes (0):
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Daily cron: fetch yesterday's transactions, match to today's deposit.
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Auto-inject payment_amount for confirmed orders with outstanding balance.
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Process the return from a Poynt payment flow. The customer is redirecte
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Process webhook notifications from Poynt. Poynt sends cloud hook events
|
||||
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Handle callback from a Poynt terminal after a payment completes. The te
|
||||
|
||||
### Community 25 - "Community 25"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Handle the OAuth2 authorization callback from Poynt. After a merchant a
|
||||
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Return available Poynt terminals for the given provider. :param int pro
|
||||
|
||||
### Community 27 - "Community 27"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Process a card payment through Poynt Cloud API. The frontend sends card
|
||||
|
||||
### Community 28 - "Community 28"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Send a payment request to a Poynt terminal device. :return: Dict with s
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): Poll the status of a terminal payment. :return: Dict with current payme
|
||||
|
||||
## Knowledge Gaps
|
||||
- **89 isolated node(s):** `Generate a unique request ID for Poynt API idempotency.`, `Build a full Poynt API URL for the given endpoint. :param str endpoint: The`, `Build the standard HTTP headers for a Poynt API request. :param str access_`, `Extract the urn:aid:... portion from a raw application ID string. Poynt dev`, `Create a self-signed JWT for Poynt OAuth2 token request. The JWT is signed` (+84 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **Thin community `Community 15`** (1 nodes): `__init__.py`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 16`** (1 nodes): `__init__.py`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 17`** (1 nodes): `__init__.py`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 18`** (1 nodes): `__manifest__.py`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 19`** (1 nodes): `const.py`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 20`** (1 nodes): `Daily cron: fetch yesterday's transactions, match to today's deposit.`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 21`** (1 nodes): `Auto-inject payment_amount for confirmed orders with outstanding balance.`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 22`** (1 nodes): `Process the return from a Poynt payment flow. The customer is redirecte`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 23`** (1 nodes): `Process webhook notifications from Poynt. Poynt sends cloud hook events`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 24`** (1 nodes): `Handle callback from a Poynt terminal after a payment completes. The te`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 25`** (1 nodes): `Handle the OAuth2 authorization callback from Poynt. After a merchant a`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 26`** (1 nodes): `Return available Poynt terminals for the given provider. :param int pro`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 27`** (1 nodes): `Process a card payment through Poynt Cloud API. The frontend sends card`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 28`** (1 nodes): `Send a payment request to a Poynt terminal device. :return: Dict with s`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 29`** (1 nodes): `Poll the status of a terminal payment. :return: Dict with current payme`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
|
||||
## Suggested Questions
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `create()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 5`, `Community 6`?**
|
||||
_High betweenness centrality (0.147) - this node is a cross-community bridge._
|
||||
- **Why does `PoyntController` connect `Community 0` to `Community 1`, `Community 4`?**
|
||||
_High betweenness centrality (0.078) - this node is a cross-community bridge._
|
||||
- **Are the 24 inferred relationships involving `PoyntController` (e.g. with `PaymentTransaction` and `Override of payment to return Poynt-specific processing values. For dir`) actually correct?**
|
||||
_`PoyntController` has 24 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 8 inferred relationships involving `format_poynt_amount()` (e.g. with `._process_referenced_refund()` and `._process_non_referenced_credit()`) actually correct?**
|
||||
_`format_poynt_amount()` has 8 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **What connects `Generate a unique request ID for Poynt API idempotency.`, `Build a full Poynt API URL for the given endpoint. :param str endpoint: The`, `Build the standard HTTP headers for a Poynt API request. :param str access_` to the rest of the system?**
|
||||
_89 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `Community 0` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.07 - nodes in this community are weakly interconnected._
|
||||
- **Should `Community 1` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.06 - nodes in this community are weakly interconnected._
|
||||
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L5", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L6", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L7", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L10", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/__init__.py", "source_location": "L11", "weight": 1.0}], "raw_calls": []}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "label": "portal.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L1"}, {"id": "portal_poyntcustomerportal", "label": "PoyntCustomerPortal", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L9"}, {"id": "customerportal", "label": "CustomerPortal", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "portal_portal_order_page", "label": "portal_order_page()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L12"}, {"id": "portal_rationale_23", "label": "Auto-inject payment_amount for confirmed orders with outstanding balance.", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L23"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "target": "odoo_http", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "target": "odoo_addons_sale_controllers_portal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L6", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "target": "portal_poyntcustomerportal", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L9", "weight": 1.0}, {"source": "portal_poyntcustomerportal", "target": "customerportal", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_portal_py", "target": "portal_portal_order_page", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L12", "weight": 1.0}, {"source": "portal_rationale_23", "target": "portal_poyntcustomerportal_portal_order_page", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L23", "weight": 1.0}], "raw_calls": [{"caller_nid": "portal_portal_order_page", "callee": "_document_check_access", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L35"}, {"caller_nid": "portal_portal_order_page", "callee": "getattr", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L42"}, {"caller_nid": "portal_portal_order_page", "callee": "super", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/portal.py", "source_location": "L51"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_manifest_py", "label": "__manifest__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__manifest__.py", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_models_account_payment_py", "label": "account_payment.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L1"}, {"id": "account_payment_accountpayment", "label": "AccountPayment", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L6"}, {"id": "account_payment_compute_poynt_settlement_count", "label": "_compute_poynt_settlement_count()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L20"}, {"id": "account_payment_accountpayment_action_view_poynt_settlement", "label": ".action_view_poynt_settlement()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L24"}, {"id": "account_payment_rationale_25", "label": "Open the settlement batch linked to this payment.", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L25"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_account_payment_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_account_payment_py", "target": "account_payment_accountpayment", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L6", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_models_account_payment_py", "target": "account_payment_compute_poynt_settlement_count", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L20", "weight": 1.0}, {"source": "account_payment_accountpayment", "target": "account_payment_accountpayment_action_view_poynt_settlement", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L24", "weight": 1.0}, {"source": "account_payment_rationale_25", "target": "account_payment_accountpayment_action_view_poynt_settlement", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L25", "weight": 1.0}], "raw_calls": [{"caller_nid": "account_payment_compute_poynt_settlement_count", "callee": "len", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L22"}, {"caller_nid": "account_payment_accountpayment_action_view_poynt_settlement", "callee": "ensure_one", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L26"}, {"caller_nid": "account_payment_accountpayment_action_view_poynt_settlement", "callee": "mapped", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L27"}, {"caller_nid": "account_payment_accountpayment_action_view_poynt_settlement", "callee": "len", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L28"}, {"caller_nid": "account_payment_accountpayment_action_view_poynt_settlement", "callee": "_", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L31"}, {"caller_nid": "account_payment_accountpayment_action_view_poynt_settlement", "callee": "_", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/models/account_payment.py", "source_location": "L38"}]}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L1"}, {"id": "init_post_init_hook", "label": "post_init_hook()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L8"}, {"id": "init_uninstall_hook", "label": "uninstall_hook()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L15"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L5", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "target": "init_post_init_hook", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_init_py", "target": "init_uninstall_hook", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L15", "weight": 1.0}], "raw_calls": [{"caller_nid": "init_post_init_hook", "callee": "ref", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L10"}, {"caller_nid": "init_post_init_hook", "callee": "_setup_provider", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L12"}, {"caller_nid": "init_uninstall_hook", "callee": "ref", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L16"}, {"caller_nid": "init_uninstall_hook", "callee": "write", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/__init__.py", "source_location": "L18"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_const_py", "label": "const.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/const.py", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_controllers_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/controllers/__init__.py", "source_location": "L4", "weight": 1.0}], "raw_calls": []}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_poynt_wizard_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/wizard/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_poynt_wizard_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_wizard_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/wizard/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_poynt_wizard_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_poynt_wizard_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_poynt/wizard/__init__.py", "source_location": "L4", "weight": 1.0}], "raw_calls": []}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
257
fusion_poynt/graphify-out/graph.html
Normal file
257
fusion_poynt/graphify-out/graph.html
Normal file
File diff suppressed because one or more lines are too long
8758
fusion_poynt/graphify-out/graph.json
Normal file
8758
fusion_poynt/graphify-out/graph.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
fusion_poynt/models/__pycache__/payment_provider.cpython-312.pyc
Normal file
BIN
fusion_poynt/models/__pycache__/payment_provider.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -208,7 +208,7 @@ class PaymentProvider(models.Model):
|
||||
json=payload,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=60,
|
||||
timeout=15,
|
||||
)
|
||||
except requests.exceptions.RequestException as e:
|
||||
_logger.error("Poynt API request failed: %s", e)
|
||||
@@ -521,6 +521,11 @@ class PaymentProvider(models.Model):
|
||||
which returns a TransactionReceipt with a ``data`` field containing
|
||||
the rendered receipt content (HTML or text).
|
||||
|
||||
If Poynt has reported a missing receipt template for this business,
|
||||
we fail fast (no network call) until the admin clears the flag.
|
||||
This protects Odoo workers from a thundering-herd of 400s when the
|
||||
merchant's Poynt account is missing its receipt template config.
|
||||
|
||||
:param str transaction_id: The Poynt transaction UUID.
|
||||
:return: The receipt content string, or None on failure.
|
||||
:rtype: str | None
|
||||
@@ -528,14 +533,46 @@ class PaymentProvider(models.Model):
|
||||
self.ensure_one()
|
||||
if not transaction_id:
|
||||
return None
|
||||
|
||||
ICP = self.env['ir.config_parameter'].sudo()
|
||||
cooldown_key = f'fusion_poynt.receipt_endpoint_cooldown_until.{self.id}'
|
||||
try:
|
||||
cooldown_until = int(ICP.get_param(cooldown_key, '0'))
|
||||
except (TypeError, ValueError):
|
||||
cooldown_until = 0
|
||||
now_ts = int(fields.Datetime.now().timestamp())
|
||||
if cooldown_until > now_ts:
|
||||
_logger.debug(
|
||||
"Skipping Poynt receipt fetch for %s — endpoint in cooldown "
|
||||
"for %ss (template missing or endpoint unhealthy)",
|
||||
transaction_id, cooldown_until - now_ts,
|
||||
)
|
||||
return None
|
||||
|
||||
try:
|
||||
result = self._poynt_make_request(
|
||||
'GET', f'transactions/{transaction_id}/receipt',
|
||||
)
|
||||
return result.get('data') or None
|
||||
except (ValidationError, Exception):
|
||||
except ValidationError as e:
|
||||
err = str(e).lower()
|
||||
if 'template' in err or '400' in err:
|
||||
# Poynt is consistently rejecting the receipt call for this
|
||||
# business. Put the endpoint in a 1-hour cooldown so subsequent
|
||||
# webhooks do not hammer Poynt with known-bad requests.
|
||||
ICP.set_param(cooldown_key, str(now_ts + 3600))
|
||||
_logger.warning(
|
||||
"Poynt receipt endpoint returned %s — suspending receipt "
|
||||
"fetches for provider %s for 1 hour. "
|
||||
"Admin: check that the Poynt business has a receipt "
|
||||
"template configured in the Poynt dashboard.",
|
||||
e, self.id,
|
||||
)
|
||||
return None
|
||||
except Exception:
|
||||
_logger.debug(
|
||||
"Could not fetch Poynt receipt for transaction %s", transaction_id,
|
||||
exc_info=True,
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@@ -904,11 +904,24 @@ class PaymentTransaction(models.Model):
|
||||
self.poynt_receipt_data = json.dumps(receipt)
|
||||
|
||||
def _poynt_attach_receipt_pdf(self):
|
||||
"""Render the QWeb receipt report and attach the PDF to the invoice."""
|
||||
"""Render the QWeb receipt report and attach the PDF to the invoice.
|
||||
|
||||
Idempotent: if a PDF for this transaction is already attached,
|
||||
skip. Poynt fires multiple webhooks per payment; without this
|
||||
guard the same invoice would get N duplicate receipt PDFs."""
|
||||
invoice = self.invoice_ids[:1]
|
||||
if not invoice:
|
||||
return
|
||||
|
||||
filename = f"Payment_Receipt_{self.reference}.pdf"
|
||||
existing = self.env['ir.attachment'].sudo().search([
|
||||
('res_model', '=', 'account.move'),
|
||||
('res_id', '=', invoice.id),
|
||||
('name', '=', filename),
|
||||
], limit=1)
|
||||
if existing:
|
||||
return
|
||||
|
||||
try:
|
||||
report = self.env.ref('fusion_poynt.action_report_poynt_receipt')
|
||||
pdf_content, _report_type = report._render_qweb_pdf(report.report_name, [self.id])
|
||||
@@ -916,7 +929,6 @@ class PaymentTransaction(models.Model):
|
||||
_logger.debug("Could not render Poynt receipt PDF for %s", self.reference)
|
||||
return
|
||||
|
||||
filename = f"Payment_Receipt_{self.reference}.pdf"
|
||||
attachment = self.env['ir.attachment'].sudo().create({
|
||||
'name': filename,
|
||||
'type': 'binary',
|
||||
@@ -935,18 +947,33 @@ class PaymentTransaction(models.Model):
|
||||
)
|
||||
|
||||
def _poynt_attach_poynt_receipt(self):
|
||||
"""Try the Poynt renderReceipt endpoint and attach the result."""
|
||||
"""Try the Poynt renderReceipt endpoint and attach the result.
|
||||
|
||||
Idempotent: if a Poynt HTML receipt for this transaction is already
|
||||
attached to the invoice, we skip the remote call. Poynt sends
|
||||
several state-change webhooks per transaction (AUTHORIZED, CAPTURED,
|
||||
UPDATED...) and each one lands here; without this guard every
|
||||
webhook would re-fetch the receipt and hammer Poynt.
|
||||
"""
|
||||
invoice = self.invoice_ids[:1]
|
||||
if not invoice:
|
||||
return
|
||||
|
||||
filename = f"Poynt_Receipt_{self.reference}.html"
|
||||
existing = self.env['ir.attachment'].sudo().search([
|
||||
('res_model', '=', 'account.move'),
|
||||
('res_id', '=', invoice.id),
|
||||
('name', '=', filename),
|
||||
], limit=1)
|
||||
if existing:
|
||||
return
|
||||
|
||||
receipt_content = self._get_provider_sudo()._poynt_fetch_receipt(
|
||||
self.poynt_transaction_id,
|
||||
)
|
||||
if not receipt_content:
|
||||
return
|
||||
|
||||
filename = f"Poynt_Receipt_{self.reference}.html"
|
||||
self.env['ir.attachment'].sudo().create({
|
||||
'name': filename,
|
||||
'type': 'binary',
|
||||
@@ -963,6 +990,11 @@ class PaymentTransaction(models.Model):
|
||||
1. Sends the invoice via the standard Odoo invoice email template.
|
||||
2. Sends the Poynt payment receipt email with the PDF attached.
|
||||
|
||||
Idempotent: Poynt fires several state-change webhooks per payment
|
||||
(AUTHORIZED, CAPTURED, UPDATED...). We use `invoice.is_move_sent`
|
||||
as the "we've already done this" flag so duplicate webhooks don't
|
||||
re-email the customer.
|
||||
|
||||
Best-effort: failures are logged but never block the payment flow.
|
||||
"""
|
||||
self.ensure_one()
|
||||
@@ -976,6 +1008,13 @@ class PaymentTransaction(models.Model):
|
||||
)
|
||||
return
|
||||
|
||||
if invoice and invoice.is_move_sent:
|
||||
_logger.debug(
|
||||
"Skipping auto-send for %s: invoice %s already sent.",
|
||||
self.reference, invoice.name,
|
||||
)
|
||||
return
|
||||
|
||||
# 1. Send the invoice PDF
|
||||
if invoice and invoice.state == 'posted':
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user