Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); docs(reports): document the on-demand refund transactions export (#159069) by gergesfikry-ottu · Pull Request #172 · ottuco/docs · GitHub
Skip to content

docs(reports): document the on-demand refund transactions export (#159069) - #172

Closed
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone
Closed

docs(reports): document the on-demand refund transactions export (#159069)#172
gergesfikry-ottu wants to merge 1 commit into
devfrom
task/159069-refund-export-timezone

Conversation

@gergesfikry-ottu

Copy link
Copy Markdown
Contributor

What

Documents the refund transactions export — an on-demand endpoint that builds a refund-only CSV/XLSX report, filtered by date, state, order, currency, or gateway, with full timezone control. It was previously undocumented, so merchants had no way to discover it or to know that its date filters are timezone-sensitive.

The endpoint is the generation half of a flow whose other two halves (List Reports, Download Report) were already documented on this page, so this extends docs/developers/reports.mdx rather than adding a new page: request a report → poll until finished → download.

Docs ticket: https://orbit.ottu.com/issues/159069
Source ticket: https://orbit.ottu.com/issues/159067 (backend change this documents)
Source PR: https://github.com/ottuco/core_backend/pull/424

Pages

  • docs/developers/reports.mdx — new Generating a Refund Export section (~290 lines): endpoint, auth matrix, four-language quick implementation, async-generation warning, full query-parameter tables, a Timezones section with a worked example, parent-transaction filtering, response-field table, error table. Also updates the page intro, use cases, workflow diagram, and report-sources list to account for the third endpoint, and adds 5 FAQ entries and 3 best practices.
  • sidebars.ts — "Refund Export" anchor added to the Reports category.

Contract documented

SurfaceDetail
EndpointGET /b/api/v1/dashboard/refund-transactions/export/
AuthAuthorization: Api-Key <key> · Basic · Keycloak JWT Bearer
New request headerX-Timezone: <IANA name> — takes priority over ?timezone=
New query paramtimezone — IANA name; sets both filter interpretation and rendered dates
Output paramsfile_format (csv/xlsx), fields, language
Filterscreated_*, modified_*, state (refunded/refund_queued), order_no, product_type, currency_code, gateway_code, initiator, q
Response 201id, status, type, file, size, file_format, records_amount, period, created_at, exported_at, username, report_type
Errors400 invalid timezone / invalid date / invalid state · 401 · 403

Also fixed on this page

The two existing samples used -H "Api-Key: your_private_api_key". HasPrivateAPIKey reads the standard Authorization header via rest_framework_api_key's KeyParser (keyword Api-Key), and no API_KEY_CUSTOM_HEADER is configured — so the correct form is Authorization: Api-Key <key>, which is what docs/developers/payments/wallet/index.mdx already uses. Corrected both.

Verification

Every claim in the new section was checked against the running endpoint, not inferred. Three drafted statements were wrong and were corrected before commit:

  • an unparseable date does not fall through unfiltered — it returns 400 {"created": ["Enter a valid date/time."]}, keyed on the filter's base name rather than the bound you sent
  • an unsupported file_format is not rejected with 404 — it returns 201 and the value is stored as-is
  • available_until is absent from this response; it is a with_available_until() queryset annotation applied by List Reports, not a stored field

The 201 example body is a captured response, not a hand-written one.

  • npm run typecheck — passes
  • npm run build — passes, [SUCCESS] Generated static files in "build". The six broken-anchor warnings it prints are pre-existing on other pages (glossary terms, checkout-api, wallet); none originates from /developers/reports/.
  • Anchors added this PR (#generating-a-refund-export, #timezones, #worked-example, #filtering-by-order) all resolve.

Source of truth

Field names, enum values, and error strings taken verbatim from ottuco/core_backend@e1e5db763:

  • contrib/dashboard/views.py:361-374 — endpoint, auth, permissions, refunded/refund_queued queryset
  • contrib/dashboard/urls.py:23-25 — path
  • utils/rest/views.py:154-193get_report_timezone (header-over-query precedence, 400 on invalid), async export(), file_format/fields/language
  • core/payment/filters.py:99-197,354-372,398-478 — filters, state choices, parent-matching order_no/product_type, TimezoneAwareExportFilterMixin
  • contrib/report/serializers.py:13-66 — response fields
  • contrib/report/models.py:128-131ReportStatus values
  • contrib/report/export/export_builders.py:154-161 + export/formatters.py:118report_timezone drives rendered dates
  • contrib/report/managers.py:7-9available_until is an annotation

…9069)
Adds a Generating a Refund Export section to the Reports API page: endpoint,
auth matrix, four-language quick implementation, the async 201-means-queued
contract, full query parameter tables, a Timezones section with a worked
example of the eight-hour spread the same literal request produces across
zones, parent-transaction filtering, and complete response and error tables.
Also corrects the page's two existing samples, which sent the API key as a
bare Api-Key header. HasPrivateAPIKey reads the standard Authorization header
with the Api-Key keyword, and no API_KEY_CUSTOM_HEADER is configured.
Documents #159067.
@gergesfikry-ottu

Copy link
Copy Markdown
ContributorAuthor

Closing this — wrong audience. The endpoint is not merchant-facing and does not belong in the public docs.

ExportRefundTransactionsView is registered as @Schema.register(namespace="dashboard"), not public. In this codebase the api_docs namespace is the audience boundary: contrib/api_docs/hooks.py::preprocessing_filter_spec filters the schema by namespace, public is the merchant surface, and dashboard is an internal back-office surface served at /schema/dashboard/redoc/. Consistent with that, static/Ottu_API.yaml here — fetched from /schema/public — contains no /api/v1/dashboard/** paths at all.

I over-weighted the fact that the view accepts HasPrivateAPIKey and read it as a merchant integration path. That was the wrong inference: the namespace registration is the deliberate signal, and it says internal dashboard.

The backend fix this documented is unaffected and still shipping: ottuco/core_backend#424 (#159067). Its OpenAPI description lives in contrib/dashboard/schema.py, which is the correct home — the dashboard namespace renders for internal developers, so the X-Timezone / timezone contract is still documented, just to the right audience.

No changes here are being carried forward. Docs ticket #159069 closed as well.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gergesfikry-ottu