Compare commits

...

68 Commits

Author SHA1 Message Date
shaw
9648c4323f fix(frontend): resolve TS2352 type assertion error in API client 2026-04-12 18:06:40 +08:00
shaw
a1a283688c chore: update sponsors 2026-04-12 17:19:44 +08:00
Wesley Liddick
82b840c16e Merge pull request #1587 from tkpdx01/fix/anthropic-credit-balance-400
fix: handle Anthropic credit balance exhausted (400) as account error
2026-04-12 16:42:02 +08:00
Wesley Liddick
16126a2c9c Merge pull request #1545 from Zqysl/qingyu/fix-smooth-sidebar-collapse
fix(sidebar): smooth sidebar collapse behavior
2026-04-12 16:36:00 +08:00
Wesley Liddick
9b7b3755fe Merge pull request #1543 from IanShaw027/fix/messages-dispatch-i18n
fix(frontend): 补全 messages 调度国际化文案
2026-04-12 16:35:34 +08:00
Wesley Liddick
54490cf65e Merge pull request #1576 from touwaeriol/feat/payment-docs
docs(payment): add built-in payment configuration guide and settings links
2026-04-12 16:34:53 +08:00
bot
cb016ad861 fix: handle Anthropic credit balance exhausted (400) as account error
When an Anthropic API key's credit balance is depleted, the upstream
returns HTTP 400 with message containing "credit balance". Previously,
the 400 handler only checked for "organization has been disabled",
so credit-exhausted accounts kept being scheduled — every request
returned the same error.

Treat this case identically to 402 (Payment Required): call
handleAuthError → SetError to stop scheduling the account until
an admin manually recovers it after topping up credits.

Closes #1586
2026-04-12 13:30:15 +08:00
qingyuzhang
c520de11de Merge branch 'main' of github.com:Wei-Shaw/sub2api into qingyu/fix-smooth-sidebar-collapse
# Conflicts:
#	frontend/src/components/layout/AppSidebar.vue
2026-04-12 06:04:34 +08:00
erio
1def627443 feat(settings): add EasyPay provider recommendation link below enabled providers 2026-04-11 21:13:46 +08:00
erio
64cee0b633 feat(settings): add payment config guide link in payment settings header 2026-04-11 21:13:28 +08:00
erio
24f95767b4 docs: align English ZPay referral description with Chinese version 2026-04-11 21:13:08 +08:00
erio
ed001d94da docs: clarify ZPay referral code belongs to Sub2ApiPay author @touwaeriol 2026-04-11 21:13:07 +08:00
erio
f3e8e5e057 docs: show ZPay URL explicitly in parentheses 2026-04-11 21:13:07 +08:00
erio
3b0dc92952 docs: move ZPay recommendation to overview section 2026-04-11 21:12:47 +08:00
erio
1a686239ed fix(docs): correct webhook paths and provider config in payment guide
- Fix webhook URLs: /payment/webhook/<provider> not /payment/<provider>/notify
- Remove notifyUrl/returnUrl from provider config tables (auto-generated by UI)
- Adjust wxpay publicKeyId/certSerial to match frontend optional marking
2026-04-11 21:11:19 +08:00
erio
c777fe5471 docs: add built-in payment configuration guide and update README
- Add docs/PAYMENT.md and docs/PAYMENT_CN.md with full payment setup guide
- Mark Sub2ApiPay as deprecated in ecosystem tables (payment is now built-in)
- Add built-in payment system to features list in all 3 READMEs
2026-04-11 21:10:55 +08:00
Wesley Liddick
97f14b7a08 Merge pull request #1572 from touwaeriol/feat/payment-system-v2
feat(payment): add complete payment system with multi-provider support
2026-04-11 19:07:31 +08:00
erio
6793503ed0 chore: remove sora_client_enabled residuals from frontend types and store 2026-04-11 19:02:25 +08:00
erio
fa833f7684 Merge remote-tracking branch 'upstream/main' into feat/payment-system-v2
# Conflicts:
#	frontend/src/api/admin/settings.ts
#	frontend/src/stores/app.ts
#	frontend/src/types/index.ts
#	frontend/src/views/admin/SettingsView.vue
2026-04-11 18:25:06 +08:00
erio
d67ecf893d chore: remove all sora dead code and fork-specific sora_client_enabled
Upstream removed sora feature (090_drop_sora.sql) but left i18n keys
and wire.go references. Clean up:
- Remove entire sora i18n block from en.ts and zh.ts (~190 lines)
- Remove sora nav key and unused 'data' settings tab key
- Remove sora_client_enabled from settings (fork-specific)
- Remove SoraMediaCleanupService from wire.go
2026-04-11 18:15:24 +08:00
erio
faee59ee15 fix(payment): propagate reason/metadata in API error responses
The API client's error interceptor was dropping the reason and metadata
fields from backend error responses. This caused PaymentView to miss
specific error codes (TOO_MANY_PENDING, CANCEL_RATE_LIMITED) and fall
back to generic error messages.
2026-04-11 17:51:06 +08:00
erio
217b7ea68c fix(deps): upgrade axios to 1.15.0 to fix GHSA-fvcv-3m26-pcqx 2026-04-11 16:46:46 +08:00
erio
a020fc52c9 fix(payment): pass expires_at for Stripe countdown timer
Stripe payment path was setting expiresAt to empty string, causing
PaymentStatusPanel to fall back to hardcoded 30-minute default when
the popup redirect switches to the waiting view.
2026-04-11 16:30:34 +08:00
Wesley Liddick
1ef3782dd4 Merge pull request #1538 from IanShaw027/fix/bug-cleanup-main
fix: 修复多个 UI 和功能问题 - 表格排序搜索、导出逻辑、分页配置和状态筛选
2026-04-11 16:29:55 +08:00
erio
7515590324 feat(payment): add H5/mobile payment support
Backend:
- Parse EasyPay `payurl2` field, prefer H5 link on mobile
- Add `device=mobile` to EasyPay submit.php (popup) mode
- Expand isMobile detection keywords (add ipad/ipod)

Frontend:
- Add `isMobileDevice()` utility (userAgentData + UA regex)
- Mobile + pay_url: direct redirect instead of QR/popup
- Popup blocked fallback: auto-redirect when window.open fails
- Stripe WeChat Pay: dynamic client param (mobile_web vs web)
2026-04-11 13:16:35 +08:00
erio
e3a000e0d4 refactor(payment): code standards fixes and regression repairs
Backend:
- Split payment_order.go (546→314 lines) into payment_order_lifecycle.go
- Replace magic strings with constants in factory, easypay, webhook handler
- Add rate limit/validity unit constants in payment_order_lifecycle, payment_service
- Fix critical regression: add PaymentEnabled to GetPublicSettings response
- Add missing migration 099_fix_migrated_purchase_menu_label_icon.sql

Frontend:
- Fix StripePopupView.vue: replace `as any` with typed interface, use extractApiErrorMessage
- Fix AdminOrderTable.vue: replace hardcoded column labels with i18n t() calls
- Fix SubscriptionsView.vue: replace hardcoded Today/Tomorrow with i18n
- Extract duplicate statusBadgeClass/canRefund/formatOrderDateTime to orderUtils.ts
- Add missing i18n keys: common.today, common.tomorrow, payment.orders.orderType/actions
- Remove dead PurchaseSubscriptionView.vue (replaced by PaymentView)
2026-04-11 13:16:35 +08:00
erio
27cd2f8e96 fix(payment): remove purchase_subscription fields replaced by payment system
The built-in payment system replaces the old external purchase subscription
iframe approach. Remove purchase_subscription_enabled/url from admin settings
interface and form defaults, as the Payment tab now handles this functionality.
Kept in stores/app.ts fallback to match backend DTO response structure.
2026-04-11 13:16:35 +08:00
erio
e1547d7835 fix(payment): resolve PR audit issues
- Add payment navigation to AppSidebar (user orders + admin payment menu group with collapse)
- Add 5 missing nav i18n keys (myOrders, orderManagement, paymentDashboard, paymentConfig, paymentPlans)
- Renumber payment migrations 090-100 → 092-102 to avoid conflict with upstream 090/091
- Remove non-payment sora_client_enabled change, restore upstream purchase_subscription fields
- Remove extra 'data' from SettingsTab type union
2026-04-11 13:16:35 +08:00
erio
63d1860dc0 feat(payment): add complete payment system with multi-provider support
Add a full payment and subscription system supporting EasyPay (Alipay/WeChat),
Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
2026-04-11 13:16:35 +08:00
IanShaw027
f480e57344 fix: align table defaults and preserve sidebar svg colors 2026-04-10 18:27:53 +08:00
IanShaw027
7dc7ff22d2 fix: preserve messages dispatch config in repository hydration 2026-04-10 18:13:18 +08:00
IanShaw027
67a05dfccd fix: honor table defaults and preserve dispatch mappings 2026-04-10 17:55:37 +08:00
IanShaw027
b6bc042302 fix(frontend): 升级 axios 修复审计高危漏洞 2026-04-10 09:28:32 +08:00
IanShaw027
1312405966 fix(settings): 补齐公开设置中的表格分页字段返回 2026-04-10 09:18:48 +08:00
qingyuzhang
07d2add674 fix(sidebar): smooth collapse transitions 2026-04-10 05:16:20 +08:00
IanShaw027
57d0f9794f fix(frontend): 补全 messages 调度国际化文案 2026-04-10 00:56:23 +08:00
IanShaw027
269c7a065c fix(test): restore integration expectations 2026-04-09 22:08:42 +08:00
IanShaw027
b6946e78a2 fix(lint): restore repository sort helpers 2026-04-09 21:49:10 +08:00
IanShaw027
2b70d1d332 merge upstream main into fix/bug-cleanup-main 2026-04-09 21:35:48 +08:00
IanShaw027
b37afd68ec fix(lint): format setting service 2026-04-09 21:31:48 +08:00
Wesley Liddick
00c08c574e Merge pull request #1539 from warksu/fix/loadfactor-not-synced-to-scheduler-cache
fix: 同步 LoadFactor 到调度快照缓存
2026-04-09 21:15:40 +08:00
Wesley Liddick
bbc79796dc Merge pull request #1529 from IanShaw027/feat/group-messages-dispatch-redo
feat: 为openai分组增加messages调度模型映射并支持instructions模板注入
2026-04-09 21:14:38 +08:00
Wesley Liddick
760cc7d6be Merge pull request #1481 from alfadb/fix/increase-error-log-body-limit
fix(ops): 将错误日志请求体存储限制从 10KB 提升至 256KB
2026-04-09 21:14:13 +08:00
Wesley Liddick
9a72025afb Merge pull request #1523 from octo-patch/fix/issue-1519-home-content-csp-frame-src
fix: include home_content URL in CSP frame-src origins
2026-04-09 21:13:46 +08:00
Wesley Liddick
74302f60ab Merge pull request #1010 from Glorhop/pr/oidc-login
feat(auth): support OIDC login and prefer IdP real email on sign-in
2026-04-09 21:13:22 +08:00
IanShaw027
62962c05f1 fix(lint): 修复 CI 中的 ineffassign 和 unused 代码告警,修正 group 排序集成测试兼容性 2026-04-09 19:25:08 +08:00
swark2006
118ff85fbf fix: 同步 LoadFactor 到调度快照缓存
LoadFactor 字段在构建调度快照缓存时缺失,导致调度算法
EffectiveLoadFactor() 无法使用配置的负载因子,回退到 Concurrency。
这会影响账号的负载率计算,进而影响调度优先级。

修复:在 buildSchedulerMetadataAccount 中添加 LoadFactor 字段。
2026-04-09 18:50:11 +08:00
IanShaw027
5f8e60a1b7 feat(table): 表格排序与搜索改为后端处理 2026-04-09 18:14:28 +08:00
IanShaw027
66e15a54a4 fix(export): 导出逻辑与当前筛选条件对齐 2026-04-09 18:14:28 +08:00
IanShaw027
ad80606a44 feat(settings): 增加全局表格分页配置,支持自定义 2026-04-09 18:14:28 +08:00
IanShaw027
d8fa38d55a fix(account): 修复账号管理中的状态筛选 2026-04-09 18:14:28 +08:00
alfadb
6401dd7cc7 fix(ops): increase error log request body limit from 10KB to 256KB
10KB is too aggressive for modern LLM API requests where conversation
context routinely exceeds 1MB. This causes error logs to contain only
a minimal placeholder, making it impossible to debug upstream failures.

256KB retains enough context for effective debugging while the existing
multi-pass trimming logic handles larger payloads gracefully.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 17:49:02 +08:00
IanShaw027
fe211fc563 fix(ui): 修复在 macOS 系统下数据表格横向滚动条闪隐和消失的问题
问题原因:
原本的 `style.css` 代码全局使用了 W3C 标准属性 (`scrollbar-width`)。而在 Chrome 121+ 以及 Safari 环境下,一旦匹配到 W3C 标准属性,浏览器就会放弃 WebKit 的定制样式,全面交由操作系统原生渲染。因为 macOS 原生的滚动条特性就是“不滚动时自动隐藏”,加之原本又配置了全局 hover 时才显色的透明度逻辑,最终导致在苹果系统下数据表常常无法明显看出横向滚动条。

修复方式:
1. 在 `style.css` 中增加 `@supports (-moz-appearance:none)`,将对全局 `scrollbar-width` 的干预严格隔离限制在 Firefox 浏览器内,防止误伤 Chrome 等 WebKit 系浏览器。
2. 移除旧版代码中对 `.table-wrapper` 直接定义的 `scrollbar-width` 和透明覆盖。
3. 在 `DataTable.vue` 内部,通过 `!important` 将 Webkit 专属定制外观(12px高度,实心圆角灰色轨道)的优先权推至最高,强制覆盖透明隐身规则。
4. 为底层 table 添加了 `min-w-max` 属性,强制阻止内容宽度受限于屏幕边界带来的收缩,充分保证合理超出范围而触发常驻横向溢出。
2026-04-09 15:13:16 +08:00
IanShaw027
7d008bd5b6 fix(test): 修正 admin service 分组测试平台字段赋值 2026-04-09 12:42:37 +08:00
IanShaw027
66ff2def8c fix(test): 补充 admin service 分组测试字符串指针辅助函数 2026-04-09 12:39:05 +08:00
IanShaw027
de9b9c9dfb feat(admin): 增加分组 messages 调度映射配置界面 2026-04-09 12:30:25 +08:00
IanShaw027
d765359f4b test(admin): 增加messages调度表单状态转换测试 2026-04-09 12:30:06 +08:00
IanShaw027
4de4823a65 feat(openai): 支持messages模型映射与instructions模板注入 2026-04-09 12:29:49 +08:00
IanShaw027
23c4d592f8 feat(group): 增加messages调度模型映射配置 2026-04-09 12:29:28 +08:00
Glorhop
311f06745a chore: clean up deprecated Sora settings after rebase 2026-04-09 03:06:53 +00:00
Wesley Liddick
1b79f6a7cf Merge pull request #1522 from xvhuan/fix/redis-snapshot-meta-fix
优化调度快照缓存,避免 1.5 万账号场景下 Redis 大 MGET
2026-04-09 10:25:33 +08:00
Glorhop
8e1a7bdfff fix: fixed an issue where OIDC login consistently used a synthetic email address 2026-04-09 02:20:51 +00:00
ruiqurm
02a66a01c3 feat: support OIDC login. 2026-04-09 02:20:51 +00:00
octo-patch
ce833d91ce fix: include home_content URL in CSP frame-src origins (fixes #1519) 2026-04-09 09:47:27 +08:00
shaw
155d3474d6 chore: update Sponsors 2026-04-09 09:21:55 +08:00
ius
265687b56d fix: 优化调度快照缓存以避免 Redis 大 MGET 2026-04-08 10:39:15 -07:00
github-actions[bot]
0d69c0cd64 chore: sync VERSION to 0.1.110 [skip ci] 2026-04-08 08:41:32 +00:00
shaw
f54e9d0b1c chore: update readme 2026-04-08 16:37:00 +08:00
332 changed files with 54617 additions and 2443 deletions

View File

@@ -28,3 +28,10 @@ exceptions:
mitigation: "No user-controlled template strings; plan to migrate to native JS alternatives"
expires_on: "2026-07-02"
owner: "security@your-domain"
- package: axios
advisory: "GHSA-3p68-rc4w-qgx5"
severity: critical
reason: "NO_PROXY bypass not exploitable; all API calls go to known endpoints via server-side proxy"
mitigation: "Proxy configuration not user-controlled; upgrade when axios releases fix"
expires_on: "2026-07-10"
owner: "security@your-domain"

2
.gitignore vendored
View File

@@ -127,6 +127,8 @@ deploy/docker-compose.override.yml
.gocache/
vite.config.js
docs/*
!docs/PAYMENT.md
!docs/PAYMENT_CN.md
.serena/
.codex/
frontend/coverage/

View File

@@ -42,8 +42,9 @@ Sub2API is an AI API gateway platform designed to distribute and manage API quot
- **Smart Scheduling** - Intelligent account selection with sticky sessions
- **Concurrency Control** - Per-user and per-account concurrency limits
- **Rate Limiting** - Configurable request and token rate limits
- **Built-in Payment System** - Supports EasyPay, Alipay, WeChat Pay, and Stripe for user self-service top-up, no separate payment service needed ([Configuration Guide](docs/PAYMENT.md))
- **Admin Dashboard** - Web interface for monitoring and management
- **External System Integration** - Embed external systems (e.g. payment, ticketing) via iframe to extend the admin dashboard
- **External System Integration** - Embed external systems (e.g. ticketing) via iframe to extend the admin dashboard
## ❤️ Sponsors
@@ -69,6 +70,22 @@ Sub2API is an AI API gateway platform designed to distribute and manage API quot
<td width="180"><a href="https://ctok.ai"><img src="assets/partners/logos/ctok.png" alt="CTok" width="150"></a></td>
<td>Thanks to CTok.ai for sponsoring this project! CTok.ai is dedicated to building a one-stop AI programming tool service platform. We offer professional Claude Code packages and technical community services, with support for Google Gemini and OpenAI Codex. Through carefully designed plans and a professional tech community, we provide developers with reliable service guarantees and continuous technical support, making AI-assisted programming a true productivity tool. Click <a href="https://ctok.ai">here</a> to register!</td>
</tr>
<tr>
<td width="180"><a href="https://code.silkapi.com/"><img src="assets/partners/logos/silkapi.png" alt="silkapi" width="150"></a></td>
<td>Thanks to SilkAPI for sponsoring this project! <a href="https://code.silkapi.com/">SilkAPI</a> is a relay service built on Sub2API, specializing in providing high-speed and stable Codex API relay.</td>
</tr>
<tr>
<td width="180"><a href="https://ylscode.com/"><img src="assets/partners/logos/ylscode.png" alt="ylscode" width="150"></a></td>
<td>Thanks to YLS Code for sponsoring this project! <a href="https://ylscode.com/">YLS Code</a> is dedicated to building secure enterprise-grade Coding Agent productivity services, offering stable and fast Codex / Claude / Gemini subscription services along with pay-as-you-go API options for flexible choices. Register now for a limited-time 3-day Codex trial bonus!</td>
</tr>
<tr>
<td width="180"><a href="https://www.aicodemirror.com/register?invitecode=KMVZQM"><img src="assets/partners/logos/AICodeMirror.jpg" alt="AICodeMirror" width="150"></a></td>
<td>Thanks to AICodeMirror for sponsoring this project! AICodeMirror provides official high-stability relay services for Claude Code / Codex / Gemini CLI, with enterprise-grade concurrency, fast invoicing, and 24/7 dedicated technical support. Claude Code / Codex / Gemini official channels at 38% / 2% / 9% of original price, with extra discounts on top-ups! AICodeMirror offers special benefits for sub2api users: register via <a href="https://www.aicodemirror.com/register?invitecode=KMVZQM">this link</a> to enjoy 20% off your first top-up, and enterprise customers can get up to 25% off!</td>
</tr>
</table>
## Ecosystem
@@ -77,7 +94,7 @@ Community projects that extend or integrate with Sub2API:
| Project | Description | Features |
|---------|-------------|----------|
| [Sub2ApiPay](https://github.com/touwaeriol/sub2apipay) | Self-service payment system | Self-service top-up and subscription purchase; supports YiPay protocol, WeChat Pay, Alipay, Stripe; embeddable via iframe |
| ~~[Sub2ApiPay](https://github.com/touwaeriol/sub2apipay)~~ | ~~Self-service payment system~~ | **Now Built-in** — Payment is now integrated into Sub2API, no separate deployment needed. See [Payment Configuration Guide](docs/PAYMENT.md) |
| [sub2api-mobile](https://github.com/ckken/sub2api-mobile) | Mobile admin console | Cross-platform app (iOS/Android/Web) for user management, account management, monitoring dashboard, and multi-backend switching; built with Expo + React Native |
## Tech Stack

View File

@@ -41,8 +41,9 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅的
- **智能调度** - 智能账号选择,支持粘性会话
- **并发控制** - 用户级和账号级并发限制
- **速率限制** - 可配置的请求和 Token 速率限制
- **内置支付系统** - 支持 EasyPay 易支付、支付宝官方、微信官方、Stripe用户自助充值无需独立部署支付服务[配置指南](docs/PAYMENT_CN.md)
- **管理后台** - Web 界面进行监控和管理
- **外部系统集成** - 支持通过 iframe 嵌入外部系统(如支付、工单等),扩展管理后台功能
- **外部系统集成** - 支持通过 iframe 嵌入外部系统(如工单等),扩展管理后台功能
## ❤️ 赞助商
@@ -69,6 +70,21 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅的
<td>感谢 CTok.ai 赞助了本项目CTok.ai 致力于打造一站式 AI 编程工具服务平台。我们提供 Claude Code 专业套餐及技术社群服务,同时支持 Google Gemini 和 OpenAI Codex。通过精心设计的套餐方案和专业的技术社群为开发者提供稳定的服务保障和持续的技术支持让 AI 辅助编程真正成为开发者的生产力工具。点击<a href="https://ctok.ai">这里</a>注册!</td>
</tr>
<tr>
<td width="180"><a href="https://code.silkapi.com/"><img src="assets/partners/logos/silkapi.png" alt="silkapi" width="150"></a></td>
<td>感谢 丝绸API 赞助了本项目! <a href="https://code.silkapi.com/">丝绸API</a> 是基于 Sub2API 搭建的中转服务,专注于提供 Codex 高速稳定API中转。</td>
</tr>
<tr>
<td width="180"><a href="https://ylscode.com/"><img src="assets/partners/logos/ylscode.png" alt="ylscode" width="150"></a></td>
<td>感谢 伊莉思Code 赞助了本项目! <a href="https://ylscode.com/">伊莉思Code</a> 致力于构建安全的企业级Coding Agent生产力服务提供稳定快速的 Codex / Claude / Gemini 订阅服务与即用即付API多种方案灵活选择限时注册赠送 3 天 Codex 试用福利!</td>
</tr>
<tr>
<td width="180"><a href="https://www.aicodemirror.com/register?invitecode=KMVZQM"><img src="assets/partners/logos/AICodeMirror.jpg" alt="AICodeMirror" width="150"></a></td>
<td>感谢 AICodeMirror 赞助了本项目AICodeMirror 提供 Claude Code / Codex / Gemini CLI 官方高稳定性中转服务企业级并发、快速开票、7×24 小时专属技术支持。Claude Code / Codex / Gemini 官方通道低至原价 38% / 2% / 9%充值更享额外折扣AICodeMirror 为 sub2api 用户提供专属福利:通过<a href="https://www.aicodemirror.com/register?invitecode=KMVZQM">此链接</a>注册,首次充值立享 8 折优惠,企业客户最高可享 75 折!</td>
</tr>
</table>
## 生态项目
@@ -77,7 +93,7 @@ Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅的
| 项目 | 说明 | 功能 |
|------|------|------|
| [Sub2ApiPay](https://github.com/touwaeriol/sub2apipay) | 自助支付系统 | 用户自助充值、自助订阅购买兼容易支付协议、微信官方支付、支付宝官方支付、Stripe支持 iframe 嵌入管理后台 |
| ~~[Sub2ApiPay](https://github.com/touwaeriol/sub2apipay)~~ | ~~自助支付系统~~ | **已内置** — 支付功能已集成到 Sub2API 中,无需独立部署。详见 [支付配置指南](docs/PAYMENT_CN.md) |
| [sub2api-mobile](https://github.com/ckken/sub2api-mobile) | 移动端管理控制台 | 跨平台应用iOS/Android/Web支持用户管理、账号管理、监控看板、多后端切换基于 Expo + React Native 构建 |
## 技术栈

View File

@@ -42,8 +42,9 @@ Sub2API は、AI 製品のサブスクリプションから API クォータを
- **スマートスケジューリング** - スティッキーセッション付きのインテリジェントなアカウント選択
- **同時実行制御** - ユーザーごと・アカウントごとの同時実行数制限
- **レート制限** - 設定可能なリクエスト数およびトークンレート制限
- **内蔵決済システム** - EasyPay、Alipay、WeChat Pay、Stripe に対応。ユーザーのセルフサービスチャージが可能で、別途決済サービスのデプロイは不要([設定ガイド](docs/PAYMENT.md)
- **管理ダッシュボード** - 監視・管理のための Web インターフェース
- **外部システム連携** - 外部システム(決済、チケット管理など)を iframe 経由で管理ダッシュボードに埋め込み可能
- **外部システム連携** - 外部システム(チケット管理など)を iframe 経由で管理ダッシュボードに埋め込み可能
## ❤️ スポンサー
@@ -68,6 +69,22 @@ Sub2API は、AI 製品のサブスクリプションから API クォータを
<td width="180"><a href="https://ctok.ai"><img src="assets/partners/logos/ctok.png" alt="CTok" width="150"></a></td>
<td>CTok.ai のご支援に感謝しますCTok.ai はワンストップ AI プログラミングツールサービスプラットフォームの構築に取り組んでいます。Claude Code の専用プランと技術コミュニティサービスを提供し、Google Gemini や OpenAI Codex もサポートしています。丁寧に設計されたプランと専門的な技術コミュニティを通じて、開発者に安定したサービス保証と継続的な技術サポートを提供し、AI アシスト プログラミングを真の生産性向上ツールにします。<a href="https://ctok.ai">こちら</a>から登録!</td>
</tr>
<tr>
<td width="180"><a href="https://code.silkapi.com/"><img src="assets/partners/logos/silkapi.png" alt="silkapi" width="150"></a></td>
<td>SilkAPI のご支援に感謝します!<a href="https://code.silkapi.com/">SilkAPI</a> は Sub2API をベースに構築された中継サービスで、高速かつ安定した Codex API 中継の提供に特化しています。</td>
</tr>
<tr>
<td width="180"><a href="https://ylscode.com/"><img src="assets/partners/logos/ylscode.png" alt="ylscode" width="150"></a></td>
<td>YLS Code のご支援に感謝します!<a href="https://ylscode.com/">YLS Code</a> は安全なエンタープライズグレードの Coding Agent 生産性サービスの構築に取り組んでおり、安定かつ高速な Codex / Claude / Gemini サブスクリプションサービスと従量課金 API の柔軟なプランを提供しています。期間限定で新規登録者に 3 日間の Codex 試用特典をプレゼント中!</td>
</tr>
<tr>
<td width="180"><a href="https://www.aicodemirror.com/register?invitecode=KMVZQM"><img src="assets/partners/logos/AICodeMirror.jpg" alt="AICodeMirror" width="150"></a></td>
<td>AICodeMirror のご支援に感謝しますAICodeMirror は Claude Code / Codex / Gemini CLI の公式高安定性リレーサービスを提供しており、エンタープライズグレードの同時実行、迅速な請求書発行、24時間年中無休の専属テクニカルサポートを備えています。Claude Code / Codex / Gemini の公式チャネルを定価の 38% / 2% / 9% で利用可能、チャージ時にはさらに追加割引AICodeMirror は sub2api ユーザー向けに特別特典を提供中:<a href="https://www.aicodemirror.com/register?invitecode=KMVZQM">こちらのリンク</a>から登録すると、初回チャージが 20% オフ、法人のお客様は最大 25% オフ!</td>
</tr>
</table>
## エコシステム
@@ -76,7 +93,7 @@ Sub2API を拡張・統合するコミュニティプロジェクト:
| プロジェクト | 説明 | 機能 |
|---------|-------------|----------|
| [Sub2ApiPay](https://github.com/touwaeriol/sub2apipay) | セルフサービス決済システム | セルフサービスによるチャージおよびサブスクリプション購入。YiPay プロトコル、WeChat Pay、Alipay、Stripe 対応。iframe での埋め込み可能 |
| ~~[Sub2ApiPay](https://github.com/touwaeriol/sub2apipay)~~ | ~~セルフサービス決済システム~~ | **内蔵済み** — 決済機能は Sub2API に統合されました。別途デプロイは不要です。[決済設定ガイド](docs/PAYMENT.md)をご参照ください |
| [sub2api-mobile](https://github.com/ckken/sub2api-mobile) | モバイル管理コンソール | ユーザー管理、アカウント管理、監視ダッシュボード、マルチバックエンド切り替えが可能なクロスプラットフォームアプリiOS/Android/Web。Expo + React Native で構築 |
## 技術スタック

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1 +1 @@
0.1.109
0.1.110

View File

@@ -13,6 +13,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/handler"
"github.com/Wei-Shaw/sub2api/internal/payment"
"github.com/Wei-Shaw/sub2api/internal/repository"
"github.com/Wei-Shaw/sub2api/internal/server"
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
@@ -41,6 +42,13 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
// Server layer ProviderSet
server.ProviderSet,
// Payment providers
payment.ProvideRegistry,
payment.ProvideEncryptionKey,
payment.ProvideDefaultLoadBalancer,
service.ProvidePaymentConfigService,
service.ProvidePaymentOrderExpiryService,
// Privacy client factory for OpenAI training opt-out
providePrivacyClientFactory,
@@ -76,7 +84,6 @@ func provideCleanup(
opsCleanup *service.OpsCleanupService,
opsScheduledReport *service.OpsScheduledReportService,
opsSystemLogSink *service.OpsSystemLogSink,
soraMediaCleanup *service.SoraMediaCleanupService,
schedulerSnapshot *service.SchedulerSnapshotService,
tokenRefresh *service.TokenRefreshService,
accountExpiry *service.AccountExpiryService,
@@ -95,6 +102,7 @@ func provideCleanup(
openAIGateway *service.OpenAIGatewayService,
scheduledTestRunner *service.ScheduledTestRunnerService,
backupSvc *service.BackupService,
paymentOrderExpiry *service.PaymentOrderExpiryService,
) func() {
return func() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -125,12 +133,6 @@ func provideCleanup(
}
return nil
}},
{"SoraMediaCleanupService", func() error {
if soraMediaCleanup != nil {
soraMediaCleanup.Stop()
}
return nil
}},
{"OpsAlertEvaluatorService", func() error {
if opsAlertEvaluator != nil {
opsAlertEvaluator.Stop()
@@ -237,6 +239,12 @@ func provideCleanup(
}
return nil
}},
{"PaymentOrderExpiryService", func() error {
if paymentOrderExpiry != nil {
paymentOrderExpiry.Stop()
}
return nil
}},
}
infraSteps := []cleanupStep{

View File

@@ -12,6 +12,7 @@ import (
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/handler"
"github.com/Wei-Shaw/sub2api/internal/handler/admin"
"github.com/Wei-Shaw/sub2api/internal/payment"
"github.com/Wei-Shaw/sub2api/internal/repository"
"github.com/Wei-Shaw/sub2api/internal/server"
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
@@ -72,6 +73,15 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
userService := service.NewUserService(userRepository, apiKeyAuthCacheInvalidator, billingCache)
redeemCache := repository.NewRedeemCache(redisClient)
redeemService := service.NewRedeemService(redeemCodeRepository, userRepository, subscriptionService, redeemCache, billingCacheService, client, apiKeyAuthCacheInvalidator)
registry := payment.ProvideRegistry()
encryptionKey, err := payment.ProvideEncryptionKey(configConfig)
if err != nil {
return nil, err
}
defaultLoadBalancer := payment.ProvideDefaultLoadBalancer(client, encryptionKey)
paymentConfigService := service.ProvidePaymentConfigService(client, settingRepository, encryptionKey)
paymentService := service.NewPaymentService(client, registry, defaultLoadBalancer, redeemService, subscriptionService, paymentConfigService, userRepository, groupRepository)
paymentOrderExpiryService := service.ProvidePaymentOrderExpiryService(paymentService)
secretEncryptor, err := repository.NewAESEncryptor(configConfig)
if err != nil {
return nil, err
@@ -100,7 +110,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
}
dashboardAggregationService := service.ProvideDashboardAggregationService(dashboardAggregationRepository, timingWheelService, configConfig)
dashboardHandler := admin.NewDashboardHandler(dashboardService, dashboardAggregationService)
schedulerCache := repository.NewSchedulerCache(redisClient)
schedulerCache := repository.ProvideSchedulerCache(redisClient, configConfig)
accountRepository := repository.NewAccountRepository(client, db, schedulerCache)
proxyRepository := repository.NewProxyRepository(client, db)
proxyExitInfoProber := repository.NewProxyExitInfoProber(configConfig)
@@ -183,7 +193,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
geminiMessagesCompatService := service.NewGeminiMessagesCompatService(accountRepository, groupRepository, gatewayCache, schedulerSnapshotService, geminiTokenProvider, rateLimitService, httpUpstream, antigravityGatewayService, configConfig)
opsSystemLogSink := service.ProvideOpsSystemLogSink(opsRepository)
opsService := service.NewOpsService(opsRepository, settingRepository, configConfig, accountRepository, userRepository, concurrencyService, gatewayService, openAIGatewayService, geminiMessagesCompatService, antigravityGatewayService, opsSystemLogSink)
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService, opsService)
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService, opsService, paymentConfigService, paymentService)
opsHandler := admin.NewOpsHandler(opsService)
updateCache := repository.NewUpdateCache(redisClient)
gitHubReleaseClient := repository.ProvideGitHubReleaseClient(configConfig)
@@ -211,7 +221,8 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
scheduledTestService := service.ProvideScheduledTestService(scheduledTestPlanRepository, scheduledTestResultRepository)
scheduledTestHandler := admin.NewScheduledTestHandler(scheduledTestService)
channelHandler := admin.NewChannelHandler(channelService, billingService)
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, adminAnnouncementHandler, dataManagementHandler, backupHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, promoHandler, settingHandler, opsHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler, errorPassthroughHandler, tlsFingerprintProfileHandler, adminAPIKeyHandler, scheduledTestHandler, channelHandler)
adminPaymentHandler := admin.NewPaymentHandler(paymentService, paymentConfigService)
adminHandlers := handler.ProvideAdminHandlers(dashboardHandler, adminUserHandler, groupHandler, accountHandler, adminAnnouncementHandler, dataManagementHandler, backupHandler, oAuthHandler, openAIOAuthHandler, geminiOAuthHandler, antigravityOAuthHandler, proxyHandler, adminRedeemHandler, promoHandler, settingHandler, opsHandler, systemHandler, adminSubscriptionHandler, adminUsageHandler, userAttributeHandler, errorPassthroughHandler, tlsFingerprintProfileHandler, adminAPIKeyHandler, scheduledTestHandler, channelHandler, adminPaymentHandler)
usageRecordWorkerPool := service.NewUsageRecordWorkerPool(configConfig)
userMsgQueueCache := repository.NewUserMsgQueueCache(redisClient)
userMessageQueueService := service.ProvideUserMessageQueueService(userMsgQueueCache, rpmCache, configConfig)
@@ -219,9 +230,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
openAIGatewayHandler := handler.NewOpenAIGatewayHandler(openAIGatewayService, concurrencyService, billingCacheService, apiKeyService, usageRecordWorkerPool, errorPassthroughService, configConfig)
handlerSettingHandler := handler.ProvideSettingHandler(settingService, buildInfo)
totpHandler := handler.NewTotpHandler(totpService)
handlerPaymentHandler := handler.NewPaymentHandler(paymentService, paymentConfigService, channelService)
paymentWebhookHandler := handler.NewPaymentWebhookHandler(paymentService, registry)
idempotencyCoordinator := service.ProvideIdempotencyCoordinator(idempotencyRepository, configConfig)
idempotencyCleanupService := service.ProvideIdempotencyCleanupService(idempotencyRepository, configConfig)
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, announcementHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler, totpHandler, idempotencyCoordinator, idempotencyCleanupService)
handlers := handler.ProvideHandlers(authHandler, userHandler, apiKeyHandler, usageHandler, redeemHandler, subscriptionHandler, announcementHandler, adminHandlers, gatewayHandler, openAIGatewayHandler, handlerSettingHandler, totpHandler, handlerPaymentHandler, paymentWebhookHandler, idempotencyCoordinator, idempotencyCleanupService)
jwtAuthMiddleware := middleware.NewJWTAuthMiddleware(authService, userService)
adminAuthMiddleware := middleware.NewAdminAuthMiddleware(authService, userService, settingService)
apiKeyAuthMiddleware := middleware.NewAPIKeyAuthMiddleware(apiKeyService, subscriptionService, configConfig)
@@ -236,7 +249,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
accountExpiryService := service.ProvideAccountExpiryService(accountRepository)
subscriptionExpiryService := service.ProvideSubscriptionExpiryService(userSubscriptionRepository)
scheduledTestRunnerService := service.ProvideScheduledTestRunnerService(scheduledTestPlanRepository, scheduledTestService, accountTestService, rateLimitService, configConfig)
v := provideCleanup(client, redisClient, opsMetricsCollector, opsAggregationService, opsAlertEvaluatorService, opsCleanupService, opsScheduledReportService, opsSystemLogSink, schedulerSnapshotService, tokenRefreshService, accountExpiryService, subscriptionExpiryService, usageCleanupService, idempotencyCleanupService, pricingService, emailQueueService, billingCacheService, usageRecordWorkerPool, subscriptionService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, openAIGatewayService, scheduledTestRunnerService, backupService)
v := provideCleanup(client, redisClient, opsMetricsCollector, opsAggregationService, opsAlertEvaluatorService, opsCleanupService, opsScheduledReportService, opsSystemLogSink, schedulerSnapshotService, tokenRefreshService, accountExpiryService, subscriptionExpiryService, usageCleanupService, idempotencyCleanupService, pricingService, emailQueueService, billingCacheService, usageRecordWorkerPool, subscriptionService, oAuthService, openAIOAuthService, geminiOAuthService, antigravityOAuthService, openAIGatewayService, scheduledTestRunnerService, backupService, paymentOrderExpiryService)
application := &Application{
Server: httpServer,
Cleanup: v,
@@ -289,6 +302,7 @@ func provideCleanup(
openAIGateway *service.OpenAIGatewayService,
scheduledTestRunner *service.ScheduledTestRunnerService,
backupSvc *service.BackupService,
paymentOrderExpiry *service.PaymentOrderExpiryService,
) func() {
return func() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -424,6 +438,12 @@ func provideCleanup(
}
return nil
}},
{"PaymentOrderExpiryService", func() error {
if paymentOrderExpiry != nil {
paymentOrderExpiry.Stop()
}
return nil
}},
}
infraSteps := []cleanupStep{

View File

@@ -75,6 +75,7 @@ func TestProvideCleanup_WithMinimalDependencies_NoPanic(t *testing.T) {
nil, // openAIGateway
nil, // scheduledTestRunner
nil, // backupSvc
nil, // paymentOrderExpiry
)
require.NotPanics(t, func() {

View File

@@ -23,12 +23,16 @@ import (
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/promocode"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/proxy"
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
"github.com/Wei-Shaw/sub2api/ent/securitysecret"
"github.com/Wei-Shaw/sub2api/ent/setting"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
"github.com/Wei-Shaw/sub2api/ent/tlsfingerprintprofile"
"github.com/Wei-Shaw/sub2api/ent/usagecleanuptask"
"github.com/Wei-Shaw/sub2api/ent/usagelog"
@@ -62,6 +66,12 @@ type Client struct {
Group *GroupClient
// IdempotencyRecord is the client for interacting with the IdempotencyRecord builders.
IdempotencyRecord *IdempotencyRecordClient
// PaymentAuditLog is the client for interacting with the PaymentAuditLog builders.
PaymentAuditLog *PaymentAuditLogClient
// PaymentOrder is the client for interacting with the PaymentOrder builders.
PaymentOrder *PaymentOrderClient
// PaymentProviderInstance is the client for interacting with the PaymentProviderInstance builders.
PaymentProviderInstance *PaymentProviderInstanceClient
// PromoCode is the client for interacting with the PromoCode builders.
PromoCode *PromoCodeClient
// PromoCodeUsage is the client for interacting with the PromoCodeUsage builders.
@@ -74,6 +84,8 @@ type Client struct {
SecuritySecret *SecuritySecretClient
// Setting is the client for interacting with the Setting builders.
Setting *SettingClient
// SubscriptionPlan is the client for interacting with the SubscriptionPlan builders.
SubscriptionPlan *SubscriptionPlanClient
// TLSFingerprintProfile is the client for interacting with the TLSFingerprintProfile builders.
TLSFingerprintProfile *TLSFingerprintProfileClient
// UsageCleanupTask is the client for interacting with the UsageCleanupTask builders.
@@ -109,12 +121,16 @@ func (c *Client) init() {
c.ErrorPassthroughRule = NewErrorPassthroughRuleClient(c.config)
c.Group = NewGroupClient(c.config)
c.IdempotencyRecord = NewIdempotencyRecordClient(c.config)
c.PaymentAuditLog = NewPaymentAuditLogClient(c.config)
c.PaymentOrder = NewPaymentOrderClient(c.config)
c.PaymentProviderInstance = NewPaymentProviderInstanceClient(c.config)
c.PromoCode = NewPromoCodeClient(c.config)
c.PromoCodeUsage = NewPromoCodeUsageClient(c.config)
c.Proxy = NewProxyClient(c.config)
c.RedeemCode = NewRedeemCodeClient(c.config)
c.SecuritySecret = NewSecuritySecretClient(c.config)
c.Setting = NewSettingClient(c.config)
c.SubscriptionPlan = NewSubscriptionPlanClient(c.config)
c.TLSFingerprintProfile = NewTLSFingerprintProfileClient(c.config)
c.UsageCleanupTask = NewUsageCleanupTaskClient(c.config)
c.UsageLog = NewUsageLogClient(c.config)
@@ -223,12 +239,16 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
Group: NewGroupClient(cfg),
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
PaymentOrder: NewPaymentOrderClient(cfg),
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
PromoCode: NewPromoCodeClient(cfg),
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
Proxy: NewProxyClient(cfg),
RedeemCode: NewRedeemCodeClient(cfg),
SecuritySecret: NewSecuritySecretClient(cfg),
Setting: NewSettingClient(cfg),
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
UsageLog: NewUsageLogClient(cfg),
@@ -264,12 +284,16 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
ErrorPassthroughRule: NewErrorPassthroughRuleClient(cfg),
Group: NewGroupClient(cfg),
IdempotencyRecord: NewIdempotencyRecordClient(cfg),
PaymentAuditLog: NewPaymentAuditLogClient(cfg),
PaymentOrder: NewPaymentOrderClient(cfg),
PaymentProviderInstance: NewPaymentProviderInstanceClient(cfg),
PromoCode: NewPromoCodeClient(cfg),
PromoCodeUsage: NewPromoCodeUsageClient(cfg),
Proxy: NewProxyClient(cfg),
RedeemCode: NewRedeemCodeClient(cfg),
SecuritySecret: NewSecuritySecretClient(cfg),
Setting: NewSettingClient(cfg),
SubscriptionPlan: NewSubscriptionPlanClient(cfg),
TLSFingerprintProfile: NewTLSFingerprintProfileClient(cfg),
UsageCleanupTask: NewUsageCleanupTaskClient(cfg),
UsageLog: NewUsageLogClient(cfg),
@@ -308,8 +332,9 @@ func (c *Client) Close() error {
func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...Hook) }{
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PromoCode,
c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting,
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PaymentAuditLog,
c.PaymentOrder, c.PaymentProviderInstance, c.PromoCode, c.PromoCodeUsage,
c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, c.SubscriptionPlan,
c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog, c.User,
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
c.UserSubscription,
@@ -323,8 +348,9 @@ func (c *Client) Use(hooks ...Hook) {
func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...Interceptor) }{
c.APIKey, c.Account, c.AccountGroup, c.Announcement, c.AnnouncementRead,
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PromoCode,
c.PromoCodeUsage, c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting,
c.ErrorPassthroughRule, c.Group, c.IdempotencyRecord, c.PaymentAuditLog,
c.PaymentOrder, c.PaymentProviderInstance, c.PromoCode, c.PromoCodeUsage,
c.Proxy, c.RedeemCode, c.SecuritySecret, c.Setting, c.SubscriptionPlan,
c.TLSFingerprintProfile, c.UsageCleanupTask, c.UsageLog, c.User,
c.UserAllowedGroup, c.UserAttributeDefinition, c.UserAttributeValue,
c.UserSubscription,
@@ -352,6 +378,12 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.Group.mutate(ctx, m)
case *IdempotencyRecordMutation:
return c.IdempotencyRecord.mutate(ctx, m)
case *PaymentAuditLogMutation:
return c.PaymentAuditLog.mutate(ctx, m)
case *PaymentOrderMutation:
return c.PaymentOrder.mutate(ctx, m)
case *PaymentProviderInstanceMutation:
return c.PaymentProviderInstance.mutate(ctx, m)
case *PromoCodeMutation:
return c.PromoCode.mutate(ctx, m)
case *PromoCodeUsageMutation:
@@ -364,6 +396,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.SecuritySecret.mutate(ctx, m)
case *SettingMutation:
return c.Setting.mutate(ctx, m)
case *SubscriptionPlanMutation:
return c.SubscriptionPlan.mutate(ctx, m)
case *TLSFingerprintProfileMutation:
return c.TLSFingerprintProfile.mutate(ctx, m)
case *UsageCleanupTaskMutation:
@@ -1726,6 +1760,421 @@ func (c *IdempotencyRecordClient) mutate(ctx context.Context, m *IdempotencyReco
}
}
// PaymentAuditLogClient is a client for the PaymentAuditLog schema.
type PaymentAuditLogClient struct {
config
}
// NewPaymentAuditLogClient returns a client for the PaymentAuditLog from the given config.
func NewPaymentAuditLogClient(c config) *PaymentAuditLogClient {
return &PaymentAuditLogClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `paymentauditlog.Hooks(f(g(h())))`.
func (c *PaymentAuditLogClient) Use(hooks ...Hook) {
c.hooks.PaymentAuditLog = append(c.hooks.PaymentAuditLog, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `paymentauditlog.Intercept(f(g(h())))`.
func (c *PaymentAuditLogClient) Intercept(interceptors ...Interceptor) {
c.inters.PaymentAuditLog = append(c.inters.PaymentAuditLog, interceptors...)
}
// Create returns a builder for creating a PaymentAuditLog entity.
func (c *PaymentAuditLogClient) Create() *PaymentAuditLogCreate {
mutation := newPaymentAuditLogMutation(c.config, OpCreate)
return &PaymentAuditLogCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of PaymentAuditLog entities.
func (c *PaymentAuditLogClient) CreateBulk(builders ...*PaymentAuditLogCreate) *PaymentAuditLogCreateBulk {
return &PaymentAuditLogCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *PaymentAuditLogClient) MapCreateBulk(slice any, setFunc func(*PaymentAuditLogCreate, int)) *PaymentAuditLogCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &PaymentAuditLogCreateBulk{err: fmt.Errorf("calling to PaymentAuditLogClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*PaymentAuditLogCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &PaymentAuditLogCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for PaymentAuditLog.
func (c *PaymentAuditLogClient) Update() *PaymentAuditLogUpdate {
mutation := newPaymentAuditLogMutation(c.config, OpUpdate)
return &PaymentAuditLogUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *PaymentAuditLogClient) UpdateOne(_m *PaymentAuditLog) *PaymentAuditLogUpdateOne {
mutation := newPaymentAuditLogMutation(c.config, OpUpdateOne, withPaymentAuditLog(_m))
return &PaymentAuditLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *PaymentAuditLogClient) UpdateOneID(id int64) *PaymentAuditLogUpdateOne {
mutation := newPaymentAuditLogMutation(c.config, OpUpdateOne, withPaymentAuditLogID(id))
return &PaymentAuditLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for PaymentAuditLog.
func (c *PaymentAuditLogClient) Delete() *PaymentAuditLogDelete {
mutation := newPaymentAuditLogMutation(c.config, OpDelete)
return &PaymentAuditLogDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *PaymentAuditLogClient) DeleteOne(_m *PaymentAuditLog) *PaymentAuditLogDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *PaymentAuditLogClient) DeleteOneID(id int64) *PaymentAuditLogDeleteOne {
builder := c.Delete().Where(paymentauditlog.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &PaymentAuditLogDeleteOne{builder}
}
// Query returns a query builder for PaymentAuditLog.
func (c *PaymentAuditLogClient) Query() *PaymentAuditLogQuery {
return &PaymentAuditLogQuery{
config: c.config,
ctx: &QueryContext{Type: TypePaymentAuditLog},
inters: c.Interceptors(),
}
}
// Get returns a PaymentAuditLog entity by its id.
func (c *PaymentAuditLogClient) Get(ctx context.Context, id int64) (*PaymentAuditLog, error) {
return c.Query().Where(paymentauditlog.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *PaymentAuditLogClient) GetX(ctx context.Context, id int64) *PaymentAuditLog {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *PaymentAuditLogClient) Hooks() []Hook {
return c.hooks.PaymentAuditLog
}
// Interceptors returns the client interceptors.
func (c *PaymentAuditLogClient) Interceptors() []Interceptor {
return c.inters.PaymentAuditLog
}
func (c *PaymentAuditLogClient) mutate(ctx context.Context, m *PaymentAuditLogMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&PaymentAuditLogCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&PaymentAuditLogUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&PaymentAuditLogUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&PaymentAuditLogDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown PaymentAuditLog mutation op: %q", m.Op())
}
}
// PaymentOrderClient is a client for the PaymentOrder schema.
type PaymentOrderClient struct {
config
}
// NewPaymentOrderClient returns a client for the PaymentOrder from the given config.
func NewPaymentOrderClient(c config) *PaymentOrderClient {
return &PaymentOrderClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `paymentorder.Hooks(f(g(h())))`.
func (c *PaymentOrderClient) Use(hooks ...Hook) {
c.hooks.PaymentOrder = append(c.hooks.PaymentOrder, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `paymentorder.Intercept(f(g(h())))`.
func (c *PaymentOrderClient) Intercept(interceptors ...Interceptor) {
c.inters.PaymentOrder = append(c.inters.PaymentOrder, interceptors...)
}
// Create returns a builder for creating a PaymentOrder entity.
func (c *PaymentOrderClient) Create() *PaymentOrderCreate {
mutation := newPaymentOrderMutation(c.config, OpCreate)
return &PaymentOrderCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of PaymentOrder entities.
func (c *PaymentOrderClient) CreateBulk(builders ...*PaymentOrderCreate) *PaymentOrderCreateBulk {
return &PaymentOrderCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *PaymentOrderClient) MapCreateBulk(slice any, setFunc func(*PaymentOrderCreate, int)) *PaymentOrderCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &PaymentOrderCreateBulk{err: fmt.Errorf("calling to PaymentOrderClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*PaymentOrderCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &PaymentOrderCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for PaymentOrder.
func (c *PaymentOrderClient) Update() *PaymentOrderUpdate {
mutation := newPaymentOrderMutation(c.config, OpUpdate)
return &PaymentOrderUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *PaymentOrderClient) UpdateOne(_m *PaymentOrder) *PaymentOrderUpdateOne {
mutation := newPaymentOrderMutation(c.config, OpUpdateOne, withPaymentOrder(_m))
return &PaymentOrderUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *PaymentOrderClient) UpdateOneID(id int64) *PaymentOrderUpdateOne {
mutation := newPaymentOrderMutation(c.config, OpUpdateOne, withPaymentOrderID(id))
return &PaymentOrderUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for PaymentOrder.
func (c *PaymentOrderClient) Delete() *PaymentOrderDelete {
mutation := newPaymentOrderMutation(c.config, OpDelete)
return &PaymentOrderDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *PaymentOrderClient) DeleteOne(_m *PaymentOrder) *PaymentOrderDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *PaymentOrderClient) DeleteOneID(id int64) *PaymentOrderDeleteOne {
builder := c.Delete().Where(paymentorder.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &PaymentOrderDeleteOne{builder}
}
// Query returns a query builder for PaymentOrder.
func (c *PaymentOrderClient) Query() *PaymentOrderQuery {
return &PaymentOrderQuery{
config: c.config,
ctx: &QueryContext{Type: TypePaymentOrder},
inters: c.Interceptors(),
}
}
// Get returns a PaymentOrder entity by its id.
func (c *PaymentOrderClient) Get(ctx context.Context, id int64) (*PaymentOrder, error) {
return c.Query().Where(paymentorder.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *PaymentOrderClient) GetX(ctx context.Context, id int64) *PaymentOrder {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUser queries the user edge of a PaymentOrder.
func (c *PaymentOrderClient) QueryUser(_m *PaymentOrder) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(paymentorder.Table, paymentorder.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, paymentorder.UserTable, paymentorder.UserColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *PaymentOrderClient) Hooks() []Hook {
return c.hooks.PaymentOrder
}
// Interceptors returns the client interceptors.
func (c *PaymentOrderClient) Interceptors() []Interceptor {
return c.inters.PaymentOrder
}
func (c *PaymentOrderClient) mutate(ctx context.Context, m *PaymentOrderMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&PaymentOrderCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&PaymentOrderUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&PaymentOrderUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&PaymentOrderDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown PaymentOrder mutation op: %q", m.Op())
}
}
// PaymentProviderInstanceClient is a client for the PaymentProviderInstance schema.
type PaymentProviderInstanceClient struct {
config
}
// NewPaymentProviderInstanceClient returns a client for the PaymentProviderInstance from the given config.
func NewPaymentProviderInstanceClient(c config) *PaymentProviderInstanceClient {
return &PaymentProviderInstanceClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `paymentproviderinstance.Hooks(f(g(h())))`.
func (c *PaymentProviderInstanceClient) Use(hooks ...Hook) {
c.hooks.PaymentProviderInstance = append(c.hooks.PaymentProviderInstance, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `paymentproviderinstance.Intercept(f(g(h())))`.
func (c *PaymentProviderInstanceClient) Intercept(interceptors ...Interceptor) {
c.inters.PaymentProviderInstance = append(c.inters.PaymentProviderInstance, interceptors...)
}
// Create returns a builder for creating a PaymentProviderInstance entity.
func (c *PaymentProviderInstanceClient) Create() *PaymentProviderInstanceCreate {
mutation := newPaymentProviderInstanceMutation(c.config, OpCreate)
return &PaymentProviderInstanceCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of PaymentProviderInstance entities.
func (c *PaymentProviderInstanceClient) CreateBulk(builders ...*PaymentProviderInstanceCreate) *PaymentProviderInstanceCreateBulk {
return &PaymentProviderInstanceCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *PaymentProviderInstanceClient) MapCreateBulk(slice any, setFunc func(*PaymentProviderInstanceCreate, int)) *PaymentProviderInstanceCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &PaymentProviderInstanceCreateBulk{err: fmt.Errorf("calling to PaymentProviderInstanceClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*PaymentProviderInstanceCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &PaymentProviderInstanceCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for PaymentProviderInstance.
func (c *PaymentProviderInstanceClient) Update() *PaymentProviderInstanceUpdate {
mutation := newPaymentProviderInstanceMutation(c.config, OpUpdate)
return &PaymentProviderInstanceUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *PaymentProviderInstanceClient) UpdateOne(_m *PaymentProviderInstance) *PaymentProviderInstanceUpdateOne {
mutation := newPaymentProviderInstanceMutation(c.config, OpUpdateOne, withPaymentProviderInstance(_m))
return &PaymentProviderInstanceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *PaymentProviderInstanceClient) UpdateOneID(id int64) *PaymentProviderInstanceUpdateOne {
mutation := newPaymentProviderInstanceMutation(c.config, OpUpdateOne, withPaymentProviderInstanceID(id))
return &PaymentProviderInstanceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for PaymentProviderInstance.
func (c *PaymentProviderInstanceClient) Delete() *PaymentProviderInstanceDelete {
mutation := newPaymentProviderInstanceMutation(c.config, OpDelete)
return &PaymentProviderInstanceDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *PaymentProviderInstanceClient) DeleteOne(_m *PaymentProviderInstance) *PaymentProviderInstanceDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *PaymentProviderInstanceClient) DeleteOneID(id int64) *PaymentProviderInstanceDeleteOne {
builder := c.Delete().Where(paymentproviderinstance.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &PaymentProviderInstanceDeleteOne{builder}
}
// Query returns a query builder for PaymentProviderInstance.
func (c *PaymentProviderInstanceClient) Query() *PaymentProviderInstanceQuery {
return &PaymentProviderInstanceQuery{
config: c.config,
ctx: &QueryContext{Type: TypePaymentProviderInstance},
inters: c.Interceptors(),
}
}
// Get returns a PaymentProviderInstance entity by its id.
func (c *PaymentProviderInstanceClient) Get(ctx context.Context, id int64) (*PaymentProviderInstance, error) {
return c.Query().Where(paymentproviderinstance.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *PaymentProviderInstanceClient) GetX(ctx context.Context, id int64) *PaymentProviderInstance {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *PaymentProviderInstanceClient) Hooks() []Hook {
return c.hooks.PaymentProviderInstance
}
// Interceptors returns the client interceptors.
func (c *PaymentProviderInstanceClient) Interceptors() []Interceptor {
return c.inters.PaymentProviderInstance
}
func (c *PaymentProviderInstanceClient) mutate(ctx context.Context, m *PaymentProviderInstanceMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&PaymentProviderInstanceCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&PaymentProviderInstanceUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&PaymentProviderInstanceUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&PaymentProviderInstanceDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown PaymentProviderInstance mutation op: %q", m.Op())
}
}
// PromoCodeClient is a client for the PromoCode schema.
type PromoCodeClient struct {
config
@@ -2622,6 +3071,139 @@ func (c *SettingClient) mutate(ctx context.Context, m *SettingMutation) (Value,
}
}
// SubscriptionPlanClient is a client for the SubscriptionPlan schema.
type SubscriptionPlanClient struct {
config
}
// NewSubscriptionPlanClient returns a client for the SubscriptionPlan from the given config.
func NewSubscriptionPlanClient(c config) *SubscriptionPlanClient {
return &SubscriptionPlanClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `subscriptionplan.Hooks(f(g(h())))`.
func (c *SubscriptionPlanClient) Use(hooks ...Hook) {
c.hooks.SubscriptionPlan = append(c.hooks.SubscriptionPlan, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `subscriptionplan.Intercept(f(g(h())))`.
func (c *SubscriptionPlanClient) Intercept(interceptors ...Interceptor) {
c.inters.SubscriptionPlan = append(c.inters.SubscriptionPlan, interceptors...)
}
// Create returns a builder for creating a SubscriptionPlan entity.
func (c *SubscriptionPlanClient) Create() *SubscriptionPlanCreate {
mutation := newSubscriptionPlanMutation(c.config, OpCreate)
return &SubscriptionPlanCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of SubscriptionPlan entities.
func (c *SubscriptionPlanClient) CreateBulk(builders ...*SubscriptionPlanCreate) *SubscriptionPlanCreateBulk {
return &SubscriptionPlanCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *SubscriptionPlanClient) MapCreateBulk(slice any, setFunc func(*SubscriptionPlanCreate, int)) *SubscriptionPlanCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &SubscriptionPlanCreateBulk{err: fmt.Errorf("calling to SubscriptionPlanClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*SubscriptionPlanCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &SubscriptionPlanCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for SubscriptionPlan.
func (c *SubscriptionPlanClient) Update() *SubscriptionPlanUpdate {
mutation := newSubscriptionPlanMutation(c.config, OpUpdate)
return &SubscriptionPlanUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *SubscriptionPlanClient) UpdateOne(_m *SubscriptionPlan) *SubscriptionPlanUpdateOne {
mutation := newSubscriptionPlanMutation(c.config, OpUpdateOne, withSubscriptionPlan(_m))
return &SubscriptionPlanUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *SubscriptionPlanClient) UpdateOneID(id int64) *SubscriptionPlanUpdateOne {
mutation := newSubscriptionPlanMutation(c.config, OpUpdateOne, withSubscriptionPlanID(id))
return &SubscriptionPlanUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for SubscriptionPlan.
func (c *SubscriptionPlanClient) Delete() *SubscriptionPlanDelete {
mutation := newSubscriptionPlanMutation(c.config, OpDelete)
return &SubscriptionPlanDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *SubscriptionPlanClient) DeleteOne(_m *SubscriptionPlan) *SubscriptionPlanDeleteOne {
return c.DeleteOneID(_m.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *SubscriptionPlanClient) DeleteOneID(id int64) *SubscriptionPlanDeleteOne {
builder := c.Delete().Where(subscriptionplan.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &SubscriptionPlanDeleteOne{builder}
}
// Query returns a query builder for SubscriptionPlan.
func (c *SubscriptionPlanClient) Query() *SubscriptionPlanQuery {
return &SubscriptionPlanQuery{
config: c.config,
ctx: &QueryContext{Type: TypeSubscriptionPlan},
inters: c.Interceptors(),
}
}
// Get returns a SubscriptionPlan entity by its id.
func (c *SubscriptionPlanClient) Get(ctx context.Context, id int64) (*SubscriptionPlan, error) {
return c.Query().Where(subscriptionplan.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *SubscriptionPlanClient) GetX(ctx context.Context, id int64) *SubscriptionPlan {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *SubscriptionPlanClient) Hooks() []Hook {
return c.hooks.SubscriptionPlan
}
// Interceptors returns the client interceptors.
func (c *SubscriptionPlanClient) Interceptors() []Interceptor {
return c.inters.SubscriptionPlan
}
func (c *SubscriptionPlanClient) mutate(ctx context.Context, m *SubscriptionPlanMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&SubscriptionPlanCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&SubscriptionPlanUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&SubscriptionPlanUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&SubscriptionPlanDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown SubscriptionPlan mutation op: %q", m.Op())
}
}
// TLSFingerprintProfileClient is a client for the TLSFingerprintProfile schema.
type TLSFingerprintProfileClient struct {
config
@@ -3353,6 +3935,22 @@ func (c *UserClient) QueryPromoCodeUsages(_m *User) *PromoCodeUsageQuery {
return query
}
// QueryPaymentOrders queries the payment_orders edge of a User.
func (c *UserClient) QueryPaymentOrders(_m *User) *PaymentOrderQuery {
query := (&PaymentOrderClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := _m.ID
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, id),
sqlgraph.To(paymentorder.Table, paymentorder.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, user.PaymentOrdersTable, user.PaymentOrdersColumn),
)
fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryUserAllowedGroups queries the user_allowed_groups edge of a User.
func (c *UserClient) QueryUserAllowedGroups(_m *User) *UserAllowedGroupQuery {
query := (&UserAllowedGroupClient{config: c.config}).Query()
@@ -4031,15 +4629,17 @@ func (c *UserSubscriptionClient) mutate(ctx context.Context, m *UserSubscription
type (
hooks struct {
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
ErrorPassthroughRule, Group, IdempotencyRecord, PromoCode, PromoCodeUsage,
Proxy, RedeemCode, SecuritySecret, Setting, TLSFingerprintProfile,
ErrorPassthroughRule, Group, IdempotencyRecord, PaymentAuditLog, PaymentOrder,
PaymentProviderInstance, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition,
UserAttributeValue, UserSubscription []ent.Hook
}
inters struct {
APIKey, Account, AccountGroup, Announcement, AnnouncementRead,
ErrorPassthroughRule, Group, IdempotencyRecord, PromoCode, PromoCodeUsage,
Proxy, RedeemCode, SecuritySecret, Setting, TLSFingerprintProfile,
ErrorPassthroughRule, Group, IdempotencyRecord, PaymentAuditLog, PaymentOrder,
PaymentProviderInstance, PromoCode, PromoCodeUsage, Proxy, RedeemCode,
SecuritySecret, Setting, SubscriptionPlan, TLSFingerprintProfile,
UsageCleanupTask, UsageLog, User, UserAllowedGroup, UserAttributeDefinition,
UserAttributeValue, UserSubscription []ent.Interceptor
}

View File

@@ -20,12 +20,16 @@ import (
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/promocode"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/proxy"
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
"github.com/Wei-Shaw/sub2api/ent/securitysecret"
"github.com/Wei-Shaw/sub2api/ent/setting"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
"github.com/Wei-Shaw/sub2api/ent/tlsfingerprintprofile"
"github.com/Wei-Shaw/sub2api/ent/usagecleanuptask"
"github.com/Wei-Shaw/sub2api/ent/usagelog"
@@ -102,12 +106,16 @@ func checkColumn(t, c string) error {
errorpassthroughrule.Table: errorpassthroughrule.ValidColumn,
group.Table: group.ValidColumn,
idempotencyrecord.Table: idempotencyrecord.ValidColumn,
paymentauditlog.Table: paymentauditlog.ValidColumn,
paymentorder.Table: paymentorder.ValidColumn,
paymentproviderinstance.Table: paymentproviderinstance.ValidColumn,
promocode.Table: promocode.ValidColumn,
promocodeusage.Table: promocodeusage.ValidColumn,
proxy.Table: proxy.ValidColumn,
redeemcode.Table: redeemcode.ValidColumn,
securitysecret.Table: securitysecret.ValidColumn,
setting.Table: setting.ValidColumn,
subscriptionplan.Table: subscriptionplan.ValidColumn,
tlsfingerprintprofile.Table: tlsfingerprintprofile.ValidColumn,
usagecleanuptask.Table: usagecleanuptask.ValidColumn,
usagelog.Table: usagelog.ValidColumn,

View File

@@ -11,6 +11,7 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
// Group is the model entity for the Group schema.
@@ -76,6 +77,8 @@ type Group struct {
RequirePrivacySet bool `json:"require_privacy_set,omitempty"`
// 默认映射模型 ID当账号级映射找不到时使用此值
DefaultMappedModel string `json:"default_mapped_model,omitempty"`
// OpenAI Messages 调度模型配置:按 Claude 系列/精确模型映射到目标 GPT 模型
MessagesDispatchModelConfig domain.OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the GroupQuery when eager-loading is set.
Edges GroupEdges `json:"edges"`
@@ -182,7 +185,7 @@ func (*Group) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case group.FieldModelRouting, group.FieldSupportedModelScopes:
case group.FieldModelRouting, group.FieldSupportedModelScopes, group.FieldMessagesDispatchModelConfig:
values[i] = new([]byte)
case group.FieldIsExclusive, group.FieldClaudeCodeOnly, group.FieldModelRoutingEnabled, group.FieldMcpXMLInject, group.FieldAllowMessagesDispatch, group.FieldRequireOauthOnly, group.FieldRequirePrivacySet:
values[i] = new(sql.NullBool)
@@ -403,6 +406,14 @@ func (_m *Group) assignValues(columns []string, values []any) error {
} else if value.Valid {
_m.DefaultMappedModel = value.String
}
case group.FieldMessagesDispatchModelConfig:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field messages_dispatch_model_config", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &_m.MessagesDispatchModelConfig); err != nil {
return fmt.Errorf("unmarshal field messages_dispatch_model_config: %w", err)
}
}
default:
_m.selectValues.Set(columns[i], values[i])
}
@@ -585,6 +596,9 @@ func (_m *Group) String() string {
builder.WriteString(", ")
builder.WriteString("default_mapped_model=")
builder.WriteString(_m.DefaultMappedModel)
builder.WriteString(", ")
builder.WriteString("messages_dispatch_model_config=")
builder.WriteString(fmt.Sprintf("%v", _m.MessagesDispatchModelConfig))
builder.WriteByte(')')
return builder.String()
}

View File

@@ -8,6 +8,7 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
const (
@@ -73,6 +74,8 @@ const (
FieldRequirePrivacySet = "require_privacy_set"
// FieldDefaultMappedModel holds the string denoting the default_mapped_model field in the database.
FieldDefaultMappedModel = "default_mapped_model"
// FieldMessagesDispatchModelConfig holds the string denoting the messages_dispatch_model_config field in the database.
FieldMessagesDispatchModelConfig = "messages_dispatch_model_config"
// EdgeAPIKeys holds the string denoting the api_keys edge name in mutations.
EdgeAPIKeys = "api_keys"
// EdgeRedeemCodes holds the string denoting the redeem_codes edge name in mutations.
@@ -177,6 +180,7 @@ var Columns = []string{
FieldRequireOauthOnly,
FieldRequirePrivacySet,
FieldDefaultMappedModel,
FieldMessagesDispatchModelConfig,
}
var (
@@ -252,6 +256,8 @@ var (
DefaultDefaultMappedModel string
// DefaultMappedModelValidator is a validator for the "default_mapped_model" field. It is called by the builders before save.
DefaultMappedModelValidator func(string) error
// DefaultMessagesDispatchModelConfig holds the default value on creation for the "messages_dispatch_model_config" field.
DefaultMessagesDispatchModelConfig domain.OpenAIMessagesDispatchModelConfig
)
// OrderOption defines the ordering options for the Group queries.

View File

@@ -18,6 +18,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/usagelog"
"github.com/Wei-Shaw/sub2api/ent/user"
"github.com/Wei-Shaw/sub2api/ent/usersubscription"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
// GroupCreate is the builder for creating a Group entity.
@@ -410,6 +411,20 @@ func (_c *GroupCreate) SetNillableDefaultMappedModel(v *string) *GroupCreate {
return _c
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (_c *GroupCreate) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupCreate {
_c.mutation.SetMessagesDispatchModelConfig(v)
return _c
}
// SetNillableMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field if the given value is not nil.
func (_c *GroupCreate) SetNillableMessagesDispatchModelConfig(v *domain.OpenAIMessagesDispatchModelConfig) *GroupCreate {
if v != nil {
_c.SetMessagesDispatchModelConfig(*v)
}
return _c
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_c *GroupCreate) AddAPIKeyIDs(ids ...int64) *GroupCreate {
_c.mutation.AddAPIKeyIDs(ids...)
@@ -611,6 +626,10 @@ func (_c *GroupCreate) defaults() error {
v := group.DefaultDefaultMappedModel
_c.mutation.SetDefaultMappedModel(v)
}
if _, ok := _c.mutation.MessagesDispatchModelConfig(); !ok {
v := group.DefaultMessagesDispatchModelConfig
_c.mutation.SetMessagesDispatchModelConfig(v)
}
return nil
}
@@ -695,6 +714,9 @@ func (_c *GroupCreate) check() error {
return &ValidationError{Name: "default_mapped_model", err: fmt.Errorf(`ent: validator failed for field "Group.default_mapped_model": %w`, err)}
}
}
if _, ok := _c.mutation.MessagesDispatchModelConfig(); !ok {
return &ValidationError{Name: "messages_dispatch_model_config", err: errors.New(`ent: missing required field "Group.messages_dispatch_model_config"`)}
}
return nil
}
@@ -838,6 +860,10 @@ func (_c *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
_spec.SetField(group.FieldDefaultMappedModel, field.TypeString, value)
_node.DefaultMappedModel = value
}
if value, ok := _c.mutation.MessagesDispatchModelConfig(); ok {
_spec.SetField(group.FieldMessagesDispatchModelConfig, field.TypeJSON, value)
_node.MessagesDispatchModelConfig = value
}
if nodes := _c.mutation.APIKeysIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
@@ -1462,6 +1488,18 @@ func (u *GroupUpsert) UpdateDefaultMappedModel() *GroupUpsert {
return u
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (u *GroupUpsert) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupUpsert {
u.Set(group.FieldMessagesDispatchModelConfig, v)
return u
}
// UpdateMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field to the value that was provided on create.
func (u *GroupUpsert) UpdateMessagesDispatchModelConfig() *GroupUpsert {
u.SetExcluded(group.FieldMessagesDispatchModelConfig)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
@@ -2053,6 +2091,20 @@ func (u *GroupUpsertOne) UpdateDefaultMappedModel() *GroupUpsertOne {
})
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (u *GroupUpsertOne) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.SetMessagesDispatchModelConfig(v)
})
}
// UpdateMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field to the value that was provided on create.
func (u *GroupUpsertOne) UpdateMessagesDispatchModelConfig() *GroupUpsertOne {
return u.Update(func(s *GroupUpsert) {
s.UpdateMessagesDispatchModelConfig()
})
}
// Exec executes the query.
func (u *GroupUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
@@ -2810,6 +2862,20 @@ func (u *GroupUpsertBulk) UpdateDefaultMappedModel() *GroupUpsertBulk {
})
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (u *GroupUpsertBulk) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.SetMessagesDispatchModelConfig(v)
})
}
// UpdateMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field to the value that was provided on create.
func (u *GroupUpsertBulk) UpdateMessagesDispatchModelConfig() *GroupUpsertBulk {
return u.Update(func(s *GroupUpsert) {
s.UpdateMessagesDispatchModelConfig()
})
}
// Exec executes the query.
func (u *GroupUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {

View File

@@ -20,6 +20,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/usagelog"
"github.com/Wei-Shaw/sub2api/ent/user"
"github.com/Wei-Shaw/sub2api/ent/usersubscription"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
// GroupUpdate is the builder for updating Group entities.
@@ -552,6 +553,20 @@ func (_u *GroupUpdate) SetNillableDefaultMappedModel(v *string) *GroupUpdate {
return _u
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (_u *GroupUpdate) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupUpdate {
_u.mutation.SetMessagesDispatchModelConfig(v)
return _u
}
// SetNillableMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field if the given value is not nil.
func (_u *GroupUpdate) SetNillableMessagesDispatchModelConfig(v *domain.OpenAIMessagesDispatchModelConfig) *GroupUpdate {
if v != nil {
_u.SetMessagesDispatchModelConfig(*v)
}
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdate) AddAPIKeyIDs(ids ...int64) *GroupUpdate {
_u.mutation.AddAPIKeyIDs(ids...)
@@ -1012,6 +1027,9 @@ func (_u *GroupUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if value, ok := _u.mutation.DefaultMappedModel(); ok {
_spec.SetField(group.FieldDefaultMappedModel, field.TypeString, value)
}
if value, ok := _u.mutation.MessagesDispatchModelConfig(); ok {
_spec.SetField(group.FieldMessagesDispatchModelConfig, field.TypeJSON, value)
}
if _u.mutation.APIKeysCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
@@ -1843,6 +1861,20 @@ func (_u *GroupUpdateOne) SetNillableDefaultMappedModel(v *string) *GroupUpdateO
return _u
}
// SetMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field.
func (_u *GroupUpdateOne) SetMessagesDispatchModelConfig(v domain.OpenAIMessagesDispatchModelConfig) *GroupUpdateOne {
_u.mutation.SetMessagesDispatchModelConfig(v)
return _u
}
// SetNillableMessagesDispatchModelConfig sets the "messages_dispatch_model_config" field if the given value is not nil.
func (_u *GroupUpdateOne) SetNillableMessagesDispatchModelConfig(v *domain.OpenAIMessagesDispatchModelConfig) *GroupUpdateOne {
if v != nil {
_u.SetMessagesDispatchModelConfig(*v)
}
return _u
}
// AddAPIKeyIDs adds the "api_keys" edge to the APIKey entity by IDs.
func (_u *GroupUpdateOne) AddAPIKeyIDs(ids ...int64) *GroupUpdateOne {
_u.mutation.AddAPIKeyIDs(ids...)
@@ -2333,6 +2365,9 @@ func (_u *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error)
if value, ok := _u.mutation.DefaultMappedModel(); ok {
_spec.SetField(group.FieldDefaultMappedModel, field.TypeString, value)
}
if value, ok := _u.mutation.MessagesDispatchModelConfig(); ok {
_spec.SetField(group.FieldMessagesDispatchModelConfig, field.TypeJSON, value)
}
if _u.mutation.APIKeysCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,

View File

@@ -105,6 +105,42 @@ func (f IdempotencyRecordFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IdempotencyRecordMutation", m)
}
// The PaymentAuditLogFunc type is an adapter to allow the use of ordinary
// function as PaymentAuditLog mutator.
type PaymentAuditLogFunc func(context.Context, *ent.PaymentAuditLogMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f PaymentAuditLogFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.PaymentAuditLogMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PaymentAuditLogMutation", m)
}
// The PaymentOrderFunc type is an adapter to allow the use of ordinary
// function as PaymentOrder mutator.
type PaymentOrderFunc func(context.Context, *ent.PaymentOrderMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f PaymentOrderFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.PaymentOrderMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PaymentOrderMutation", m)
}
// The PaymentProviderInstanceFunc type is an adapter to allow the use of ordinary
// function as PaymentProviderInstance mutator.
type PaymentProviderInstanceFunc func(context.Context, *ent.PaymentProviderInstanceMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f PaymentProviderInstanceFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.PaymentProviderInstanceMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PaymentProviderInstanceMutation", m)
}
// The PromoCodeFunc type is an adapter to allow the use of ordinary
// function as PromoCode mutator.
type PromoCodeFunc func(context.Context, *ent.PromoCodeMutation) (ent.Value, error)
@@ -177,6 +213,18 @@ func (f SettingFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, err
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.SettingMutation", m)
}
// The SubscriptionPlanFunc type is an adapter to allow the use of ordinary
// function as SubscriptionPlan mutator.
type SubscriptionPlanFunc func(context.Context, *ent.SubscriptionPlanMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f SubscriptionPlanFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.SubscriptionPlanMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.SubscriptionPlanMutation", m)
}
// The TLSFingerprintProfileFunc type is an adapter to allow the use of ordinary
// function as TLSFingerprintProfile mutator.
type TLSFingerprintProfileFunc func(context.Context, *ent.TLSFingerprintProfileMutation) (ent.Value, error)

View File

@@ -16,6 +16,9 @@ import (
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/promocode"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
@@ -23,6 +26,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
"github.com/Wei-Shaw/sub2api/ent/securitysecret"
"github.com/Wei-Shaw/sub2api/ent/setting"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
"github.com/Wei-Shaw/sub2api/ent/tlsfingerprintprofile"
"github.com/Wei-Shaw/sub2api/ent/usagecleanuptask"
"github.com/Wei-Shaw/sub2api/ent/usagelog"
@@ -305,6 +309,87 @@ func (f TraverseIdempotencyRecord) Traverse(ctx context.Context, q ent.Query) er
return fmt.Errorf("unexpected query type %T. expect *ent.IdempotencyRecordQuery", q)
}
// The PaymentAuditLogFunc type is an adapter to allow the use of ordinary function as a Querier.
type PaymentAuditLogFunc func(context.Context, *ent.PaymentAuditLogQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f PaymentAuditLogFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.PaymentAuditLogQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.PaymentAuditLogQuery", q)
}
// The TraversePaymentAuditLog type is an adapter to allow the use of ordinary function as Traverser.
type TraversePaymentAuditLog func(context.Context, *ent.PaymentAuditLogQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraversePaymentAuditLog) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraversePaymentAuditLog) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.PaymentAuditLogQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.PaymentAuditLogQuery", q)
}
// The PaymentOrderFunc type is an adapter to allow the use of ordinary function as a Querier.
type PaymentOrderFunc func(context.Context, *ent.PaymentOrderQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f PaymentOrderFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.PaymentOrderQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.PaymentOrderQuery", q)
}
// The TraversePaymentOrder type is an adapter to allow the use of ordinary function as Traverser.
type TraversePaymentOrder func(context.Context, *ent.PaymentOrderQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraversePaymentOrder) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraversePaymentOrder) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.PaymentOrderQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.PaymentOrderQuery", q)
}
// The PaymentProviderInstanceFunc type is an adapter to allow the use of ordinary function as a Querier.
type PaymentProviderInstanceFunc func(context.Context, *ent.PaymentProviderInstanceQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f PaymentProviderInstanceFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.PaymentProviderInstanceQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.PaymentProviderInstanceQuery", q)
}
// The TraversePaymentProviderInstance type is an adapter to allow the use of ordinary function as Traverser.
type TraversePaymentProviderInstance func(context.Context, *ent.PaymentProviderInstanceQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraversePaymentProviderInstance) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraversePaymentProviderInstance) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.PaymentProviderInstanceQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.PaymentProviderInstanceQuery", q)
}
// The PromoCodeFunc type is an adapter to allow the use of ordinary function as a Querier.
type PromoCodeFunc func(context.Context, *ent.PromoCodeQuery) (ent.Value, error)
@@ -467,6 +552,33 @@ func (f TraverseSetting) Traverse(ctx context.Context, q ent.Query) error {
return fmt.Errorf("unexpected query type %T. expect *ent.SettingQuery", q)
}
// The SubscriptionPlanFunc type is an adapter to allow the use of ordinary function as a Querier.
type SubscriptionPlanFunc func(context.Context, *ent.SubscriptionPlanQuery) (ent.Value, error)
// Query calls f(ctx, q).
func (f SubscriptionPlanFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
if q, ok := q.(*ent.SubscriptionPlanQuery); ok {
return f(ctx, q)
}
return nil, fmt.Errorf("unexpected query type %T. expect *ent.SubscriptionPlanQuery", q)
}
// The TraverseSubscriptionPlan type is an adapter to allow the use of ordinary function as Traverser.
type TraverseSubscriptionPlan func(context.Context, *ent.SubscriptionPlanQuery) error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func (f TraverseSubscriptionPlan) Intercept(next ent.Querier) ent.Querier {
return next
}
// Traverse calls f(ctx, q).
func (f TraverseSubscriptionPlan) Traverse(ctx context.Context, q ent.Query) error {
if q, ok := q.(*ent.SubscriptionPlanQuery); ok {
return f(ctx, q)
}
return fmt.Errorf("unexpected query type %T. expect *ent.SubscriptionPlanQuery", q)
}
// The TLSFingerprintProfileFunc type is an adapter to allow the use of ordinary function as a Querier.
type TLSFingerprintProfileFunc func(context.Context, *ent.TLSFingerprintProfileQuery) (ent.Value, error)
@@ -702,6 +814,12 @@ func NewQuery(q ent.Query) (Query, error) {
return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil
case *ent.IdempotencyRecordQuery:
return &query[*ent.IdempotencyRecordQuery, predicate.IdempotencyRecord, idempotencyrecord.OrderOption]{typ: ent.TypeIdempotencyRecord, tq: q}, nil
case *ent.PaymentAuditLogQuery:
return &query[*ent.PaymentAuditLogQuery, predicate.PaymentAuditLog, paymentauditlog.OrderOption]{typ: ent.TypePaymentAuditLog, tq: q}, nil
case *ent.PaymentOrderQuery:
return &query[*ent.PaymentOrderQuery, predicate.PaymentOrder, paymentorder.OrderOption]{typ: ent.TypePaymentOrder, tq: q}, nil
case *ent.PaymentProviderInstanceQuery:
return &query[*ent.PaymentProviderInstanceQuery, predicate.PaymentProviderInstance, paymentproviderinstance.OrderOption]{typ: ent.TypePaymentProviderInstance, tq: q}, nil
case *ent.PromoCodeQuery:
return &query[*ent.PromoCodeQuery, predicate.PromoCode, promocode.OrderOption]{typ: ent.TypePromoCode, tq: q}, nil
case *ent.PromoCodeUsageQuery:
@@ -714,6 +832,8 @@ func NewQuery(q ent.Query) (Query, error) {
return &query[*ent.SecuritySecretQuery, predicate.SecuritySecret, securitysecret.OrderOption]{typ: ent.TypeSecuritySecret, tq: q}, nil
case *ent.SettingQuery:
return &query[*ent.SettingQuery, predicate.Setting, setting.OrderOption]{typ: ent.TypeSetting, tq: q}, nil
case *ent.SubscriptionPlanQuery:
return &query[*ent.SubscriptionPlanQuery, predicate.SubscriptionPlan, subscriptionplan.OrderOption]{typ: ent.TypeSubscriptionPlan, tq: q}, nil
case *ent.TLSFingerprintProfileQuery:
return &query[*ent.TLSFingerprintProfileQuery, predicate.TLSFingerprintProfile, tlsfingerprintprofile.OrderOption]{typ: ent.TypeTLSFingerprintProfile, tq: q}, nil
case *ent.UsageCleanupTaskQuery:

View File

@@ -407,6 +407,7 @@ var (
{Name: "require_oauth_only", Type: field.TypeBool, Default: false},
{Name: "require_privacy_set", Type: field.TypeBool, Default: false},
{Name: "default_mapped_model", Type: field.TypeString, Size: 100, Default: ""},
{Name: "messages_dispatch_model_config", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}},
}
// GroupsTable holds the schema information for the "groups" table.
GroupsTable = &schema.Table{
@@ -484,6 +485,158 @@ var (
},
},
}
// PaymentAuditLogsColumns holds the columns for the "payment_audit_logs" table.
PaymentAuditLogsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "order_id", Type: field.TypeString, Size: 64},
{Name: "action", Type: field.TypeString, Size: 50},
{Name: "detail", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
{Name: "operator", Type: field.TypeString, Size: 100, Default: "system"},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
}
// PaymentAuditLogsTable holds the schema information for the "payment_audit_logs" table.
PaymentAuditLogsTable = &schema.Table{
Name: "payment_audit_logs",
Columns: PaymentAuditLogsColumns,
PrimaryKey: []*schema.Column{PaymentAuditLogsColumns[0]},
Indexes: []*schema.Index{
{
Name: "paymentauditlog_order_id",
Unique: false,
Columns: []*schema.Column{PaymentAuditLogsColumns[1]},
},
},
}
// PaymentOrdersColumns holds the columns for the "payment_orders" table.
PaymentOrdersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "user_email", Type: field.TypeString, Size: 255},
{Name: "user_name", Type: field.TypeString, Size: 100},
{Name: "user_notes", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "amount", Type: field.TypeFloat64, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
{Name: "pay_amount", Type: field.TypeFloat64, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
{Name: "fee_rate", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(10,4)"}},
{Name: "recharge_code", Type: field.TypeString, Size: 64},
{Name: "out_trade_no", Type: field.TypeString, Size: 64, Default: ""},
{Name: "payment_type", Type: field.TypeString, Size: 30},
{Name: "payment_trade_no", Type: field.TypeString, Size: 128},
{Name: "pay_url", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "qr_code", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "qr_code_img", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "order_type", Type: field.TypeString, Size: 20, Default: "balance"},
{Name: "plan_id", Type: field.TypeInt64, Nullable: true},
{Name: "subscription_group_id", Type: field.TypeInt64, Nullable: true},
{Name: "subscription_days", Type: field.TypeInt, Nullable: true},
{Name: "provider_instance_id", Type: field.TypeString, Nullable: true, Size: 64},
{Name: "status", Type: field.TypeString, Size: 30, Default: "PENDING"},
{Name: "refund_amount", Type: field.TypeFloat64, Default: 0, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
{Name: "refund_reason", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "refund_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "force_refund", Type: field.TypeBool, Default: false},
{Name: "refund_requested_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "refund_request_reason", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "refund_requested_by", Type: field.TypeString, Nullable: true, Size: 20},
{Name: "expires_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "paid_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "completed_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "failed_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "failed_reason", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "client_ip", Type: field.TypeString, Size: 50},
{Name: "src_host", Type: field.TypeString, Size: 255},
{Name: "src_url", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "text"}},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "user_id", Type: field.TypeInt64},
}
// PaymentOrdersTable holds the schema information for the "payment_orders" table.
PaymentOrdersTable = &schema.Table{
Name: "payment_orders",
Columns: PaymentOrdersColumns,
PrimaryKey: []*schema.Column{PaymentOrdersColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "payment_orders_users_payment_orders",
Columns: []*schema.Column{PaymentOrdersColumns[37]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
Indexes: []*schema.Index{
{
Name: "paymentorder_out_trade_no",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[8]},
},
{
Name: "paymentorder_user_id",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[37]},
},
{
Name: "paymentorder_status",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[19]},
},
{
Name: "paymentorder_expires_at",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[27]},
},
{
Name: "paymentorder_created_at",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[35]},
},
{
Name: "paymentorder_paid_at",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[28]},
},
{
Name: "paymentorder_payment_type_paid_at",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[9], PaymentOrdersColumns[28]},
},
{
Name: "paymentorder_order_type",
Unique: false,
Columns: []*schema.Column{PaymentOrdersColumns[14]},
},
},
}
// PaymentProviderInstancesColumns holds the columns for the "payment_provider_instances" table.
PaymentProviderInstancesColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "provider_key", Type: field.TypeString, Size: 30},
{Name: "name", Type: field.TypeString, Size: 100, Default: ""},
{Name: "config", Type: field.TypeString, SchemaType: map[string]string{"postgres": "text"}},
{Name: "supported_types", Type: field.TypeString, Size: 200, Default: ""},
{Name: "enabled", Type: field.TypeBool, Default: true},
{Name: "payment_mode", Type: field.TypeString, Size: 20, Default: ""},
{Name: "sort_order", Type: field.TypeInt, Default: 0},
{Name: "limits", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
{Name: "refund_enabled", Type: field.TypeBool, Default: false},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
}
// PaymentProviderInstancesTable holds the schema information for the "payment_provider_instances" table.
PaymentProviderInstancesTable = &schema.Table{
Name: "payment_provider_instances",
Columns: PaymentProviderInstancesColumns,
PrimaryKey: []*schema.Column{PaymentProviderInstancesColumns[0]},
Indexes: []*schema.Index{
{
Name: "paymentproviderinstance_provider_key",
Unique: false,
Columns: []*schema.Column{PaymentProviderInstancesColumns[1]},
},
{
Name: "paymentproviderinstance_enabled",
Unique: false,
Columns: []*schema.Column{PaymentProviderInstancesColumns[5]},
},
},
}
// PromoCodesColumns holds the columns for the "promo_codes" table.
PromoCodesColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
@@ -670,6 +823,41 @@ var (
Columns: SettingsColumns,
PrimaryKey: []*schema.Column{SettingsColumns[0]},
}
// SubscriptionPlansColumns holds the columns for the "subscription_plans" table.
SubscriptionPlansColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
{Name: "group_id", Type: field.TypeInt64},
{Name: "name", Type: field.TypeString, Size: 100},
{Name: "description", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
{Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
{Name: "original_price", Type: field.TypeFloat64, Nullable: true, SchemaType: map[string]string{"postgres": "decimal(20,2)"}},
{Name: "validity_days", Type: field.TypeInt, Default: 30},
{Name: "validity_unit", Type: field.TypeString, Size: 10, Default: "day"},
{Name: "features", Type: field.TypeString, Default: "", SchemaType: map[string]string{"postgres": "text"}},
{Name: "product_name", Type: field.TypeString, Size: 100, Default: ""},
{Name: "for_sale", Type: field.TypeBool, Default: true},
{Name: "sort_order", Type: field.TypeInt, Default: 0},
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamptz"}},
}
// SubscriptionPlansTable holds the schema information for the "subscription_plans" table.
SubscriptionPlansTable = &schema.Table{
Name: "subscription_plans",
Columns: SubscriptionPlansColumns,
PrimaryKey: []*schema.Column{SubscriptionPlansColumns[0]},
Indexes: []*schema.Index{
{
Name: "subscriptionplan_group_id",
Unique: false,
Columns: []*schema.Column{SubscriptionPlansColumns[1]},
},
{
Name: "subscriptionplan_for_sale",
Unique: false,
Columns: []*schema.Column{SubscriptionPlansColumns[10]},
},
},
}
// TLSFingerprintProfilesColumns holds the columns for the "tls_fingerprint_profiles" table.
TLSFingerprintProfilesColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt64, Increment: true},
@@ -1127,12 +1315,16 @@ var (
ErrorPassthroughRulesTable,
GroupsTable,
IdempotencyRecordsTable,
PaymentAuditLogsTable,
PaymentOrdersTable,
PaymentProviderInstancesTable,
PromoCodesTable,
PromoCodeUsagesTable,
ProxiesTable,
RedeemCodesTable,
SecuritySecretsTable,
SettingsTable,
SubscriptionPlansTable,
TLSFingerprintProfilesTable,
UsageCleanupTasksTable,
UsageLogsTable,
@@ -1176,6 +1368,16 @@ func init() {
IdempotencyRecordsTable.Annotation = &entsql.Annotation{
Table: "idempotency_records",
}
PaymentAuditLogsTable.Annotation = &entsql.Annotation{
Table: "payment_audit_logs",
}
PaymentOrdersTable.ForeignKeys[0].RefTable = UsersTable
PaymentOrdersTable.Annotation = &entsql.Annotation{
Table: "payment_orders",
}
PaymentProviderInstancesTable.Annotation = &entsql.Annotation{
Table: "payment_provider_instances",
}
PromoCodesTable.Annotation = &entsql.Annotation{
Table: "promo_codes",
}
@@ -1198,6 +1400,9 @@ func init() {
SettingsTable.Annotation = &entsql.Annotation{
Table: "settings",
}
SubscriptionPlansTable.Annotation = &entsql.Annotation{
Table: "subscription_plans",
}
TLSFingerprintProfilesTable.Annotation = &entsql.Annotation{
Table: "tls_fingerprint_profiles",
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,150 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
)
// PaymentAuditLog is the model entity for the PaymentAuditLog schema.
type PaymentAuditLog struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// OrderID holds the value of the "order_id" field.
OrderID string `json:"order_id,omitempty"`
// Action holds the value of the "action" field.
Action string `json:"action,omitempty"`
// Detail holds the value of the "detail" field.
Detail string `json:"detail,omitempty"`
// Operator holds the value of the "operator" field.
Operator string `json:"operator,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
selectValues sql.SelectValues
}
// scanValues returns the types for scanning values from sql.Rows.
func (*PaymentAuditLog) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case paymentauditlog.FieldID:
values[i] = new(sql.NullInt64)
case paymentauditlog.FieldOrderID, paymentauditlog.FieldAction, paymentauditlog.FieldDetail, paymentauditlog.FieldOperator:
values[i] = new(sql.NullString)
case paymentauditlog.FieldCreatedAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the PaymentAuditLog fields.
func (_m *PaymentAuditLog) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case paymentauditlog.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case paymentauditlog.FieldOrderID:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field order_id", values[i])
} else if value.Valid {
_m.OrderID = value.String
}
case paymentauditlog.FieldAction:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field action", values[i])
} else if value.Valid {
_m.Action = value.String
}
case paymentauditlog.FieldDetail:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field detail", values[i])
} else if value.Valid {
_m.Detail = value.String
}
case paymentauditlog.FieldOperator:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field operator", values[i])
} else if value.Valid {
_m.Operator = value.String
}
case paymentauditlog.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
_m.CreatedAt = value.Time
}
default:
_m.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the PaymentAuditLog.
// This includes values selected through modifiers, order, etc.
func (_m *PaymentAuditLog) Value(name string) (ent.Value, error) {
return _m.selectValues.Get(name)
}
// Update returns a builder for updating this PaymentAuditLog.
// Note that you need to call PaymentAuditLog.Unwrap() before calling this method if this PaymentAuditLog
// was returned from a transaction, and the transaction was committed or rolled back.
func (_m *PaymentAuditLog) Update() *PaymentAuditLogUpdateOne {
return NewPaymentAuditLogClient(_m.config).UpdateOne(_m)
}
// Unwrap unwraps the PaymentAuditLog entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (_m *PaymentAuditLog) Unwrap() *PaymentAuditLog {
_tx, ok := _m.config.driver.(*txDriver)
if !ok {
panic("ent: PaymentAuditLog is not a transactional entity")
}
_m.config.driver = _tx.drv
return _m
}
// String implements the fmt.Stringer.
func (_m *PaymentAuditLog) String() string {
var builder strings.Builder
builder.WriteString("PaymentAuditLog(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("order_id=")
builder.WriteString(_m.OrderID)
builder.WriteString(", ")
builder.WriteString("action=")
builder.WriteString(_m.Action)
builder.WriteString(", ")
builder.WriteString("detail=")
builder.WriteString(_m.Detail)
builder.WriteString(", ")
builder.WriteString("operator=")
builder.WriteString(_m.Operator)
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// PaymentAuditLogs is a parsable slice of PaymentAuditLog.
type PaymentAuditLogs []*PaymentAuditLog

View File

@@ -0,0 +1,96 @@
// Code generated by ent, DO NOT EDIT.
package paymentauditlog
import (
"time"
"entgo.io/ent/dialect/sql"
)
const (
// Label holds the string label denoting the paymentauditlog type in the database.
Label = "payment_audit_log"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldOrderID holds the string denoting the order_id field in the database.
FieldOrderID = "order_id"
// FieldAction holds the string denoting the action field in the database.
FieldAction = "action"
// FieldDetail holds the string denoting the detail field in the database.
FieldDetail = "detail"
// FieldOperator holds the string denoting the operator field in the database.
FieldOperator = "operator"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// Table holds the table name of the paymentauditlog in the database.
Table = "payment_audit_logs"
)
// Columns holds all SQL columns for paymentauditlog fields.
var Columns = []string{
FieldID,
FieldOrderID,
FieldAction,
FieldDetail,
FieldOperator,
FieldCreatedAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// OrderIDValidator is a validator for the "order_id" field. It is called by the builders before save.
OrderIDValidator func(string) error
// ActionValidator is a validator for the "action" field. It is called by the builders before save.
ActionValidator func(string) error
// DefaultDetail holds the default value on creation for the "detail" field.
DefaultDetail string
// DefaultOperator holds the default value on creation for the "operator" field.
DefaultOperator string
// OperatorValidator is a validator for the "operator" field. It is called by the builders before save.
OperatorValidator func(string) error
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
)
// OrderOption defines the ordering options for the PaymentAuditLog queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByOrderID orders the results by the order_id field.
func ByOrderID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOrderID, opts...).ToFunc()
}
// ByAction orders the results by the action field.
func ByAction(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldAction, opts...).ToFunc()
}
// ByDetail orders the results by the detail field.
func ByDetail(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDetail, opts...).ToFunc()
}
// ByOperator orders the results by the operator field.
func ByOperator(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOperator, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}

View File

@@ -0,0 +1,395 @@
// Code generated by ent, DO NOT EDIT.
package paymentauditlog
import (
"time"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int64) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldID, id))
}
// OrderID applies equality check predicate on the "order_id" field. It's identical to OrderIDEQ.
func OrderID(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldOrderID, v))
}
// Action applies equality check predicate on the "action" field. It's identical to ActionEQ.
func Action(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldAction, v))
}
// Detail applies equality check predicate on the "detail" field. It's identical to DetailEQ.
func Detail(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldDetail, v))
}
// Operator applies equality check predicate on the "operator" field. It's identical to OperatorEQ.
func Operator(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldOperator, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldCreatedAt, v))
}
// OrderIDEQ applies the EQ predicate on the "order_id" field.
func OrderIDEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldOrderID, v))
}
// OrderIDNEQ applies the NEQ predicate on the "order_id" field.
func OrderIDNEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldOrderID, v))
}
// OrderIDIn applies the In predicate on the "order_id" field.
func OrderIDIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldOrderID, vs...))
}
// OrderIDNotIn applies the NotIn predicate on the "order_id" field.
func OrderIDNotIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldOrderID, vs...))
}
// OrderIDGT applies the GT predicate on the "order_id" field.
func OrderIDGT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldOrderID, v))
}
// OrderIDGTE applies the GTE predicate on the "order_id" field.
func OrderIDGTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldOrderID, v))
}
// OrderIDLT applies the LT predicate on the "order_id" field.
func OrderIDLT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldOrderID, v))
}
// OrderIDLTE applies the LTE predicate on the "order_id" field.
func OrderIDLTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldOrderID, v))
}
// OrderIDContains applies the Contains predicate on the "order_id" field.
func OrderIDContains(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContains(FieldOrderID, v))
}
// OrderIDHasPrefix applies the HasPrefix predicate on the "order_id" field.
func OrderIDHasPrefix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasPrefix(FieldOrderID, v))
}
// OrderIDHasSuffix applies the HasSuffix predicate on the "order_id" field.
func OrderIDHasSuffix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasSuffix(FieldOrderID, v))
}
// OrderIDEqualFold applies the EqualFold predicate on the "order_id" field.
func OrderIDEqualFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEqualFold(FieldOrderID, v))
}
// OrderIDContainsFold applies the ContainsFold predicate on the "order_id" field.
func OrderIDContainsFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContainsFold(FieldOrderID, v))
}
// ActionEQ applies the EQ predicate on the "action" field.
func ActionEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldAction, v))
}
// ActionNEQ applies the NEQ predicate on the "action" field.
func ActionNEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldAction, v))
}
// ActionIn applies the In predicate on the "action" field.
func ActionIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldAction, vs...))
}
// ActionNotIn applies the NotIn predicate on the "action" field.
func ActionNotIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldAction, vs...))
}
// ActionGT applies the GT predicate on the "action" field.
func ActionGT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldAction, v))
}
// ActionGTE applies the GTE predicate on the "action" field.
func ActionGTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldAction, v))
}
// ActionLT applies the LT predicate on the "action" field.
func ActionLT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldAction, v))
}
// ActionLTE applies the LTE predicate on the "action" field.
func ActionLTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldAction, v))
}
// ActionContains applies the Contains predicate on the "action" field.
func ActionContains(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContains(FieldAction, v))
}
// ActionHasPrefix applies the HasPrefix predicate on the "action" field.
func ActionHasPrefix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasPrefix(FieldAction, v))
}
// ActionHasSuffix applies the HasSuffix predicate on the "action" field.
func ActionHasSuffix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasSuffix(FieldAction, v))
}
// ActionEqualFold applies the EqualFold predicate on the "action" field.
func ActionEqualFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEqualFold(FieldAction, v))
}
// ActionContainsFold applies the ContainsFold predicate on the "action" field.
func ActionContainsFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContainsFold(FieldAction, v))
}
// DetailEQ applies the EQ predicate on the "detail" field.
func DetailEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldDetail, v))
}
// DetailNEQ applies the NEQ predicate on the "detail" field.
func DetailNEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldDetail, v))
}
// DetailIn applies the In predicate on the "detail" field.
func DetailIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldDetail, vs...))
}
// DetailNotIn applies the NotIn predicate on the "detail" field.
func DetailNotIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldDetail, vs...))
}
// DetailGT applies the GT predicate on the "detail" field.
func DetailGT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldDetail, v))
}
// DetailGTE applies the GTE predicate on the "detail" field.
func DetailGTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldDetail, v))
}
// DetailLT applies the LT predicate on the "detail" field.
func DetailLT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldDetail, v))
}
// DetailLTE applies the LTE predicate on the "detail" field.
func DetailLTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldDetail, v))
}
// DetailContains applies the Contains predicate on the "detail" field.
func DetailContains(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContains(FieldDetail, v))
}
// DetailHasPrefix applies the HasPrefix predicate on the "detail" field.
func DetailHasPrefix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasPrefix(FieldDetail, v))
}
// DetailHasSuffix applies the HasSuffix predicate on the "detail" field.
func DetailHasSuffix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasSuffix(FieldDetail, v))
}
// DetailEqualFold applies the EqualFold predicate on the "detail" field.
func DetailEqualFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEqualFold(FieldDetail, v))
}
// DetailContainsFold applies the ContainsFold predicate on the "detail" field.
func DetailContainsFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContainsFold(FieldDetail, v))
}
// OperatorEQ applies the EQ predicate on the "operator" field.
func OperatorEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldOperator, v))
}
// OperatorNEQ applies the NEQ predicate on the "operator" field.
func OperatorNEQ(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldOperator, v))
}
// OperatorIn applies the In predicate on the "operator" field.
func OperatorIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldOperator, vs...))
}
// OperatorNotIn applies the NotIn predicate on the "operator" field.
func OperatorNotIn(vs ...string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldOperator, vs...))
}
// OperatorGT applies the GT predicate on the "operator" field.
func OperatorGT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldOperator, v))
}
// OperatorGTE applies the GTE predicate on the "operator" field.
func OperatorGTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldOperator, v))
}
// OperatorLT applies the LT predicate on the "operator" field.
func OperatorLT(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldOperator, v))
}
// OperatorLTE applies the LTE predicate on the "operator" field.
func OperatorLTE(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldOperator, v))
}
// OperatorContains applies the Contains predicate on the "operator" field.
func OperatorContains(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContains(FieldOperator, v))
}
// OperatorHasPrefix applies the HasPrefix predicate on the "operator" field.
func OperatorHasPrefix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasPrefix(FieldOperator, v))
}
// OperatorHasSuffix applies the HasSuffix predicate on the "operator" field.
func OperatorHasSuffix(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldHasSuffix(FieldOperator, v))
}
// OperatorEqualFold applies the EqualFold predicate on the "operator" field.
func OperatorEqualFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEqualFold(FieldOperator, v))
}
// OperatorContainsFold applies the ContainsFold predicate on the "operator" field.
func OperatorContainsFold(v string) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldContainsFold(FieldOperator, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.FieldLTE(FieldCreatedAt, v))
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.PaymentAuditLog) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.PaymentAuditLog) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.PaymentAuditLog) predicate.PaymentAuditLog {
return predicate.PaymentAuditLog(sql.NotPredicates(p))
}

View File

@@ -0,0 +1,696 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
)
// PaymentAuditLogCreate is the builder for creating a PaymentAuditLog entity.
type PaymentAuditLogCreate struct {
config
mutation *PaymentAuditLogMutation
hooks []Hook
conflict []sql.ConflictOption
}
// SetOrderID sets the "order_id" field.
func (_c *PaymentAuditLogCreate) SetOrderID(v string) *PaymentAuditLogCreate {
_c.mutation.SetOrderID(v)
return _c
}
// SetAction sets the "action" field.
func (_c *PaymentAuditLogCreate) SetAction(v string) *PaymentAuditLogCreate {
_c.mutation.SetAction(v)
return _c
}
// SetDetail sets the "detail" field.
func (_c *PaymentAuditLogCreate) SetDetail(v string) *PaymentAuditLogCreate {
_c.mutation.SetDetail(v)
return _c
}
// SetNillableDetail sets the "detail" field if the given value is not nil.
func (_c *PaymentAuditLogCreate) SetNillableDetail(v *string) *PaymentAuditLogCreate {
if v != nil {
_c.SetDetail(*v)
}
return _c
}
// SetOperator sets the "operator" field.
func (_c *PaymentAuditLogCreate) SetOperator(v string) *PaymentAuditLogCreate {
_c.mutation.SetOperator(v)
return _c
}
// SetNillableOperator sets the "operator" field if the given value is not nil.
func (_c *PaymentAuditLogCreate) SetNillableOperator(v *string) *PaymentAuditLogCreate {
if v != nil {
_c.SetOperator(*v)
}
return _c
}
// SetCreatedAt sets the "created_at" field.
func (_c *PaymentAuditLogCreate) SetCreatedAt(v time.Time) *PaymentAuditLogCreate {
_c.mutation.SetCreatedAt(v)
return _c
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (_c *PaymentAuditLogCreate) SetNillableCreatedAt(v *time.Time) *PaymentAuditLogCreate {
if v != nil {
_c.SetCreatedAt(*v)
}
return _c
}
// Mutation returns the PaymentAuditLogMutation object of the builder.
func (_c *PaymentAuditLogCreate) Mutation() *PaymentAuditLogMutation {
return _c.mutation
}
// Save creates the PaymentAuditLog in the database.
func (_c *PaymentAuditLogCreate) Save(ctx context.Context) (*PaymentAuditLog, error) {
_c.defaults()
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (_c *PaymentAuditLogCreate) SaveX(ctx context.Context) *PaymentAuditLog {
v, err := _c.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (_c *PaymentAuditLogCreate) Exec(ctx context.Context) error {
_, err := _c.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_c *PaymentAuditLogCreate) ExecX(ctx context.Context) {
if err := _c.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_c *PaymentAuditLogCreate) defaults() {
if _, ok := _c.mutation.Detail(); !ok {
v := paymentauditlog.DefaultDetail
_c.mutation.SetDetail(v)
}
if _, ok := _c.mutation.Operator(); !ok {
v := paymentauditlog.DefaultOperator
_c.mutation.SetOperator(v)
}
if _, ok := _c.mutation.CreatedAt(); !ok {
v := paymentauditlog.DefaultCreatedAt()
_c.mutation.SetCreatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (_c *PaymentAuditLogCreate) check() error {
if _, ok := _c.mutation.OrderID(); !ok {
return &ValidationError{Name: "order_id", err: errors.New(`ent: missing required field "PaymentAuditLog.order_id"`)}
}
if v, ok := _c.mutation.OrderID(); ok {
if err := paymentauditlog.OrderIDValidator(v); err != nil {
return &ValidationError{Name: "order_id", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.order_id": %w`, err)}
}
}
if _, ok := _c.mutation.Action(); !ok {
return &ValidationError{Name: "action", err: errors.New(`ent: missing required field "PaymentAuditLog.action"`)}
}
if v, ok := _c.mutation.Action(); ok {
if err := paymentauditlog.ActionValidator(v); err != nil {
return &ValidationError{Name: "action", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.action": %w`, err)}
}
}
if _, ok := _c.mutation.Detail(); !ok {
return &ValidationError{Name: "detail", err: errors.New(`ent: missing required field "PaymentAuditLog.detail"`)}
}
if _, ok := _c.mutation.Operator(); !ok {
return &ValidationError{Name: "operator", err: errors.New(`ent: missing required field "PaymentAuditLog.operator"`)}
}
if v, ok := _c.mutation.Operator(); ok {
if err := paymentauditlog.OperatorValidator(v); err != nil {
return &ValidationError{Name: "operator", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.operator": %w`, err)}
}
}
if _, ok := _c.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "PaymentAuditLog.created_at"`)}
}
return nil
}
func (_c *PaymentAuditLogCreate) sqlSave(ctx context.Context) (*PaymentAuditLog, error) {
if err := _c.check(); err != nil {
return nil, err
}
_node, _spec := _c.createSpec()
if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int64(id)
_c.mutation.id = &_node.ID
_c.mutation.done = true
return _node, nil
}
func (_c *PaymentAuditLogCreate) createSpec() (*PaymentAuditLog, *sqlgraph.CreateSpec) {
var (
_node = &PaymentAuditLog{config: _c.config}
_spec = sqlgraph.NewCreateSpec(paymentauditlog.Table, sqlgraph.NewFieldSpec(paymentauditlog.FieldID, field.TypeInt64))
)
_spec.OnConflict = _c.conflict
if value, ok := _c.mutation.OrderID(); ok {
_spec.SetField(paymentauditlog.FieldOrderID, field.TypeString, value)
_node.OrderID = value
}
if value, ok := _c.mutation.Action(); ok {
_spec.SetField(paymentauditlog.FieldAction, field.TypeString, value)
_node.Action = value
}
if value, ok := _c.mutation.Detail(); ok {
_spec.SetField(paymentauditlog.FieldDetail, field.TypeString, value)
_node.Detail = value
}
if value, ok := _c.mutation.Operator(); ok {
_spec.SetField(paymentauditlog.FieldOperator, field.TypeString, value)
_node.Operator = value
}
if value, ok := _c.mutation.CreatedAt(); ok {
_spec.SetField(paymentauditlog.FieldCreatedAt, field.TypeTime, value)
_node.CreatedAt = value
}
return _node, _spec
}
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.PaymentAuditLog.Create().
// SetOrderID(v).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
// sql.ResolveWithNewValues(),
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.PaymentAuditLogUpsert) {
// SetOrderID(v+v).
// }).
// Exec(ctx)
func (_c *PaymentAuditLogCreate) OnConflict(opts ...sql.ConflictOption) *PaymentAuditLogUpsertOne {
_c.conflict = opts
return &PaymentAuditLogUpsertOne{
create: _c,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (_c *PaymentAuditLogCreate) OnConflictColumns(columns ...string) *PaymentAuditLogUpsertOne {
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
return &PaymentAuditLogUpsertOne{
create: _c,
}
}
type (
// PaymentAuditLogUpsertOne is the builder for "upsert"-ing
// one PaymentAuditLog node.
PaymentAuditLogUpsertOne struct {
create *PaymentAuditLogCreate
}
// PaymentAuditLogUpsert is the "OnConflict" setter.
PaymentAuditLogUpsert struct {
*sql.UpdateSet
}
)
// SetOrderID sets the "order_id" field.
func (u *PaymentAuditLogUpsert) SetOrderID(v string) *PaymentAuditLogUpsert {
u.Set(paymentauditlog.FieldOrderID, v)
return u
}
// UpdateOrderID sets the "order_id" field to the value that was provided on create.
func (u *PaymentAuditLogUpsert) UpdateOrderID() *PaymentAuditLogUpsert {
u.SetExcluded(paymentauditlog.FieldOrderID)
return u
}
// SetAction sets the "action" field.
func (u *PaymentAuditLogUpsert) SetAction(v string) *PaymentAuditLogUpsert {
u.Set(paymentauditlog.FieldAction, v)
return u
}
// UpdateAction sets the "action" field to the value that was provided on create.
func (u *PaymentAuditLogUpsert) UpdateAction() *PaymentAuditLogUpsert {
u.SetExcluded(paymentauditlog.FieldAction)
return u
}
// SetDetail sets the "detail" field.
func (u *PaymentAuditLogUpsert) SetDetail(v string) *PaymentAuditLogUpsert {
u.Set(paymentauditlog.FieldDetail, v)
return u
}
// UpdateDetail sets the "detail" field to the value that was provided on create.
func (u *PaymentAuditLogUpsert) UpdateDetail() *PaymentAuditLogUpsert {
u.SetExcluded(paymentauditlog.FieldDetail)
return u
}
// SetOperator sets the "operator" field.
func (u *PaymentAuditLogUpsert) SetOperator(v string) *PaymentAuditLogUpsert {
u.Set(paymentauditlog.FieldOperator, v)
return u
}
// UpdateOperator sets the "operator" field to the value that was provided on create.
func (u *PaymentAuditLogUpsert) UpdateOperator() *PaymentAuditLogUpsert {
u.SetExcluded(paymentauditlog.FieldOperator)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create.
// Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *PaymentAuditLogUpsertOne) UpdateNewValues() *PaymentAuditLogUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
if _, exists := u.create.mutation.CreatedAt(); exists {
s.SetIgnore(paymentauditlog.FieldCreatedAt)
}
}))
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *PaymentAuditLogUpsertOne) Ignore() *PaymentAuditLogUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
return u
}
// DoNothing configures the conflict_action to `DO NOTHING`.
// Supported only by SQLite and PostgreSQL.
func (u *PaymentAuditLogUpsertOne) DoNothing() *PaymentAuditLogUpsertOne {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the PaymentAuditLogCreate.OnConflict
// documentation for more info.
func (u *PaymentAuditLogUpsertOne) Update(set func(*PaymentAuditLogUpsert)) *PaymentAuditLogUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&PaymentAuditLogUpsert{UpdateSet: update})
}))
return u
}
// SetOrderID sets the "order_id" field.
func (u *PaymentAuditLogUpsertOne) SetOrderID(v string) *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetOrderID(v)
})
}
// UpdateOrderID sets the "order_id" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertOne) UpdateOrderID() *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateOrderID()
})
}
// SetAction sets the "action" field.
func (u *PaymentAuditLogUpsertOne) SetAction(v string) *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetAction(v)
})
}
// UpdateAction sets the "action" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertOne) UpdateAction() *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateAction()
})
}
// SetDetail sets the "detail" field.
func (u *PaymentAuditLogUpsertOne) SetDetail(v string) *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetDetail(v)
})
}
// UpdateDetail sets the "detail" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertOne) UpdateDetail() *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateDetail()
})
}
// SetOperator sets the "operator" field.
func (u *PaymentAuditLogUpsertOne) SetOperator(v string) *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetOperator(v)
})
}
// UpdateOperator sets the "operator" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertOne) UpdateOperator() *PaymentAuditLogUpsertOne {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateOperator()
})
}
// Exec executes the query.
func (u *PaymentAuditLogUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for PaymentAuditLogCreate.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *PaymentAuditLogUpsertOne) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}
// Exec executes the UPSERT query and returns the inserted/updated ID.
func (u *PaymentAuditLogUpsertOne) ID(ctx context.Context) (id int64, err error) {
node, err := u.create.Save(ctx)
if err != nil {
return id, err
}
return node.ID, nil
}
// IDX is like ID, but panics if an error occurs.
func (u *PaymentAuditLogUpsertOne) IDX(ctx context.Context) int64 {
id, err := u.ID(ctx)
if err != nil {
panic(err)
}
return id
}
// PaymentAuditLogCreateBulk is the builder for creating many PaymentAuditLog entities in bulk.
type PaymentAuditLogCreateBulk struct {
config
err error
builders []*PaymentAuditLogCreate
conflict []sql.ConflictOption
}
// Save creates the PaymentAuditLog entities in the database.
func (_c *PaymentAuditLogCreateBulk) Save(ctx context.Context) ([]*PaymentAuditLog, error) {
if _c.err != nil {
return nil, _c.err
}
specs := make([]*sqlgraph.CreateSpec, len(_c.builders))
nodes := make([]*PaymentAuditLog, len(_c.builders))
mutators := make([]Mutator, len(_c.builders))
for i := range _c.builders {
func(i int, root context.Context) {
builder := _c.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*PaymentAuditLogMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
var err error
nodes[i], specs[i] = builder.createSpec()
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
spec.OnConflict = _c.conflict
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
}
}
if err != nil {
return nil, err
}
mutation.id = &nodes[i].ID
if specs[i].ID.Value != nil {
id := specs[i].ID.Value.(int64)
nodes[i].ID = int64(id)
}
mutation.done = true
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (_c *PaymentAuditLogCreateBulk) SaveX(ctx context.Context) []*PaymentAuditLog {
v, err := _c.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (_c *PaymentAuditLogCreateBulk) Exec(ctx context.Context) error {
_, err := _c.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_c *PaymentAuditLogCreateBulk) ExecX(ctx context.Context) {
if err := _c.Exec(ctx); err != nil {
panic(err)
}
}
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
// of the `INSERT` statement. For example:
//
// client.PaymentAuditLog.CreateBulk(builders...).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
// sql.ResolveWithNewValues(),
// ).
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.PaymentAuditLogUpsert) {
// SetOrderID(v+v).
// }).
// Exec(ctx)
func (_c *PaymentAuditLogCreateBulk) OnConflict(opts ...sql.ConflictOption) *PaymentAuditLogUpsertBulk {
_c.conflict = opts
return &PaymentAuditLogUpsertBulk{
create: _c,
}
}
// OnConflictColumns calls `OnConflict` and configures the columns
// as conflict target. Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(sql.ConflictColumns(columns...)).
// Exec(ctx)
func (_c *PaymentAuditLogCreateBulk) OnConflictColumns(columns ...string) *PaymentAuditLogUpsertBulk {
_c.conflict = append(_c.conflict, sql.ConflictColumns(columns...))
return &PaymentAuditLogUpsertBulk{
create: _c,
}
}
// PaymentAuditLogUpsertBulk is the builder for "upsert"-ing
// a bulk of PaymentAuditLog nodes.
type PaymentAuditLogUpsertBulk struct {
create *PaymentAuditLogCreateBulk
}
// UpdateNewValues updates the mutable fields using the new values that
// were set on create. Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(
// sql.ResolveWithNewValues(),
// ).
// Exec(ctx)
func (u *PaymentAuditLogUpsertBulk) UpdateNewValues() *PaymentAuditLogUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
for _, b := range u.create.builders {
if _, exists := b.mutation.CreatedAt(); exists {
s.SetIgnore(paymentauditlog.FieldCreatedAt)
}
}
}))
return u
}
// Ignore sets each column to itself in case of conflict.
// Using this option is equivalent to using:
//
// client.PaymentAuditLog.Create().
// OnConflict(sql.ResolveWithIgnore()).
// Exec(ctx)
func (u *PaymentAuditLogUpsertBulk) Ignore() *PaymentAuditLogUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
return u
}
// DoNothing configures the conflict_action to `DO NOTHING`.
// Supported only by SQLite and PostgreSQL.
func (u *PaymentAuditLogUpsertBulk) DoNothing() *PaymentAuditLogUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.DoNothing())
return u
}
// Update allows overriding fields `UPDATE` values. See the PaymentAuditLogCreateBulk.OnConflict
// documentation for more info.
func (u *PaymentAuditLogUpsertBulk) Update(set func(*PaymentAuditLogUpsert)) *PaymentAuditLogUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
set(&PaymentAuditLogUpsert{UpdateSet: update})
}))
return u
}
// SetOrderID sets the "order_id" field.
func (u *PaymentAuditLogUpsertBulk) SetOrderID(v string) *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetOrderID(v)
})
}
// UpdateOrderID sets the "order_id" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertBulk) UpdateOrderID() *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateOrderID()
})
}
// SetAction sets the "action" field.
func (u *PaymentAuditLogUpsertBulk) SetAction(v string) *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetAction(v)
})
}
// UpdateAction sets the "action" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertBulk) UpdateAction() *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateAction()
})
}
// SetDetail sets the "detail" field.
func (u *PaymentAuditLogUpsertBulk) SetDetail(v string) *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetDetail(v)
})
}
// UpdateDetail sets the "detail" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertBulk) UpdateDetail() *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateDetail()
})
}
// SetOperator sets the "operator" field.
func (u *PaymentAuditLogUpsertBulk) SetOperator(v string) *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.SetOperator(v)
})
}
// UpdateOperator sets the "operator" field to the value that was provided on create.
func (u *PaymentAuditLogUpsertBulk) UpdateOperator() *PaymentAuditLogUpsertBulk {
return u.Update(func(s *PaymentAuditLogUpsert) {
s.UpdateOperator()
})
}
// Exec executes the query.
func (u *PaymentAuditLogUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {
return u.create.err
}
for i, b := range u.create.builders {
if len(b.conflict) != 0 {
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the PaymentAuditLogCreateBulk instead", i)
}
}
if len(u.create.conflict) == 0 {
return errors.New("ent: missing options for PaymentAuditLogCreateBulk.OnConflict")
}
return u.create.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (u *PaymentAuditLogUpsertBulk) ExecX(ctx context.Context) {
if err := u.create.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentAuditLogDelete is the builder for deleting a PaymentAuditLog entity.
type PaymentAuditLogDelete struct {
config
hooks []Hook
mutation *PaymentAuditLogMutation
}
// Where appends a list predicates to the PaymentAuditLogDelete builder.
func (_d *PaymentAuditLogDelete) Where(ps ...predicate.PaymentAuditLog) *PaymentAuditLogDelete {
_d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (_d *PaymentAuditLogDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentAuditLogDelete) ExecX(ctx context.Context) int {
n, err := _d.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (_d *PaymentAuditLogDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(paymentauditlog.Table, sqlgraph.NewFieldSpec(paymentauditlog.FieldID, field.TypeInt64))
if ps := _d.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
_d.mutation.done = true
return affected, err
}
// PaymentAuditLogDeleteOne is the builder for deleting a single PaymentAuditLog entity.
type PaymentAuditLogDeleteOne struct {
_d *PaymentAuditLogDelete
}
// Where appends a list predicates to the PaymentAuditLogDelete builder.
func (_d *PaymentAuditLogDeleteOne) Where(ps ...predicate.PaymentAuditLog) *PaymentAuditLogDeleteOne {
_d._d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query.
func (_d *PaymentAuditLogDeleteOne) Exec(ctx context.Context) error {
n, err := _d._d.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{paymentauditlog.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentAuditLogDeleteOne) ExecX(ctx context.Context) {
if err := _d.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,564 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentAuditLogQuery is the builder for querying PaymentAuditLog entities.
type PaymentAuditLogQuery struct {
config
ctx *QueryContext
order []paymentauditlog.OrderOption
inters []Interceptor
predicates []predicate.PaymentAuditLog
modifiers []func(*sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the PaymentAuditLogQuery builder.
func (_q *PaymentAuditLogQuery) Where(ps ...predicate.PaymentAuditLog) *PaymentAuditLogQuery {
_q.predicates = append(_q.predicates, ps...)
return _q
}
// Limit the number of records to be returned by this query.
func (_q *PaymentAuditLogQuery) Limit(limit int) *PaymentAuditLogQuery {
_q.ctx.Limit = &limit
return _q
}
// Offset to start from.
func (_q *PaymentAuditLogQuery) Offset(offset int) *PaymentAuditLogQuery {
_q.ctx.Offset = &offset
return _q
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (_q *PaymentAuditLogQuery) Unique(unique bool) *PaymentAuditLogQuery {
_q.ctx.Unique = &unique
return _q
}
// Order specifies how the records should be ordered.
func (_q *PaymentAuditLogQuery) Order(o ...paymentauditlog.OrderOption) *PaymentAuditLogQuery {
_q.order = append(_q.order, o...)
return _q
}
// First returns the first PaymentAuditLog entity from the query.
// Returns a *NotFoundError when no PaymentAuditLog was found.
func (_q *PaymentAuditLogQuery) First(ctx context.Context) (*PaymentAuditLog, error) {
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{paymentauditlog.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) FirstX(ctx context.Context) *PaymentAuditLog {
node, err := _q.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first PaymentAuditLog ID from the query.
// Returns a *NotFoundError when no PaymentAuditLog ID was found.
func (_q *PaymentAuditLogQuery) FirstID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{paymentauditlog.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) FirstIDX(ctx context.Context) int64 {
id, err := _q.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single PaymentAuditLog entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one PaymentAuditLog entity is found.
// Returns a *NotFoundError when no PaymentAuditLog entities are found.
func (_q *PaymentAuditLogQuery) Only(ctx context.Context) (*PaymentAuditLog, error) {
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{paymentauditlog.Label}
default:
return nil, &NotSingularError{paymentauditlog.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) OnlyX(ctx context.Context) *PaymentAuditLog {
node, err := _q.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only PaymentAuditLog ID in the query.
// Returns a *NotSingularError when more than one PaymentAuditLog ID is found.
// Returns a *NotFoundError when no entities are found.
func (_q *PaymentAuditLogQuery) OnlyID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{paymentauditlog.Label}
default:
err = &NotSingularError{paymentauditlog.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) OnlyIDX(ctx context.Context) int64 {
id, err := _q.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of PaymentAuditLogs.
func (_q *PaymentAuditLogQuery) All(ctx context.Context) ([]*PaymentAuditLog, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*PaymentAuditLog, *PaymentAuditLogQuery]()
return withInterceptors[[]*PaymentAuditLog](ctx, _q, qr, _q.inters)
}
// AllX is like All, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) AllX(ctx context.Context) []*PaymentAuditLog {
nodes, err := _q.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of PaymentAuditLog IDs.
func (_q *PaymentAuditLogQuery) IDs(ctx context.Context) (ids []int64, err error) {
if _q.ctx.Unique == nil && _q.path != nil {
_q.Unique(true)
}
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
if err = _q.Select(paymentauditlog.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) IDsX(ctx context.Context) []int64 {
ids, err := _q.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (_q *PaymentAuditLogQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
if err := _q.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, _q, querierCount[*PaymentAuditLogQuery](), _q.inters)
}
// CountX is like Count, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) CountX(ctx context.Context) int {
count, err := _q.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (_q *PaymentAuditLogQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
switch _, err := _q.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (_q *PaymentAuditLogQuery) ExistX(ctx context.Context) bool {
exist, err := _q.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the PaymentAuditLogQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (_q *PaymentAuditLogQuery) Clone() *PaymentAuditLogQuery {
if _q == nil {
return nil
}
return &PaymentAuditLogQuery{
config: _q.config,
ctx: _q.ctx.Clone(),
order: append([]paymentauditlog.OrderOption{}, _q.order...),
inters: append([]Interceptor{}, _q.inters...),
predicates: append([]predicate.PaymentAuditLog{}, _q.predicates...),
// clone intermediate query.
sql: _q.sql.Clone(),
path: _q.path,
}
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// OrderID string `json:"order_id,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.PaymentAuditLog.Query().
// GroupBy(paymentauditlog.FieldOrderID).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *PaymentAuditLogQuery) GroupBy(field string, fields ...string) *PaymentAuditLogGroupBy {
_q.ctx.Fields = append([]string{field}, fields...)
grbuild := &PaymentAuditLogGroupBy{build: _q}
grbuild.flds = &_q.ctx.Fields
grbuild.label = paymentauditlog.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// OrderID string `json:"order_id,omitempty"`
// }
//
// client.PaymentAuditLog.Query().
// Select(paymentauditlog.FieldOrderID).
// Scan(ctx, &v)
func (_q *PaymentAuditLogQuery) Select(fields ...string) *PaymentAuditLogSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
sbuild := &PaymentAuditLogSelect{PaymentAuditLogQuery: _q}
sbuild.label = paymentauditlog.Label
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a PaymentAuditLogSelect configured with the given aggregations.
func (_q *PaymentAuditLogQuery) Aggregate(fns ...AggregateFunc) *PaymentAuditLogSelect {
return _q.Select().Aggregate(fns...)
}
func (_q *PaymentAuditLogQuery) prepareQuery(ctx context.Context) error {
for _, inter := range _q.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, _q); err != nil {
return err
}
}
}
for _, f := range _q.ctx.Fields {
if !paymentauditlog.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if _q.path != nil {
prev, err := _q.path(ctx)
if err != nil {
return err
}
_q.sql = prev
}
return nil
}
func (_q *PaymentAuditLogQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PaymentAuditLog, error) {
var (
nodes = []*PaymentAuditLog{}
_spec = _q.querySpec()
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*PaymentAuditLog).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &PaymentAuditLog{config: _q.config}
nodes = append(nodes, node)
return node.assignValues(columns, values)
}
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
return nodes, nil
}
func (_q *PaymentAuditLogQuery) sqlCount(ctx context.Context) (int, error) {
_spec := _q.querySpec()
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
_spec.Node.Columns = _q.ctx.Fields
if len(_q.ctx.Fields) > 0 {
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
}
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
}
func (_q *PaymentAuditLogQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(paymentauditlog.Table, paymentauditlog.Columns, sqlgraph.NewFieldSpec(paymentauditlog.FieldID, field.TypeInt64))
_spec.From = _q.sql
if unique := _q.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if _q.path != nil {
_spec.Unique = true
}
if fields := _q.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, paymentauditlog.FieldID)
for i := range fields {
if fields[i] != paymentauditlog.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := _q.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := _q.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := _q.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := _q.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (_q *PaymentAuditLogQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(_q.driver.Dialect())
t1 := builder.Table(paymentauditlog.Table)
columns := _q.ctx.Fields
if len(columns) == 0 {
columns = paymentauditlog.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if _q.sql != nil {
selector = _q.sql
selector.Select(selector.Columns(columns...)...)
}
if _q.ctx.Unique != nil && *_q.ctx.Unique {
selector.Distinct()
}
for _, m := range _q.modifiers {
m(selector)
}
for _, p := range _q.predicates {
p(selector)
}
for _, p := range _q.order {
p(selector)
}
if offset := _q.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := _q.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
// either committed or rolled-back.
func (_q *PaymentAuditLogQuery) ForUpdate(opts ...sql.LockOption) *PaymentAuditLogQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForUpdate(opts...)
})
return _q
}
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
// on any rows that are read. Other sessions can read the rows, but cannot modify them
// until your transaction commits.
func (_q *PaymentAuditLogQuery) ForShare(opts ...sql.LockOption) *PaymentAuditLogQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForShare(opts...)
})
return _q
}
// PaymentAuditLogGroupBy is the group-by builder for PaymentAuditLog entities.
type PaymentAuditLogGroupBy struct {
selector
build *PaymentAuditLogQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (_g *PaymentAuditLogGroupBy) Aggregate(fns ...AggregateFunc) *PaymentAuditLogGroupBy {
_g.fns = append(_g.fns, fns...)
return _g
}
// Scan applies the selector query and scans the result into the given value.
func (_g *PaymentAuditLogGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
if err := _g.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentAuditLogQuery, *PaymentAuditLogGroupBy](ctx, _g.build, _g, _g.build.inters, v)
}
func (_g *PaymentAuditLogGroupBy) sqlScan(ctx context.Context, root *PaymentAuditLogQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(_g.fns))
for _, fn := range _g.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
for _, f := range *_g.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*_g.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// PaymentAuditLogSelect is the builder for selecting fields of PaymentAuditLog entities.
type PaymentAuditLogSelect struct {
*PaymentAuditLogQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (_s *PaymentAuditLogSelect) Aggregate(fns ...AggregateFunc) *PaymentAuditLogSelect {
_s.fns = append(_s.fns, fns...)
return _s
}
// Scan applies the selector query and scans the result into the given value.
func (_s *PaymentAuditLogSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
if err := _s.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentAuditLogQuery, *PaymentAuditLogSelect](ctx, _s.PaymentAuditLogQuery, _s, _s.inters, v)
}
func (_s *PaymentAuditLogSelect) sqlScan(ctx context.Context, root *PaymentAuditLogQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(_s.fns))
for _, fn := range _s.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*_s.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@@ -0,0 +1,357 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentAuditLogUpdate is the builder for updating PaymentAuditLog entities.
type PaymentAuditLogUpdate struct {
config
hooks []Hook
mutation *PaymentAuditLogMutation
}
// Where appends a list predicates to the PaymentAuditLogUpdate builder.
func (_u *PaymentAuditLogUpdate) Where(ps ...predicate.PaymentAuditLog) *PaymentAuditLogUpdate {
_u.mutation.Where(ps...)
return _u
}
// SetOrderID sets the "order_id" field.
func (_u *PaymentAuditLogUpdate) SetOrderID(v string) *PaymentAuditLogUpdate {
_u.mutation.SetOrderID(v)
return _u
}
// SetNillableOrderID sets the "order_id" field if the given value is not nil.
func (_u *PaymentAuditLogUpdate) SetNillableOrderID(v *string) *PaymentAuditLogUpdate {
if v != nil {
_u.SetOrderID(*v)
}
return _u
}
// SetAction sets the "action" field.
func (_u *PaymentAuditLogUpdate) SetAction(v string) *PaymentAuditLogUpdate {
_u.mutation.SetAction(v)
return _u
}
// SetNillableAction sets the "action" field if the given value is not nil.
func (_u *PaymentAuditLogUpdate) SetNillableAction(v *string) *PaymentAuditLogUpdate {
if v != nil {
_u.SetAction(*v)
}
return _u
}
// SetDetail sets the "detail" field.
func (_u *PaymentAuditLogUpdate) SetDetail(v string) *PaymentAuditLogUpdate {
_u.mutation.SetDetail(v)
return _u
}
// SetNillableDetail sets the "detail" field if the given value is not nil.
func (_u *PaymentAuditLogUpdate) SetNillableDetail(v *string) *PaymentAuditLogUpdate {
if v != nil {
_u.SetDetail(*v)
}
return _u
}
// SetOperator sets the "operator" field.
func (_u *PaymentAuditLogUpdate) SetOperator(v string) *PaymentAuditLogUpdate {
_u.mutation.SetOperator(v)
return _u
}
// SetNillableOperator sets the "operator" field if the given value is not nil.
func (_u *PaymentAuditLogUpdate) SetNillableOperator(v *string) *PaymentAuditLogUpdate {
if v != nil {
_u.SetOperator(*v)
}
return _u
}
// Mutation returns the PaymentAuditLogMutation object of the builder.
func (_u *PaymentAuditLogUpdate) Mutation() *PaymentAuditLogMutation {
return _u.mutation
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (_u *PaymentAuditLogUpdate) Save(ctx context.Context) (int, error) {
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *PaymentAuditLogUpdate) SaveX(ctx context.Context) int {
affected, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (_u *PaymentAuditLogUpdate) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *PaymentAuditLogUpdate) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *PaymentAuditLogUpdate) check() error {
if v, ok := _u.mutation.OrderID(); ok {
if err := paymentauditlog.OrderIDValidator(v); err != nil {
return &ValidationError{Name: "order_id", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.order_id": %w`, err)}
}
}
if v, ok := _u.mutation.Action(); ok {
if err := paymentauditlog.ActionValidator(v); err != nil {
return &ValidationError{Name: "action", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.action": %w`, err)}
}
}
if v, ok := _u.mutation.Operator(); ok {
if err := paymentauditlog.OperatorValidator(v); err != nil {
return &ValidationError{Name: "operator", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.operator": %w`, err)}
}
}
return nil
}
func (_u *PaymentAuditLogUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(paymentauditlog.Table, paymentauditlog.Columns, sqlgraph.NewFieldSpec(paymentauditlog.FieldID, field.TypeInt64))
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.OrderID(); ok {
_spec.SetField(paymentauditlog.FieldOrderID, field.TypeString, value)
}
if value, ok := _u.mutation.Action(); ok {
_spec.SetField(paymentauditlog.FieldAction, field.TypeString, value)
}
if value, ok := _u.mutation.Detail(); ok {
_spec.SetField(paymentauditlog.FieldDetail, field.TypeString, value)
}
if value, ok := _u.mutation.Operator(); ok {
_spec.SetField(paymentauditlog.FieldOperator, field.TypeString, value)
}
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{paymentauditlog.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
_u.mutation.done = true
return _node, nil
}
// PaymentAuditLogUpdateOne is the builder for updating a single PaymentAuditLog entity.
type PaymentAuditLogUpdateOne struct {
config
fields []string
hooks []Hook
mutation *PaymentAuditLogMutation
}
// SetOrderID sets the "order_id" field.
func (_u *PaymentAuditLogUpdateOne) SetOrderID(v string) *PaymentAuditLogUpdateOne {
_u.mutation.SetOrderID(v)
return _u
}
// SetNillableOrderID sets the "order_id" field if the given value is not nil.
func (_u *PaymentAuditLogUpdateOne) SetNillableOrderID(v *string) *PaymentAuditLogUpdateOne {
if v != nil {
_u.SetOrderID(*v)
}
return _u
}
// SetAction sets the "action" field.
func (_u *PaymentAuditLogUpdateOne) SetAction(v string) *PaymentAuditLogUpdateOne {
_u.mutation.SetAction(v)
return _u
}
// SetNillableAction sets the "action" field if the given value is not nil.
func (_u *PaymentAuditLogUpdateOne) SetNillableAction(v *string) *PaymentAuditLogUpdateOne {
if v != nil {
_u.SetAction(*v)
}
return _u
}
// SetDetail sets the "detail" field.
func (_u *PaymentAuditLogUpdateOne) SetDetail(v string) *PaymentAuditLogUpdateOne {
_u.mutation.SetDetail(v)
return _u
}
// SetNillableDetail sets the "detail" field if the given value is not nil.
func (_u *PaymentAuditLogUpdateOne) SetNillableDetail(v *string) *PaymentAuditLogUpdateOne {
if v != nil {
_u.SetDetail(*v)
}
return _u
}
// SetOperator sets the "operator" field.
func (_u *PaymentAuditLogUpdateOne) SetOperator(v string) *PaymentAuditLogUpdateOne {
_u.mutation.SetOperator(v)
return _u
}
// SetNillableOperator sets the "operator" field if the given value is not nil.
func (_u *PaymentAuditLogUpdateOne) SetNillableOperator(v *string) *PaymentAuditLogUpdateOne {
if v != nil {
_u.SetOperator(*v)
}
return _u
}
// Mutation returns the PaymentAuditLogMutation object of the builder.
func (_u *PaymentAuditLogUpdateOne) Mutation() *PaymentAuditLogMutation {
return _u.mutation
}
// Where appends a list predicates to the PaymentAuditLogUpdate builder.
func (_u *PaymentAuditLogUpdateOne) Where(ps ...predicate.PaymentAuditLog) *PaymentAuditLogUpdateOne {
_u.mutation.Where(ps...)
return _u
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (_u *PaymentAuditLogUpdateOne) Select(field string, fields ...string) *PaymentAuditLogUpdateOne {
_u.fields = append([]string{field}, fields...)
return _u
}
// Save executes the query and returns the updated PaymentAuditLog entity.
func (_u *PaymentAuditLogUpdateOne) Save(ctx context.Context) (*PaymentAuditLog, error) {
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *PaymentAuditLogUpdateOne) SaveX(ctx context.Context) *PaymentAuditLog {
node, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (_u *PaymentAuditLogUpdateOne) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *PaymentAuditLogUpdateOne) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *PaymentAuditLogUpdateOne) check() error {
if v, ok := _u.mutation.OrderID(); ok {
if err := paymentauditlog.OrderIDValidator(v); err != nil {
return &ValidationError{Name: "order_id", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.order_id": %w`, err)}
}
}
if v, ok := _u.mutation.Action(); ok {
if err := paymentauditlog.ActionValidator(v); err != nil {
return &ValidationError{Name: "action", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.action": %w`, err)}
}
}
if v, ok := _u.mutation.Operator(); ok {
if err := paymentauditlog.OperatorValidator(v); err != nil {
return &ValidationError{Name: "operator", err: fmt.Errorf(`ent: validator failed for field "PaymentAuditLog.operator": %w`, err)}
}
}
return nil
}
func (_u *PaymentAuditLogUpdateOne) sqlSave(ctx context.Context) (_node *PaymentAuditLog, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(paymentauditlog.Table, paymentauditlog.Columns, sqlgraph.NewFieldSpec(paymentauditlog.FieldID, field.TypeInt64))
id, ok := _u.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "PaymentAuditLog.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := _u.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, paymentauditlog.FieldID)
for _, f := range fields {
if !paymentauditlog.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != paymentauditlog.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.OrderID(); ok {
_spec.SetField(paymentauditlog.FieldOrderID, field.TypeString, value)
}
if value, ok := _u.mutation.Action(); ok {
_spec.SetField(paymentauditlog.FieldAction, field.TypeString, value)
}
if value, ok := _u.mutation.Detail(); ok {
_spec.SetField(paymentauditlog.FieldDetail, field.TypeString, value)
}
if value, ok := _u.mutation.Operator(); ok {
_spec.SetField(paymentauditlog.FieldOperator, field.TypeString, value)
}
_node = &PaymentAuditLog{config: _u.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{paymentauditlog.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
_u.mutation.done = true
return _node, nil
}

589
backend/ent/paymentorder.go Normal file
View File

@@ -0,0 +1,589 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/user"
)
// PaymentOrder is the model entity for the PaymentOrder schema.
type PaymentOrder struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// UserID holds the value of the "user_id" field.
UserID int64 `json:"user_id,omitempty"`
// UserEmail holds the value of the "user_email" field.
UserEmail string `json:"user_email,omitempty"`
// UserName holds the value of the "user_name" field.
UserName string `json:"user_name,omitempty"`
// UserNotes holds the value of the "user_notes" field.
UserNotes *string `json:"user_notes,omitempty"`
// Amount holds the value of the "amount" field.
Amount float64 `json:"amount,omitempty"`
// PayAmount holds the value of the "pay_amount" field.
PayAmount float64 `json:"pay_amount,omitempty"`
// FeeRate holds the value of the "fee_rate" field.
FeeRate float64 `json:"fee_rate,omitempty"`
// RechargeCode holds the value of the "recharge_code" field.
RechargeCode string `json:"recharge_code,omitempty"`
// OutTradeNo holds the value of the "out_trade_no" field.
OutTradeNo string `json:"out_trade_no,omitempty"`
// PaymentType holds the value of the "payment_type" field.
PaymentType string `json:"payment_type,omitempty"`
// PaymentTradeNo holds the value of the "payment_trade_no" field.
PaymentTradeNo string `json:"payment_trade_no,omitempty"`
// PayURL holds the value of the "pay_url" field.
PayURL *string `json:"pay_url,omitempty"`
// QrCode holds the value of the "qr_code" field.
QrCode *string `json:"qr_code,omitempty"`
// QrCodeImg holds the value of the "qr_code_img" field.
QrCodeImg *string `json:"qr_code_img,omitempty"`
// OrderType holds the value of the "order_type" field.
OrderType string `json:"order_type,omitempty"`
// PlanID holds the value of the "plan_id" field.
PlanID *int64 `json:"plan_id,omitempty"`
// SubscriptionGroupID holds the value of the "subscription_group_id" field.
SubscriptionGroupID *int64 `json:"subscription_group_id,omitempty"`
// SubscriptionDays holds the value of the "subscription_days" field.
SubscriptionDays *int `json:"subscription_days,omitempty"`
// ProviderInstanceID holds the value of the "provider_instance_id" field.
ProviderInstanceID *string `json:"provider_instance_id,omitempty"`
// Status holds the value of the "status" field.
Status string `json:"status,omitempty"`
// RefundAmount holds the value of the "refund_amount" field.
RefundAmount float64 `json:"refund_amount,omitempty"`
// RefundReason holds the value of the "refund_reason" field.
RefundReason *string `json:"refund_reason,omitempty"`
// RefundAt holds the value of the "refund_at" field.
RefundAt *time.Time `json:"refund_at,omitempty"`
// ForceRefund holds the value of the "force_refund" field.
ForceRefund bool `json:"force_refund,omitempty"`
// RefundRequestedAt holds the value of the "refund_requested_at" field.
RefundRequestedAt *time.Time `json:"refund_requested_at,omitempty"`
// RefundRequestReason holds the value of the "refund_request_reason" field.
RefundRequestReason *string `json:"refund_request_reason,omitempty"`
// RefundRequestedBy holds the value of the "refund_requested_by" field.
RefundRequestedBy *string `json:"refund_requested_by,omitempty"`
// ExpiresAt holds the value of the "expires_at" field.
ExpiresAt time.Time `json:"expires_at,omitempty"`
// PaidAt holds the value of the "paid_at" field.
PaidAt *time.Time `json:"paid_at,omitempty"`
// CompletedAt holds the value of the "completed_at" field.
CompletedAt *time.Time `json:"completed_at,omitempty"`
// FailedAt holds the value of the "failed_at" field.
FailedAt *time.Time `json:"failed_at,omitempty"`
// FailedReason holds the value of the "failed_reason" field.
FailedReason *string `json:"failed_reason,omitempty"`
// ClientIP holds the value of the "client_ip" field.
ClientIP string `json:"client_ip,omitempty"`
// SrcHost holds the value of the "src_host" field.
SrcHost string `json:"src_host,omitempty"`
// SrcURL holds the value of the "src_url" field.
SrcURL *string `json:"src_url,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the PaymentOrderQuery when eager-loading is set.
Edges PaymentOrderEdges `json:"edges"`
selectValues sql.SelectValues
}
// PaymentOrderEdges holds the relations/edges for other nodes in the graph.
type PaymentOrderEdges struct {
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [1]bool
}
// UserOrErr returns the User value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e PaymentOrderEdges) UserOrErr() (*User, error) {
if e.User != nil {
return e.User, nil
} else if e.loadedTypes[0] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "user"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*PaymentOrder) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case paymentorder.FieldForceRefund:
values[i] = new(sql.NullBool)
case paymentorder.FieldAmount, paymentorder.FieldPayAmount, paymentorder.FieldFeeRate, paymentorder.FieldRefundAmount:
values[i] = new(sql.NullFloat64)
case paymentorder.FieldID, paymentorder.FieldUserID, paymentorder.FieldPlanID, paymentorder.FieldSubscriptionGroupID, paymentorder.FieldSubscriptionDays:
values[i] = new(sql.NullInt64)
case paymentorder.FieldUserEmail, paymentorder.FieldUserName, paymentorder.FieldUserNotes, paymentorder.FieldRechargeCode, paymentorder.FieldOutTradeNo, paymentorder.FieldPaymentType, paymentorder.FieldPaymentTradeNo, paymentorder.FieldPayURL, paymentorder.FieldQrCode, paymentorder.FieldQrCodeImg, paymentorder.FieldOrderType, paymentorder.FieldProviderInstanceID, paymentorder.FieldStatus, paymentorder.FieldRefundReason, paymentorder.FieldRefundRequestReason, paymentorder.FieldRefundRequestedBy, paymentorder.FieldFailedReason, paymentorder.FieldClientIP, paymentorder.FieldSrcHost, paymentorder.FieldSrcURL:
values[i] = new(sql.NullString)
case paymentorder.FieldRefundAt, paymentorder.FieldRefundRequestedAt, paymentorder.FieldExpiresAt, paymentorder.FieldPaidAt, paymentorder.FieldCompletedAt, paymentorder.FieldFailedAt, paymentorder.FieldCreatedAt, paymentorder.FieldUpdatedAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the PaymentOrder fields.
func (_m *PaymentOrder) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case paymentorder.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case paymentorder.FieldUserID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field user_id", values[i])
} else if value.Valid {
_m.UserID = value.Int64
}
case paymentorder.FieldUserEmail:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field user_email", values[i])
} else if value.Valid {
_m.UserEmail = value.String
}
case paymentorder.FieldUserName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field user_name", values[i])
} else if value.Valid {
_m.UserName = value.String
}
case paymentorder.FieldUserNotes:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field user_notes", values[i])
} else if value.Valid {
_m.UserNotes = new(string)
*_m.UserNotes = value.String
}
case paymentorder.FieldAmount:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field amount", values[i])
} else if value.Valid {
_m.Amount = value.Float64
}
case paymentorder.FieldPayAmount:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field pay_amount", values[i])
} else if value.Valid {
_m.PayAmount = value.Float64
}
case paymentorder.FieldFeeRate:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field fee_rate", values[i])
} else if value.Valid {
_m.FeeRate = value.Float64
}
case paymentorder.FieldRechargeCode:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field recharge_code", values[i])
} else if value.Valid {
_m.RechargeCode = value.String
}
case paymentorder.FieldOutTradeNo:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field out_trade_no", values[i])
} else if value.Valid {
_m.OutTradeNo = value.String
}
case paymentorder.FieldPaymentType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field payment_type", values[i])
} else if value.Valid {
_m.PaymentType = value.String
}
case paymentorder.FieldPaymentTradeNo:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field payment_trade_no", values[i])
} else if value.Valid {
_m.PaymentTradeNo = value.String
}
case paymentorder.FieldPayURL:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field pay_url", values[i])
} else if value.Valid {
_m.PayURL = new(string)
*_m.PayURL = value.String
}
case paymentorder.FieldQrCode:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field qr_code", values[i])
} else if value.Valid {
_m.QrCode = new(string)
*_m.QrCode = value.String
}
case paymentorder.FieldQrCodeImg:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field qr_code_img", values[i])
} else if value.Valid {
_m.QrCodeImg = new(string)
*_m.QrCodeImg = value.String
}
case paymentorder.FieldOrderType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field order_type", values[i])
} else if value.Valid {
_m.OrderType = value.String
}
case paymentorder.FieldPlanID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field plan_id", values[i])
} else if value.Valid {
_m.PlanID = new(int64)
*_m.PlanID = value.Int64
}
case paymentorder.FieldSubscriptionGroupID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field subscription_group_id", values[i])
} else if value.Valid {
_m.SubscriptionGroupID = new(int64)
*_m.SubscriptionGroupID = value.Int64
}
case paymentorder.FieldSubscriptionDays:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field subscription_days", values[i])
} else if value.Valid {
_m.SubscriptionDays = new(int)
*_m.SubscriptionDays = int(value.Int64)
}
case paymentorder.FieldProviderInstanceID:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field provider_instance_id", values[i])
} else if value.Valid {
_m.ProviderInstanceID = new(string)
*_m.ProviderInstanceID = value.String
}
case paymentorder.FieldStatus:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field status", values[i])
} else if value.Valid {
_m.Status = value.String
}
case paymentorder.FieldRefundAmount:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field refund_amount", values[i])
} else if value.Valid {
_m.RefundAmount = value.Float64
}
case paymentorder.FieldRefundReason:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field refund_reason", values[i])
} else if value.Valid {
_m.RefundReason = new(string)
*_m.RefundReason = value.String
}
case paymentorder.FieldRefundAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field refund_at", values[i])
} else if value.Valid {
_m.RefundAt = new(time.Time)
*_m.RefundAt = value.Time
}
case paymentorder.FieldForceRefund:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field force_refund", values[i])
} else if value.Valid {
_m.ForceRefund = value.Bool
}
case paymentorder.FieldRefundRequestedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field refund_requested_at", values[i])
} else if value.Valid {
_m.RefundRequestedAt = new(time.Time)
*_m.RefundRequestedAt = value.Time
}
case paymentorder.FieldRefundRequestReason:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field refund_request_reason", values[i])
} else if value.Valid {
_m.RefundRequestReason = new(string)
*_m.RefundRequestReason = value.String
}
case paymentorder.FieldRefundRequestedBy:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field refund_requested_by", values[i])
} else if value.Valid {
_m.RefundRequestedBy = new(string)
*_m.RefundRequestedBy = value.String
}
case paymentorder.FieldExpiresAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field expires_at", values[i])
} else if value.Valid {
_m.ExpiresAt = value.Time
}
case paymentorder.FieldPaidAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field paid_at", values[i])
} else if value.Valid {
_m.PaidAt = new(time.Time)
*_m.PaidAt = value.Time
}
case paymentorder.FieldCompletedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field completed_at", values[i])
} else if value.Valid {
_m.CompletedAt = new(time.Time)
*_m.CompletedAt = value.Time
}
case paymentorder.FieldFailedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field failed_at", values[i])
} else if value.Valid {
_m.FailedAt = new(time.Time)
*_m.FailedAt = value.Time
}
case paymentorder.FieldFailedReason:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field failed_reason", values[i])
} else if value.Valid {
_m.FailedReason = new(string)
*_m.FailedReason = value.String
}
case paymentorder.FieldClientIP:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field client_ip", values[i])
} else if value.Valid {
_m.ClientIP = value.String
}
case paymentorder.FieldSrcHost:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field src_host", values[i])
} else if value.Valid {
_m.SrcHost = value.String
}
case paymentorder.FieldSrcURL:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field src_url", values[i])
} else if value.Valid {
_m.SrcURL = new(string)
*_m.SrcURL = value.String
}
case paymentorder.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
_m.CreatedAt = value.Time
}
case paymentorder.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
_m.UpdatedAt = value.Time
}
default:
_m.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the PaymentOrder.
// This includes values selected through modifiers, order, etc.
func (_m *PaymentOrder) Value(name string) (ent.Value, error) {
return _m.selectValues.Get(name)
}
// QueryUser queries the "user" edge of the PaymentOrder entity.
func (_m *PaymentOrder) QueryUser() *UserQuery {
return NewPaymentOrderClient(_m.config).QueryUser(_m)
}
// Update returns a builder for updating this PaymentOrder.
// Note that you need to call PaymentOrder.Unwrap() before calling this method if this PaymentOrder
// was returned from a transaction, and the transaction was committed or rolled back.
func (_m *PaymentOrder) Update() *PaymentOrderUpdateOne {
return NewPaymentOrderClient(_m.config).UpdateOne(_m)
}
// Unwrap unwraps the PaymentOrder entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (_m *PaymentOrder) Unwrap() *PaymentOrder {
_tx, ok := _m.config.driver.(*txDriver)
if !ok {
panic("ent: PaymentOrder is not a transactional entity")
}
_m.config.driver = _tx.drv
return _m
}
// String implements the fmt.Stringer.
func (_m *PaymentOrder) String() string {
var builder strings.Builder
builder.WriteString("PaymentOrder(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("user_id=")
builder.WriteString(fmt.Sprintf("%v", _m.UserID))
builder.WriteString(", ")
builder.WriteString("user_email=")
builder.WriteString(_m.UserEmail)
builder.WriteString(", ")
builder.WriteString("user_name=")
builder.WriteString(_m.UserName)
builder.WriteString(", ")
if v := _m.UserNotes; v != nil {
builder.WriteString("user_notes=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("amount=")
builder.WriteString(fmt.Sprintf("%v", _m.Amount))
builder.WriteString(", ")
builder.WriteString("pay_amount=")
builder.WriteString(fmt.Sprintf("%v", _m.PayAmount))
builder.WriteString(", ")
builder.WriteString("fee_rate=")
builder.WriteString(fmt.Sprintf("%v", _m.FeeRate))
builder.WriteString(", ")
builder.WriteString("recharge_code=")
builder.WriteString(_m.RechargeCode)
builder.WriteString(", ")
builder.WriteString("out_trade_no=")
builder.WriteString(_m.OutTradeNo)
builder.WriteString(", ")
builder.WriteString("payment_type=")
builder.WriteString(_m.PaymentType)
builder.WriteString(", ")
builder.WriteString("payment_trade_no=")
builder.WriteString(_m.PaymentTradeNo)
builder.WriteString(", ")
if v := _m.PayURL; v != nil {
builder.WriteString("pay_url=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := _m.QrCode; v != nil {
builder.WriteString("qr_code=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := _m.QrCodeImg; v != nil {
builder.WriteString("qr_code_img=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("order_type=")
builder.WriteString(_m.OrderType)
builder.WriteString(", ")
if v := _m.PlanID; v != nil {
builder.WriteString("plan_id=")
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
if v := _m.SubscriptionGroupID; v != nil {
builder.WriteString("subscription_group_id=")
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
if v := _m.SubscriptionDays; v != nil {
builder.WriteString("subscription_days=")
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
if v := _m.ProviderInstanceID; v != nil {
builder.WriteString("provider_instance_id=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("status=")
builder.WriteString(_m.Status)
builder.WriteString(", ")
builder.WriteString("refund_amount=")
builder.WriteString(fmt.Sprintf("%v", _m.RefundAmount))
builder.WriteString(", ")
if v := _m.RefundReason; v != nil {
builder.WriteString("refund_reason=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := _m.RefundAt; v != nil {
builder.WriteString("refund_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteString(", ")
builder.WriteString("force_refund=")
builder.WriteString(fmt.Sprintf("%v", _m.ForceRefund))
builder.WriteString(", ")
if v := _m.RefundRequestedAt; v != nil {
builder.WriteString("refund_requested_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteString(", ")
if v := _m.RefundRequestReason; v != nil {
builder.WriteString("refund_request_reason=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := _m.RefundRequestedBy; v != nil {
builder.WriteString("refund_requested_by=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("expires_at=")
builder.WriteString(_m.ExpiresAt.Format(time.ANSIC))
builder.WriteString(", ")
if v := _m.PaidAt; v != nil {
builder.WriteString("paid_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteString(", ")
if v := _m.CompletedAt; v != nil {
builder.WriteString("completed_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteString(", ")
if v := _m.FailedAt; v != nil {
builder.WriteString("failed_at=")
builder.WriteString(v.Format(time.ANSIC))
}
builder.WriteString(", ")
if v := _m.FailedReason; v != nil {
builder.WriteString("failed_reason=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("client_ip=")
builder.WriteString(_m.ClientIP)
builder.WriteString(", ")
builder.WriteString("src_host=")
builder.WriteString(_m.SrcHost)
builder.WriteString(", ")
if v := _m.SrcURL; v != nil {
builder.WriteString("src_url=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// PaymentOrders is a parsable slice of PaymentOrder.
type PaymentOrders []*PaymentOrder

View File

@@ -0,0 +1,406 @@
// Code generated by ent, DO NOT EDIT.
package paymentorder
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
const (
// Label holds the string label denoting the paymentorder type in the database.
Label = "payment_order"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldUserID holds the string denoting the user_id field in the database.
FieldUserID = "user_id"
// FieldUserEmail holds the string denoting the user_email field in the database.
FieldUserEmail = "user_email"
// FieldUserName holds the string denoting the user_name field in the database.
FieldUserName = "user_name"
// FieldUserNotes holds the string denoting the user_notes field in the database.
FieldUserNotes = "user_notes"
// FieldAmount holds the string denoting the amount field in the database.
FieldAmount = "amount"
// FieldPayAmount holds the string denoting the pay_amount field in the database.
FieldPayAmount = "pay_amount"
// FieldFeeRate holds the string denoting the fee_rate field in the database.
FieldFeeRate = "fee_rate"
// FieldRechargeCode holds the string denoting the recharge_code field in the database.
FieldRechargeCode = "recharge_code"
// FieldOutTradeNo holds the string denoting the out_trade_no field in the database.
FieldOutTradeNo = "out_trade_no"
// FieldPaymentType holds the string denoting the payment_type field in the database.
FieldPaymentType = "payment_type"
// FieldPaymentTradeNo holds the string denoting the payment_trade_no field in the database.
FieldPaymentTradeNo = "payment_trade_no"
// FieldPayURL holds the string denoting the pay_url field in the database.
FieldPayURL = "pay_url"
// FieldQrCode holds the string denoting the qr_code field in the database.
FieldQrCode = "qr_code"
// FieldQrCodeImg holds the string denoting the qr_code_img field in the database.
FieldQrCodeImg = "qr_code_img"
// FieldOrderType holds the string denoting the order_type field in the database.
FieldOrderType = "order_type"
// FieldPlanID holds the string denoting the plan_id field in the database.
FieldPlanID = "plan_id"
// FieldSubscriptionGroupID holds the string denoting the subscription_group_id field in the database.
FieldSubscriptionGroupID = "subscription_group_id"
// FieldSubscriptionDays holds the string denoting the subscription_days field in the database.
FieldSubscriptionDays = "subscription_days"
// FieldProviderInstanceID holds the string denoting the provider_instance_id field in the database.
FieldProviderInstanceID = "provider_instance_id"
// FieldStatus holds the string denoting the status field in the database.
FieldStatus = "status"
// FieldRefundAmount holds the string denoting the refund_amount field in the database.
FieldRefundAmount = "refund_amount"
// FieldRefundReason holds the string denoting the refund_reason field in the database.
FieldRefundReason = "refund_reason"
// FieldRefundAt holds the string denoting the refund_at field in the database.
FieldRefundAt = "refund_at"
// FieldForceRefund holds the string denoting the force_refund field in the database.
FieldForceRefund = "force_refund"
// FieldRefundRequestedAt holds the string denoting the refund_requested_at field in the database.
FieldRefundRequestedAt = "refund_requested_at"
// FieldRefundRequestReason holds the string denoting the refund_request_reason field in the database.
FieldRefundRequestReason = "refund_request_reason"
// FieldRefundRequestedBy holds the string denoting the refund_requested_by field in the database.
FieldRefundRequestedBy = "refund_requested_by"
// FieldExpiresAt holds the string denoting the expires_at field in the database.
FieldExpiresAt = "expires_at"
// FieldPaidAt holds the string denoting the paid_at field in the database.
FieldPaidAt = "paid_at"
// FieldCompletedAt holds the string denoting the completed_at field in the database.
FieldCompletedAt = "completed_at"
// FieldFailedAt holds the string denoting the failed_at field in the database.
FieldFailedAt = "failed_at"
// FieldFailedReason holds the string denoting the failed_reason field in the database.
FieldFailedReason = "failed_reason"
// FieldClientIP holds the string denoting the client_ip field in the database.
FieldClientIP = "client_ip"
// FieldSrcHost holds the string denoting the src_host field in the database.
FieldSrcHost = "src_host"
// FieldSrcURL holds the string denoting the src_url field in the database.
FieldSrcURL = "src_url"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// EdgeUser holds the string denoting the user edge name in mutations.
EdgeUser = "user"
// Table holds the table name of the paymentorder in the database.
Table = "payment_orders"
// UserTable is the table that holds the user relation/edge.
UserTable = "payment_orders"
// UserInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
UserInverseTable = "users"
// UserColumn is the table column denoting the user relation/edge.
UserColumn = "user_id"
)
// Columns holds all SQL columns for paymentorder fields.
var Columns = []string{
FieldID,
FieldUserID,
FieldUserEmail,
FieldUserName,
FieldUserNotes,
FieldAmount,
FieldPayAmount,
FieldFeeRate,
FieldRechargeCode,
FieldOutTradeNo,
FieldPaymentType,
FieldPaymentTradeNo,
FieldPayURL,
FieldQrCode,
FieldQrCodeImg,
FieldOrderType,
FieldPlanID,
FieldSubscriptionGroupID,
FieldSubscriptionDays,
FieldProviderInstanceID,
FieldStatus,
FieldRefundAmount,
FieldRefundReason,
FieldRefundAt,
FieldForceRefund,
FieldRefundRequestedAt,
FieldRefundRequestReason,
FieldRefundRequestedBy,
FieldExpiresAt,
FieldPaidAt,
FieldCompletedAt,
FieldFailedAt,
FieldFailedReason,
FieldClientIP,
FieldSrcHost,
FieldSrcURL,
FieldCreatedAt,
FieldUpdatedAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// UserEmailValidator is a validator for the "user_email" field. It is called by the builders before save.
UserEmailValidator func(string) error
// UserNameValidator is a validator for the "user_name" field. It is called by the builders before save.
UserNameValidator func(string) error
// DefaultFeeRate holds the default value on creation for the "fee_rate" field.
DefaultFeeRate float64
// RechargeCodeValidator is a validator for the "recharge_code" field. It is called by the builders before save.
RechargeCodeValidator func(string) error
// DefaultOutTradeNo holds the default value on creation for the "out_trade_no" field.
DefaultOutTradeNo string
// OutTradeNoValidator is a validator for the "out_trade_no" field. It is called by the builders before save.
OutTradeNoValidator func(string) error
// PaymentTypeValidator is a validator for the "payment_type" field. It is called by the builders before save.
PaymentTypeValidator func(string) error
// PaymentTradeNoValidator is a validator for the "payment_trade_no" field. It is called by the builders before save.
PaymentTradeNoValidator func(string) error
// DefaultOrderType holds the default value on creation for the "order_type" field.
DefaultOrderType string
// OrderTypeValidator is a validator for the "order_type" field. It is called by the builders before save.
OrderTypeValidator func(string) error
// ProviderInstanceIDValidator is a validator for the "provider_instance_id" field. It is called by the builders before save.
ProviderInstanceIDValidator func(string) error
// DefaultStatus holds the default value on creation for the "status" field.
DefaultStatus string
// StatusValidator is a validator for the "status" field. It is called by the builders before save.
StatusValidator func(string) error
// DefaultRefundAmount holds the default value on creation for the "refund_amount" field.
DefaultRefundAmount float64
// DefaultForceRefund holds the default value on creation for the "force_refund" field.
DefaultForceRefund bool
// RefundRequestedByValidator is a validator for the "refund_requested_by" field. It is called by the builders before save.
RefundRequestedByValidator func(string) error
// ClientIPValidator is a validator for the "client_ip" field. It is called by the builders before save.
ClientIPValidator func(string) error
// SrcHostValidator is a validator for the "src_host" field. It is called by the builders before save.
SrcHostValidator func(string) error
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
)
// OrderOption defines the ordering options for the PaymentOrder queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByUserID orders the results by the user_id field.
func ByUserID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserID, opts...).ToFunc()
}
// ByUserEmail orders the results by the user_email field.
func ByUserEmail(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserEmail, opts...).ToFunc()
}
// ByUserName orders the results by the user_name field.
func ByUserName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserName, opts...).ToFunc()
}
// ByUserNotes orders the results by the user_notes field.
func ByUserNotes(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUserNotes, opts...).ToFunc()
}
// ByAmount orders the results by the amount field.
func ByAmount(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldAmount, opts...).ToFunc()
}
// ByPayAmount orders the results by the pay_amount field.
func ByPayAmount(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPayAmount, opts...).ToFunc()
}
// ByFeeRate orders the results by the fee_rate field.
func ByFeeRate(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFeeRate, opts...).ToFunc()
}
// ByRechargeCode orders the results by the recharge_code field.
func ByRechargeCode(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRechargeCode, opts...).ToFunc()
}
// ByOutTradeNo orders the results by the out_trade_no field.
func ByOutTradeNo(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOutTradeNo, opts...).ToFunc()
}
// ByPaymentType orders the results by the payment_type field.
func ByPaymentType(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPaymentType, opts...).ToFunc()
}
// ByPaymentTradeNo orders the results by the payment_trade_no field.
func ByPaymentTradeNo(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPaymentTradeNo, opts...).ToFunc()
}
// ByPayURL orders the results by the pay_url field.
func ByPayURL(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPayURL, opts...).ToFunc()
}
// ByQrCode orders the results by the qr_code field.
func ByQrCode(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldQrCode, opts...).ToFunc()
}
// ByQrCodeImg orders the results by the qr_code_img field.
func ByQrCodeImg(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldQrCodeImg, opts...).ToFunc()
}
// ByOrderType orders the results by the order_type field.
func ByOrderType(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOrderType, opts...).ToFunc()
}
// ByPlanID orders the results by the plan_id field.
func ByPlanID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPlanID, opts...).ToFunc()
}
// BySubscriptionGroupID orders the results by the subscription_group_id field.
func BySubscriptionGroupID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSubscriptionGroupID, opts...).ToFunc()
}
// BySubscriptionDays orders the results by the subscription_days field.
func BySubscriptionDays(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSubscriptionDays, opts...).ToFunc()
}
// ByProviderInstanceID orders the results by the provider_instance_id field.
func ByProviderInstanceID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldProviderInstanceID, opts...).ToFunc()
}
// ByStatus orders the results by the status field.
func ByStatus(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldStatus, opts...).ToFunc()
}
// ByRefundAmount orders the results by the refund_amount field.
func ByRefundAmount(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundAmount, opts...).ToFunc()
}
// ByRefundReason orders the results by the refund_reason field.
func ByRefundReason(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundReason, opts...).ToFunc()
}
// ByRefundAt orders the results by the refund_at field.
func ByRefundAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundAt, opts...).ToFunc()
}
// ByForceRefund orders the results by the force_refund field.
func ByForceRefund(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldForceRefund, opts...).ToFunc()
}
// ByRefundRequestedAt orders the results by the refund_requested_at field.
func ByRefundRequestedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundRequestedAt, opts...).ToFunc()
}
// ByRefundRequestReason orders the results by the refund_request_reason field.
func ByRefundRequestReason(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundRequestReason, opts...).ToFunc()
}
// ByRefundRequestedBy orders the results by the refund_requested_by field.
func ByRefundRequestedBy(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundRequestedBy, opts...).ToFunc()
}
// ByExpiresAt orders the results by the expires_at field.
func ByExpiresAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldExpiresAt, opts...).ToFunc()
}
// ByPaidAt orders the results by the paid_at field.
func ByPaidAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPaidAt, opts...).ToFunc()
}
// ByCompletedAt orders the results by the completed_at field.
func ByCompletedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCompletedAt, opts...).ToFunc()
}
// ByFailedAt orders the results by the failed_at field.
func ByFailedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFailedAt, opts...).ToFunc()
}
// ByFailedReason orders the results by the failed_reason field.
func ByFailedReason(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFailedReason, opts...).ToFunc()
}
// ByClientIP orders the results by the client_ip field.
func ByClientIP(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldClientIP, opts...).ToFunc()
}
// BySrcHost orders the results by the src_host field.
func BySrcHost(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSrcHost, opts...).ToFunc()
}
// BySrcURL orders the results by the src_url field.
func BySrcURL(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSrcURL, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByUserField orders the results by user field.
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
}
}
func newUserStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentOrderDelete is the builder for deleting a PaymentOrder entity.
type PaymentOrderDelete struct {
config
hooks []Hook
mutation *PaymentOrderMutation
}
// Where appends a list predicates to the PaymentOrderDelete builder.
func (_d *PaymentOrderDelete) Where(ps ...predicate.PaymentOrder) *PaymentOrderDelete {
_d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (_d *PaymentOrderDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentOrderDelete) ExecX(ctx context.Context) int {
n, err := _d.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (_d *PaymentOrderDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(paymentorder.Table, sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64))
if ps := _d.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
_d.mutation.done = true
return affected, err
}
// PaymentOrderDeleteOne is the builder for deleting a single PaymentOrder entity.
type PaymentOrderDeleteOne struct {
_d *PaymentOrderDelete
}
// Where appends a list predicates to the PaymentOrderDelete builder.
func (_d *PaymentOrderDeleteOne) Where(ps ...predicate.PaymentOrder) *PaymentOrderDeleteOne {
_d._d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query.
func (_d *PaymentOrderDeleteOne) Exec(ctx context.Context) error {
n, err := _d._d.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{paymentorder.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentOrderDeleteOne) ExecX(ctx context.Context) {
if err := _d.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,643 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/user"
)
// PaymentOrderQuery is the builder for querying PaymentOrder entities.
type PaymentOrderQuery struct {
config
ctx *QueryContext
order []paymentorder.OrderOption
inters []Interceptor
predicates []predicate.PaymentOrder
withUser *UserQuery
modifiers []func(*sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the PaymentOrderQuery builder.
func (_q *PaymentOrderQuery) Where(ps ...predicate.PaymentOrder) *PaymentOrderQuery {
_q.predicates = append(_q.predicates, ps...)
return _q
}
// Limit the number of records to be returned by this query.
func (_q *PaymentOrderQuery) Limit(limit int) *PaymentOrderQuery {
_q.ctx.Limit = &limit
return _q
}
// Offset to start from.
func (_q *PaymentOrderQuery) Offset(offset int) *PaymentOrderQuery {
_q.ctx.Offset = &offset
return _q
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (_q *PaymentOrderQuery) Unique(unique bool) *PaymentOrderQuery {
_q.ctx.Unique = &unique
return _q
}
// Order specifies how the records should be ordered.
func (_q *PaymentOrderQuery) Order(o ...paymentorder.OrderOption) *PaymentOrderQuery {
_q.order = append(_q.order, o...)
return _q
}
// QueryUser chains the current query on the "user" edge.
func (_q *PaymentOrderQuery) QueryUser() *UserQuery {
query := (&UserClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
selector := _q.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(paymentorder.Table, paymentorder.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, paymentorder.UserTable, paymentorder.UserColumn),
)
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first PaymentOrder entity from the query.
// Returns a *NotFoundError when no PaymentOrder was found.
func (_q *PaymentOrderQuery) First(ctx context.Context) (*PaymentOrder, error) {
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{paymentorder.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (_q *PaymentOrderQuery) FirstX(ctx context.Context) *PaymentOrder {
node, err := _q.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first PaymentOrder ID from the query.
// Returns a *NotFoundError when no PaymentOrder ID was found.
func (_q *PaymentOrderQuery) FirstID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{paymentorder.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (_q *PaymentOrderQuery) FirstIDX(ctx context.Context) int64 {
id, err := _q.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single PaymentOrder entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one PaymentOrder entity is found.
// Returns a *NotFoundError when no PaymentOrder entities are found.
func (_q *PaymentOrderQuery) Only(ctx context.Context) (*PaymentOrder, error) {
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{paymentorder.Label}
default:
return nil, &NotSingularError{paymentorder.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (_q *PaymentOrderQuery) OnlyX(ctx context.Context) *PaymentOrder {
node, err := _q.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only PaymentOrder ID in the query.
// Returns a *NotSingularError when more than one PaymentOrder ID is found.
// Returns a *NotFoundError when no entities are found.
func (_q *PaymentOrderQuery) OnlyID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{paymentorder.Label}
default:
err = &NotSingularError{paymentorder.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (_q *PaymentOrderQuery) OnlyIDX(ctx context.Context) int64 {
id, err := _q.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of PaymentOrders.
func (_q *PaymentOrderQuery) All(ctx context.Context) ([]*PaymentOrder, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*PaymentOrder, *PaymentOrderQuery]()
return withInterceptors[[]*PaymentOrder](ctx, _q, qr, _q.inters)
}
// AllX is like All, but panics if an error occurs.
func (_q *PaymentOrderQuery) AllX(ctx context.Context) []*PaymentOrder {
nodes, err := _q.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of PaymentOrder IDs.
func (_q *PaymentOrderQuery) IDs(ctx context.Context) (ids []int64, err error) {
if _q.ctx.Unique == nil && _q.path != nil {
_q.Unique(true)
}
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
if err = _q.Select(paymentorder.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (_q *PaymentOrderQuery) IDsX(ctx context.Context) []int64 {
ids, err := _q.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (_q *PaymentOrderQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
if err := _q.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, _q, querierCount[*PaymentOrderQuery](), _q.inters)
}
// CountX is like Count, but panics if an error occurs.
func (_q *PaymentOrderQuery) CountX(ctx context.Context) int {
count, err := _q.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (_q *PaymentOrderQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
switch _, err := _q.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (_q *PaymentOrderQuery) ExistX(ctx context.Context) bool {
exist, err := _q.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the PaymentOrderQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (_q *PaymentOrderQuery) Clone() *PaymentOrderQuery {
if _q == nil {
return nil
}
return &PaymentOrderQuery{
config: _q.config,
ctx: _q.ctx.Clone(),
order: append([]paymentorder.OrderOption{}, _q.order...),
inters: append([]Interceptor{}, _q.inters...),
predicates: append([]predicate.PaymentOrder{}, _q.predicates...),
withUser: _q.withUser.Clone(),
// clone intermediate query.
sql: _q.sql.Clone(),
path: _q.path,
}
}
// WithUser tells the query-builder to eager-load the nodes that are connected to
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *PaymentOrderQuery) WithUser(opts ...func(*UserQuery)) *PaymentOrderQuery {
query := (&UserClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
_q.withUser = query
return _q
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// UserID int64 `json:"user_id,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.PaymentOrder.Query().
// GroupBy(paymentorder.FieldUserID).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *PaymentOrderQuery) GroupBy(field string, fields ...string) *PaymentOrderGroupBy {
_q.ctx.Fields = append([]string{field}, fields...)
grbuild := &PaymentOrderGroupBy{build: _q}
grbuild.flds = &_q.ctx.Fields
grbuild.label = paymentorder.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// UserID int64 `json:"user_id,omitempty"`
// }
//
// client.PaymentOrder.Query().
// Select(paymentorder.FieldUserID).
// Scan(ctx, &v)
func (_q *PaymentOrderQuery) Select(fields ...string) *PaymentOrderSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
sbuild := &PaymentOrderSelect{PaymentOrderQuery: _q}
sbuild.label = paymentorder.Label
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a PaymentOrderSelect configured with the given aggregations.
func (_q *PaymentOrderQuery) Aggregate(fns ...AggregateFunc) *PaymentOrderSelect {
return _q.Select().Aggregate(fns...)
}
func (_q *PaymentOrderQuery) prepareQuery(ctx context.Context) error {
for _, inter := range _q.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, _q); err != nil {
return err
}
}
}
for _, f := range _q.ctx.Fields {
if !paymentorder.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if _q.path != nil {
prev, err := _q.path(ctx)
if err != nil {
return err
}
_q.sql = prev
}
return nil
}
func (_q *PaymentOrderQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PaymentOrder, error) {
var (
nodes = []*PaymentOrder{}
_spec = _q.querySpec()
loadedTypes = [1]bool{
_q.withUser != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*PaymentOrder).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &PaymentOrder{config: _q.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := _q.withUser; query != nil {
if err := _q.loadUser(ctx, query, nodes, nil,
func(n *PaymentOrder, e *User) { n.Edges.User = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (_q *PaymentOrderQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*PaymentOrder, init func(*PaymentOrder), assign func(*PaymentOrder, *User)) error {
ids := make([]int64, 0, len(nodes))
nodeids := make(map[int64][]*PaymentOrder)
for i := range nodes {
fk := nodes[i].UserID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "user_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (_q *PaymentOrderQuery) sqlCount(ctx context.Context) (int, error) {
_spec := _q.querySpec()
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
_spec.Node.Columns = _q.ctx.Fields
if len(_q.ctx.Fields) > 0 {
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
}
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
}
func (_q *PaymentOrderQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(paymentorder.Table, paymentorder.Columns, sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64))
_spec.From = _q.sql
if unique := _q.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if _q.path != nil {
_spec.Unique = true
}
if fields := _q.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, paymentorder.FieldID)
for i := range fields {
if fields[i] != paymentorder.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
if _q.withUser != nil {
_spec.Node.AddColumnOnce(paymentorder.FieldUserID)
}
}
if ps := _q.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := _q.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := _q.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := _q.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (_q *PaymentOrderQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(_q.driver.Dialect())
t1 := builder.Table(paymentorder.Table)
columns := _q.ctx.Fields
if len(columns) == 0 {
columns = paymentorder.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if _q.sql != nil {
selector = _q.sql
selector.Select(selector.Columns(columns...)...)
}
if _q.ctx.Unique != nil && *_q.ctx.Unique {
selector.Distinct()
}
for _, m := range _q.modifiers {
m(selector)
}
for _, p := range _q.predicates {
p(selector)
}
for _, p := range _q.order {
p(selector)
}
if offset := _q.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := _q.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
// either committed or rolled-back.
func (_q *PaymentOrderQuery) ForUpdate(opts ...sql.LockOption) *PaymentOrderQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForUpdate(opts...)
})
return _q
}
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
// on any rows that are read. Other sessions can read the rows, but cannot modify them
// until your transaction commits.
func (_q *PaymentOrderQuery) ForShare(opts ...sql.LockOption) *PaymentOrderQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForShare(opts...)
})
return _q
}
// PaymentOrderGroupBy is the group-by builder for PaymentOrder entities.
type PaymentOrderGroupBy struct {
selector
build *PaymentOrderQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (_g *PaymentOrderGroupBy) Aggregate(fns ...AggregateFunc) *PaymentOrderGroupBy {
_g.fns = append(_g.fns, fns...)
return _g
}
// Scan applies the selector query and scans the result into the given value.
func (_g *PaymentOrderGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
if err := _g.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentOrderQuery, *PaymentOrderGroupBy](ctx, _g.build, _g, _g.build.inters, v)
}
func (_g *PaymentOrderGroupBy) sqlScan(ctx context.Context, root *PaymentOrderQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(_g.fns))
for _, fn := range _g.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
for _, f := range *_g.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*_g.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// PaymentOrderSelect is the builder for selecting fields of PaymentOrder entities.
type PaymentOrderSelect struct {
*PaymentOrderQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (_s *PaymentOrderSelect) Aggregate(fns ...AggregateFunc) *PaymentOrderSelect {
_s.fns = append(_s.fns, fns...)
return _s
}
// Scan applies the selector query and scans the result into the given value.
func (_s *PaymentOrderSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
if err := _s.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentOrderQuery, *PaymentOrderSelect](ctx, _s.PaymentOrderQuery, _s, _s.inters, v)
}
func (_s *PaymentOrderSelect) sqlScan(ctx context.Context, root *PaymentOrderQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(_s.fns))
for _, fn := range _s.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*_s.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
)
// PaymentProviderInstance is the model entity for the PaymentProviderInstance schema.
type PaymentProviderInstance struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// ProviderKey holds the value of the "provider_key" field.
ProviderKey string `json:"provider_key,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Config holds the value of the "config" field.
Config string `json:"config,omitempty"`
// SupportedTypes holds the value of the "supported_types" field.
SupportedTypes string `json:"supported_types,omitempty"`
// Enabled holds the value of the "enabled" field.
Enabled bool `json:"enabled,omitempty"`
// PaymentMode holds the value of the "payment_mode" field.
PaymentMode string `json:"payment_mode,omitempty"`
// SortOrder holds the value of the "sort_order" field.
SortOrder int `json:"sort_order,omitempty"`
// Limits holds the value of the "limits" field.
Limits string `json:"limits,omitempty"`
// RefundEnabled holds the value of the "refund_enabled" field.
RefundEnabled bool `json:"refund_enabled,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
selectValues sql.SelectValues
}
// scanValues returns the types for scanning values from sql.Rows.
func (*PaymentProviderInstance) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case paymentproviderinstance.FieldEnabled, paymentproviderinstance.FieldRefundEnabled:
values[i] = new(sql.NullBool)
case paymentproviderinstance.FieldID, paymentproviderinstance.FieldSortOrder:
values[i] = new(sql.NullInt64)
case paymentproviderinstance.FieldProviderKey, paymentproviderinstance.FieldName, paymentproviderinstance.FieldConfig, paymentproviderinstance.FieldSupportedTypes, paymentproviderinstance.FieldPaymentMode, paymentproviderinstance.FieldLimits:
values[i] = new(sql.NullString)
case paymentproviderinstance.FieldCreatedAt, paymentproviderinstance.FieldUpdatedAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the PaymentProviderInstance fields.
func (_m *PaymentProviderInstance) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case paymentproviderinstance.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case paymentproviderinstance.FieldProviderKey:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field provider_key", values[i])
} else if value.Valid {
_m.ProviderKey = value.String
}
case paymentproviderinstance.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
_m.Name = value.String
}
case paymentproviderinstance.FieldConfig:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field config", values[i])
} else if value.Valid {
_m.Config = value.String
}
case paymentproviderinstance.FieldSupportedTypes:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field supported_types", values[i])
} else if value.Valid {
_m.SupportedTypes = value.String
}
case paymentproviderinstance.FieldEnabled:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field enabled", values[i])
} else if value.Valid {
_m.Enabled = value.Bool
}
case paymentproviderinstance.FieldPaymentMode:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field payment_mode", values[i])
} else if value.Valid {
_m.PaymentMode = value.String
}
case paymentproviderinstance.FieldSortOrder:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field sort_order", values[i])
} else if value.Valid {
_m.SortOrder = int(value.Int64)
}
case paymentproviderinstance.FieldLimits:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field limits", values[i])
} else if value.Valid {
_m.Limits = value.String
}
case paymentproviderinstance.FieldRefundEnabled:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field refund_enabled", values[i])
} else if value.Valid {
_m.RefundEnabled = value.Bool
}
case paymentproviderinstance.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
_m.CreatedAt = value.Time
}
case paymentproviderinstance.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
_m.UpdatedAt = value.Time
}
default:
_m.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the PaymentProviderInstance.
// This includes values selected through modifiers, order, etc.
func (_m *PaymentProviderInstance) Value(name string) (ent.Value, error) {
return _m.selectValues.Get(name)
}
// Update returns a builder for updating this PaymentProviderInstance.
// Note that you need to call PaymentProviderInstance.Unwrap() before calling this method if this PaymentProviderInstance
// was returned from a transaction, and the transaction was committed or rolled back.
func (_m *PaymentProviderInstance) Update() *PaymentProviderInstanceUpdateOne {
return NewPaymentProviderInstanceClient(_m.config).UpdateOne(_m)
}
// Unwrap unwraps the PaymentProviderInstance entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (_m *PaymentProviderInstance) Unwrap() *PaymentProviderInstance {
_tx, ok := _m.config.driver.(*txDriver)
if !ok {
panic("ent: PaymentProviderInstance is not a transactional entity")
}
_m.config.driver = _tx.drv
return _m
}
// String implements the fmt.Stringer.
func (_m *PaymentProviderInstance) String() string {
var builder strings.Builder
builder.WriteString("PaymentProviderInstance(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("provider_key=")
builder.WriteString(_m.ProviderKey)
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(_m.Name)
builder.WriteString(", ")
builder.WriteString("config=")
builder.WriteString(_m.Config)
builder.WriteString(", ")
builder.WriteString("supported_types=")
builder.WriteString(_m.SupportedTypes)
builder.WriteString(", ")
builder.WriteString("enabled=")
builder.WriteString(fmt.Sprintf("%v", _m.Enabled))
builder.WriteString(", ")
builder.WriteString("payment_mode=")
builder.WriteString(_m.PaymentMode)
builder.WriteString(", ")
builder.WriteString("sort_order=")
builder.WriteString(fmt.Sprintf("%v", _m.SortOrder))
builder.WriteString(", ")
builder.WriteString("limits=")
builder.WriteString(_m.Limits)
builder.WriteString(", ")
builder.WriteString("refund_enabled=")
builder.WriteString(fmt.Sprintf("%v", _m.RefundEnabled))
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// PaymentProviderInstances is a parsable slice of PaymentProviderInstance.
type PaymentProviderInstances []*PaymentProviderInstance

View File

@@ -0,0 +1,160 @@
// Code generated by ent, DO NOT EDIT.
package paymentproviderinstance
import (
"time"
"entgo.io/ent/dialect/sql"
)
const (
// Label holds the string label denoting the paymentproviderinstance type in the database.
Label = "payment_provider_instance"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldProviderKey holds the string denoting the provider_key field in the database.
FieldProviderKey = "provider_key"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldConfig holds the string denoting the config field in the database.
FieldConfig = "config"
// FieldSupportedTypes holds the string denoting the supported_types field in the database.
FieldSupportedTypes = "supported_types"
// FieldEnabled holds the string denoting the enabled field in the database.
FieldEnabled = "enabled"
// FieldPaymentMode holds the string denoting the payment_mode field in the database.
FieldPaymentMode = "payment_mode"
// FieldSortOrder holds the string denoting the sort_order field in the database.
FieldSortOrder = "sort_order"
// FieldLimits holds the string denoting the limits field in the database.
FieldLimits = "limits"
// FieldRefundEnabled holds the string denoting the refund_enabled field in the database.
FieldRefundEnabled = "refund_enabled"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// Table holds the table name of the paymentproviderinstance in the database.
Table = "payment_provider_instances"
)
// Columns holds all SQL columns for paymentproviderinstance fields.
var Columns = []string{
FieldID,
FieldProviderKey,
FieldName,
FieldConfig,
FieldSupportedTypes,
FieldEnabled,
FieldPaymentMode,
FieldSortOrder,
FieldLimits,
FieldRefundEnabled,
FieldCreatedAt,
FieldUpdatedAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
ProviderKeyValidator func(string) error
// DefaultName holds the default value on creation for the "name" field.
DefaultName string
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// DefaultSupportedTypes holds the default value on creation for the "supported_types" field.
DefaultSupportedTypes string
// SupportedTypesValidator is a validator for the "supported_types" field. It is called by the builders before save.
SupportedTypesValidator func(string) error
// DefaultEnabled holds the default value on creation for the "enabled" field.
DefaultEnabled bool
// DefaultPaymentMode holds the default value on creation for the "payment_mode" field.
DefaultPaymentMode string
// PaymentModeValidator is a validator for the "payment_mode" field. It is called by the builders before save.
PaymentModeValidator func(string) error
// DefaultSortOrder holds the default value on creation for the "sort_order" field.
DefaultSortOrder int
// DefaultLimits holds the default value on creation for the "limits" field.
DefaultLimits string
// DefaultRefundEnabled holds the default value on creation for the "refund_enabled" field.
DefaultRefundEnabled bool
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
)
// OrderOption defines the ordering options for the PaymentProviderInstance queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByProviderKey orders the results by the provider_key field.
func ByProviderKey(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldProviderKey, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByConfig orders the results by the config field.
func ByConfig(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldConfig, opts...).ToFunc()
}
// BySupportedTypes orders the results by the supported_types field.
func BySupportedTypes(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSupportedTypes, opts...).ToFunc()
}
// ByEnabled orders the results by the enabled field.
func ByEnabled(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldEnabled, opts...).ToFunc()
}
// ByPaymentMode orders the results by the payment_mode field.
func ByPaymentMode(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPaymentMode, opts...).ToFunc()
}
// BySortOrder orders the results by the sort_order field.
func BySortOrder(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSortOrder, opts...).ToFunc()
}
// ByLimits orders the results by the limits field.
func ByLimits(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldLimits, opts...).ToFunc()
}
// ByRefundEnabled orders the results by the refund_enabled field.
func ByRefundEnabled(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRefundEnabled, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}

View File

@@ -0,0 +1,655 @@
// Code generated by ent, DO NOT EDIT.
package paymentproviderinstance
import (
"time"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int64) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldID, id))
}
// ProviderKey applies equality check predicate on the "provider_key" field. It's identical to ProviderKeyEQ.
func ProviderKey(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldProviderKey, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldName, v))
}
// Config applies equality check predicate on the "config" field. It's identical to ConfigEQ.
func Config(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldConfig, v))
}
// SupportedTypes applies equality check predicate on the "supported_types" field. It's identical to SupportedTypesEQ.
func SupportedTypes(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldSupportedTypes, v))
}
// Enabled applies equality check predicate on the "enabled" field. It's identical to EnabledEQ.
func Enabled(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldEnabled, v))
}
// PaymentMode applies equality check predicate on the "payment_mode" field. It's identical to PaymentModeEQ.
func PaymentMode(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldPaymentMode, v))
}
// SortOrder applies equality check predicate on the "sort_order" field. It's identical to SortOrderEQ.
func SortOrder(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldSortOrder, v))
}
// Limits applies equality check predicate on the "limits" field. It's identical to LimitsEQ.
func Limits(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldLimits, v))
}
// RefundEnabled applies equality check predicate on the "refund_enabled" field. It's identical to RefundEnabledEQ.
func RefundEnabled(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldRefundEnabled, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldUpdatedAt, v))
}
// ProviderKeyEQ applies the EQ predicate on the "provider_key" field.
func ProviderKeyEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldProviderKey, v))
}
// ProviderKeyNEQ applies the NEQ predicate on the "provider_key" field.
func ProviderKeyNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldProviderKey, v))
}
// ProviderKeyIn applies the In predicate on the "provider_key" field.
func ProviderKeyIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldProviderKey, vs...))
}
// ProviderKeyNotIn applies the NotIn predicate on the "provider_key" field.
func ProviderKeyNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldProviderKey, vs...))
}
// ProviderKeyGT applies the GT predicate on the "provider_key" field.
func ProviderKeyGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldProviderKey, v))
}
// ProviderKeyGTE applies the GTE predicate on the "provider_key" field.
func ProviderKeyGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldProviderKey, v))
}
// ProviderKeyLT applies the LT predicate on the "provider_key" field.
func ProviderKeyLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldProviderKey, v))
}
// ProviderKeyLTE applies the LTE predicate on the "provider_key" field.
func ProviderKeyLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldProviderKey, v))
}
// ProviderKeyContains applies the Contains predicate on the "provider_key" field.
func ProviderKeyContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldProviderKey, v))
}
// ProviderKeyHasPrefix applies the HasPrefix predicate on the "provider_key" field.
func ProviderKeyHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldProviderKey, v))
}
// ProviderKeyHasSuffix applies the HasSuffix predicate on the "provider_key" field.
func ProviderKeyHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldProviderKey, v))
}
// ProviderKeyEqualFold applies the EqualFold predicate on the "provider_key" field.
func ProviderKeyEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldProviderKey, v))
}
// ProviderKeyContainsFold applies the ContainsFold predicate on the "provider_key" field.
func ProviderKeyContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldProviderKey, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldName, v))
}
// ConfigEQ applies the EQ predicate on the "config" field.
func ConfigEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldConfig, v))
}
// ConfigNEQ applies the NEQ predicate on the "config" field.
func ConfigNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldConfig, v))
}
// ConfigIn applies the In predicate on the "config" field.
func ConfigIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldConfig, vs...))
}
// ConfigNotIn applies the NotIn predicate on the "config" field.
func ConfigNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldConfig, vs...))
}
// ConfigGT applies the GT predicate on the "config" field.
func ConfigGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldConfig, v))
}
// ConfigGTE applies the GTE predicate on the "config" field.
func ConfigGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldConfig, v))
}
// ConfigLT applies the LT predicate on the "config" field.
func ConfigLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldConfig, v))
}
// ConfigLTE applies the LTE predicate on the "config" field.
func ConfigLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldConfig, v))
}
// ConfigContains applies the Contains predicate on the "config" field.
func ConfigContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldConfig, v))
}
// ConfigHasPrefix applies the HasPrefix predicate on the "config" field.
func ConfigHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldConfig, v))
}
// ConfigHasSuffix applies the HasSuffix predicate on the "config" field.
func ConfigHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldConfig, v))
}
// ConfigEqualFold applies the EqualFold predicate on the "config" field.
func ConfigEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldConfig, v))
}
// ConfigContainsFold applies the ContainsFold predicate on the "config" field.
func ConfigContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldConfig, v))
}
// SupportedTypesEQ applies the EQ predicate on the "supported_types" field.
func SupportedTypesEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldSupportedTypes, v))
}
// SupportedTypesNEQ applies the NEQ predicate on the "supported_types" field.
func SupportedTypesNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldSupportedTypes, v))
}
// SupportedTypesIn applies the In predicate on the "supported_types" field.
func SupportedTypesIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldSupportedTypes, vs...))
}
// SupportedTypesNotIn applies the NotIn predicate on the "supported_types" field.
func SupportedTypesNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldSupportedTypes, vs...))
}
// SupportedTypesGT applies the GT predicate on the "supported_types" field.
func SupportedTypesGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldSupportedTypes, v))
}
// SupportedTypesGTE applies the GTE predicate on the "supported_types" field.
func SupportedTypesGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldSupportedTypes, v))
}
// SupportedTypesLT applies the LT predicate on the "supported_types" field.
func SupportedTypesLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldSupportedTypes, v))
}
// SupportedTypesLTE applies the LTE predicate on the "supported_types" field.
func SupportedTypesLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldSupportedTypes, v))
}
// SupportedTypesContains applies the Contains predicate on the "supported_types" field.
func SupportedTypesContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldSupportedTypes, v))
}
// SupportedTypesHasPrefix applies the HasPrefix predicate on the "supported_types" field.
func SupportedTypesHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldSupportedTypes, v))
}
// SupportedTypesHasSuffix applies the HasSuffix predicate on the "supported_types" field.
func SupportedTypesHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldSupportedTypes, v))
}
// SupportedTypesEqualFold applies the EqualFold predicate on the "supported_types" field.
func SupportedTypesEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldSupportedTypes, v))
}
// SupportedTypesContainsFold applies the ContainsFold predicate on the "supported_types" field.
func SupportedTypesContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldSupportedTypes, v))
}
// EnabledEQ applies the EQ predicate on the "enabled" field.
func EnabledEQ(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldEnabled, v))
}
// EnabledNEQ applies the NEQ predicate on the "enabled" field.
func EnabledNEQ(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldEnabled, v))
}
// PaymentModeEQ applies the EQ predicate on the "payment_mode" field.
func PaymentModeEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldPaymentMode, v))
}
// PaymentModeNEQ applies the NEQ predicate on the "payment_mode" field.
func PaymentModeNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldPaymentMode, v))
}
// PaymentModeIn applies the In predicate on the "payment_mode" field.
func PaymentModeIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldPaymentMode, vs...))
}
// PaymentModeNotIn applies the NotIn predicate on the "payment_mode" field.
func PaymentModeNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldPaymentMode, vs...))
}
// PaymentModeGT applies the GT predicate on the "payment_mode" field.
func PaymentModeGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldPaymentMode, v))
}
// PaymentModeGTE applies the GTE predicate on the "payment_mode" field.
func PaymentModeGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldPaymentMode, v))
}
// PaymentModeLT applies the LT predicate on the "payment_mode" field.
func PaymentModeLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldPaymentMode, v))
}
// PaymentModeLTE applies the LTE predicate on the "payment_mode" field.
func PaymentModeLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldPaymentMode, v))
}
// PaymentModeContains applies the Contains predicate on the "payment_mode" field.
func PaymentModeContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldPaymentMode, v))
}
// PaymentModeHasPrefix applies the HasPrefix predicate on the "payment_mode" field.
func PaymentModeHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldPaymentMode, v))
}
// PaymentModeHasSuffix applies the HasSuffix predicate on the "payment_mode" field.
func PaymentModeHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldPaymentMode, v))
}
// PaymentModeEqualFold applies the EqualFold predicate on the "payment_mode" field.
func PaymentModeEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldPaymentMode, v))
}
// PaymentModeContainsFold applies the ContainsFold predicate on the "payment_mode" field.
func PaymentModeContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldPaymentMode, v))
}
// SortOrderEQ applies the EQ predicate on the "sort_order" field.
func SortOrderEQ(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldSortOrder, v))
}
// SortOrderNEQ applies the NEQ predicate on the "sort_order" field.
func SortOrderNEQ(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldSortOrder, v))
}
// SortOrderIn applies the In predicate on the "sort_order" field.
func SortOrderIn(vs ...int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldSortOrder, vs...))
}
// SortOrderNotIn applies the NotIn predicate on the "sort_order" field.
func SortOrderNotIn(vs ...int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldSortOrder, vs...))
}
// SortOrderGT applies the GT predicate on the "sort_order" field.
func SortOrderGT(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldSortOrder, v))
}
// SortOrderGTE applies the GTE predicate on the "sort_order" field.
func SortOrderGTE(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldSortOrder, v))
}
// SortOrderLT applies the LT predicate on the "sort_order" field.
func SortOrderLT(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldSortOrder, v))
}
// SortOrderLTE applies the LTE predicate on the "sort_order" field.
func SortOrderLTE(v int) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldSortOrder, v))
}
// LimitsEQ applies the EQ predicate on the "limits" field.
func LimitsEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldLimits, v))
}
// LimitsNEQ applies the NEQ predicate on the "limits" field.
func LimitsNEQ(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldLimits, v))
}
// LimitsIn applies the In predicate on the "limits" field.
func LimitsIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldLimits, vs...))
}
// LimitsNotIn applies the NotIn predicate on the "limits" field.
func LimitsNotIn(vs ...string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldLimits, vs...))
}
// LimitsGT applies the GT predicate on the "limits" field.
func LimitsGT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldLimits, v))
}
// LimitsGTE applies the GTE predicate on the "limits" field.
func LimitsGTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldLimits, v))
}
// LimitsLT applies the LT predicate on the "limits" field.
func LimitsLT(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldLimits, v))
}
// LimitsLTE applies the LTE predicate on the "limits" field.
func LimitsLTE(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldLimits, v))
}
// LimitsContains applies the Contains predicate on the "limits" field.
func LimitsContains(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContains(FieldLimits, v))
}
// LimitsHasPrefix applies the HasPrefix predicate on the "limits" field.
func LimitsHasPrefix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasPrefix(FieldLimits, v))
}
// LimitsHasSuffix applies the HasSuffix predicate on the "limits" field.
func LimitsHasSuffix(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldHasSuffix(FieldLimits, v))
}
// LimitsEqualFold applies the EqualFold predicate on the "limits" field.
func LimitsEqualFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEqualFold(FieldLimits, v))
}
// LimitsContainsFold applies the ContainsFold predicate on the "limits" field.
func LimitsContainsFold(v string) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldContainsFold(FieldLimits, v))
}
// RefundEnabledEQ applies the EQ predicate on the "refund_enabled" field.
func RefundEnabledEQ(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldRefundEnabled, v))
}
// RefundEnabledNEQ applies the NEQ predicate on the "refund_enabled" field.
func RefundEnabledNEQ(v bool) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldRefundEnabled, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.FieldLTE(FieldUpdatedAt, v))
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.PaymentProviderInstance) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.PaymentProviderInstance) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.PaymentProviderInstance) predicate.PaymentProviderInstance {
return predicate.PaymentProviderInstance(sql.NotPredicates(p))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentProviderInstanceDelete is the builder for deleting a PaymentProviderInstance entity.
type PaymentProviderInstanceDelete struct {
config
hooks []Hook
mutation *PaymentProviderInstanceMutation
}
// Where appends a list predicates to the PaymentProviderInstanceDelete builder.
func (_d *PaymentProviderInstanceDelete) Where(ps ...predicate.PaymentProviderInstance) *PaymentProviderInstanceDelete {
_d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (_d *PaymentProviderInstanceDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentProviderInstanceDelete) ExecX(ctx context.Context) int {
n, err := _d.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (_d *PaymentProviderInstanceDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(paymentproviderinstance.Table, sqlgraph.NewFieldSpec(paymentproviderinstance.FieldID, field.TypeInt64))
if ps := _d.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
_d.mutation.done = true
return affected, err
}
// PaymentProviderInstanceDeleteOne is the builder for deleting a single PaymentProviderInstance entity.
type PaymentProviderInstanceDeleteOne struct {
_d *PaymentProviderInstanceDelete
}
// Where appends a list predicates to the PaymentProviderInstanceDelete builder.
func (_d *PaymentProviderInstanceDeleteOne) Where(ps ...predicate.PaymentProviderInstance) *PaymentProviderInstanceDeleteOne {
_d._d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query.
func (_d *PaymentProviderInstanceDeleteOne) Exec(ctx context.Context) error {
n, err := _d._d.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{paymentproviderinstance.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *PaymentProviderInstanceDeleteOne) ExecX(ctx context.Context) {
if err := _d.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,564 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentProviderInstanceQuery is the builder for querying PaymentProviderInstance entities.
type PaymentProviderInstanceQuery struct {
config
ctx *QueryContext
order []paymentproviderinstance.OrderOption
inters []Interceptor
predicates []predicate.PaymentProviderInstance
modifiers []func(*sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the PaymentProviderInstanceQuery builder.
func (_q *PaymentProviderInstanceQuery) Where(ps ...predicate.PaymentProviderInstance) *PaymentProviderInstanceQuery {
_q.predicates = append(_q.predicates, ps...)
return _q
}
// Limit the number of records to be returned by this query.
func (_q *PaymentProviderInstanceQuery) Limit(limit int) *PaymentProviderInstanceQuery {
_q.ctx.Limit = &limit
return _q
}
// Offset to start from.
func (_q *PaymentProviderInstanceQuery) Offset(offset int) *PaymentProviderInstanceQuery {
_q.ctx.Offset = &offset
return _q
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (_q *PaymentProviderInstanceQuery) Unique(unique bool) *PaymentProviderInstanceQuery {
_q.ctx.Unique = &unique
return _q
}
// Order specifies how the records should be ordered.
func (_q *PaymentProviderInstanceQuery) Order(o ...paymentproviderinstance.OrderOption) *PaymentProviderInstanceQuery {
_q.order = append(_q.order, o...)
return _q
}
// First returns the first PaymentProviderInstance entity from the query.
// Returns a *NotFoundError when no PaymentProviderInstance was found.
func (_q *PaymentProviderInstanceQuery) First(ctx context.Context) (*PaymentProviderInstance, error) {
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{paymentproviderinstance.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) FirstX(ctx context.Context) *PaymentProviderInstance {
node, err := _q.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first PaymentProviderInstance ID from the query.
// Returns a *NotFoundError when no PaymentProviderInstance ID was found.
func (_q *PaymentProviderInstanceQuery) FirstID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{paymentproviderinstance.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) FirstIDX(ctx context.Context) int64 {
id, err := _q.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single PaymentProviderInstance entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one PaymentProviderInstance entity is found.
// Returns a *NotFoundError when no PaymentProviderInstance entities are found.
func (_q *PaymentProviderInstanceQuery) Only(ctx context.Context) (*PaymentProviderInstance, error) {
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{paymentproviderinstance.Label}
default:
return nil, &NotSingularError{paymentproviderinstance.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) OnlyX(ctx context.Context) *PaymentProviderInstance {
node, err := _q.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only PaymentProviderInstance ID in the query.
// Returns a *NotSingularError when more than one PaymentProviderInstance ID is found.
// Returns a *NotFoundError when no entities are found.
func (_q *PaymentProviderInstanceQuery) OnlyID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{paymentproviderinstance.Label}
default:
err = &NotSingularError{paymentproviderinstance.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) OnlyIDX(ctx context.Context) int64 {
id, err := _q.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of PaymentProviderInstances.
func (_q *PaymentProviderInstanceQuery) All(ctx context.Context) ([]*PaymentProviderInstance, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*PaymentProviderInstance, *PaymentProviderInstanceQuery]()
return withInterceptors[[]*PaymentProviderInstance](ctx, _q, qr, _q.inters)
}
// AllX is like All, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) AllX(ctx context.Context) []*PaymentProviderInstance {
nodes, err := _q.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of PaymentProviderInstance IDs.
func (_q *PaymentProviderInstanceQuery) IDs(ctx context.Context) (ids []int64, err error) {
if _q.ctx.Unique == nil && _q.path != nil {
_q.Unique(true)
}
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
if err = _q.Select(paymentproviderinstance.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) IDsX(ctx context.Context) []int64 {
ids, err := _q.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (_q *PaymentProviderInstanceQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
if err := _q.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, _q, querierCount[*PaymentProviderInstanceQuery](), _q.inters)
}
// CountX is like Count, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) CountX(ctx context.Context) int {
count, err := _q.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (_q *PaymentProviderInstanceQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
switch _, err := _q.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (_q *PaymentProviderInstanceQuery) ExistX(ctx context.Context) bool {
exist, err := _q.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the PaymentProviderInstanceQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (_q *PaymentProviderInstanceQuery) Clone() *PaymentProviderInstanceQuery {
if _q == nil {
return nil
}
return &PaymentProviderInstanceQuery{
config: _q.config,
ctx: _q.ctx.Clone(),
order: append([]paymentproviderinstance.OrderOption{}, _q.order...),
inters: append([]Interceptor{}, _q.inters...),
predicates: append([]predicate.PaymentProviderInstance{}, _q.predicates...),
// clone intermediate query.
sql: _q.sql.Clone(),
path: _q.path,
}
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// ProviderKey string `json:"provider_key,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.PaymentProviderInstance.Query().
// GroupBy(paymentproviderinstance.FieldProviderKey).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *PaymentProviderInstanceQuery) GroupBy(field string, fields ...string) *PaymentProviderInstanceGroupBy {
_q.ctx.Fields = append([]string{field}, fields...)
grbuild := &PaymentProviderInstanceGroupBy{build: _q}
grbuild.flds = &_q.ctx.Fields
grbuild.label = paymentproviderinstance.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// ProviderKey string `json:"provider_key,omitempty"`
// }
//
// client.PaymentProviderInstance.Query().
// Select(paymentproviderinstance.FieldProviderKey).
// Scan(ctx, &v)
func (_q *PaymentProviderInstanceQuery) Select(fields ...string) *PaymentProviderInstanceSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
sbuild := &PaymentProviderInstanceSelect{PaymentProviderInstanceQuery: _q}
sbuild.label = paymentproviderinstance.Label
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a PaymentProviderInstanceSelect configured with the given aggregations.
func (_q *PaymentProviderInstanceQuery) Aggregate(fns ...AggregateFunc) *PaymentProviderInstanceSelect {
return _q.Select().Aggregate(fns...)
}
func (_q *PaymentProviderInstanceQuery) prepareQuery(ctx context.Context) error {
for _, inter := range _q.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, _q); err != nil {
return err
}
}
}
for _, f := range _q.ctx.Fields {
if !paymentproviderinstance.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if _q.path != nil {
prev, err := _q.path(ctx)
if err != nil {
return err
}
_q.sql = prev
}
return nil
}
func (_q *PaymentProviderInstanceQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PaymentProviderInstance, error) {
var (
nodes = []*PaymentProviderInstance{}
_spec = _q.querySpec()
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*PaymentProviderInstance).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &PaymentProviderInstance{config: _q.config}
nodes = append(nodes, node)
return node.assignValues(columns, values)
}
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
return nodes, nil
}
func (_q *PaymentProviderInstanceQuery) sqlCount(ctx context.Context) (int, error) {
_spec := _q.querySpec()
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
_spec.Node.Columns = _q.ctx.Fields
if len(_q.ctx.Fields) > 0 {
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
}
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
}
func (_q *PaymentProviderInstanceQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(paymentproviderinstance.Table, paymentproviderinstance.Columns, sqlgraph.NewFieldSpec(paymentproviderinstance.FieldID, field.TypeInt64))
_spec.From = _q.sql
if unique := _q.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if _q.path != nil {
_spec.Unique = true
}
if fields := _q.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, paymentproviderinstance.FieldID)
for i := range fields {
if fields[i] != paymentproviderinstance.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := _q.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := _q.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := _q.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := _q.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (_q *PaymentProviderInstanceQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(_q.driver.Dialect())
t1 := builder.Table(paymentproviderinstance.Table)
columns := _q.ctx.Fields
if len(columns) == 0 {
columns = paymentproviderinstance.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if _q.sql != nil {
selector = _q.sql
selector.Select(selector.Columns(columns...)...)
}
if _q.ctx.Unique != nil && *_q.ctx.Unique {
selector.Distinct()
}
for _, m := range _q.modifiers {
m(selector)
}
for _, p := range _q.predicates {
p(selector)
}
for _, p := range _q.order {
p(selector)
}
if offset := _q.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := _q.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
// either committed or rolled-back.
func (_q *PaymentProviderInstanceQuery) ForUpdate(opts ...sql.LockOption) *PaymentProviderInstanceQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForUpdate(opts...)
})
return _q
}
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
// on any rows that are read. Other sessions can read the rows, but cannot modify them
// until your transaction commits.
func (_q *PaymentProviderInstanceQuery) ForShare(opts ...sql.LockOption) *PaymentProviderInstanceQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForShare(opts...)
})
return _q
}
// PaymentProviderInstanceGroupBy is the group-by builder for PaymentProviderInstance entities.
type PaymentProviderInstanceGroupBy struct {
selector
build *PaymentProviderInstanceQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (_g *PaymentProviderInstanceGroupBy) Aggregate(fns ...AggregateFunc) *PaymentProviderInstanceGroupBy {
_g.fns = append(_g.fns, fns...)
return _g
}
// Scan applies the selector query and scans the result into the given value.
func (_g *PaymentProviderInstanceGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
if err := _g.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentProviderInstanceQuery, *PaymentProviderInstanceGroupBy](ctx, _g.build, _g, _g.build.inters, v)
}
func (_g *PaymentProviderInstanceGroupBy) sqlScan(ctx context.Context, root *PaymentProviderInstanceQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(_g.fns))
for _, fn := range _g.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
for _, f := range *_g.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*_g.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// PaymentProviderInstanceSelect is the builder for selecting fields of PaymentProviderInstance entities.
type PaymentProviderInstanceSelect struct {
*PaymentProviderInstanceQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (_s *PaymentProviderInstanceSelect) Aggregate(fns ...AggregateFunc) *PaymentProviderInstanceSelect {
_s.fns = append(_s.fns, fns...)
return _s
}
// Scan applies the selector query and scans the result into the given value.
func (_s *PaymentProviderInstanceSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
if err := _s.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PaymentProviderInstanceQuery, *PaymentProviderInstanceSelect](ctx, _s.PaymentProviderInstanceQuery, _s, _s.inters, v)
}
func (_s *PaymentProviderInstanceSelect) sqlScan(ctx context.Context, root *PaymentProviderInstanceQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(_s.fns))
for _, fn := range _s.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*_s.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@@ -0,0 +1,594 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// PaymentProviderInstanceUpdate is the builder for updating PaymentProviderInstance entities.
type PaymentProviderInstanceUpdate struct {
config
hooks []Hook
mutation *PaymentProviderInstanceMutation
}
// Where appends a list predicates to the PaymentProviderInstanceUpdate builder.
func (_u *PaymentProviderInstanceUpdate) Where(ps ...predicate.PaymentProviderInstance) *PaymentProviderInstanceUpdate {
_u.mutation.Where(ps...)
return _u
}
// SetProviderKey sets the "provider_key" field.
func (_u *PaymentProviderInstanceUpdate) SetProviderKey(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetProviderKey(v)
return _u
}
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableProviderKey(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetProviderKey(*v)
}
return _u
}
// SetName sets the "name" field.
func (_u *PaymentProviderInstanceUpdate) SetName(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableName(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetName(*v)
}
return _u
}
// SetConfig sets the "config" field.
func (_u *PaymentProviderInstanceUpdate) SetConfig(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetConfig(v)
return _u
}
// SetNillableConfig sets the "config" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableConfig(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetConfig(*v)
}
return _u
}
// SetSupportedTypes sets the "supported_types" field.
func (_u *PaymentProviderInstanceUpdate) SetSupportedTypes(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetSupportedTypes(v)
return _u
}
// SetNillableSupportedTypes sets the "supported_types" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableSupportedTypes(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetSupportedTypes(*v)
}
return _u
}
// SetEnabled sets the "enabled" field.
func (_u *PaymentProviderInstanceUpdate) SetEnabled(v bool) *PaymentProviderInstanceUpdate {
_u.mutation.SetEnabled(v)
return _u
}
// SetNillableEnabled sets the "enabled" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableEnabled(v *bool) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetEnabled(*v)
}
return _u
}
// SetPaymentMode sets the "payment_mode" field.
func (_u *PaymentProviderInstanceUpdate) SetPaymentMode(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetPaymentMode(v)
return _u
}
// SetNillablePaymentMode sets the "payment_mode" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillablePaymentMode(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetPaymentMode(*v)
}
return _u
}
// SetSortOrder sets the "sort_order" field.
func (_u *PaymentProviderInstanceUpdate) SetSortOrder(v int) *PaymentProviderInstanceUpdate {
_u.mutation.ResetSortOrder()
_u.mutation.SetSortOrder(v)
return _u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableSortOrder(v *int) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetSortOrder(*v)
}
return _u
}
// AddSortOrder adds value to the "sort_order" field.
func (_u *PaymentProviderInstanceUpdate) AddSortOrder(v int) *PaymentProviderInstanceUpdate {
_u.mutation.AddSortOrder(v)
return _u
}
// SetLimits sets the "limits" field.
func (_u *PaymentProviderInstanceUpdate) SetLimits(v string) *PaymentProviderInstanceUpdate {
_u.mutation.SetLimits(v)
return _u
}
// SetNillableLimits sets the "limits" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableLimits(v *string) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetLimits(*v)
}
return _u
}
// SetRefundEnabled sets the "refund_enabled" field.
func (_u *PaymentProviderInstanceUpdate) SetRefundEnabled(v bool) *PaymentProviderInstanceUpdate {
_u.mutation.SetRefundEnabled(v)
return _u
}
// SetNillableRefundEnabled sets the "refund_enabled" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdate) SetNillableRefundEnabled(v *bool) *PaymentProviderInstanceUpdate {
if v != nil {
_u.SetRefundEnabled(*v)
}
return _u
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *PaymentProviderInstanceUpdate) SetUpdatedAt(v time.Time) *PaymentProviderInstanceUpdate {
_u.mutation.SetUpdatedAt(v)
return _u
}
// Mutation returns the PaymentProviderInstanceMutation object of the builder.
func (_u *PaymentProviderInstanceUpdate) Mutation() *PaymentProviderInstanceMutation {
return _u.mutation
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (_u *PaymentProviderInstanceUpdate) Save(ctx context.Context) (int, error) {
_u.defaults()
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *PaymentProviderInstanceUpdate) SaveX(ctx context.Context) int {
affected, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (_u *PaymentProviderInstanceUpdate) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *PaymentProviderInstanceUpdate) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *PaymentProviderInstanceUpdate) defaults() {
if _, ok := _u.mutation.UpdatedAt(); !ok {
v := paymentproviderinstance.UpdateDefaultUpdatedAt()
_u.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *PaymentProviderInstanceUpdate) check() error {
if v, ok := _u.mutation.ProviderKey(); ok {
if err := paymentproviderinstance.ProviderKeyValidator(v); err != nil {
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.provider_key": %w`, err)}
}
}
if v, ok := _u.mutation.Name(); ok {
if err := paymentproviderinstance.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.name": %w`, err)}
}
}
if v, ok := _u.mutation.SupportedTypes(); ok {
if err := paymentproviderinstance.SupportedTypesValidator(v); err != nil {
return &ValidationError{Name: "supported_types", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.supported_types": %w`, err)}
}
}
if v, ok := _u.mutation.PaymentMode(); ok {
if err := paymentproviderinstance.PaymentModeValidator(v); err != nil {
return &ValidationError{Name: "payment_mode", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.payment_mode": %w`, err)}
}
}
return nil
}
func (_u *PaymentProviderInstanceUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(paymentproviderinstance.Table, paymentproviderinstance.Columns, sqlgraph.NewFieldSpec(paymentproviderinstance.FieldID, field.TypeInt64))
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.ProviderKey(); ok {
_spec.SetField(paymentproviderinstance.FieldProviderKey, field.TypeString, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(paymentproviderinstance.FieldName, field.TypeString, value)
}
if value, ok := _u.mutation.Config(); ok {
_spec.SetField(paymentproviderinstance.FieldConfig, field.TypeString, value)
}
if value, ok := _u.mutation.SupportedTypes(); ok {
_spec.SetField(paymentproviderinstance.FieldSupportedTypes, field.TypeString, value)
}
if value, ok := _u.mutation.Enabled(); ok {
_spec.SetField(paymentproviderinstance.FieldEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.PaymentMode(); ok {
_spec.SetField(paymentproviderinstance.FieldPaymentMode, field.TypeString, value)
}
if value, ok := _u.mutation.SortOrder(); ok {
_spec.SetField(paymentproviderinstance.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedSortOrder(); ok {
_spec.AddField(paymentproviderinstance.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.Limits(); ok {
_spec.SetField(paymentproviderinstance.FieldLimits, field.TypeString, value)
}
if value, ok := _u.mutation.RefundEnabled(); ok {
_spec.SetField(paymentproviderinstance.FieldRefundEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.UpdatedAt(); ok {
_spec.SetField(paymentproviderinstance.FieldUpdatedAt, field.TypeTime, value)
}
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{paymentproviderinstance.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
_u.mutation.done = true
return _node, nil
}
// PaymentProviderInstanceUpdateOne is the builder for updating a single PaymentProviderInstance entity.
type PaymentProviderInstanceUpdateOne struct {
config
fields []string
hooks []Hook
mutation *PaymentProviderInstanceMutation
}
// SetProviderKey sets the "provider_key" field.
func (_u *PaymentProviderInstanceUpdateOne) SetProviderKey(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetProviderKey(v)
return _u
}
// SetNillableProviderKey sets the "provider_key" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableProviderKey(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetProviderKey(*v)
}
return _u
}
// SetName sets the "name" field.
func (_u *PaymentProviderInstanceUpdateOne) SetName(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableName(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetName(*v)
}
return _u
}
// SetConfig sets the "config" field.
func (_u *PaymentProviderInstanceUpdateOne) SetConfig(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetConfig(v)
return _u
}
// SetNillableConfig sets the "config" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableConfig(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetConfig(*v)
}
return _u
}
// SetSupportedTypes sets the "supported_types" field.
func (_u *PaymentProviderInstanceUpdateOne) SetSupportedTypes(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetSupportedTypes(v)
return _u
}
// SetNillableSupportedTypes sets the "supported_types" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableSupportedTypes(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetSupportedTypes(*v)
}
return _u
}
// SetEnabled sets the "enabled" field.
func (_u *PaymentProviderInstanceUpdateOne) SetEnabled(v bool) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetEnabled(v)
return _u
}
// SetNillableEnabled sets the "enabled" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableEnabled(v *bool) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetEnabled(*v)
}
return _u
}
// SetPaymentMode sets the "payment_mode" field.
func (_u *PaymentProviderInstanceUpdateOne) SetPaymentMode(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetPaymentMode(v)
return _u
}
// SetNillablePaymentMode sets the "payment_mode" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillablePaymentMode(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetPaymentMode(*v)
}
return _u
}
// SetSortOrder sets the "sort_order" field.
func (_u *PaymentProviderInstanceUpdateOne) SetSortOrder(v int) *PaymentProviderInstanceUpdateOne {
_u.mutation.ResetSortOrder()
_u.mutation.SetSortOrder(v)
return _u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableSortOrder(v *int) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetSortOrder(*v)
}
return _u
}
// AddSortOrder adds value to the "sort_order" field.
func (_u *PaymentProviderInstanceUpdateOne) AddSortOrder(v int) *PaymentProviderInstanceUpdateOne {
_u.mutation.AddSortOrder(v)
return _u
}
// SetLimits sets the "limits" field.
func (_u *PaymentProviderInstanceUpdateOne) SetLimits(v string) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetLimits(v)
return _u
}
// SetNillableLimits sets the "limits" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableLimits(v *string) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetLimits(*v)
}
return _u
}
// SetRefundEnabled sets the "refund_enabled" field.
func (_u *PaymentProviderInstanceUpdateOne) SetRefundEnabled(v bool) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetRefundEnabled(v)
return _u
}
// SetNillableRefundEnabled sets the "refund_enabled" field if the given value is not nil.
func (_u *PaymentProviderInstanceUpdateOne) SetNillableRefundEnabled(v *bool) *PaymentProviderInstanceUpdateOne {
if v != nil {
_u.SetRefundEnabled(*v)
}
return _u
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *PaymentProviderInstanceUpdateOne) SetUpdatedAt(v time.Time) *PaymentProviderInstanceUpdateOne {
_u.mutation.SetUpdatedAt(v)
return _u
}
// Mutation returns the PaymentProviderInstanceMutation object of the builder.
func (_u *PaymentProviderInstanceUpdateOne) Mutation() *PaymentProviderInstanceMutation {
return _u.mutation
}
// Where appends a list predicates to the PaymentProviderInstanceUpdate builder.
func (_u *PaymentProviderInstanceUpdateOne) Where(ps ...predicate.PaymentProviderInstance) *PaymentProviderInstanceUpdateOne {
_u.mutation.Where(ps...)
return _u
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (_u *PaymentProviderInstanceUpdateOne) Select(field string, fields ...string) *PaymentProviderInstanceUpdateOne {
_u.fields = append([]string{field}, fields...)
return _u
}
// Save executes the query and returns the updated PaymentProviderInstance entity.
func (_u *PaymentProviderInstanceUpdateOne) Save(ctx context.Context) (*PaymentProviderInstance, error) {
_u.defaults()
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *PaymentProviderInstanceUpdateOne) SaveX(ctx context.Context) *PaymentProviderInstance {
node, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (_u *PaymentProviderInstanceUpdateOne) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *PaymentProviderInstanceUpdateOne) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *PaymentProviderInstanceUpdateOne) defaults() {
if _, ok := _u.mutation.UpdatedAt(); !ok {
v := paymentproviderinstance.UpdateDefaultUpdatedAt()
_u.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *PaymentProviderInstanceUpdateOne) check() error {
if v, ok := _u.mutation.ProviderKey(); ok {
if err := paymentproviderinstance.ProviderKeyValidator(v); err != nil {
return &ValidationError{Name: "provider_key", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.provider_key": %w`, err)}
}
}
if v, ok := _u.mutation.Name(); ok {
if err := paymentproviderinstance.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.name": %w`, err)}
}
}
if v, ok := _u.mutation.SupportedTypes(); ok {
if err := paymentproviderinstance.SupportedTypesValidator(v); err != nil {
return &ValidationError{Name: "supported_types", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.supported_types": %w`, err)}
}
}
if v, ok := _u.mutation.PaymentMode(); ok {
if err := paymentproviderinstance.PaymentModeValidator(v); err != nil {
return &ValidationError{Name: "payment_mode", err: fmt.Errorf(`ent: validator failed for field "PaymentProviderInstance.payment_mode": %w`, err)}
}
}
return nil
}
func (_u *PaymentProviderInstanceUpdateOne) sqlSave(ctx context.Context) (_node *PaymentProviderInstance, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(paymentproviderinstance.Table, paymentproviderinstance.Columns, sqlgraph.NewFieldSpec(paymentproviderinstance.FieldID, field.TypeInt64))
id, ok := _u.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "PaymentProviderInstance.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := _u.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, paymentproviderinstance.FieldID)
for _, f := range fields {
if !paymentproviderinstance.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != paymentproviderinstance.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.ProviderKey(); ok {
_spec.SetField(paymentproviderinstance.FieldProviderKey, field.TypeString, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(paymentproviderinstance.FieldName, field.TypeString, value)
}
if value, ok := _u.mutation.Config(); ok {
_spec.SetField(paymentproviderinstance.FieldConfig, field.TypeString, value)
}
if value, ok := _u.mutation.SupportedTypes(); ok {
_spec.SetField(paymentproviderinstance.FieldSupportedTypes, field.TypeString, value)
}
if value, ok := _u.mutation.Enabled(); ok {
_spec.SetField(paymentproviderinstance.FieldEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.PaymentMode(); ok {
_spec.SetField(paymentproviderinstance.FieldPaymentMode, field.TypeString, value)
}
if value, ok := _u.mutation.SortOrder(); ok {
_spec.SetField(paymentproviderinstance.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedSortOrder(); ok {
_spec.AddField(paymentproviderinstance.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.Limits(); ok {
_spec.SetField(paymentproviderinstance.FieldLimits, field.TypeString, value)
}
if value, ok := _u.mutation.RefundEnabled(); ok {
_spec.SetField(paymentproviderinstance.FieldRefundEnabled, field.TypeBool, value)
}
if value, ok := _u.mutation.UpdatedAt(); ok {
_spec.SetField(paymentproviderinstance.FieldUpdatedAt, field.TypeTime, value)
}
_node = &PaymentProviderInstance{config: _u.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{paymentproviderinstance.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
_u.mutation.done = true
return _node, nil
}

View File

@@ -30,6 +30,15 @@ type Group func(*sql.Selector)
// IdempotencyRecord is the predicate function for idempotencyrecord builders.
type IdempotencyRecord func(*sql.Selector)
// PaymentAuditLog is the predicate function for paymentauditlog builders.
type PaymentAuditLog func(*sql.Selector)
// PaymentOrder is the predicate function for paymentorder builders.
type PaymentOrder func(*sql.Selector)
// PaymentProviderInstance is the predicate function for paymentproviderinstance builders.
type PaymentProviderInstance func(*sql.Selector)
// PromoCode is the predicate function for promocode builders.
type PromoCode func(*sql.Selector)
@@ -48,6 +57,9 @@ type SecuritySecret func(*sql.Selector)
// Setting is the predicate function for setting builders.
type Setting func(*sql.Selector)
// SubscriptionPlan is the predicate function for subscriptionplan builders.
type SubscriptionPlan func(*sql.Selector)
// TLSFingerprintProfile is the predicate function for tlsfingerprintprofile builders.
type TLSFingerprintProfile func(*sql.Selector)

View File

@@ -13,6 +13,9 @@ import (
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/idempotencyrecord"
"github.com/Wei-Shaw/sub2api/ent/paymentauditlog"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/paymentproviderinstance"
"github.com/Wei-Shaw/sub2api/ent/promocode"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/proxy"
@@ -20,6 +23,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/schema"
"github.com/Wei-Shaw/sub2api/ent/securitysecret"
"github.com/Wei-Shaw/sub2api/ent/setting"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
"github.com/Wei-Shaw/sub2api/ent/tlsfingerprintprofile"
"github.com/Wei-Shaw/sub2api/ent/usagecleanuptask"
"github.com/Wei-Shaw/sub2api/ent/usagelog"
@@ -28,6 +32,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/userattributedefinition"
"github.com/Wei-Shaw/sub2api/ent/userattributevalue"
"github.com/Wei-Shaw/sub2api/ent/usersubscription"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
// The init function reads all schema descriptors with runtime code
@@ -468,6 +473,10 @@ func init() {
group.DefaultDefaultMappedModel = groupDescDefaultMappedModel.Default.(string)
// group.DefaultMappedModelValidator is a validator for the "default_mapped_model" field. It is called by the builders before save.
group.DefaultMappedModelValidator = groupDescDefaultMappedModel.Validators[0].(func(string) error)
// groupDescMessagesDispatchModelConfig is the schema descriptor for messages_dispatch_model_config field.
groupDescMessagesDispatchModelConfig := groupFields[26].Descriptor()
// group.DefaultMessagesDispatchModelConfig holds the default value on creation for the messages_dispatch_model_config field.
group.DefaultMessagesDispatchModelConfig = groupDescMessagesDispatchModelConfig.Default.(domain.OpenAIMessagesDispatchModelConfig)
idempotencyrecordMixin := schema.IdempotencyRecord{}.Mixin()
idempotencyrecordMixinFields0 := idempotencyrecordMixin[0].Fields()
_ = idempotencyrecordMixinFields0
@@ -503,6 +512,172 @@ func init() {
idempotencyrecordDescErrorReason := idempotencyrecordFields[6].Descriptor()
// idempotencyrecord.ErrorReasonValidator is a validator for the "error_reason" field. It is called by the builders before save.
idempotencyrecord.ErrorReasonValidator = idempotencyrecordDescErrorReason.Validators[0].(func(string) error)
paymentauditlogFields := schema.PaymentAuditLog{}.Fields()
_ = paymentauditlogFields
// paymentauditlogDescOrderID is the schema descriptor for order_id field.
paymentauditlogDescOrderID := paymentauditlogFields[0].Descriptor()
// paymentauditlog.OrderIDValidator is a validator for the "order_id" field. It is called by the builders before save.
paymentauditlog.OrderIDValidator = paymentauditlogDescOrderID.Validators[0].(func(string) error)
// paymentauditlogDescAction is the schema descriptor for action field.
paymentauditlogDescAction := paymentauditlogFields[1].Descriptor()
// paymentauditlog.ActionValidator is a validator for the "action" field. It is called by the builders before save.
paymentauditlog.ActionValidator = paymentauditlogDescAction.Validators[0].(func(string) error)
// paymentauditlogDescDetail is the schema descriptor for detail field.
paymentauditlogDescDetail := paymentauditlogFields[2].Descriptor()
// paymentauditlog.DefaultDetail holds the default value on creation for the detail field.
paymentauditlog.DefaultDetail = paymentauditlogDescDetail.Default.(string)
// paymentauditlogDescOperator is the schema descriptor for operator field.
paymentauditlogDescOperator := paymentauditlogFields[3].Descriptor()
// paymentauditlog.DefaultOperator holds the default value on creation for the operator field.
paymentauditlog.DefaultOperator = paymentauditlogDescOperator.Default.(string)
// paymentauditlog.OperatorValidator is a validator for the "operator" field. It is called by the builders before save.
paymentauditlog.OperatorValidator = paymentauditlogDescOperator.Validators[0].(func(string) error)
// paymentauditlogDescCreatedAt is the schema descriptor for created_at field.
paymentauditlogDescCreatedAt := paymentauditlogFields[4].Descriptor()
// paymentauditlog.DefaultCreatedAt holds the default value on creation for the created_at field.
paymentauditlog.DefaultCreatedAt = paymentauditlogDescCreatedAt.Default.(func() time.Time)
paymentorderFields := schema.PaymentOrder{}.Fields()
_ = paymentorderFields
// paymentorderDescUserEmail is the schema descriptor for user_email field.
paymentorderDescUserEmail := paymentorderFields[1].Descriptor()
// paymentorder.UserEmailValidator is a validator for the "user_email" field. It is called by the builders before save.
paymentorder.UserEmailValidator = paymentorderDescUserEmail.Validators[0].(func(string) error)
// paymentorderDescUserName is the schema descriptor for user_name field.
paymentorderDescUserName := paymentorderFields[2].Descriptor()
// paymentorder.UserNameValidator is a validator for the "user_name" field. It is called by the builders before save.
paymentorder.UserNameValidator = paymentorderDescUserName.Validators[0].(func(string) error)
// paymentorderDescFeeRate is the schema descriptor for fee_rate field.
paymentorderDescFeeRate := paymentorderFields[6].Descriptor()
// paymentorder.DefaultFeeRate holds the default value on creation for the fee_rate field.
paymentorder.DefaultFeeRate = paymentorderDescFeeRate.Default.(float64)
// paymentorderDescRechargeCode is the schema descriptor for recharge_code field.
paymentorderDescRechargeCode := paymentorderFields[7].Descriptor()
// paymentorder.RechargeCodeValidator is a validator for the "recharge_code" field. It is called by the builders before save.
paymentorder.RechargeCodeValidator = paymentorderDescRechargeCode.Validators[0].(func(string) error)
// paymentorderDescOutTradeNo is the schema descriptor for out_trade_no field.
paymentorderDescOutTradeNo := paymentorderFields[8].Descriptor()
// paymentorder.DefaultOutTradeNo holds the default value on creation for the out_trade_no field.
paymentorder.DefaultOutTradeNo = paymentorderDescOutTradeNo.Default.(string)
// paymentorder.OutTradeNoValidator is a validator for the "out_trade_no" field. It is called by the builders before save.
paymentorder.OutTradeNoValidator = paymentorderDescOutTradeNo.Validators[0].(func(string) error)
// paymentorderDescPaymentType is the schema descriptor for payment_type field.
paymentorderDescPaymentType := paymentorderFields[9].Descriptor()
// paymentorder.PaymentTypeValidator is a validator for the "payment_type" field. It is called by the builders before save.
paymentorder.PaymentTypeValidator = paymentorderDescPaymentType.Validators[0].(func(string) error)
// paymentorderDescPaymentTradeNo is the schema descriptor for payment_trade_no field.
paymentorderDescPaymentTradeNo := paymentorderFields[10].Descriptor()
// paymentorder.PaymentTradeNoValidator is a validator for the "payment_trade_no" field. It is called by the builders before save.
paymentorder.PaymentTradeNoValidator = paymentorderDescPaymentTradeNo.Validators[0].(func(string) error)
// paymentorderDescOrderType is the schema descriptor for order_type field.
paymentorderDescOrderType := paymentorderFields[14].Descriptor()
// paymentorder.DefaultOrderType holds the default value on creation for the order_type field.
paymentorder.DefaultOrderType = paymentorderDescOrderType.Default.(string)
// paymentorder.OrderTypeValidator is a validator for the "order_type" field. It is called by the builders before save.
paymentorder.OrderTypeValidator = paymentorderDescOrderType.Validators[0].(func(string) error)
// paymentorderDescProviderInstanceID is the schema descriptor for provider_instance_id field.
paymentorderDescProviderInstanceID := paymentorderFields[18].Descriptor()
// paymentorder.ProviderInstanceIDValidator is a validator for the "provider_instance_id" field. It is called by the builders before save.
paymentorder.ProviderInstanceIDValidator = paymentorderDescProviderInstanceID.Validators[0].(func(string) error)
// paymentorderDescStatus is the schema descriptor for status field.
paymentorderDescStatus := paymentorderFields[19].Descriptor()
// paymentorder.DefaultStatus holds the default value on creation for the status field.
paymentorder.DefaultStatus = paymentorderDescStatus.Default.(string)
// paymentorder.StatusValidator is a validator for the "status" field. It is called by the builders before save.
paymentorder.StatusValidator = paymentorderDescStatus.Validators[0].(func(string) error)
// paymentorderDescRefundAmount is the schema descriptor for refund_amount field.
paymentorderDescRefundAmount := paymentorderFields[20].Descriptor()
// paymentorder.DefaultRefundAmount holds the default value on creation for the refund_amount field.
paymentorder.DefaultRefundAmount = paymentorderDescRefundAmount.Default.(float64)
// paymentorderDescForceRefund is the schema descriptor for force_refund field.
paymentorderDescForceRefund := paymentorderFields[23].Descriptor()
// paymentorder.DefaultForceRefund holds the default value on creation for the force_refund field.
paymentorder.DefaultForceRefund = paymentorderDescForceRefund.Default.(bool)
// paymentorderDescRefundRequestedBy is the schema descriptor for refund_requested_by field.
paymentorderDescRefundRequestedBy := paymentorderFields[26].Descriptor()
// paymentorder.RefundRequestedByValidator is a validator for the "refund_requested_by" field. It is called by the builders before save.
paymentorder.RefundRequestedByValidator = paymentorderDescRefundRequestedBy.Validators[0].(func(string) error)
// paymentorderDescClientIP is the schema descriptor for client_ip field.
paymentorderDescClientIP := paymentorderFields[32].Descriptor()
// paymentorder.ClientIPValidator is a validator for the "client_ip" field. It is called by the builders before save.
paymentorder.ClientIPValidator = paymentorderDescClientIP.Validators[0].(func(string) error)
// paymentorderDescSrcHost is the schema descriptor for src_host field.
paymentorderDescSrcHost := paymentorderFields[33].Descriptor()
// paymentorder.SrcHostValidator is a validator for the "src_host" field. It is called by the builders before save.
paymentorder.SrcHostValidator = paymentorderDescSrcHost.Validators[0].(func(string) error)
// paymentorderDescCreatedAt is the schema descriptor for created_at field.
paymentorderDescCreatedAt := paymentorderFields[35].Descriptor()
// paymentorder.DefaultCreatedAt holds the default value on creation for the created_at field.
paymentorder.DefaultCreatedAt = paymentorderDescCreatedAt.Default.(func() time.Time)
// paymentorderDescUpdatedAt is the schema descriptor for updated_at field.
paymentorderDescUpdatedAt := paymentorderFields[36].Descriptor()
// paymentorder.DefaultUpdatedAt holds the default value on creation for the updated_at field.
paymentorder.DefaultUpdatedAt = paymentorderDescUpdatedAt.Default.(func() time.Time)
// paymentorder.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
paymentorder.UpdateDefaultUpdatedAt = paymentorderDescUpdatedAt.UpdateDefault.(func() time.Time)
paymentproviderinstanceFields := schema.PaymentProviderInstance{}.Fields()
_ = paymentproviderinstanceFields
// paymentproviderinstanceDescProviderKey is the schema descriptor for provider_key field.
paymentproviderinstanceDescProviderKey := paymentproviderinstanceFields[0].Descriptor()
// paymentproviderinstance.ProviderKeyValidator is a validator for the "provider_key" field. It is called by the builders before save.
paymentproviderinstance.ProviderKeyValidator = func() func(string) error {
validators := paymentproviderinstanceDescProviderKey.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(provider_key string) error {
for _, fn := range fns {
if err := fn(provider_key); err != nil {
return err
}
}
return nil
}
}()
// paymentproviderinstanceDescName is the schema descriptor for name field.
paymentproviderinstanceDescName := paymentproviderinstanceFields[1].Descriptor()
// paymentproviderinstance.DefaultName holds the default value on creation for the name field.
paymentproviderinstance.DefaultName = paymentproviderinstanceDescName.Default.(string)
// paymentproviderinstance.NameValidator is a validator for the "name" field. It is called by the builders before save.
paymentproviderinstance.NameValidator = paymentproviderinstanceDescName.Validators[0].(func(string) error)
// paymentproviderinstanceDescSupportedTypes is the schema descriptor for supported_types field.
paymentproviderinstanceDescSupportedTypes := paymentproviderinstanceFields[3].Descriptor()
// paymentproviderinstance.DefaultSupportedTypes holds the default value on creation for the supported_types field.
paymentproviderinstance.DefaultSupportedTypes = paymentproviderinstanceDescSupportedTypes.Default.(string)
// paymentproviderinstance.SupportedTypesValidator is a validator for the "supported_types" field. It is called by the builders before save.
paymentproviderinstance.SupportedTypesValidator = paymentproviderinstanceDescSupportedTypes.Validators[0].(func(string) error)
// paymentproviderinstanceDescEnabled is the schema descriptor for enabled field.
paymentproviderinstanceDescEnabled := paymentproviderinstanceFields[4].Descriptor()
// paymentproviderinstance.DefaultEnabled holds the default value on creation for the enabled field.
paymentproviderinstance.DefaultEnabled = paymentproviderinstanceDescEnabled.Default.(bool)
// paymentproviderinstanceDescPaymentMode is the schema descriptor for payment_mode field.
paymentproviderinstanceDescPaymentMode := paymentproviderinstanceFields[5].Descriptor()
// paymentproviderinstance.DefaultPaymentMode holds the default value on creation for the payment_mode field.
paymentproviderinstance.DefaultPaymentMode = paymentproviderinstanceDescPaymentMode.Default.(string)
// paymentproviderinstance.PaymentModeValidator is a validator for the "payment_mode" field. It is called by the builders before save.
paymentproviderinstance.PaymentModeValidator = paymentproviderinstanceDescPaymentMode.Validators[0].(func(string) error)
// paymentproviderinstanceDescSortOrder is the schema descriptor for sort_order field.
paymentproviderinstanceDescSortOrder := paymentproviderinstanceFields[6].Descriptor()
// paymentproviderinstance.DefaultSortOrder holds the default value on creation for the sort_order field.
paymentproviderinstance.DefaultSortOrder = paymentproviderinstanceDescSortOrder.Default.(int)
// paymentproviderinstanceDescLimits is the schema descriptor for limits field.
paymentproviderinstanceDescLimits := paymentproviderinstanceFields[7].Descriptor()
// paymentproviderinstance.DefaultLimits holds the default value on creation for the limits field.
paymentproviderinstance.DefaultLimits = paymentproviderinstanceDescLimits.Default.(string)
// paymentproviderinstanceDescRefundEnabled is the schema descriptor for refund_enabled field.
paymentproviderinstanceDescRefundEnabled := paymentproviderinstanceFields[8].Descriptor()
// paymentproviderinstance.DefaultRefundEnabled holds the default value on creation for the refund_enabled field.
paymentproviderinstance.DefaultRefundEnabled = paymentproviderinstanceDescRefundEnabled.Default.(bool)
// paymentproviderinstanceDescCreatedAt is the schema descriptor for created_at field.
paymentproviderinstanceDescCreatedAt := paymentproviderinstanceFields[9].Descriptor()
// paymentproviderinstance.DefaultCreatedAt holds the default value on creation for the created_at field.
paymentproviderinstance.DefaultCreatedAt = paymentproviderinstanceDescCreatedAt.Default.(func() time.Time)
// paymentproviderinstanceDescUpdatedAt is the schema descriptor for updated_at field.
paymentproviderinstanceDescUpdatedAt := paymentproviderinstanceFields[10].Descriptor()
// paymentproviderinstance.DefaultUpdatedAt holds the default value on creation for the updated_at field.
paymentproviderinstance.DefaultUpdatedAt = paymentproviderinstanceDescUpdatedAt.Default.(func() time.Time)
// paymentproviderinstance.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
paymentproviderinstance.UpdateDefaultUpdatedAt = paymentproviderinstanceDescUpdatedAt.UpdateDefault.(func() time.Time)
promocodeFields := schema.PromoCode{}.Fields()
_ = promocodeFields
// promocodeDescCode is the schema descriptor for code field.
@@ -751,6 +926,68 @@ func init() {
setting.DefaultUpdatedAt = settingDescUpdatedAt.Default.(func() time.Time)
// setting.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
setting.UpdateDefaultUpdatedAt = settingDescUpdatedAt.UpdateDefault.(func() time.Time)
subscriptionplanFields := schema.SubscriptionPlan{}.Fields()
_ = subscriptionplanFields
// subscriptionplanDescName is the schema descriptor for name field.
subscriptionplanDescName := subscriptionplanFields[1].Descriptor()
// subscriptionplan.NameValidator is a validator for the "name" field. It is called by the builders before save.
subscriptionplan.NameValidator = func() func(string) error {
validators := subscriptionplanDescName.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(name string) error {
for _, fn := range fns {
if err := fn(name); err != nil {
return err
}
}
return nil
}
}()
// subscriptionplanDescDescription is the schema descriptor for description field.
subscriptionplanDescDescription := subscriptionplanFields[2].Descriptor()
// subscriptionplan.DefaultDescription holds the default value on creation for the description field.
subscriptionplan.DefaultDescription = subscriptionplanDescDescription.Default.(string)
// subscriptionplanDescValidityDays is the schema descriptor for validity_days field.
subscriptionplanDescValidityDays := subscriptionplanFields[5].Descriptor()
// subscriptionplan.DefaultValidityDays holds the default value on creation for the validity_days field.
subscriptionplan.DefaultValidityDays = subscriptionplanDescValidityDays.Default.(int)
// subscriptionplanDescValidityUnit is the schema descriptor for validity_unit field.
subscriptionplanDescValidityUnit := subscriptionplanFields[6].Descriptor()
// subscriptionplan.DefaultValidityUnit holds the default value on creation for the validity_unit field.
subscriptionplan.DefaultValidityUnit = subscriptionplanDescValidityUnit.Default.(string)
// subscriptionplan.ValidityUnitValidator is a validator for the "validity_unit" field. It is called by the builders before save.
subscriptionplan.ValidityUnitValidator = subscriptionplanDescValidityUnit.Validators[0].(func(string) error)
// subscriptionplanDescFeatures is the schema descriptor for features field.
subscriptionplanDescFeatures := subscriptionplanFields[7].Descriptor()
// subscriptionplan.DefaultFeatures holds the default value on creation for the features field.
subscriptionplan.DefaultFeatures = subscriptionplanDescFeatures.Default.(string)
// subscriptionplanDescProductName is the schema descriptor for product_name field.
subscriptionplanDescProductName := subscriptionplanFields[8].Descriptor()
// subscriptionplan.DefaultProductName holds the default value on creation for the product_name field.
subscriptionplan.DefaultProductName = subscriptionplanDescProductName.Default.(string)
// subscriptionplan.ProductNameValidator is a validator for the "product_name" field. It is called by the builders before save.
subscriptionplan.ProductNameValidator = subscriptionplanDescProductName.Validators[0].(func(string) error)
// subscriptionplanDescForSale is the schema descriptor for for_sale field.
subscriptionplanDescForSale := subscriptionplanFields[9].Descriptor()
// subscriptionplan.DefaultForSale holds the default value on creation for the for_sale field.
subscriptionplan.DefaultForSale = subscriptionplanDescForSale.Default.(bool)
// subscriptionplanDescSortOrder is the schema descriptor for sort_order field.
subscriptionplanDescSortOrder := subscriptionplanFields[10].Descriptor()
// subscriptionplan.DefaultSortOrder holds the default value on creation for the sort_order field.
subscriptionplan.DefaultSortOrder = subscriptionplanDescSortOrder.Default.(int)
// subscriptionplanDescCreatedAt is the schema descriptor for created_at field.
subscriptionplanDescCreatedAt := subscriptionplanFields[11].Descriptor()
// subscriptionplan.DefaultCreatedAt holds the default value on creation for the created_at field.
subscriptionplan.DefaultCreatedAt = subscriptionplanDescCreatedAt.Default.(func() time.Time)
// subscriptionplanDescUpdatedAt is the schema descriptor for updated_at field.
subscriptionplanDescUpdatedAt := subscriptionplanFields[12].Descriptor()
// subscriptionplan.DefaultUpdatedAt holds the default value on creation for the updated_at field.
subscriptionplan.DefaultUpdatedAt = subscriptionplanDescUpdatedAt.Default.(func() time.Time)
// subscriptionplan.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
subscriptionplan.UpdateDefaultUpdatedAt = subscriptionplanDescUpdatedAt.UpdateDefault.(func() time.Time)
tlsfingerprintprofileMixin := schema.TLSFingerprintProfile{}.Mixin()
tlsfingerprintprofileMixinFields0 := tlsfingerprintprofileMixin[0].Fields()
_ = tlsfingerprintprofileMixinFields0

View File

@@ -141,6 +141,10 @@ func (Group) Fields() []ent.Field {
MaxLen(100).
Default("").
Comment("默认映射模型 ID当账号级映射找不到时使用此值"),
field.JSON("messages_dispatch_model_config", domain.OpenAIMessagesDispatchModelConfig{}).
Default(domain.OpenAIMessagesDispatchModelConfig{}).
SchemaType(map[string]string{dialect.Postgres: "jsonb"}).
Comment("OpenAI Messages 调度模型配置:按 Claude 系列/精确模型映射到目标 GPT 模型"),
}
}

View File

@@ -0,0 +1,54 @@
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// PaymentAuditLog holds the schema definition for the PaymentAuditLog entity.
//
// 删除策略:硬删除
// PaymentAuditLog 使用硬删除而非软删除,原因如下:
// - 审计日志本身即为不可变记录,通常只追加不修改
// - 如需清理历史日志,直接按时间范围批量删除即可
// - 保持表结构简洁,提升插入和查询性能
type PaymentAuditLog struct {
ent.Schema
}
func (PaymentAuditLog) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "payment_audit_logs"},
}
}
func (PaymentAuditLog) Fields() []ent.Field {
return []ent.Field{
field.String("order_id").
MaxLen(64),
field.String("action").
MaxLen(50),
field.String("detail").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Default(""),
field.String("operator").
MaxLen(100).
Default("system"),
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (PaymentAuditLog) Indexes() []ent.Index {
return []ent.Index{
index.Fields("order_id"),
}
}

View File

@@ -0,0 +1,190 @@
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// PaymentOrder holds the schema definition for the PaymentOrder entity.
//
// 删除策略:硬删除
// PaymentOrder 使用硬删除而非软删除,原因如下:
// - 订单通过 status 字段追踪完整生命周期,无需依赖软删除
// - 订单审计通过 PaymentAuditLog 表记录,删除前可归档
// - 减少查询复杂度,避免软删除过滤开销
type PaymentOrder struct {
ent.Schema
}
func (PaymentOrder) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "payment_orders"},
}
}
func (PaymentOrder) Fields() []ent.Field {
return []ent.Field{
// 用户信息(冗余存储,避免关联查询)
field.Int64("user_id"),
field.String("user_email").
MaxLen(255),
field.String("user_name").
MaxLen(100),
field.String("user_notes").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
// 金额信息
field.Float("amount").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,2)"}),
field.Float("pay_amount").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,2)"}),
field.Float("fee_rate").
SchemaType(map[string]string{dialect.Postgres: "decimal(10,4)"}).
Default(0),
field.String("recharge_code").
MaxLen(64),
// 支付信息
field.String("out_trade_no").
MaxLen(64).
Default(""),
field.String("payment_type").
MaxLen(30),
field.String("payment_trade_no").
MaxLen(128),
field.String("pay_url").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
field.String("qr_code").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
field.String("qr_code_img").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
// 订单类型 & 订阅关联
field.String("order_type").
MaxLen(20).
Default("balance"),
field.Int64("plan_id").
Optional().
Nillable(),
field.Int64("subscription_group_id").
Optional().
Nillable(),
field.Int("subscription_days").
Optional().
Nillable(),
field.String("provider_instance_id").
Optional().
Nillable().
MaxLen(64),
// 状态
field.String("status").
MaxLen(30).
Default("PENDING"),
// 退款信息
field.Float("refund_amount").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,2)"}).
Default(0),
field.String("refund_reason").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
field.Time("refund_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Bool("force_refund").
Default(false),
field.Time("refund_requested_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.String("refund_request_reason").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
field.String("refund_requested_by").
Optional().
Nillable().
MaxLen(20),
// 时间节点
field.Time("expires_at").
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("paid_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("completed_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("failed_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.String("failed_reason").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
// 来源信息
field.String("client_ip").
MaxLen(50),
field.String("src_host").
MaxLen(255),
field.String("src_url").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "text"}),
// 时间戳
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (PaymentOrder) Edges() []ent.Edge {
return []ent.Edge{
edge.From("user", User.Type).
Ref("payment_orders").
Field("user_id").
Unique().
Required(),
}
}
func (PaymentOrder) Indexes() []ent.Index {
return []ent.Index{
index.Fields("out_trade_no"),
index.Fields("user_id"),
index.Fields("status"),
index.Fields("expires_at"),
index.Fields("created_at"),
index.Fields("paid_at"),
index.Fields("payment_type", "paid_at"),
index.Fields("order_type"),
}
}

View File

@@ -0,0 +1,72 @@
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// PaymentProviderInstance holds the schema definition for the PaymentProviderInstance entity.
//
// 删除策略:硬删除
// PaymentProviderInstance 使用硬删除而非软删除,原因如下:
// - 服务商实例为管理员配置的支付通道,删除即表示废弃
// - 通过 enabled 字段控制是否启用,删除仅用于彻底移除
// - config 字段存储加密后的密钥信息,删除时应彻底清除
type PaymentProviderInstance struct {
ent.Schema
}
func (PaymentProviderInstance) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "payment_provider_instances"},
}
}
func (PaymentProviderInstance) Fields() []ent.Field {
return []ent.Field{
field.String("provider_key").
MaxLen(30).
NotEmpty(),
field.String("name").
MaxLen(100).
Default(""),
field.String("config").
SchemaType(map[string]string{dialect.Postgres: "text"}),
field.String("supported_types").
MaxLen(200).
Default(""),
field.Bool("enabled").
Default(true),
field.String("payment_mode").
MaxLen(20).
Default(""),
field.Int("sort_order").
Default(0),
field.String("limits").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Default(""),
field.Bool("refund_enabled").
Default(false),
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (PaymentProviderInstance) Indexes() []ent.Index {
return []ent.Index{
index.Fields("provider_key"),
index.Fields("enabled"),
}
}

View File

@@ -0,0 +1,77 @@
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// SubscriptionPlan holds the schema definition for the SubscriptionPlan entity.
//
// 删除策略:硬删除
// SubscriptionPlan 使用硬删除而非软删除,原因如下:
// - 套餐为管理员维护的商品配置,删除即表示下架移除
// - 通过 for_sale 字段控制是否在售,删除仅用于彻底移除
// - 已购买的订阅记录保存在 UserSubscription 中,不受套餐删除影响
type SubscriptionPlan struct {
ent.Schema
}
func (SubscriptionPlan) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "subscription_plans"},
}
}
func (SubscriptionPlan) Fields() []ent.Field {
return []ent.Field{
field.Int64("group_id"),
field.String("name").
MaxLen(100).
NotEmpty(),
field.String("description").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Default(""),
field.Float("price").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,2)"}),
field.Float("original_price").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,2)"}).
Optional().
Nillable(),
field.Int("validity_days").
Default(30),
field.String("validity_unit").
MaxLen(10).
Default("day"),
field.String("features").
SchemaType(map[string]string{dialect.Postgres: "text"}).
Default(""),
field.String("product_name").
MaxLen(100).
Default(""),
field.Bool("for_sale").
Default(true),
field.Int("sort_order").
Default(0),
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (SubscriptionPlan) Indexes() []ent.Index {
return []ent.Index{
index.Fields("group_id"),
index.Fields("for_sale"),
}
}

View File

@@ -87,6 +87,7 @@ func (User) Edges() []ent.Edge {
edge.To("usage_logs", UsageLog.Type),
edge.To("attribute_values", UserAttributeValue.Type),
edge.To("promo_code_usages", PromoCodeUsage.Type),
edge.To("payment_orders", PaymentOrder.Type),
}
}

View File

@@ -0,0 +1,245 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
)
// SubscriptionPlan is the model entity for the SubscriptionPlan schema.
type SubscriptionPlan struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// GroupID holds the value of the "group_id" field.
GroupID int64 `json:"group_id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Description holds the value of the "description" field.
Description string `json:"description,omitempty"`
// Price holds the value of the "price" field.
Price float64 `json:"price,omitempty"`
// OriginalPrice holds the value of the "original_price" field.
OriginalPrice *float64 `json:"original_price,omitempty"`
// ValidityDays holds the value of the "validity_days" field.
ValidityDays int `json:"validity_days,omitempty"`
// ValidityUnit holds the value of the "validity_unit" field.
ValidityUnit string `json:"validity_unit,omitempty"`
// Features holds the value of the "features" field.
Features string `json:"features,omitempty"`
// ProductName holds the value of the "product_name" field.
ProductName string `json:"product_name,omitempty"`
// ForSale holds the value of the "for_sale" field.
ForSale bool `json:"for_sale,omitempty"`
// SortOrder holds the value of the "sort_order" field.
SortOrder int `json:"sort_order,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
selectValues sql.SelectValues
}
// scanValues returns the types for scanning values from sql.Rows.
func (*SubscriptionPlan) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case subscriptionplan.FieldForSale:
values[i] = new(sql.NullBool)
case subscriptionplan.FieldPrice, subscriptionplan.FieldOriginalPrice:
values[i] = new(sql.NullFloat64)
case subscriptionplan.FieldID, subscriptionplan.FieldGroupID, subscriptionplan.FieldValidityDays, subscriptionplan.FieldSortOrder:
values[i] = new(sql.NullInt64)
case subscriptionplan.FieldName, subscriptionplan.FieldDescription, subscriptionplan.FieldValidityUnit, subscriptionplan.FieldFeatures, subscriptionplan.FieldProductName:
values[i] = new(sql.NullString)
case subscriptionplan.FieldCreatedAt, subscriptionplan.FieldUpdatedAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the SubscriptionPlan fields.
func (_m *SubscriptionPlan) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case subscriptionplan.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case subscriptionplan.FieldGroupID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field group_id", values[i])
} else if value.Valid {
_m.GroupID = value.Int64
}
case subscriptionplan.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
_m.Name = value.String
}
case subscriptionplan.FieldDescription:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field description", values[i])
} else if value.Valid {
_m.Description = value.String
}
case subscriptionplan.FieldPrice:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field price", values[i])
} else if value.Valid {
_m.Price = value.Float64
}
case subscriptionplan.FieldOriginalPrice:
if value, ok := values[i].(*sql.NullFloat64); !ok {
return fmt.Errorf("unexpected type %T for field original_price", values[i])
} else if value.Valid {
_m.OriginalPrice = new(float64)
*_m.OriginalPrice = value.Float64
}
case subscriptionplan.FieldValidityDays:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field validity_days", values[i])
} else if value.Valid {
_m.ValidityDays = int(value.Int64)
}
case subscriptionplan.FieldValidityUnit:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field validity_unit", values[i])
} else if value.Valid {
_m.ValidityUnit = value.String
}
case subscriptionplan.FieldFeatures:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field features", values[i])
} else if value.Valid {
_m.Features = value.String
}
case subscriptionplan.FieldProductName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field product_name", values[i])
} else if value.Valid {
_m.ProductName = value.String
}
case subscriptionplan.FieldForSale:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field for_sale", values[i])
} else if value.Valid {
_m.ForSale = value.Bool
}
case subscriptionplan.FieldSortOrder:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field sort_order", values[i])
} else if value.Valid {
_m.SortOrder = int(value.Int64)
}
case subscriptionplan.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
_m.CreatedAt = value.Time
}
case subscriptionplan.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
_m.UpdatedAt = value.Time
}
default:
_m.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the SubscriptionPlan.
// This includes values selected through modifiers, order, etc.
func (_m *SubscriptionPlan) Value(name string) (ent.Value, error) {
return _m.selectValues.Get(name)
}
// Update returns a builder for updating this SubscriptionPlan.
// Note that you need to call SubscriptionPlan.Unwrap() before calling this method if this SubscriptionPlan
// was returned from a transaction, and the transaction was committed or rolled back.
func (_m *SubscriptionPlan) Update() *SubscriptionPlanUpdateOne {
return NewSubscriptionPlanClient(_m.config).UpdateOne(_m)
}
// Unwrap unwraps the SubscriptionPlan entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (_m *SubscriptionPlan) Unwrap() *SubscriptionPlan {
_tx, ok := _m.config.driver.(*txDriver)
if !ok {
panic("ent: SubscriptionPlan is not a transactional entity")
}
_m.config.driver = _tx.drv
return _m
}
// String implements the fmt.Stringer.
func (_m *SubscriptionPlan) String() string {
var builder strings.Builder
builder.WriteString("SubscriptionPlan(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("group_id=")
builder.WriteString(fmt.Sprintf("%v", _m.GroupID))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(_m.Name)
builder.WriteString(", ")
builder.WriteString("description=")
builder.WriteString(_m.Description)
builder.WriteString(", ")
builder.WriteString("price=")
builder.WriteString(fmt.Sprintf("%v", _m.Price))
builder.WriteString(", ")
if v := _m.OriginalPrice; v != nil {
builder.WriteString("original_price=")
builder.WriteString(fmt.Sprintf("%v", *v))
}
builder.WriteString(", ")
builder.WriteString("validity_days=")
builder.WriteString(fmt.Sprintf("%v", _m.ValidityDays))
builder.WriteString(", ")
builder.WriteString("validity_unit=")
builder.WriteString(_m.ValidityUnit)
builder.WriteString(", ")
builder.WriteString("features=")
builder.WriteString(_m.Features)
builder.WriteString(", ")
builder.WriteString("product_name=")
builder.WriteString(_m.ProductName)
builder.WriteString(", ")
builder.WriteString("for_sale=")
builder.WriteString(fmt.Sprintf("%v", _m.ForSale))
builder.WriteString(", ")
builder.WriteString("sort_order=")
builder.WriteString(fmt.Sprintf("%v", _m.SortOrder))
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// SubscriptionPlans is a parsable slice of SubscriptionPlan.
type SubscriptionPlans []*SubscriptionPlan

View File

@@ -0,0 +1,174 @@
// Code generated by ent, DO NOT EDIT.
package subscriptionplan
import (
"time"
"entgo.io/ent/dialect/sql"
)
const (
// Label holds the string label denoting the subscriptionplan type in the database.
Label = "subscription_plan"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldGroupID holds the string denoting the group_id field in the database.
FieldGroupID = "group_id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldDescription holds the string denoting the description field in the database.
FieldDescription = "description"
// FieldPrice holds the string denoting the price field in the database.
FieldPrice = "price"
// FieldOriginalPrice holds the string denoting the original_price field in the database.
FieldOriginalPrice = "original_price"
// FieldValidityDays holds the string denoting the validity_days field in the database.
FieldValidityDays = "validity_days"
// FieldValidityUnit holds the string denoting the validity_unit field in the database.
FieldValidityUnit = "validity_unit"
// FieldFeatures holds the string denoting the features field in the database.
FieldFeatures = "features"
// FieldProductName holds the string denoting the product_name field in the database.
FieldProductName = "product_name"
// FieldForSale holds the string denoting the for_sale field in the database.
FieldForSale = "for_sale"
// FieldSortOrder holds the string denoting the sort_order field in the database.
FieldSortOrder = "sort_order"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// Table holds the table name of the subscriptionplan in the database.
Table = "subscription_plans"
)
// Columns holds all SQL columns for subscriptionplan fields.
var Columns = []string{
FieldID,
FieldGroupID,
FieldName,
FieldDescription,
FieldPrice,
FieldOriginalPrice,
FieldValidityDays,
FieldValidityUnit,
FieldFeatures,
FieldProductName,
FieldForSale,
FieldSortOrder,
FieldCreatedAt,
FieldUpdatedAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// DefaultDescription holds the default value on creation for the "description" field.
DefaultDescription string
// DefaultValidityDays holds the default value on creation for the "validity_days" field.
DefaultValidityDays int
// DefaultValidityUnit holds the default value on creation for the "validity_unit" field.
DefaultValidityUnit string
// ValidityUnitValidator is a validator for the "validity_unit" field. It is called by the builders before save.
ValidityUnitValidator func(string) error
// DefaultFeatures holds the default value on creation for the "features" field.
DefaultFeatures string
// DefaultProductName holds the default value on creation for the "product_name" field.
DefaultProductName string
// ProductNameValidator is a validator for the "product_name" field. It is called by the builders before save.
ProductNameValidator func(string) error
// DefaultForSale holds the default value on creation for the "for_sale" field.
DefaultForSale bool
// DefaultSortOrder holds the default value on creation for the "sort_order" field.
DefaultSortOrder int
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
)
// OrderOption defines the ordering options for the SubscriptionPlan queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByGroupID orders the results by the group_id field.
func ByGroupID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldGroupID, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByDescription orders the results by the description field.
func ByDescription(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDescription, opts...).ToFunc()
}
// ByPrice orders the results by the price field.
func ByPrice(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPrice, opts...).ToFunc()
}
// ByOriginalPrice orders the results by the original_price field.
func ByOriginalPrice(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOriginalPrice, opts...).ToFunc()
}
// ByValidityDays orders the results by the validity_days field.
func ByValidityDays(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldValidityDays, opts...).ToFunc()
}
// ByValidityUnit orders the results by the validity_unit field.
func ByValidityUnit(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldValidityUnit, opts...).ToFunc()
}
// ByFeatures orders the results by the features field.
func ByFeatures(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldFeatures, opts...).ToFunc()
}
// ByProductName orders the results by the product_name field.
func ByProductName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldProductName, opts...).ToFunc()
}
// ByForSale orders the results by the for_sale field.
func ByForSale(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldForSale, opts...).ToFunc()
}
// BySortOrder orders the results by the sort_order field.
func BySortOrder(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSortOrder, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}

View File

@@ -0,0 +1,760 @@
// Code generated by ent, DO NOT EDIT.
package subscriptionplan
import (
"time"
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldID, id))
}
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
func GroupID(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldGroupID, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldName, v))
}
// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ.
func Description(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldDescription, v))
}
// Price applies equality check predicate on the "price" field. It's identical to PriceEQ.
func Price(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldPrice, v))
}
// OriginalPrice applies equality check predicate on the "original_price" field. It's identical to OriginalPriceEQ.
func OriginalPrice(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldOriginalPrice, v))
}
// ValidityDays applies equality check predicate on the "validity_days" field. It's identical to ValidityDaysEQ.
func ValidityDays(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldValidityDays, v))
}
// ValidityUnit applies equality check predicate on the "validity_unit" field. It's identical to ValidityUnitEQ.
func ValidityUnit(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldValidityUnit, v))
}
// Features applies equality check predicate on the "features" field. It's identical to FeaturesEQ.
func Features(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldFeatures, v))
}
// ProductName applies equality check predicate on the "product_name" field. It's identical to ProductNameEQ.
func ProductName(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldProductName, v))
}
// ForSale applies equality check predicate on the "for_sale" field. It's identical to ForSaleEQ.
func ForSale(v bool) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldForSale, v))
}
// SortOrder applies equality check predicate on the "sort_order" field. It's identical to SortOrderEQ.
func SortOrder(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldSortOrder, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldUpdatedAt, v))
}
// GroupIDEQ applies the EQ predicate on the "group_id" field.
func GroupIDEQ(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldGroupID, v))
}
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
func GroupIDNEQ(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldGroupID, v))
}
// GroupIDIn applies the In predicate on the "group_id" field.
func GroupIDIn(vs ...int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldGroupID, vs...))
}
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
func GroupIDNotIn(vs ...int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldGroupID, vs...))
}
// GroupIDGT applies the GT predicate on the "group_id" field.
func GroupIDGT(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldGroupID, v))
}
// GroupIDGTE applies the GTE predicate on the "group_id" field.
func GroupIDGTE(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldGroupID, v))
}
// GroupIDLT applies the LT predicate on the "group_id" field.
func GroupIDLT(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldGroupID, v))
}
// GroupIDLTE applies the LTE predicate on the "group_id" field.
func GroupIDLTE(v int64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldGroupID, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContainsFold(FieldName, v))
}
// DescriptionEQ applies the EQ predicate on the "description" field.
func DescriptionEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldDescription, v))
}
// DescriptionNEQ applies the NEQ predicate on the "description" field.
func DescriptionNEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldDescription, v))
}
// DescriptionIn applies the In predicate on the "description" field.
func DescriptionIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldDescription, vs...))
}
// DescriptionNotIn applies the NotIn predicate on the "description" field.
func DescriptionNotIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldDescription, vs...))
}
// DescriptionGT applies the GT predicate on the "description" field.
func DescriptionGT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldDescription, v))
}
// DescriptionGTE applies the GTE predicate on the "description" field.
func DescriptionGTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldDescription, v))
}
// DescriptionLT applies the LT predicate on the "description" field.
func DescriptionLT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldDescription, v))
}
// DescriptionLTE applies the LTE predicate on the "description" field.
func DescriptionLTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldDescription, v))
}
// DescriptionContains applies the Contains predicate on the "description" field.
func DescriptionContains(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContains(FieldDescription, v))
}
// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field.
func DescriptionHasPrefix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasPrefix(FieldDescription, v))
}
// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field.
func DescriptionHasSuffix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasSuffix(FieldDescription, v))
}
// DescriptionEqualFold applies the EqualFold predicate on the "description" field.
func DescriptionEqualFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEqualFold(FieldDescription, v))
}
// DescriptionContainsFold applies the ContainsFold predicate on the "description" field.
func DescriptionContainsFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContainsFold(FieldDescription, v))
}
// PriceEQ applies the EQ predicate on the "price" field.
func PriceEQ(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldPrice, v))
}
// PriceNEQ applies the NEQ predicate on the "price" field.
func PriceNEQ(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldPrice, v))
}
// PriceIn applies the In predicate on the "price" field.
func PriceIn(vs ...float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldPrice, vs...))
}
// PriceNotIn applies the NotIn predicate on the "price" field.
func PriceNotIn(vs ...float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldPrice, vs...))
}
// PriceGT applies the GT predicate on the "price" field.
func PriceGT(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldPrice, v))
}
// PriceGTE applies the GTE predicate on the "price" field.
func PriceGTE(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldPrice, v))
}
// PriceLT applies the LT predicate on the "price" field.
func PriceLT(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldPrice, v))
}
// PriceLTE applies the LTE predicate on the "price" field.
func PriceLTE(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldPrice, v))
}
// OriginalPriceEQ applies the EQ predicate on the "original_price" field.
func OriginalPriceEQ(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldOriginalPrice, v))
}
// OriginalPriceNEQ applies the NEQ predicate on the "original_price" field.
func OriginalPriceNEQ(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldOriginalPrice, v))
}
// OriginalPriceIn applies the In predicate on the "original_price" field.
func OriginalPriceIn(vs ...float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldOriginalPrice, vs...))
}
// OriginalPriceNotIn applies the NotIn predicate on the "original_price" field.
func OriginalPriceNotIn(vs ...float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldOriginalPrice, vs...))
}
// OriginalPriceGT applies the GT predicate on the "original_price" field.
func OriginalPriceGT(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldOriginalPrice, v))
}
// OriginalPriceGTE applies the GTE predicate on the "original_price" field.
func OriginalPriceGTE(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldOriginalPrice, v))
}
// OriginalPriceLT applies the LT predicate on the "original_price" field.
func OriginalPriceLT(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldOriginalPrice, v))
}
// OriginalPriceLTE applies the LTE predicate on the "original_price" field.
func OriginalPriceLTE(v float64) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldOriginalPrice, v))
}
// OriginalPriceIsNil applies the IsNil predicate on the "original_price" field.
func OriginalPriceIsNil() predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIsNull(FieldOriginalPrice))
}
// OriginalPriceNotNil applies the NotNil predicate on the "original_price" field.
func OriginalPriceNotNil() predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotNull(FieldOriginalPrice))
}
// ValidityDaysEQ applies the EQ predicate on the "validity_days" field.
func ValidityDaysEQ(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldValidityDays, v))
}
// ValidityDaysNEQ applies the NEQ predicate on the "validity_days" field.
func ValidityDaysNEQ(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldValidityDays, v))
}
// ValidityDaysIn applies the In predicate on the "validity_days" field.
func ValidityDaysIn(vs ...int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldValidityDays, vs...))
}
// ValidityDaysNotIn applies the NotIn predicate on the "validity_days" field.
func ValidityDaysNotIn(vs ...int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldValidityDays, vs...))
}
// ValidityDaysGT applies the GT predicate on the "validity_days" field.
func ValidityDaysGT(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldValidityDays, v))
}
// ValidityDaysGTE applies the GTE predicate on the "validity_days" field.
func ValidityDaysGTE(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldValidityDays, v))
}
// ValidityDaysLT applies the LT predicate on the "validity_days" field.
func ValidityDaysLT(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldValidityDays, v))
}
// ValidityDaysLTE applies the LTE predicate on the "validity_days" field.
func ValidityDaysLTE(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldValidityDays, v))
}
// ValidityUnitEQ applies the EQ predicate on the "validity_unit" field.
func ValidityUnitEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldValidityUnit, v))
}
// ValidityUnitNEQ applies the NEQ predicate on the "validity_unit" field.
func ValidityUnitNEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldValidityUnit, v))
}
// ValidityUnitIn applies the In predicate on the "validity_unit" field.
func ValidityUnitIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldValidityUnit, vs...))
}
// ValidityUnitNotIn applies the NotIn predicate on the "validity_unit" field.
func ValidityUnitNotIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldValidityUnit, vs...))
}
// ValidityUnitGT applies the GT predicate on the "validity_unit" field.
func ValidityUnitGT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldValidityUnit, v))
}
// ValidityUnitGTE applies the GTE predicate on the "validity_unit" field.
func ValidityUnitGTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldValidityUnit, v))
}
// ValidityUnitLT applies the LT predicate on the "validity_unit" field.
func ValidityUnitLT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldValidityUnit, v))
}
// ValidityUnitLTE applies the LTE predicate on the "validity_unit" field.
func ValidityUnitLTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldValidityUnit, v))
}
// ValidityUnitContains applies the Contains predicate on the "validity_unit" field.
func ValidityUnitContains(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContains(FieldValidityUnit, v))
}
// ValidityUnitHasPrefix applies the HasPrefix predicate on the "validity_unit" field.
func ValidityUnitHasPrefix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasPrefix(FieldValidityUnit, v))
}
// ValidityUnitHasSuffix applies the HasSuffix predicate on the "validity_unit" field.
func ValidityUnitHasSuffix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasSuffix(FieldValidityUnit, v))
}
// ValidityUnitEqualFold applies the EqualFold predicate on the "validity_unit" field.
func ValidityUnitEqualFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEqualFold(FieldValidityUnit, v))
}
// ValidityUnitContainsFold applies the ContainsFold predicate on the "validity_unit" field.
func ValidityUnitContainsFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContainsFold(FieldValidityUnit, v))
}
// FeaturesEQ applies the EQ predicate on the "features" field.
func FeaturesEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldFeatures, v))
}
// FeaturesNEQ applies the NEQ predicate on the "features" field.
func FeaturesNEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldFeatures, v))
}
// FeaturesIn applies the In predicate on the "features" field.
func FeaturesIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldFeatures, vs...))
}
// FeaturesNotIn applies the NotIn predicate on the "features" field.
func FeaturesNotIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldFeatures, vs...))
}
// FeaturesGT applies the GT predicate on the "features" field.
func FeaturesGT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldFeatures, v))
}
// FeaturesGTE applies the GTE predicate on the "features" field.
func FeaturesGTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldFeatures, v))
}
// FeaturesLT applies the LT predicate on the "features" field.
func FeaturesLT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldFeatures, v))
}
// FeaturesLTE applies the LTE predicate on the "features" field.
func FeaturesLTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldFeatures, v))
}
// FeaturesContains applies the Contains predicate on the "features" field.
func FeaturesContains(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContains(FieldFeatures, v))
}
// FeaturesHasPrefix applies the HasPrefix predicate on the "features" field.
func FeaturesHasPrefix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasPrefix(FieldFeatures, v))
}
// FeaturesHasSuffix applies the HasSuffix predicate on the "features" field.
func FeaturesHasSuffix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasSuffix(FieldFeatures, v))
}
// FeaturesEqualFold applies the EqualFold predicate on the "features" field.
func FeaturesEqualFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEqualFold(FieldFeatures, v))
}
// FeaturesContainsFold applies the ContainsFold predicate on the "features" field.
func FeaturesContainsFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContainsFold(FieldFeatures, v))
}
// ProductNameEQ applies the EQ predicate on the "product_name" field.
func ProductNameEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldProductName, v))
}
// ProductNameNEQ applies the NEQ predicate on the "product_name" field.
func ProductNameNEQ(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldProductName, v))
}
// ProductNameIn applies the In predicate on the "product_name" field.
func ProductNameIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldProductName, vs...))
}
// ProductNameNotIn applies the NotIn predicate on the "product_name" field.
func ProductNameNotIn(vs ...string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldProductName, vs...))
}
// ProductNameGT applies the GT predicate on the "product_name" field.
func ProductNameGT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldProductName, v))
}
// ProductNameGTE applies the GTE predicate on the "product_name" field.
func ProductNameGTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldProductName, v))
}
// ProductNameLT applies the LT predicate on the "product_name" field.
func ProductNameLT(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldProductName, v))
}
// ProductNameLTE applies the LTE predicate on the "product_name" field.
func ProductNameLTE(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldProductName, v))
}
// ProductNameContains applies the Contains predicate on the "product_name" field.
func ProductNameContains(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContains(FieldProductName, v))
}
// ProductNameHasPrefix applies the HasPrefix predicate on the "product_name" field.
func ProductNameHasPrefix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasPrefix(FieldProductName, v))
}
// ProductNameHasSuffix applies the HasSuffix predicate on the "product_name" field.
func ProductNameHasSuffix(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldHasSuffix(FieldProductName, v))
}
// ProductNameEqualFold applies the EqualFold predicate on the "product_name" field.
func ProductNameEqualFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEqualFold(FieldProductName, v))
}
// ProductNameContainsFold applies the ContainsFold predicate on the "product_name" field.
func ProductNameContainsFold(v string) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldContainsFold(FieldProductName, v))
}
// ForSaleEQ applies the EQ predicate on the "for_sale" field.
func ForSaleEQ(v bool) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldForSale, v))
}
// ForSaleNEQ applies the NEQ predicate on the "for_sale" field.
func ForSaleNEQ(v bool) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldForSale, v))
}
// SortOrderEQ applies the EQ predicate on the "sort_order" field.
func SortOrderEQ(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldSortOrder, v))
}
// SortOrderNEQ applies the NEQ predicate on the "sort_order" field.
func SortOrderNEQ(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldSortOrder, v))
}
// SortOrderIn applies the In predicate on the "sort_order" field.
func SortOrderIn(vs ...int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldSortOrder, vs...))
}
// SortOrderNotIn applies the NotIn predicate on the "sort_order" field.
func SortOrderNotIn(vs ...int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldSortOrder, vs...))
}
// SortOrderGT applies the GT predicate on the "sort_order" field.
func SortOrderGT(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldSortOrder, v))
}
// SortOrderGTE applies the GTE predicate on the "sort_order" field.
func SortOrderGTE(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldSortOrder, v))
}
// SortOrderLT applies the LT predicate on the "sort_order" field.
func SortOrderLT(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldSortOrder, v))
}
// SortOrderLTE applies the LTE predicate on the "sort_order" field.
func SortOrderLTE(v int) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldSortOrder, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.FieldLTE(FieldUpdatedAt, v))
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.SubscriptionPlan) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.SubscriptionPlan) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.SubscriptionPlan) predicate.SubscriptionPlan {
return predicate.SubscriptionPlan(sql.NotPredicates(p))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
)
// SubscriptionPlanDelete is the builder for deleting a SubscriptionPlan entity.
type SubscriptionPlanDelete struct {
config
hooks []Hook
mutation *SubscriptionPlanMutation
}
// Where appends a list predicates to the SubscriptionPlanDelete builder.
func (_d *SubscriptionPlanDelete) Where(ps ...predicate.SubscriptionPlan) *SubscriptionPlanDelete {
_d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (_d *SubscriptionPlanDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *SubscriptionPlanDelete) ExecX(ctx context.Context) int {
n, err := _d.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (_d *SubscriptionPlanDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(subscriptionplan.Table, sqlgraph.NewFieldSpec(subscriptionplan.FieldID, field.TypeInt64))
if ps := _d.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
_d.mutation.done = true
return affected, err
}
// SubscriptionPlanDeleteOne is the builder for deleting a single SubscriptionPlan entity.
type SubscriptionPlanDeleteOne struct {
_d *SubscriptionPlanDelete
}
// Where appends a list predicates to the SubscriptionPlanDelete builder.
func (_d *SubscriptionPlanDeleteOne) Where(ps ...predicate.SubscriptionPlan) *SubscriptionPlanDeleteOne {
_d._d.mutation.Where(ps...)
return _d
}
// Exec executes the deletion query.
func (_d *SubscriptionPlanDeleteOne) Exec(ctx context.Context) error {
n, err := _d._d.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{subscriptionplan.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (_d *SubscriptionPlanDeleteOne) ExecX(ctx context.Context) {
if err := _d.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,564 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
)
// SubscriptionPlanQuery is the builder for querying SubscriptionPlan entities.
type SubscriptionPlanQuery struct {
config
ctx *QueryContext
order []subscriptionplan.OrderOption
inters []Interceptor
predicates []predicate.SubscriptionPlan
modifiers []func(*sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the SubscriptionPlanQuery builder.
func (_q *SubscriptionPlanQuery) Where(ps ...predicate.SubscriptionPlan) *SubscriptionPlanQuery {
_q.predicates = append(_q.predicates, ps...)
return _q
}
// Limit the number of records to be returned by this query.
func (_q *SubscriptionPlanQuery) Limit(limit int) *SubscriptionPlanQuery {
_q.ctx.Limit = &limit
return _q
}
// Offset to start from.
func (_q *SubscriptionPlanQuery) Offset(offset int) *SubscriptionPlanQuery {
_q.ctx.Offset = &offset
return _q
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (_q *SubscriptionPlanQuery) Unique(unique bool) *SubscriptionPlanQuery {
_q.ctx.Unique = &unique
return _q
}
// Order specifies how the records should be ordered.
func (_q *SubscriptionPlanQuery) Order(o ...subscriptionplan.OrderOption) *SubscriptionPlanQuery {
_q.order = append(_q.order, o...)
return _q
}
// First returns the first SubscriptionPlan entity from the query.
// Returns a *NotFoundError when no SubscriptionPlan was found.
func (_q *SubscriptionPlanQuery) First(ctx context.Context) (*SubscriptionPlan, error) {
nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{subscriptionplan.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) FirstX(ctx context.Context) *SubscriptionPlan {
node, err := _q.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first SubscriptionPlan ID from the query.
// Returns a *NotFoundError when no SubscriptionPlan ID was found.
func (_q *SubscriptionPlanQuery) FirstID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{subscriptionplan.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) FirstIDX(ctx context.Context) int64 {
id, err := _q.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single SubscriptionPlan entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one SubscriptionPlan entity is found.
// Returns a *NotFoundError when no SubscriptionPlan entities are found.
func (_q *SubscriptionPlanQuery) Only(ctx context.Context) (*SubscriptionPlan, error) {
nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{subscriptionplan.Label}
default:
return nil, &NotSingularError{subscriptionplan.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) OnlyX(ctx context.Context) *SubscriptionPlan {
node, err := _q.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only SubscriptionPlan ID in the query.
// Returns a *NotSingularError when more than one SubscriptionPlan ID is found.
// Returns a *NotFoundError when no entities are found.
func (_q *SubscriptionPlanQuery) OnlyID(ctx context.Context) (id int64, err error) {
var ids []int64
if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{subscriptionplan.Label}
default:
err = &NotSingularError{subscriptionplan.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) OnlyIDX(ctx context.Context) int64 {
id, err := _q.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of SubscriptionPlans.
func (_q *SubscriptionPlanQuery) All(ctx context.Context) ([]*SubscriptionPlan, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll)
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*SubscriptionPlan, *SubscriptionPlanQuery]()
return withInterceptors[[]*SubscriptionPlan](ctx, _q, qr, _q.inters)
}
// AllX is like All, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) AllX(ctx context.Context) []*SubscriptionPlan {
nodes, err := _q.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of SubscriptionPlan IDs.
func (_q *SubscriptionPlanQuery) IDs(ctx context.Context) (ids []int64, err error) {
if _q.ctx.Unique == nil && _q.path != nil {
_q.Unique(true)
}
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs)
if err = _q.Select(subscriptionplan.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) IDsX(ctx context.Context) []int64 {
ids, err := _q.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (_q *SubscriptionPlanQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount)
if err := _q.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, _q, querierCount[*SubscriptionPlanQuery](), _q.inters)
}
// CountX is like Count, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) CountX(ctx context.Context) int {
count, err := _q.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (_q *SubscriptionPlanQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist)
switch _, err := _q.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (_q *SubscriptionPlanQuery) ExistX(ctx context.Context) bool {
exist, err := _q.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the SubscriptionPlanQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (_q *SubscriptionPlanQuery) Clone() *SubscriptionPlanQuery {
if _q == nil {
return nil
}
return &SubscriptionPlanQuery{
config: _q.config,
ctx: _q.ctx.Clone(),
order: append([]subscriptionplan.OrderOption{}, _q.order...),
inters: append([]Interceptor{}, _q.inters...),
predicates: append([]predicate.SubscriptionPlan{}, _q.predicates...),
// clone intermediate query.
sql: _q.sql.Clone(),
path: _q.path,
}
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// GroupID int64 `json:"group_id,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.SubscriptionPlan.Query().
// GroupBy(subscriptionplan.FieldGroupID).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *SubscriptionPlanQuery) GroupBy(field string, fields ...string) *SubscriptionPlanGroupBy {
_q.ctx.Fields = append([]string{field}, fields...)
grbuild := &SubscriptionPlanGroupBy{build: _q}
grbuild.flds = &_q.ctx.Fields
grbuild.label = subscriptionplan.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// GroupID int64 `json:"group_id,omitempty"`
// }
//
// client.SubscriptionPlan.Query().
// Select(subscriptionplan.FieldGroupID).
// Scan(ctx, &v)
func (_q *SubscriptionPlanQuery) Select(fields ...string) *SubscriptionPlanSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
sbuild := &SubscriptionPlanSelect{SubscriptionPlanQuery: _q}
sbuild.label = subscriptionplan.Label
sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a SubscriptionPlanSelect configured with the given aggregations.
func (_q *SubscriptionPlanQuery) Aggregate(fns ...AggregateFunc) *SubscriptionPlanSelect {
return _q.Select().Aggregate(fns...)
}
func (_q *SubscriptionPlanQuery) prepareQuery(ctx context.Context) error {
for _, inter := range _q.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, _q); err != nil {
return err
}
}
}
for _, f := range _q.ctx.Fields {
if !subscriptionplan.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if _q.path != nil {
prev, err := _q.path(ctx)
if err != nil {
return err
}
_q.sql = prev
}
return nil
}
func (_q *SubscriptionPlanQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*SubscriptionPlan, error) {
var (
nodes = []*SubscriptionPlan{}
_spec = _q.querySpec()
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*SubscriptionPlan).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &SubscriptionPlan{config: _q.config}
nodes = append(nodes, node)
return node.assignValues(columns, values)
}
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
return nodes, nil
}
func (_q *SubscriptionPlanQuery) sqlCount(ctx context.Context) (int, error) {
_spec := _q.querySpec()
if len(_q.modifiers) > 0 {
_spec.Modifiers = _q.modifiers
}
_spec.Node.Columns = _q.ctx.Fields
if len(_q.ctx.Fields) > 0 {
_spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique
}
return sqlgraph.CountNodes(ctx, _q.driver, _spec)
}
func (_q *SubscriptionPlanQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(subscriptionplan.Table, subscriptionplan.Columns, sqlgraph.NewFieldSpec(subscriptionplan.FieldID, field.TypeInt64))
_spec.From = _q.sql
if unique := _q.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if _q.path != nil {
_spec.Unique = true
}
if fields := _q.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, subscriptionplan.FieldID)
for i := range fields {
if fields[i] != subscriptionplan.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := _q.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := _q.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := _q.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := _q.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (_q *SubscriptionPlanQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(_q.driver.Dialect())
t1 := builder.Table(subscriptionplan.Table)
columns := _q.ctx.Fields
if len(columns) == 0 {
columns = subscriptionplan.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if _q.sql != nil {
selector = _q.sql
selector.Select(selector.Columns(columns...)...)
}
if _q.ctx.Unique != nil && *_q.ctx.Unique {
selector.Distinct()
}
for _, m := range _q.modifiers {
m(selector)
}
for _, p := range _q.predicates {
p(selector)
}
for _, p := range _q.order {
p(selector)
}
if offset := _q.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := _q.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
// updated, deleted or "selected ... for update" by other sessions, until the transaction is
// either committed or rolled-back.
func (_q *SubscriptionPlanQuery) ForUpdate(opts ...sql.LockOption) *SubscriptionPlanQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForUpdate(opts...)
})
return _q
}
// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
// on any rows that are read. Other sessions can read the rows, but cannot modify them
// until your transaction commits.
func (_q *SubscriptionPlanQuery) ForShare(opts ...sql.LockOption) *SubscriptionPlanQuery {
if _q.driver.Dialect() == dialect.Postgres {
_q.Unique(false)
}
_q.modifiers = append(_q.modifiers, func(s *sql.Selector) {
s.ForShare(opts...)
})
return _q
}
// SubscriptionPlanGroupBy is the group-by builder for SubscriptionPlan entities.
type SubscriptionPlanGroupBy struct {
selector
build *SubscriptionPlanQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (_g *SubscriptionPlanGroupBy) Aggregate(fns ...AggregateFunc) *SubscriptionPlanGroupBy {
_g.fns = append(_g.fns, fns...)
return _g
}
// Scan applies the selector query and scans the result into the given value.
func (_g *SubscriptionPlanGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy)
if err := _g.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*SubscriptionPlanQuery, *SubscriptionPlanGroupBy](ctx, _g.build, _g, _g.build.inters, v)
}
func (_g *SubscriptionPlanGroupBy) sqlScan(ctx context.Context, root *SubscriptionPlanQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(_g.fns))
for _, fn := range _g.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*_g.flds)+len(_g.fns))
for _, f := range *_g.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*_g.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _g.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// SubscriptionPlanSelect is the builder for selecting fields of SubscriptionPlan entities.
type SubscriptionPlanSelect struct {
*SubscriptionPlanQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (_s *SubscriptionPlanSelect) Aggregate(fns ...AggregateFunc) *SubscriptionPlanSelect {
_s.fns = append(_s.fns, fns...)
return _s
}
// Scan applies the selector query and scans the result into the given value.
func (_s *SubscriptionPlanSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect)
if err := _s.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*SubscriptionPlanQuery, *SubscriptionPlanSelect](ctx, _s.SubscriptionPlanQuery, _s, _s.inters, v)
}
func (_s *SubscriptionPlanSelect) sqlScan(ctx context.Context, root *SubscriptionPlanQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(_s.fns))
for _, fn := range _s.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*_s.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := _s.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@@ -0,0 +1,750 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/subscriptionplan"
)
// SubscriptionPlanUpdate is the builder for updating SubscriptionPlan entities.
type SubscriptionPlanUpdate struct {
config
hooks []Hook
mutation *SubscriptionPlanMutation
}
// Where appends a list predicates to the SubscriptionPlanUpdate builder.
func (_u *SubscriptionPlanUpdate) Where(ps ...predicate.SubscriptionPlan) *SubscriptionPlanUpdate {
_u.mutation.Where(ps...)
return _u
}
// SetGroupID sets the "group_id" field.
func (_u *SubscriptionPlanUpdate) SetGroupID(v int64) *SubscriptionPlanUpdate {
_u.mutation.ResetGroupID()
_u.mutation.SetGroupID(v)
return _u
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableGroupID(v *int64) *SubscriptionPlanUpdate {
if v != nil {
_u.SetGroupID(*v)
}
return _u
}
// AddGroupID adds value to the "group_id" field.
func (_u *SubscriptionPlanUpdate) AddGroupID(v int64) *SubscriptionPlanUpdate {
_u.mutation.AddGroupID(v)
return _u
}
// SetName sets the "name" field.
func (_u *SubscriptionPlanUpdate) SetName(v string) *SubscriptionPlanUpdate {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableName(v *string) *SubscriptionPlanUpdate {
if v != nil {
_u.SetName(*v)
}
return _u
}
// SetDescription sets the "description" field.
func (_u *SubscriptionPlanUpdate) SetDescription(v string) *SubscriptionPlanUpdate {
_u.mutation.SetDescription(v)
return _u
}
// SetNillableDescription sets the "description" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableDescription(v *string) *SubscriptionPlanUpdate {
if v != nil {
_u.SetDescription(*v)
}
return _u
}
// SetPrice sets the "price" field.
func (_u *SubscriptionPlanUpdate) SetPrice(v float64) *SubscriptionPlanUpdate {
_u.mutation.ResetPrice()
_u.mutation.SetPrice(v)
return _u
}
// SetNillablePrice sets the "price" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillablePrice(v *float64) *SubscriptionPlanUpdate {
if v != nil {
_u.SetPrice(*v)
}
return _u
}
// AddPrice adds value to the "price" field.
func (_u *SubscriptionPlanUpdate) AddPrice(v float64) *SubscriptionPlanUpdate {
_u.mutation.AddPrice(v)
return _u
}
// SetOriginalPrice sets the "original_price" field.
func (_u *SubscriptionPlanUpdate) SetOriginalPrice(v float64) *SubscriptionPlanUpdate {
_u.mutation.ResetOriginalPrice()
_u.mutation.SetOriginalPrice(v)
return _u
}
// SetNillableOriginalPrice sets the "original_price" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableOriginalPrice(v *float64) *SubscriptionPlanUpdate {
if v != nil {
_u.SetOriginalPrice(*v)
}
return _u
}
// AddOriginalPrice adds value to the "original_price" field.
func (_u *SubscriptionPlanUpdate) AddOriginalPrice(v float64) *SubscriptionPlanUpdate {
_u.mutation.AddOriginalPrice(v)
return _u
}
// ClearOriginalPrice clears the value of the "original_price" field.
func (_u *SubscriptionPlanUpdate) ClearOriginalPrice() *SubscriptionPlanUpdate {
_u.mutation.ClearOriginalPrice()
return _u
}
// SetValidityDays sets the "validity_days" field.
func (_u *SubscriptionPlanUpdate) SetValidityDays(v int) *SubscriptionPlanUpdate {
_u.mutation.ResetValidityDays()
_u.mutation.SetValidityDays(v)
return _u
}
// SetNillableValidityDays sets the "validity_days" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableValidityDays(v *int) *SubscriptionPlanUpdate {
if v != nil {
_u.SetValidityDays(*v)
}
return _u
}
// AddValidityDays adds value to the "validity_days" field.
func (_u *SubscriptionPlanUpdate) AddValidityDays(v int) *SubscriptionPlanUpdate {
_u.mutation.AddValidityDays(v)
return _u
}
// SetValidityUnit sets the "validity_unit" field.
func (_u *SubscriptionPlanUpdate) SetValidityUnit(v string) *SubscriptionPlanUpdate {
_u.mutation.SetValidityUnit(v)
return _u
}
// SetNillableValidityUnit sets the "validity_unit" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableValidityUnit(v *string) *SubscriptionPlanUpdate {
if v != nil {
_u.SetValidityUnit(*v)
}
return _u
}
// SetFeatures sets the "features" field.
func (_u *SubscriptionPlanUpdate) SetFeatures(v string) *SubscriptionPlanUpdate {
_u.mutation.SetFeatures(v)
return _u
}
// SetNillableFeatures sets the "features" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableFeatures(v *string) *SubscriptionPlanUpdate {
if v != nil {
_u.SetFeatures(*v)
}
return _u
}
// SetProductName sets the "product_name" field.
func (_u *SubscriptionPlanUpdate) SetProductName(v string) *SubscriptionPlanUpdate {
_u.mutation.SetProductName(v)
return _u
}
// SetNillableProductName sets the "product_name" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableProductName(v *string) *SubscriptionPlanUpdate {
if v != nil {
_u.SetProductName(*v)
}
return _u
}
// SetForSale sets the "for_sale" field.
func (_u *SubscriptionPlanUpdate) SetForSale(v bool) *SubscriptionPlanUpdate {
_u.mutation.SetForSale(v)
return _u
}
// SetNillableForSale sets the "for_sale" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableForSale(v *bool) *SubscriptionPlanUpdate {
if v != nil {
_u.SetForSale(*v)
}
return _u
}
// SetSortOrder sets the "sort_order" field.
func (_u *SubscriptionPlanUpdate) SetSortOrder(v int) *SubscriptionPlanUpdate {
_u.mutation.ResetSortOrder()
_u.mutation.SetSortOrder(v)
return _u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func (_u *SubscriptionPlanUpdate) SetNillableSortOrder(v *int) *SubscriptionPlanUpdate {
if v != nil {
_u.SetSortOrder(*v)
}
return _u
}
// AddSortOrder adds value to the "sort_order" field.
func (_u *SubscriptionPlanUpdate) AddSortOrder(v int) *SubscriptionPlanUpdate {
_u.mutation.AddSortOrder(v)
return _u
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *SubscriptionPlanUpdate) SetUpdatedAt(v time.Time) *SubscriptionPlanUpdate {
_u.mutation.SetUpdatedAt(v)
return _u
}
// Mutation returns the SubscriptionPlanMutation object of the builder.
func (_u *SubscriptionPlanUpdate) Mutation() *SubscriptionPlanMutation {
return _u.mutation
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (_u *SubscriptionPlanUpdate) Save(ctx context.Context) (int, error) {
_u.defaults()
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *SubscriptionPlanUpdate) SaveX(ctx context.Context) int {
affected, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (_u *SubscriptionPlanUpdate) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *SubscriptionPlanUpdate) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *SubscriptionPlanUpdate) defaults() {
if _, ok := _u.mutation.UpdatedAt(); !ok {
v := subscriptionplan.UpdateDefaultUpdatedAt()
_u.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *SubscriptionPlanUpdate) check() error {
if v, ok := _u.mutation.Name(); ok {
if err := subscriptionplan.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.name": %w`, err)}
}
}
if v, ok := _u.mutation.ValidityUnit(); ok {
if err := subscriptionplan.ValidityUnitValidator(v); err != nil {
return &ValidationError{Name: "validity_unit", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.validity_unit": %w`, err)}
}
}
if v, ok := _u.mutation.ProductName(); ok {
if err := subscriptionplan.ProductNameValidator(v); err != nil {
return &ValidationError{Name: "product_name", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.product_name": %w`, err)}
}
}
return nil
}
func (_u *SubscriptionPlanUpdate) sqlSave(ctx context.Context) (_node int, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(subscriptionplan.Table, subscriptionplan.Columns, sqlgraph.NewFieldSpec(subscriptionplan.FieldID, field.TypeInt64))
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.GroupID(); ok {
_spec.SetField(subscriptionplan.FieldGroupID, field.TypeInt64, value)
}
if value, ok := _u.mutation.AddedGroupID(); ok {
_spec.AddField(subscriptionplan.FieldGroupID, field.TypeInt64, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(subscriptionplan.FieldName, field.TypeString, value)
}
if value, ok := _u.mutation.Description(); ok {
_spec.SetField(subscriptionplan.FieldDescription, field.TypeString, value)
}
if value, ok := _u.mutation.Price(); ok {
_spec.SetField(subscriptionplan.FieldPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedPrice(); ok {
_spec.AddField(subscriptionplan.FieldPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.OriginalPrice(); ok {
_spec.SetField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedOriginalPrice(); ok {
_spec.AddField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64, value)
}
if _u.mutation.OriginalPriceCleared() {
_spec.ClearField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64)
}
if value, ok := _u.mutation.ValidityDays(); ok {
_spec.SetField(subscriptionplan.FieldValidityDays, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedValidityDays(); ok {
_spec.AddField(subscriptionplan.FieldValidityDays, field.TypeInt, value)
}
if value, ok := _u.mutation.ValidityUnit(); ok {
_spec.SetField(subscriptionplan.FieldValidityUnit, field.TypeString, value)
}
if value, ok := _u.mutation.Features(); ok {
_spec.SetField(subscriptionplan.FieldFeatures, field.TypeString, value)
}
if value, ok := _u.mutation.ProductName(); ok {
_spec.SetField(subscriptionplan.FieldProductName, field.TypeString, value)
}
if value, ok := _u.mutation.ForSale(); ok {
_spec.SetField(subscriptionplan.FieldForSale, field.TypeBool, value)
}
if value, ok := _u.mutation.SortOrder(); ok {
_spec.SetField(subscriptionplan.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedSortOrder(); ok {
_spec.AddField(subscriptionplan.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.UpdatedAt(); ok {
_spec.SetField(subscriptionplan.FieldUpdatedAt, field.TypeTime, value)
}
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{subscriptionplan.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
_u.mutation.done = true
return _node, nil
}
// SubscriptionPlanUpdateOne is the builder for updating a single SubscriptionPlan entity.
type SubscriptionPlanUpdateOne struct {
config
fields []string
hooks []Hook
mutation *SubscriptionPlanMutation
}
// SetGroupID sets the "group_id" field.
func (_u *SubscriptionPlanUpdateOne) SetGroupID(v int64) *SubscriptionPlanUpdateOne {
_u.mutation.ResetGroupID()
_u.mutation.SetGroupID(v)
return _u
}
// SetNillableGroupID sets the "group_id" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableGroupID(v *int64) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetGroupID(*v)
}
return _u
}
// AddGroupID adds value to the "group_id" field.
func (_u *SubscriptionPlanUpdateOne) AddGroupID(v int64) *SubscriptionPlanUpdateOne {
_u.mutation.AddGroupID(v)
return _u
}
// SetName sets the "name" field.
func (_u *SubscriptionPlanUpdateOne) SetName(v string) *SubscriptionPlanUpdateOne {
_u.mutation.SetName(v)
return _u
}
// SetNillableName sets the "name" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableName(v *string) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetName(*v)
}
return _u
}
// SetDescription sets the "description" field.
func (_u *SubscriptionPlanUpdateOne) SetDescription(v string) *SubscriptionPlanUpdateOne {
_u.mutation.SetDescription(v)
return _u
}
// SetNillableDescription sets the "description" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableDescription(v *string) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetDescription(*v)
}
return _u
}
// SetPrice sets the "price" field.
func (_u *SubscriptionPlanUpdateOne) SetPrice(v float64) *SubscriptionPlanUpdateOne {
_u.mutation.ResetPrice()
_u.mutation.SetPrice(v)
return _u
}
// SetNillablePrice sets the "price" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillablePrice(v *float64) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetPrice(*v)
}
return _u
}
// AddPrice adds value to the "price" field.
func (_u *SubscriptionPlanUpdateOne) AddPrice(v float64) *SubscriptionPlanUpdateOne {
_u.mutation.AddPrice(v)
return _u
}
// SetOriginalPrice sets the "original_price" field.
func (_u *SubscriptionPlanUpdateOne) SetOriginalPrice(v float64) *SubscriptionPlanUpdateOne {
_u.mutation.ResetOriginalPrice()
_u.mutation.SetOriginalPrice(v)
return _u
}
// SetNillableOriginalPrice sets the "original_price" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableOriginalPrice(v *float64) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetOriginalPrice(*v)
}
return _u
}
// AddOriginalPrice adds value to the "original_price" field.
func (_u *SubscriptionPlanUpdateOne) AddOriginalPrice(v float64) *SubscriptionPlanUpdateOne {
_u.mutation.AddOriginalPrice(v)
return _u
}
// ClearOriginalPrice clears the value of the "original_price" field.
func (_u *SubscriptionPlanUpdateOne) ClearOriginalPrice() *SubscriptionPlanUpdateOne {
_u.mutation.ClearOriginalPrice()
return _u
}
// SetValidityDays sets the "validity_days" field.
func (_u *SubscriptionPlanUpdateOne) SetValidityDays(v int) *SubscriptionPlanUpdateOne {
_u.mutation.ResetValidityDays()
_u.mutation.SetValidityDays(v)
return _u
}
// SetNillableValidityDays sets the "validity_days" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableValidityDays(v *int) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetValidityDays(*v)
}
return _u
}
// AddValidityDays adds value to the "validity_days" field.
func (_u *SubscriptionPlanUpdateOne) AddValidityDays(v int) *SubscriptionPlanUpdateOne {
_u.mutation.AddValidityDays(v)
return _u
}
// SetValidityUnit sets the "validity_unit" field.
func (_u *SubscriptionPlanUpdateOne) SetValidityUnit(v string) *SubscriptionPlanUpdateOne {
_u.mutation.SetValidityUnit(v)
return _u
}
// SetNillableValidityUnit sets the "validity_unit" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableValidityUnit(v *string) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetValidityUnit(*v)
}
return _u
}
// SetFeatures sets the "features" field.
func (_u *SubscriptionPlanUpdateOne) SetFeatures(v string) *SubscriptionPlanUpdateOne {
_u.mutation.SetFeatures(v)
return _u
}
// SetNillableFeatures sets the "features" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableFeatures(v *string) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetFeatures(*v)
}
return _u
}
// SetProductName sets the "product_name" field.
func (_u *SubscriptionPlanUpdateOne) SetProductName(v string) *SubscriptionPlanUpdateOne {
_u.mutation.SetProductName(v)
return _u
}
// SetNillableProductName sets the "product_name" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableProductName(v *string) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetProductName(*v)
}
return _u
}
// SetForSale sets the "for_sale" field.
func (_u *SubscriptionPlanUpdateOne) SetForSale(v bool) *SubscriptionPlanUpdateOne {
_u.mutation.SetForSale(v)
return _u
}
// SetNillableForSale sets the "for_sale" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableForSale(v *bool) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetForSale(*v)
}
return _u
}
// SetSortOrder sets the "sort_order" field.
func (_u *SubscriptionPlanUpdateOne) SetSortOrder(v int) *SubscriptionPlanUpdateOne {
_u.mutation.ResetSortOrder()
_u.mutation.SetSortOrder(v)
return _u
}
// SetNillableSortOrder sets the "sort_order" field if the given value is not nil.
func (_u *SubscriptionPlanUpdateOne) SetNillableSortOrder(v *int) *SubscriptionPlanUpdateOne {
if v != nil {
_u.SetSortOrder(*v)
}
return _u
}
// AddSortOrder adds value to the "sort_order" field.
func (_u *SubscriptionPlanUpdateOne) AddSortOrder(v int) *SubscriptionPlanUpdateOne {
_u.mutation.AddSortOrder(v)
return _u
}
// SetUpdatedAt sets the "updated_at" field.
func (_u *SubscriptionPlanUpdateOne) SetUpdatedAt(v time.Time) *SubscriptionPlanUpdateOne {
_u.mutation.SetUpdatedAt(v)
return _u
}
// Mutation returns the SubscriptionPlanMutation object of the builder.
func (_u *SubscriptionPlanUpdateOne) Mutation() *SubscriptionPlanMutation {
return _u.mutation
}
// Where appends a list predicates to the SubscriptionPlanUpdate builder.
func (_u *SubscriptionPlanUpdateOne) Where(ps ...predicate.SubscriptionPlan) *SubscriptionPlanUpdateOne {
_u.mutation.Where(ps...)
return _u
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (_u *SubscriptionPlanUpdateOne) Select(field string, fields ...string) *SubscriptionPlanUpdateOne {
_u.fields = append([]string{field}, fields...)
return _u
}
// Save executes the query and returns the updated SubscriptionPlan entity.
func (_u *SubscriptionPlanUpdateOne) Save(ctx context.Context) (*SubscriptionPlan, error) {
_u.defaults()
return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (_u *SubscriptionPlanUpdateOne) SaveX(ctx context.Context) *SubscriptionPlan {
node, err := _u.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (_u *SubscriptionPlanUpdateOne) Exec(ctx context.Context) error {
_, err := _u.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (_u *SubscriptionPlanUpdateOne) ExecX(ctx context.Context) {
if err := _u.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (_u *SubscriptionPlanUpdateOne) defaults() {
if _, ok := _u.mutation.UpdatedAt(); !ok {
v := subscriptionplan.UpdateDefaultUpdatedAt()
_u.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (_u *SubscriptionPlanUpdateOne) check() error {
if v, ok := _u.mutation.Name(); ok {
if err := subscriptionplan.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.name": %w`, err)}
}
}
if v, ok := _u.mutation.ValidityUnit(); ok {
if err := subscriptionplan.ValidityUnitValidator(v); err != nil {
return &ValidationError{Name: "validity_unit", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.validity_unit": %w`, err)}
}
}
if v, ok := _u.mutation.ProductName(); ok {
if err := subscriptionplan.ProductNameValidator(v); err != nil {
return &ValidationError{Name: "product_name", err: fmt.Errorf(`ent: validator failed for field "SubscriptionPlan.product_name": %w`, err)}
}
}
return nil
}
func (_u *SubscriptionPlanUpdateOne) sqlSave(ctx context.Context) (_node *SubscriptionPlan, err error) {
if err := _u.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(subscriptionplan.Table, subscriptionplan.Columns, sqlgraph.NewFieldSpec(subscriptionplan.FieldID, field.TypeInt64))
id, ok := _u.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "SubscriptionPlan.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := _u.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, subscriptionplan.FieldID)
for _, f := range fields {
if !subscriptionplan.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != subscriptionplan.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := _u.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := _u.mutation.GroupID(); ok {
_spec.SetField(subscriptionplan.FieldGroupID, field.TypeInt64, value)
}
if value, ok := _u.mutation.AddedGroupID(); ok {
_spec.AddField(subscriptionplan.FieldGroupID, field.TypeInt64, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(subscriptionplan.FieldName, field.TypeString, value)
}
if value, ok := _u.mutation.Description(); ok {
_spec.SetField(subscriptionplan.FieldDescription, field.TypeString, value)
}
if value, ok := _u.mutation.Price(); ok {
_spec.SetField(subscriptionplan.FieldPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedPrice(); ok {
_spec.AddField(subscriptionplan.FieldPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.OriginalPrice(); ok {
_spec.SetField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64, value)
}
if value, ok := _u.mutation.AddedOriginalPrice(); ok {
_spec.AddField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64, value)
}
if _u.mutation.OriginalPriceCleared() {
_spec.ClearField(subscriptionplan.FieldOriginalPrice, field.TypeFloat64)
}
if value, ok := _u.mutation.ValidityDays(); ok {
_spec.SetField(subscriptionplan.FieldValidityDays, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedValidityDays(); ok {
_spec.AddField(subscriptionplan.FieldValidityDays, field.TypeInt, value)
}
if value, ok := _u.mutation.ValidityUnit(); ok {
_spec.SetField(subscriptionplan.FieldValidityUnit, field.TypeString, value)
}
if value, ok := _u.mutation.Features(); ok {
_spec.SetField(subscriptionplan.FieldFeatures, field.TypeString, value)
}
if value, ok := _u.mutation.ProductName(); ok {
_spec.SetField(subscriptionplan.FieldProductName, field.TypeString, value)
}
if value, ok := _u.mutation.ForSale(); ok {
_spec.SetField(subscriptionplan.FieldForSale, field.TypeBool, value)
}
if value, ok := _u.mutation.SortOrder(); ok {
_spec.SetField(subscriptionplan.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.AddedSortOrder(); ok {
_spec.AddField(subscriptionplan.FieldSortOrder, field.TypeInt, value)
}
if value, ok := _u.mutation.UpdatedAt(); ok {
_spec.SetField(subscriptionplan.FieldUpdatedAt, field.TypeTime, value)
}
_node = &SubscriptionPlan{config: _u.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{subscriptionplan.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
_u.mutation.done = true
return _node, nil
}

View File

@@ -30,6 +30,12 @@ type Tx struct {
Group *GroupClient
// IdempotencyRecord is the client for interacting with the IdempotencyRecord builders.
IdempotencyRecord *IdempotencyRecordClient
// PaymentAuditLog is the client for interacting with the PaymentAuditLog builders.
PaymentAuditLog *PaymentAuditLogClient
// PaymentOrder is the client for interacting with the PaymentOrder builders.
PaymentOrder *PaymentOrderClient
// PaymentProviderInstance is the client for interacting with the PaymentProviderInstance builders.
PaymentProviderInstance *PaymentProviderInstanceClient
// PromoCode is the client for interacting with the PromoCode builders.
PromoCode *PromoCodeClient
// PromoCodeUsage is the client for interacting with the PromoCodeUsage builders.
@@ -42,6 +48,8 @@ type Tx struct {
SecuritySecret *SecuritySecretClient
// Setting is the client for interacting with the Setting builders.
Setting *SettingClient
// SubscriptionPlan is the client for interacting with the SubscriptionPlan builders.
SubscriptionPlan *SubscriptionPlanClient
// TLSFingerprintProfile is the client for interacting with the TLSFingerprintProfile builders.
TLSFingerprintProfile *TLSFingerprintProfileClient
// UsageCleanupTask is the client for interacting with the UsageCleanupTask builders.
@@ -197,12 +205,16 @@ func (tx *Tx) init() {
tx.ErrorPassthroughRule = NewErrorPassthroughRuleClient(tx.config)
tx.Group = NewGroupClient(tx.config)
tx.IdempotencyRecord = NewIdempotencyRecordClient(tx.config)
tx.PaymentAuditLog = NewPaymentAuditLogClient(tx.config)
tx.PaymentOrder = NewPaymentOrderClient(tx.config)
tx.PaymentProviderInstance = NewPaymentProviderInstanceClient(tx.config)
tx.PromoCode = NewPromoCodeClient(tx.config)
tx.PromoCodeUsage = NewPromoCodeUsageClient(tx.config)
tx.Proxy = NewProxyClient(tx.config)
tx.RedeemCode = NewRedeemCodeClient(tx.config)
tx.SecuritySecret = NewSecuritySecretClient(tx.config)
tx.Setting = NewSettingClient(tx.config)
tx.SubscriptionPlan = NewSubscriptionPlanClient(tx.config)
tx.TLSFingerprintProfile = NewTLSFingerprintProfileClient(tx.config)
tx.UsageCleanupTask = NewUsageCleanupTaskClient(tx.config)
tx.UsageLog = NewUsageLogClient(tx.config)

View File

@@ -71,11 +71,13 @@ type UserEdges struct {
AttributeValues []*UserAttributeValue `json:"attribute_values,omitempty"`
// PromoCodeUsages holds the value of the promo_code_usages edge.
PromoCodeUsages []*PromoCodeUsage `json:"promo_code_usages,omitempty"`
// PaymentOrders holds the value of the payment_orders edge.
PaymentOrders []*PaymentOrder `json:"payment_orders,omitempty"`
// UserAllowedGroups holds the value of the user_allowed_groups edge.
UserAllowedGroups []*UserAllowedGroup `json:"user_allowed_groups,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [10]bool
loadedTypes [11]bool
}
// APIKeysOrErr returns the APIKeys value or an error if the edge
@@ -159,10 +161,19 @@ func (e UserEdges) PromoCodeUsagesOrErr() ([]*PromoCodeUsage, error) {
return nil, &NotLoadedError{edge: "promo_code_usages"}
}
// PaymentOrdersOrErr returns the PaymentOrders value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) PaymentOrdersOrErr() ([]*PaymentOrder, error) {
if e.loadedTypes[9] {
return e.PaymentOrders, nil
}
return nil, &NotLoadedError{edge: "payment_orders"}
}
// UserAllowedGroupsOrErr returns the UserAllowedGroups value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) UserAllowedGroupsOrErr() ([]*UserAllowedGroup, error) {
if e.loadedTypes[9] {
if e.loadedTypes[10] {
return e.UserAllowedGroups, nil
}
return nil, &NotLoadedError{edge: "user_allowed_groups"}
@@ -349,6 +360,11 @@ func (_m *User) QueryPromoCodeUsages() *PromoCodeUsageQuery {
return NewUserClient(_m.config).QueryPromoCodeUsages(_m)
}
// QueryPaymentOrders queries the "payment_orders" edge of the User entity.
func (_m *User) QueryPaymentOrders() *PaymentOrderQuery {
return NewUserClient(_m.config).QueryPaymentOrders(_m)
}
// QueryUserAllowedGroups queries the "user_allowed_groups" edge of the User entity.
func (_m *User) QueryUserAllowedGroups() *UserAllowedGroupQuery {
return NewUserClient(_m.config).QueryUserAllowedGroups(_m)

View File

@@ -61,6 +61,8 @@ const (
EdgeAttributeValues = "attribute_values"
// EdgePromoCodeUsages holds the string denoting the promo_code_usages edge name in mutations.
EdgePromoCodeUsages = "promo_code_usages"
// EdgePaymentOrders holds the string denoting the payment_orders edge name in mutations.
EdgePaymentOrders = "payment_orders"
// EdgeUserAllowedGroups holds the string denoting the user_allowed_groups edge name in mutations.
EdgeUserAllowedGroups = "user_allowed_groups"
// Table holds the table name of the user in the database.
@@ -126,6 +128,13 @@ const (
PromoCodeUsagesInverseTable = "promo_code_usages"
// PromoCodeUsagesColumn is the table column denoting the promo_code_usages relation/edge.
PromoCodeUsagesColumn = "user_id"
// PaymentOrdersTable is the table that holds the payment_orders relation/edge.
PaymentOrdersTable = "payment_orders"
// PaymentOrdersInverseTable is the table name for the PaymentOrder entity.
// It exists in this package in order to avoid circular dependency with the "paymentorder" package.
PaymentOrdersInverseTable = "payment_orders"
// PaymentOrdersColumn is the table column denoting the payment_orders relation/edge.
PaymentOrdersColumn = "user_id"
// UserAllowedGroupsTable is the table that holds the user_allowed_groups relation/edge.
UserAllowedGroupsTable = "user_allowed_groups"
// UserAllowedGroupsInverseTable is the table name for the UserAllowedGroup entity.
@@ -414,6 +423,20 @@ func ByPromoCodeUsages(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
}
}
// ByPaymentOrdersCount orders the results by payment_orders count.
func ByPaymentOrdersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newPaymentOrdersStep(), opts...)
}
}
// ByPaymentOrders orders the results by payment_orders terms.
func ByPaymentOrders(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newPaymentOrdersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByUserAllowedGroupsCount orders the results by user_allowed_groups count.
func ByUserAllowedGroupsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
@@ -490,6 +513,13 @@ func newPromoCodeUsagesStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.O2M, false, PromoCodeUsagesTable, PromoCodeUsagesColumn),
)
}
func newPaymentOrdersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(PaymentOrdersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, PaymentOrdersTable, PaymentOrdersColumn),
)
}
func newUserAllowedGroupsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),

View File

@@ -1067,6 +1067,29 @@ func HasPromoCodeUsagesWith(preds ...predicate.PromoCodeUsage) predicate.User {
})
}
// HasPaymentOrders applies the HasEdge predicate on the "payment_orders" edge.
func HasPaymentOrders() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, PaymentOrdersTable, PaymentOrdersColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasPaymentOrdersWith applies the HasEdge predicate on the "payment_orders" edge with a given conditions (other predicates).
func HasPaymentOrdersWith(preds ...predicate.PaymentOrder) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newPaymentOrdersStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasUserAllowedGroups applies the HasEdge predicate on the "user_allowed_groups" edge.
func HasUserAllowedGroups() predicate.User {
return predicate.User(func(s *sql.Selector) {

View File

@@ -14,6 +14,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
"github.com/Wei-Shaw/sub2api/ent/usagelog"
@@ -345,6 +346,21 @@ func (_c *UserCreate) AddPromoCodeUsages(v ...*PromoCodeUsage) *UserCreate {
return _c.AddPromoCodeUsageIDs(ids...)
}
// AddPaymentOrderIDs adds the "payment_orders" edge to the PaymentOrder entity by IDs.
func (_c *UserCreate) AddPaymentOrderIDs(ids ...int64) *UserCreate {
_c.mutation.AddPaymentOrderIDs(ids...)
return _c
}
// AddPaymentOrders adds the "payment_orders" edges to the PaymentOrder entity.
func (_c *UserCreate) AddPaymentOrders(v ...*PaymentOrder) *UserCreate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _c.AddPaymentOrderIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (_c *UserCreate) Mutation() *UserMutation {
return _c.mutation
@@ -718,6 +734,22 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := _c.mutation.PaymentOrdersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
@@ -42,6 +43,7 @@ type UserQuery struct {
withUsageLogs *UsageLogQuery
withAttributeValues *UserAttributeValueQuery
withPromoCodeUsages *PromoCodeUsageQuery
withPaymentOrders *PaymentOrderQuery
withUserAllowedGroups *UserAllowedGroupQuery
modifiers []func(*sql.Selector)
// intermediate query (i.e. traversal path).
@@ -278,6 +280,28 @@ func (_q *UserQuery) QueryPromoCodeUsages() *PromoCodeUsageQuery {
return query
}
// QueryPaymentOrders chains the current query on the "payment_orders" edge.
func (_q *UserQuery) QueryPaymentOrders() *PaymentOrderQuery {
query := (&PaymentOrderClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
selector := _q.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, selector),
sqlgraph.To(paymentorder.Table, paymentorder.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, user.PaymentOrdersTable, user.PaymentOrdersColumn),
)
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryUserAllowedGroups chains the current query on the "user_allowed_groups" edge.
func (_q *UserQuery) QueryUserAllowedGroups() *UserAllowedGroupQuery {
query := (&UserAllowedGroupClient{config: _q.config}).Query()
@@ -501,6 +525,7 @@ func (_q *UserQuery) Clone() *UserQuery {
withUsageLogs: _q.withUsageLogs.Clone(),
withAttributeValues: _q.withAttributeValues.Clone(),
withPromoCodeUsages: _q.withPromoCodeUsages.Clone(),
withPaymentOrders: _q.withPaymentOrders.Clone(),
withUserAllowedGroups: _q.withUserAllowedGroups.Clone(),
// clone intermediate query.
sql: _q.sql.Clone(),
@@ -607,6 +632,17 @@ func (_q *UserQuery) WithPromoCodeUsages(opts ...func(*PromoCodeUsageQuery)) *Us
return _q
}
// WithPaymentOrders tells the query-builder to eager-load the nodes that are connected to
// the "payment_orders" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UserQuery) WithPaymentOrders(opts ...func(*PaymentOrderQuery)) *UserQuery {
query := (&PaymentOrderClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
_q.withPaymentOrders = query
return _q
}
// WithUserAllowedGroups tells the query-builder to eager-load the nodes that are connected to
// the "user_allowed_groups" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UserQuery) WithUserAllowedGroups(opts ...func(*UserAllowedGroupQuery)) *UserQuery {
@@ -696,7 +732,7 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
var (
nodes = []*User{}
_spec = _q.querySpec()
loadedTypes = [10]bool{
loadedTypes = [11]bool{
_q.withAPIKeys != nil,
_q.withRedeemCodes != nil,
_q.withSubscriptions != nil,
@@ -706,6 +742,7 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
_q.withUsageLogs != nil,
_q.withAttributeValues != nil,
_q.withPromoCodeUsages != nil,
_q.withPaymentOrders != nil,
_q.withUserAllowedGroups != nil,
}
)
@@ -795,6 +832,13 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nil, err
}
}
if query := _q.withPaymentOrders; query != nil {
if err := _q.loadPaymentOrders(ctx, query, nodes,
func(n *User) { n.Edges.PaymentOrders = []*PaymentOrder{} },
func(n *User, e *PaymentOrder) { n.Edges.PaymentOrders = append(n.Edges.PaymentOrders, e) }); err != nil {
return nil, err
}
}
if query := _q.withUserAllowedGroups; query != nil {
if err := _q.loadUserAllowedGroups(ctx, query, nodes,
func(n *User) { n.Edges.UserAllowedGroups = []*UserAllowedGroup{} },
@@ -1112,6 +1156,36 @@ func (_q *UserQuery) loadPromoCodeUsages(ctx context.Context, query *PromoCodeUs
}
return nil
}
func (_q *UserQuery) loadPaymentOrders(ctx context.Context, query *PaymentOrderQuery, nodes []*User, init func(*User), assign func(*User, *PaymentOrder)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*User)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
if len(query.ctx.Fields) > 0 {
query.ctx.AppendFieldOnce(paymentorder.FieldUserID)
}
query.Where(predicate.PaymentOrder(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(user.PaymentOrdersColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.UserID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "user_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (_q *UserQuery) loadUserAllowedGroups(ctx context.Context, query *UserAllowedGroupQuery, nodes []*User, init func(*User), assign func(*User, *UserAllowedGroup)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*User)

View File

@@ -14,6 +14,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/paymentorder"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
"github.com/Wei-Shaw/sub2api/ent/redeemcode"
@@ -377,6 +378,21 @@ func (_u *UserUpdate) AddPromoCodeUsages(v ...*PromoCodeUsage) *UserUpdate {
return _u.AddPromoCodeUsageIDs(ids...)
}
// AddPaymentOrderIDs adds the "payment_orders" edge to the PaymentOrder entity by IDs.
func (_u *UserUpdate) AddPaymentOrderIDs(ids ...int64) *UserUpdate {
_u.mutation.AddPaymentOrderIDs(ids...)
return _u
}
// AddPaymentOrders adds the "payment_orders" edges to the PaymentOrder entity.
func (_u *UserUpdate) AddPaymentOrders(v ...*PaymentOrder) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.AddPaymentOrderIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (_u *UserUpdate) Mutation() *UserMutation {
return _u.mutation
@@ -571,6 +587,27 @@ func (_u *UserUpdate) RemovePromoCodeUsages(v ...*PromoCodeUsage) *UserUpdate {
return _u.RemovePromoCodeUsageIDs(ids...)
}
// ClearPaymentOrders clears all "payment_orders" edges to the PaymentOrder entity.
func (_u *UserUpdate) ClearPaymentOrders() *UserUpdate {
_u.mutation.ClearPaymentOrders()
return _u
}
// RemovePaymentOrderIDs removes the "payment_orders" edge to PaymentOrder entities by IDs.
func (_u *UserUpdate) RemovePaymentOrderIDs(ids ...int64) *UserUpdate {
_u.mutation.RemovePaymentOrderIDs(ids...)
return _u
}
// RemovePaymentOrders removes "payment_orders" edges to PaymentOrder entities.
func (_u *UserUpdate) RemovePaymentOrders(v ...*PaymentOrder) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.RemovePaymentOrderIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (_u *UserUpdate) Save(ctx context.Context) (int, error) {
if err := _u.defaults(); err != nil {
@@ -1126,6 +1163,51 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.PaymentOrdersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.RemovedPaymentOrdersIDs(); len(nodes) > 0 && !_u.mutation.PaymentOrdersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.PaymentOrdersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label}
@@ -1487,6 +1569,21 @@ func (_u *UserUpdateOne) AddPromoCodeUsages(v ...*PromoCodeUsage) *UserUpdateOne
return _u.AddPromoCodeUsageIDs(ids...)
}
// AddPaymentOrderIDs adds the "payment_orders" edge to the PaymentOrder entity by IDs.
func (_u *UserUpdateOne) AddPaymentOrderIDs(ids ...int64) *UserUpdateOne {
_u.mutation.AddPaymentOrderIDs(ids...)
return _u
}
// AddPaymentOrders adds the "payment_orders" edges to the PaymentOrder entity.
func (_u *UserUpdateOne) AddPaymentOrders(v ...*PaymentOrder) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.AddPaymentOrderIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (_u *UserUpdateOne) Mutation() *UserMutation {
return _u.mutation
@@ -1681,6 +1778,27 @@ func (_u *UserUpdateOne) RemovePromoCodeUsages(v ...*PromoCodeUsage) *UserUpdate
return _u.RemovePromoCodeUsageIDs(ids...)
}
// ClearPaymentOrders clears all "payment_orders" edges to the PaymentOrder entity.
func (_u *UserUpdateOne) ClearPaymentOrders() *UserUpdateOne {
_u.mutation.ClearPaymentOrders()
return _u
}
// RemovePaymentOrderIDs removes the "payment_orders" edge to PaymentOrder entities by IDs.
func (_u *UserUpdateOne) RemovePaymentOrderIDs(ids ...int64) *UserUpdateOne {
_u.mutation.RemovePaymentOrderIDs(ids...)
return _u
}
// RemovePaymentOrders removes "payment_orders" edges to PaymentOrder entities.
func (_u *UserUpdateOne) RemovePaymentOrders(v ...*PaymentOrder) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.RemovePaymentOrderIDs(ids...)
}
// Where appends a list predicates to the UserUpdate builder.
func (_u *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
_u.mutation.Where(ps...)
@@ -2266,6 +2384,51 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.PaymentOrdersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.RemovedPaymentOrdersIDs(); len(nodes) > 0 && !_u.mutation.PaymentOrdersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.PaymentOrdersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.PaymentOrdersTable,
Columns: []string{user.PaymentOrdersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(paymentorder.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &User{config: _u.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues

View File

@@ -27,12 +27,16 @@ require (
github.com/refraction-networking/utls v1.8.2
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.25.6
github.com/shopspring/decimal v1.4.0
github.com/smartwalle/alipay/v3 v3.2.29
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.11.1
github.com/stripe/stripe-go/v85 v85.0.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0
github.com/testcontainers/testcontainers-go/modules/redis v0.40.0
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
github.com/wechatpay-apiv3/wechatpay-go v0.2.21
github.com/zeromicro/go-zero v1.9.4
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.48.0
@@ -99,6 +103,7 @@ require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/subcommands v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
@@ -137,6 +142,9 @@ require (
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartwalle/ncrypto v1.0.4 // indirect
github.com/smartwalle/ngx v1.1.0 // indirect
github.com/smartwalle/nsign v1.0.9 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
@@ -167,6 +175,7 @@ require (
golang.org/x/mod v0.32.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.41.0 // indirect
google.golang.org/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

View File

@@ -14,6 +14,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
github.com/alitto/pond/v2 v2.6.2 h1:Sphe40g0ILeM1pA2c2K+Th0DGU+pt0A/Kprr+WB24Pw=
github.com/alitto/pond/v2 v2.6.2/go.mod h1:xkjYEgQ05RSpWdfSd1nM3OVv7TBhLdy7rMp3+2Nq+yE=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
@@ -160,6 +162,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
@@ -288,8 +292,18 @@ github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartwalle/alipay/v3 v3.2.29 h1:roGFqlml8hDa//0TpFmlyxZhndTYs7rbYLu/HlNFNJo=
github.com/smartwalle/alipay/v3 v3.2.29/go.mod h1:XarBLuAkwK3ah7mYjVtghRu+ysxzlex9sRkgqNMzMRU=
github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8=
github.com/smartwalle/ncrypto v1.0.4/go.mod h1:Dwlp6sfeNaPMnOxMNayMTacvC5JGEVln3CVdiVDgbBk=
github.com/smartwalle/ngx v1.1.0 h1:q8nANgWSPRGeI/u+ixBoA4mf68DrUq6vZ+n9L5UKv9I=
github.com/smartwalle/ngx v1.1.0/go.mod h1:mx/nz2Pk5j+RBs7t6u6k22MPiBG/8CtOMpCnALIG8Y0=
github.com/smartwalle/nsign v1.0.9 h1:8poAgG7zBd8HkZy9RQDwasC6XZvJpDGQWSjzL2FZL6E=
github.com/smartwalle/nsign v1.0.9/go.mod h1:eY6I4CJlyNdVMP+t6z1H6Jpd4m5/V+8xi44ufSTxXgc=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@@ -317,6 +331,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stripe/stripe-go/v85 v85.0.0 h1:HMlFJXW6I/9WvkeSAtj8V7dI5pzeDu4gS1TaqR1ccI4=
github.com/stripe/stripe-go/v85 v85.0.0/go.mod h1:5P+HGFenpWgak27T5Is6JMsmDfUC1yJnjhhmquz7kXw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
@@ -342,6 +358,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/wechatpay-apiv3/wechatpay-go v0.2.21 h1:uIyMpzvcaHA33W/QPtHstccw+X52HO1gFdvVL9O6Lfs=
github.com/wechatpay-apiv3/wechatpay-go v0.2.21/go.mod h1:A254AUBVB6R+EqQFo3yTgeh7HtyqRRtN2w9hQSOrd4Q=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=

View File

@@ -65,6 +65,7 @@ type Config struct {
JWT JWTConfig `mapstructure:"jwt"`
Totp TotpConfig `mapstructure:"totp"`
LinuxDo LinuxDoConnectConfig `mapstructure:"linuxdo_connect"`
OIDC OIDCConnectConfig `mapstructure:"oidc_connect"`
Default DefaultConfig `mapstructure:"default"`
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
Pricing PricingConfig `mapstructure:"pricing"`
@@ -184,6 +185,34 @@ type LinuxDoConnectConfig struct {
UserInfoUsernamePath string `mapstructure:"userinfo_username_path"`
}
type OIDCConnectConfig struct {
Enabled bool `mapstructure:"enabled"`
ProviderName string `mapstructure:"provider_name"` // 显示名: "Keycloak" 等
ClientID string `mapstructure:"client_id"`
ClientSecret string `mapstructure:"client_secret"`
IssuerURL string `mapstructure:"issuer_url"`
DiscoveryURL string `mapstructure:"discovery_url"`
AuthorizeURL string `mapstructure:"authorize_url"`
TokenURL string `mapstructure:"token_url"`
UserInfoURL string `mapstructure:"userinfo_url"`
JWKSURL string `mapstructure:"jwks_url"`
Scopes string `mapstructure:"scopes"` // 默认 "openid email profile"
RedirectURL string `mapstructure:"redirect_url"` // 后端回调地址(需在提供方后台登记)
FrontendRedirectURL string `mapstructure:"frontend_redirect_url"` // 前端接收 token 的路由(默认:/auth/oidc/callback
TokenAuthMethod string `mapstructure:"token_auth_method"` // client_secret_post / client_secret_basic / none
UsePKCE bool `mapstructure:"use_pkce"`
ValidateIDToken bool `mapstructure:"validate_id_token"`
AllowedSigningAlgs string `mapstructure:"allowed_signing_algs"` // 默认 "RS256,ES256,PS256"
ClockSkewSeconds int `mapstructure:"clock_skew_seconds"` // 默认 120
RequireEmailVerified bool `mapstructure:"require_email_verified"` // 默认 false
// 可选:用于从 userinfo JSON 中提取字段的 gjson 路径。
// 为空时,服务端会尝试一组常见字段名。
UserInfoEmailPath string `mapstructure:"userinfo_email_path"`
UserInfoIDPath string `mapstructure:"userinfo_id_path"`
UserInfoUsernamePath string `mapstructure:"userinfo_username_path"`
}
// TokenRefreshConfig OAuth token自动刷新配置
type TokenRefreshConfig struct {
// 是否启用自动刷新
@@ -318,6 +347,12 @@ type GatewayConfig struct {
// ForceCodexCLI: 强制将 OpenAI `/v1/responses` 请求按 Codex CLI 处理。
// 用于网关未透传/改写 User-Agent 时的兼容兜底(默认关闭,避免影响其他客户端)。
ForceCodexCLI bool `mapstructure:"force_codex_cli"`
// ForcedCodexInstructionsTemplateFile: 服务端强制附加到 Codex 顶层 instructions 的模板文件路径。
// 模板渲染后会直接覆盖最终 instructions若需要保留客户端 system 转换结果,请在模板中显式引用 {{ .ExistingInstructions }}。
ForcedCodexInstructionsTemplateFile string `mapstructure:"forced_codex_instructions_template_file"`
// ForcedCodexInstructionsTemplate: 启动时从模板文件读取并缓存的模板内容。
// 该字段不直接参与配置反序列化,仅用于请求热路径避免重复读盘。
ForcedCodexInstructionsTemplate string `mapstructure:"-"`
// OpenAIPassthroughAllowTimeoutHeaders: OpenAI 透传模式是否放行客户端超时头
// 关闭(默认)可避免 x-stainless-timeout 等头导致上游提前断流。
OpenAIPassthroughAllowTimeoutHeaders bool `mapstructure:"openai_passthrough_allow_timeout_headers"`
@@ -620,6 +655,10 @@ type GatewaySchedulingConfig struct {
// 负载计算
LoadBatchEnabled bool `mapstructure:"load_batch_enabled"`
// 快照桶读取时的 MGET 分块大小
SnapshotMGetChunkSize int `mapstructure:"snapshot_mget_chunk_size"`
// 快照重建时的缓存写入分块大小
SnapshotWriteChunkSize int `mapstructure:"snapshot_write_chunk_size"`
// 过期槽位清理周期0 表示禁用)
SlotCleanupInterval time.Duration `mapstructure:"slot_cleanup_interval"`
@@ -968,6 +1007,23 @@ func load(allowMissingJWTSecret bool) (*Config, error) {
cfg.LinuxDo.UserInfoEmailPath = strings.TrimSpace(cfg.LinuxDo.UserInfoEmailPath)
cfg.LinuxDo.UserInfoIDPath = strings.TrimSpace(cfg.LinuxDo.UserInfoIDPath)
cfg.LinuxDo.UserInfoUsernamePath = strings.TrimSpace(cfg.LinuxDo.UserInfoUsernamePath)
cfg.OIDC.ProviderName = strings.TrimSpace(cfg.OIDC.ProviderName)
cfg.OIDC.ClientID = strings.TrimSpace(cfg.OIDC.ClientID)
cfg.OIDC.ClientSecret = strings.TrimSpace(cfg.OIDC.ClientSecret)
cfg.OIDC.IssuerURL = strings.TrimSpace(cfg.OIDC.IssuerURL)
cfg.OIDC.DiscoveryURL = strings.TrimSpace(cfg.OIDC.DiscoveryURL)
cfg.OIDC.AuthorizeURL = strings.TrimSpace(cfg.OIDC.AuthorizeURL)
cfg.OIDC.TokenURL = strings.TrimSpace(cfg.OIDC.TokenURL)
cfg.OIDC.UserInfoURL = strings.TrimSpace(cfg.OIDC.UserInfoURL)
cfg.OIDC.JWKSURL = strings.TrimSpace(cfg.OIDC.JWKSURL)
cfg.OIDC.Scopes = strings.TrimSpace(cfg.OIDC.Scopes)
cfg.OIDC.RedirectURL = strings.TrimSpace(cfg.OIDC.RedirectURL)
cfg.OIDC.FrontendRedirectURL = strings.TrimSpace(cfg.OIDC.FrontendRedirectURL)
cfg.OIDC.TokenAuthMethod = strings.ToLower(strings.TrimSpace(cfg.OIDC.TokenAuthMethod))
cfg.OIDC.AllowedSigningAlgs = strings.TrimSpace(cfg.OIDC.AllowedSigningAlgs)
cfg.OIDC.UserInfoEmailPath = strings.TrimSpace(cfg.OIDC.UserInfoEmailPath)
cfg.OIDC.UserInfoIDPath = strings.TrimSpace(cfg.OIDC.UserInfoIDPath)
cfg.OIDC.UserInfoUsernamePath = strings.TrimSpace(cfg.OIDC.UserInfoUsernamePath)
cfg.Dashboard.KeyPrefix = strings.TrimSpace(cfg.Dashboard.KeyPrefix)
cfg.CORS.AllowedOrigins = normalizeStringSlice(cfg.CORS.AllowedOrigins)
cfg.Security.ResponseHeaders.AdditionalAllowed = normalizeStringSlice(cfg.Security.ResponseHeaders.AdditionalAllowed)
@@ -979,6 +1035,14 @@ func load(allowMissingJWTSecret bool) (*Config, error) {
cfg.Log.Environment = strings.TrimSpace(cfg.Log.Environment)
cfg.Log.StacktraceLevel = strings.ToLower(strings.TrimSpace(cfg.Log.StacktraceLevel))
cfg.Log.Output.FilePath = strings.TrimSpace(cfg.Log.Output.FilePath)
cfg.Gateway.ForcedCodexInstructionsTemplateFile = strings.TrimSpace(cfg.Gateway.ForcedCodexInstructionsTemplateFile)
if cfg.Gateway.ForcedCodexInstructionsTemplateFile != "" {
content, err := os.ReadFile(cfg.Gateway.ForcedCodexInstructionsTemplateFile)
if err != nil {
return nil, fmt.Errorf("read forced codex instructions template %q: %w", cfg.Gateway.ForcedCodexInstructionsTemplateFile, err)
}
cfg.Gateway.ForcedCodexInstructionsTemplate = string(content)
}
// 兼容旧键 gateway.openai_ws.sticky_previous_response_ttl_seconds。
// 新键未配置(<=0时回退旧键新键优先。
@@ -1138,6 +1202,30 @@ func setDefaults() {
viper.SetDefault("linuxdo_connect.userinfo_id_path", "")
viper.SetDefault("linuxdo_connect.userinfo_username_path", "")
// Generic OIDC OAuth 登录
viper.SetDefault("oidc_connect.enabled", false)
viper.SetDefault("oidc_connect.provider_name", "OIDC")
viper.SetDefault("oidc_connect.client_id", "")
viper.SetDefault("oidc_connect.client_secret", "")
viper.SetDefault("oidc_connect.issuer_url", "")
viper.SetDefault("oidc_connect.discovery_url", "")
viper.SetDefault("oidc_connect.authorize_url", "")
viper.SetDefault("oidc_connect.token_url", "")
viper.SetDefault("oidc_connect.userinfo_url", "")
viper.SetDefault("oidc_connect.jwks_url", "")
viper.SetDefault("oidc_connect.scopes", "openid email profile")
viper.SetDefault("oidc_connect.redirect_url", "")
viper.SetDefault("oidc_connect.frontend_redirect_url", "/auth/oidc/callback")
viper.SetDefault("oidc_connect.token_auth_method", "client_secret_post")
viper.SetDefault("oidc_connect.use_pkce", false)
viper.SetDefault("oidc_connect.validate_id_token", true)
viper.SetDefault("oidc_connect.allowed_signing_algs", "RS256,ES256,PS256")
viper.SetDefault("oidc_connect.clock_skew_seconds", 120)
viper.SetDefault("oidc_connect.require_email_verified", false)
viper.SetDefault("oidc_connect.userinfo_email_path", "")
viper.SetDefault("oidc_connect.userinfo_id_path", "")
viper.SetDefault("oidc_connect.userinfo_username_path", "")
// Database
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.port", 5432)
@@ -1340,6 +1428,8 @@ func setDefaults() {
viper.SetDefault("gateway.scheduling.fallback_max_waiting", 100)
viper.SetDefault("gateway.scheduling.fallback_selection_mode", "last_used")
viper.SetDefault("gateway.scheduling.load_batch_enabled", true)
viper.SetDefault("gateway.scheduling.snapshot_mget_chunk_size", 128)
viper.SetDefault("gateway.scheduling.snapshot_write_chunk_size", 256)
viper.SetDefault("gateway.scheduling.slot_cleanup_interval", 30*time.Second)
viper.SetDefault("gateway.scheduling.db_fallback_enabled", true)
viper.SetDefault("gateway.scheduling.db_fallback_timeout_seconds", 0)
@@ -1572,6 +1662,87 @@ func (c *Config) Validate() error {
warnIfInsecureURL("linuxdo_connect.redirect_url", c.LinuxDo.RedirectURL)
warnIfInsecureURL("linuxdo_connect.frontend_redirect_url", c.LinuxDo.FrontendRedirectURL)
}
if c.OIDC.Enabled {
if strings.TrimSpace(c.OIDC.ClientID) == "" {
return fmt.Errorf("oidc_connect.client_id is required when oidc_connect.enabled=true")
}
if strings.TrimSpace(c.OIDC.IssuerURL) == "" {
return fmt.Errorf("oidc_connect.issuer_url is required when oidc_connect.enabled=true")
}
if strings.TrimSpace(c.OIDC.RedirectURL) == "" {
return fmt.Errorf("oidc_connect.redirect_url is required when oidc_connect.enabled=true")
}
if strings.TrimSpace(c.OIDC.FrontendRedirectURL) == "" {
return fmt.Errorf("oidc_connect.frontend_redirect_url is required when oidc_connect.enabled=true")
}
if !scopeContainsOpenID(c.OIDC.Scopes) {
return fmt.Errorf("oidc_connect.scopes must contain openid")
}
method := strings.ToLower(strings.TrimSpace(c.OIDC.TokenAuthMethod))
switch method {
case "", "client_secret_post", "client_secret_basic", "none":
default:
return fmt.Errorf("oidc_connect.token_auth_method must be one of: client_secret_post/client_secret_basic/none")
}
if method == "none" && !c.OIDC.UsePKCE {
return fmt.Errorf("oidc_connect.use_pkce must be true when oidc_connect.token_auth_method=none")
}
if (method == "" || method == "client_secret_post" || method == "client_secret_basic") &&
strings.TrimSpace(c.OIDC.ClientSecret) == "" {
return fmt.Errorf("oidc_connect.client_secret is required when oidc_connect.enabled=true and token_auth_method is client_secret_post/client_secret_basic")
}
if c.OIDC.ClockSkewSeconds < 0 || c.OIDC.ClockSkewSeconds > 600 {
return fmt.Errorf("oidc_connect.clock_skew_seconds must be between 0 and 600")
}
if c.OIDC.ValidateIDToken && strings.TrimSpace(c.OIDC.AllowedSigningAlgs) == "" {
return fmt.Errorf("oidc_connect.allowed_signing_algs is required when oidc_connect.validate_id_token=true")
}
if err := ValidateAbsoluteHTTPURL(c.OIDC.IssuerURL); err != nil {
return fmt.Errorf("oidc_connect.issuer_url invalid: %w", err)
}
if v := strings.TrimSpace(c.OIDC.DiscoveryURL); v != "" {
if err := ValidateAbsoluteHTTPURL(v); err != nil {
return fmt.Errorf("oidc_connect.discovery_url invalid: %w", err)
}
}
if v := strings.TrimSpace(c.OIDC.AuthorizeURL); v != "" {
if err := ValidateAbsoluteHTTPURL(v); err != nil {
return fmt.Errorf("oidc_connect.authorize_url invalid: %w", err)
}
}
if v := strings.TrimSpace(c.OIDC.TokenURL); v != "" {
if err := ValidateAbsoluteHTTPURL(v); err != nil {
return fmt.Errorf("oidc_connect.token_url invalid: %w", err)
}
}
if v := strings.TrimSpace(c.OIDC.UserInfoURL); v != "" {
if err := ValidateAbsoluteHTTPURL(v); err != nil {
return fmt.Errorf("oidc_connect.userinfo_url invalid: %w", err)
}
}
if v := strings.TrimSpace(c.OIDC.JWKSURL); v != "" {
if err := ValidateAbsoluteHTTPURL(v); err != nil {
return fmt.Errorf("oidc_connect.jwks_url invalid: %w", err)
}
}
if err := ValidateAbsoluteHTTPURL(c.OIDC.RedirectURL); err != nil {
return fmt.Errorf("oidc_connect.redirect_url invalid: %w", err)
}
if err := ValidateFrontendRedirectURL(c.OIDC.FrontendRedirectURL); err != nil {
return fmt.Errorf("oidc_connect.frontend_redirect_url invalid: %w", err)
}
warnIfInsecureURL("oidc_connect.issuer_url", c.OIDC.IssuerURL)
warnIfInsecureURL("oidc_connect.discovery_url", c.OIDC.DiscoveryURL)
warnIfInsecureURL("oidc_connect.authorize_url", c.OIDC.AuthorizeURL)
warnIfInsecureURL("oidc_connect.token_url", c.OIDC.TokenURL)
warnIfInsecureURL("oidc_connect.userinfo_url", c.OIDC.UserInfoURL)
warnIfInsecureURL("oidc_connect.jwks_url", c.OIDC.JWKSURL)
warnIfInsecureURL("oidc_connect.redirect_url", c.OIDC.RedirectURL)
warnIfInsecureURL("oidc_connect.frontend_redirect_url", c.OIDC.FrontendRedirectURL)
}
if c.Billing.CircuitBreaker.Enabled {
if c.Billing.CircuitBreaker.FailureThreshold <= 0 {
return fmt.Errorf("billing.circuit_breaker.failure_threshold must be positive")
@@ -2001,6 +2172,12 @@ func (c *Config) Validate() error {
if c.Gateway.Scheduling.FallbackMaxWaiting <= 0 {
return fmt.Errorf("gateway.scheduling.fallback_max_waiting must be positive")
}
if c.Gateway.Scheduling.SnapshotMGetChunkSize <= 0 {
return fmt.Errorf("gateway.scheduling.snapshot_mget_chunk_size must be positive")
}
if c.Gateway.Scheduling.SnapshotWriteChunkSize <= 0 {
return fmt.Errorf("gateway.scheduling.snapshot_write_chunk_size must be positive")
}
if c.Gateway.Scheduling.SlotCleanupInterval < 0 {
return fmt.Errorf("gateway.scheduling.slot_cleanup_interval must be non-negative")
}
@@ -2184,6 +2361,15 @@ func ValidateFrontendRedirectURL(raw string) error {
return nil
}
func scopeContainsOpenID(scopes string) bool {
for _, scope := range strings.Fields(strings.ToLower(strings.TrimSpace(scopes))) {
if scope == "openid" {
return true
}
}
return false
}
// isHTTPScheme 检查是否为 HTTP 或 HTTPS 协议
func isHTTPScheme(scheme string) bool {
return strings.EqualFold(scheme, "http") || strings.EqualFold(scheme, "https")

View File

@@ -1,6 +1,8 @@
package config
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
@@ -223,6 +225,23 @@ func TestLoadSchedulingConfigFromEnv(t *testing.T) {
}
}
func TestLoadForcedCodexInstructionsTemplate(t *testing.T) {
resetViperWithJWTSecret(t)
tempDir := t.TempDir()
templatePath := filepath.Join(tempDir, "codex-instructions.md.tmpl")
configPath := filepath.Join(tempDir, "config.yaml")
require.NoError(t, os.WriteFile(templatePath, []byte("server-prefix\n\n{{ .ExistingInstructions }}"), 0o644))
require.NoError(t, os.WriteFile(configPath, []byte("gateway:\n forced_codex_instructions_template_file: \""+templatePath+"\"\n"), 0o644))
t.Setenv("DATA_DIR", tempDir)
cfg, err := Load()
require.NoError(t, err)
require.Equal(t, templatePath, cfg.Gateway.ForcedCodexInstructionsTemplateFile)
require.Equal(t, "server-prefix\n\n{{ .ExistingInstructions }}", cfg.Gateway.ForcedCodexInstructionsTemplate)
}
func TestLoadDefaultSecurityToggles(t *testing.T) {
resetViperWithJWTSecret(t)
@@ -351,6 +370,60 @@ func TestValidateLinuxDoPKCERequiredForPublicClient(t *testing.T) {
}
}
func TestValidateOIDCScopesMustContainOpenID(t *testing.T) {
resetViperWithJWTSecret(t)
cfg, err := Load()
if err != nil {
t.Fatalf("Load() error: %v", err)
}
cfg.OIDC.Enabled = true
cfg.OIDC.ClientID = "oidc-client"
cfg.OIDC.ClientSecret = "oidc-secret"
cfg.OIDC.IssuerURL = "https://issuer.example.com"
cfg.OIDC.AuthorizeURL = "https://issuer.example.com/auth"
cfg.OIDC.TokenURL = "https://issuer.example.com/token"
cfg.OIDC.JWKSURL = "https://issuer.example.com/jwks"
cfg.OIDC.RedirectURL = "https://example.com/api/v1/auth/oauth/oidc/callback"
cfg.OIDC.FrontendRedirectURL = "/auth/oidc/callback"
cfg.OIDC.Scopes = "profile email"
err = cfg.Validate()
if err == nil {
t.Fatalf("Validate() expected error when scopes do not include openid, got nil")
}
if !strings.Contains(err.Error(), "oidc_connect.scopes") {
t.Fatalf("Validate() expected oidc_connect.scopes error, got: %v", err)
}
}
func TestValidateOIDCAllowsIssuerOnlyEndpointsWithDiscoveryFallback(t *testing.T) {
resetViperWithJWTSecret(t)
cfg, err := Load()
if err != nil {
t.Fatalf("Load() error: %v", err)
}
cfg.OIDC.Enabled = true
cfg.OIDC.ClientID = "oidc-client"
cfg.OIDC.ClientSecret = "oidc-secret"
cfg.OIDC.IssuerURL = "https://issuer.example.com"
cfg.OIDC.AuthorizeURL = ""
cfg.OIDC.TokenURL = ""
cfg.OIDC.JWKSURL = ""
cfg.OIDC.RedirectURL = "https://example.com/api/v1/auth/oauth/oidc/callback"
cfg.OIDC.FrontendRedirectURL = "/auth/oidc/callback"
cfg.OIDC.Scopes = "openid email profile"
cfg.OIDC.ValidateIDToken = true
err = cfg.Validate()
if err != nil {
t.Fatalf("Validate() expected issuer-only OIDC config to pass with discovery fallback, got: %v", err)
}
}
func TestLoadDefaultDashboardCacheConfig(t *testing.T) {
resetViperWithJWTSecret(t)

View File

@@ -0,0 +1,10 @@
package domain
// OpenAIMessagesDispatchModelConfig controls how Anthropic /v1/messages
// requests are mapped onto OpenAI/Codex models.
type OpenAIMessagesDispatchModelConfig struct {
OpusMappedModel string `json:"opus_mapped_model,omitempty"`
SonnetMappedModel string `json:"sonnet_mapped_model,omitempty"`
HaikuMappedModel string `json:"haiku_mapped_model,omitempty"`
ExactModelMappings map[string]string `json:"exact_model_mappings,omitempty"`
}

View File

@@ -10,6 +10,7 @@ import (
"log/slog"
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
"github.com/Wei-Shaw/sub2api/internal/service"
@@ -359,7 +360,7 @@ func (h *AccountHandler) listAllProxies(ctx context.Context) ([]service.Proxy, e
pageSize := dataPageCap
var out []service.Proxy
for {
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, "", "", "")
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, "", "", "", "created_at", "desc")
if err != nil {
return nil, err
}
@@ -372,12 +373,12 @@ func (h *AccountHandler) listAllProxies(ctx context.Context) ([]service.Proxy, e
return out, nil
}
func (h *AccountHandler) listAccountsFiltered(ctx context.Context, platform, accountType, status, search string) ([]service.Account, error) {
func (h *AccountHandler) listAccountsFiltered(ctx context.Context, platform, accountType, status, search string, groupID int64, privacyMode, sortBy, sortOrder string) ([]service.Account, error) {
page := 1
pageSize := dataPageCap
var out []service.Account
for {
items, total, err := h.adminService.ListAccounts(ctx, page, pageSize, platform, accountType, status, search, 0, "")
items, total, err := h.adminService.ListAccounts(ctx, page, pageSize, platform, accountType, status, search, groupID, privacyMode, sortBy, sortOrder)
if err != nil {
return nil, err
}
@@ -409,11 +410,28 @@ func (h *AccountHandler) resolveExportAccounts(ctx context.Context, ids []int64,
platform := c.Query("platform")
accountType := c.Query("type")
status := c.Query("status")
privacyMode := strings.TrimSpace(c.Query("privacy_mode"))
search := strings.TrimSpace(c.Query("search"))
sortBy := c.DefaultQuery("sort_by", "name")
sortOrder := c.DefaultQuery("sort_order", "asc")
if len(search) > 100 {
search = search[:100]
}
return h.listAccountsFiltered(ctx, platform, accountType, status, search)
groupID := int64(0)
if groupIDStr := c.Query("group"); groupIDStr != "" {
if groupIDStr == accountListGroupUngroupedQueryValue {
groupID = service.AccountListGroupUngrouped
} else {
parsedGroupID, parseErr := strconv.ParseInt(groupIDStr, 10, 64)
if parseErr != nil || parsedGroupID <= 0 {
return nil, infraerrors.BadRequest("INVALID_GROUP_FILTER", "invalid group filter")
}
groupID = parsedGroupID
}
}
return h.listAccountsFiltered(ctx, platform, accountType, status, search, groupID, privacyMode, sortBy, sortOrder)
}
func (h *AccountHandler) resolveExportProxies(ctx context.Context, accounts []service.Account) ([]service.Proxy, error) {

View File

@@ -172,6 +172,51 @@ func TestExportDataWithoutProxies(t *testing.T) {
require.Nil(t, resp.Data.Accounts[0].ProxyKey)
}
func TestExportDataPassesAccountFiltersAndSort(t *testing.T) {
router, adminSvc := setupAccountDataRouter()
adminSvc.accounts = []service.Account{
{ID: 1, Name: "acc-1", Status: service.StatusActive},
}
rec := httptest.NewRecorder()
req := httptest.NewRequest(
http.MethodGet,
"/api/v1/admin/accounts/data?platform=openai&type=oauth&status=active&group=12&privacy_mode=blocked&search=keyword&sort_by=priority&sort_order=desc",
nil,
)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, 1, adminSvc.lastListAccounts.calls)
require.Equal(t, "openai", adminSvc.lastListAccounts.platform)
require.Equal(t, "oauth", adminSvc.lastListAccounts.accountType)
require.Equal(t, "active", adminSvc.lastListAccounts.status)
require.Equal(t, int64(12), adminSvc.lastListAccounts.groupID)
require.Equal(t, "blocked", adminSvc.lastListAccounts.privacyMode)
require.Equal(t, "keyword", adminSvc.lastListAccounts.search)
require.Equal(t, "priority", adminSvc.lastListAccounts.sortBy)
require.Equal(t, "desc", adminSvc.lastListAccounts.sortOrder)
}
func TestExportDataSelectedIDsOverrideFilters(t *testing.T) {
router, adminSvc := setupAccountDataRouter()
rec := httptest.NewRecorder()
req := httptest.NewRequest(
http.MethodGet,
"/api/v1/admin/accounts/data?ids=1,2&platform=openai&search=keyword&sort_by=priority&sort_order=desc",
nil,
)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
var resp dataResponse
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
require.Equal(t, 0, resp.Code)
require.Len(t, resp.Data.Accounts, 2)
require.Equal(t, 0, adminSvc.lastListAccounts.calls)
}
func TestImportDataReusesProxyAndSkipsDefaultGroup(t *testing.T) {
router, adminSvc := setupAccountDataRouter()

View File

@@ -221,6 +221,8 @@ func (h *AccountHandler) List(c *gin.Context) {
status := c.Query("status")
search := c.Query("search")
privacyMode := strings.TrimSpace(c.Query("privacy_mode"))
sortBy := c.DefaultQuery("sort_by", "name")
sortOrder := c.DefaultQuery("sort_order", "asc")
// 标准化和验证 search 参数
search = strings.TrimSpace(search)
if len(search) > 100 {
@@ -246,7 +248,7 @@ func (h *AccountHandler) List(c *gin.Context) {
}
}
accounts, total, err := h.adminService.ListAccounts(c.Request.Context(), page, pageSize, platform, accountType, status, search, groupID, privacyMode)
accounts, total, err := h.adminService.ListAccounts(c.Request.Context(), page, pageSize, platform, accountType, status, search, groupID, privacyMode, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -2029,7 +2031,7 @@ func (h *AccountHandler) BatchRefreshTier(c *gin.Context) {
accounts := make([]*service.Account, 0)
if len(req.AccountIDs) == 0 {
allAccounts, _, err := h.adminService.ListAccounts(ctx, 1, 10000, "gemini", "oauth", "", "", 0, "")
allAccounts, _, err := h.adminService.ListAccounts(ctx, 1, 10000, "gemini", "oauth", "", "", 0, "", "name", "asc")
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -31,6 +31,33 @@ type stubAdminService struct {
platform string
groupIDs []int64
}
lastListAccounts struct {
platform string
accountType string
status string
search string
groupID int64
privacyMode string
sortBy string
sortOrder string
calls int
}
lastListProxies struct {
protocol string
status string
search string
sortBy string
sortOrder string
calls int
}
lastListRedeemCodes struct {
codeType string
status string
search string
sortBy string
sortOrder string
calls int
}
mu sync.Mutex
}
@@ -99,7 +126,7 @@ func newStubAdminService() *stubAdminService {
}
}
func (s *stubAdminService) ListUsers(ctx context.Context, page, pageSize int, filters service.UserListFilters) ([]service.User, int64, error) {
func (s *stubAdminService) ListUsers(ctx context.Context, page, pageSize int, filters service.UserListFilters, sortBy, sortOrder string) ([]service.User, int64, error) {
return s.users, int64(len(s.users)), nil
}
@@ -132,7 +159,7 @@ func (s *stubAdminService) UpdateUserBalance(ctx context.Context, userID int64,
return &user, nil
}
func (s *stubAdminService) GetUserAPIKeys(ctx context.Context, userID int64, page, pageSize int) ([]service.APIKey, int64, error) {
func (s *stubAdminService) GetUserAPIKeys(ctx context.Context, userID int64, page, pageSize int, sortBy, sortOrder string) ([]service.APIKey, int64, error) {
return s.apiKeys, int64(len(s.apiKeys)), nil
}
@@ -140,7 +167,7 @@ func (s *stubAdminService) GetUserUsageStats(ctx context.Context, userID int64,
return map[string]any{"user_id": userID}, nil
}
func (s *stubAdminService) ListGroups(ctx context.Context, page, pageSize int, platform, status, search string, isExclusive *bool) ([]service.Group, int64, error) {
func (s *stubAdminService) ListGroups(ctx context.Context, page, pageSize int, platform, status, search string, isExclusive *bool, sortBy, sortOrder string) ([]service.Group, int64, error) {
return s.groups, int64(len(s.groups)), nil
}
@@ -187,7 +214,16 @@ func (s *stubAdminService) BatchSetGroupRateMultipliers(_ context.Context, _ int
return nil
}
func (s *stubAdminService) ListAccounts(ctx context.Context, page, pageSize int, platform, accountType, status, search string, groupID int64, privacyMode string) ([]service.Account, int64, error) {
func (s *stubAdminService) ListAccounts(ctx context.Context, page, pageSize int, platform, accountType, status, search string, groupID int64, privacyMode string, sortBy, sortOrder string) ([]service.Account, int64, error) {
s.lastListAccounts.platform = platform
s.lastListAccounts.accountType = accountType
s.lastListAccounts.status = status
s.lastListAccounts.search = search
s.lastListAccounts.groupID = groupID
s.lastListAccounts.privacyMode = privacyMode
s.lastListAccounts.sortBy = sortBy
s.lastListAccounts.sortOrder = sortOrder
s.lastListAccounts.calls++
return s.accounts, int64(len(s.accounts)), nil
}
@@ -261,7 +297,13 @@ func (s *stubAdminService) CheckMixedChannelRisk(ctx context.Context, currentAcc
return s.checkMixedErr
}
func (s *stubAdminService) ListProxies(ctx context.Context, page, pageSize int, protocol, status, search string) ([]service.Proxy, int64, error) {
func (s *stubAdminService) ListProxies(ctx context.Context, page, pageSize int, protocol, status, search string, sortBy, sortOrder string) ([]service.Proxy, int64, error) {
s.lastListProxies.protocol = protocol
s.lastListProxies.status = status
s.lastListProxies.search = search
s.lastListProxies.sortBy = sortBy
s.lastListProxies.sortOrder = sortOrder
s.lastListProxies.calls++
search = strings.TrimSpace(strings.ToLower(search))
filtered := make([]service.Proxy, 0, len(s.proxies))
for _, proxy := range s.proxies {
@@ -283,7 +325,7 @@ func (s *stubAdminService) ListProxies(ctx context.Context, page, pageSize int,
return filtered, int64(len(filtered)), nil
}
func (s *stubAdminService) ListProxiesWithAccountCount(ctx context.Context, page, pageSize int, protocol, status, search string) ([]service.ProxyWithAccountCount, int64, error) {
func (s *stubAdminService) ListProxiesWithAccountCount(ctx context.Context, page, pageSize int, protocol, status, search string, sortBy, sortOrder string) ([]service.ProxyWithAccountCount, int64, error) {
return s.proxyCounts, int64(len(s.proxyCounts)), nil
}
@@ -384,7 +426,13 @@ func (s *stubAdminService) CheckProxyQuality(ctx context.Context, id int64) (*se
}, nil
}
func (s *stubAdminService) ListRedeemCodes(ctx context.Context, page, pageSize int, codeType, status, search string) ([]service.RedeemCode, int64, error) {
func (s *stubAdminService) ListRedeemCodes(ctx context.Context, page, pageSize int, codeType, status, search string, sortBy, sortOrder string) ([]service.RedeemCode, int64, error) {
s.lastListRedeemCodes.codeType = codeType
s.lastListRedeemCodes.status = status
s.lastListRedeemCodes.search = search
s.lastListRedeemCodes.sortBy = sortBy
s.lastListRedeemCodes.sortOrder = sortOrder
s.lastListRedeemCodes.calls++
return s.redeems, int64(len(s.redeems)), nil
}

View File

@@ -52,13 +52,17 @@ func (h *AnnouncementHandler) List(c *gin.Context) {
page, pageSize := response.ParsePagination(c)
status := strings.TrimSpace(c.Query("status"))
search := strings.TrimSpace(c.Query("search"))
sortBy := c.DefaultQuery("sort_by", "created_at")
sortOrder := c.DefaultQuery("sort_order", "desc")
if len(search) > 200 {
search = search[:200]
}
params := pagination.PaginationParams{
Page: page,
PageSize: pageSize,
Page: page,
PageSize: pageSize,
SortBy: sortBy,
SortOrder: sortOrder,
}
items, paginationResult, err := h.announcementService.List(
@@ -227,8 +231,10 @@ func (h *AnnouncementHandler) ListReadStatus(c *gin.Context) {
page, pageSize := response.ParsePagination(c)
params := pagination.PaginationParams{
Page: page,
PageSize: pageSize,
Page: page,
PageSize: pageSize,
SortBy: c.DefaultQuery("sort_by", "email"),
SortOrder: c.DefaultQuery("sort_order", "asc"),
}
search := strings.TrimSpace(c.Query("search"))
if len(search) > 200 {

View File

@@ -0,0 +1,138 @@
package admin
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
)
type announcementRepoCapture struct {
service.AnnouncementRepository
listParams pagination.PaginationParams
}
func (r *announcementRepoCapture) List(ctx context.Context, params pagination.PaginationParams, filters service.AnnouncementListFilters) ([]service.Announcement, *pagination.PaginationResult, error) {
r.listParams = params
return []service.Announcement{}, &pagination.PaginationResult{
Total: 0,
Page: params.Page,
PageSize: params.PageSize,
Pages: 0,
}, nil
}
func (r *announcementRepoCapture) GetByID(ctx context.Context, id int64) (*service.Announcement, error) {
return &service.Announcement{
ID: id,
Title: "announcement",
Content: "content",
Status: service.AnnouncementStatusActive,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}, nil
}
type announcementUserRepoCapture struct {
service.UserRepository
listParams pagination.PaginationParams
}
func (r *announcementUserRepoCapture) ListWithFilters(ctx context.Context, params pagination.PaginationParams, filters service.UserListFilters) ([]service.User, *pagination.PaginationResult, error) {
r.listParams = params
return []service.User{}, &pagination.PaginationResult{
Total: 0,
Page: params.Page,
PageSize: params.PageSize,
Pages: 0,
}, nil
}
type announcementReadRepoCapture struct {
service.AnnouncementReadRepository
}
func (r *announcementReadRepoCapture) GetReadMapByUsers(ctx context.Context, announcementID int64, userIDs []int64) (map[int64]time.Time, error) {
return map[int64]time.Time{}, nil
}
type announcementUserSubRepoCapture struct {
service.UserSubscriptionRepository
}
func newAnnouncementSortTestRouter(announcementRepo *announcementRepoCapture, userRepo *announcementUserRepoCapture) *gin.Engine {
gin.SetMode(gin.TestMode)
svc := service.NewAnnouncementService(
announcementRepo,
&announcementReadRepoCapture{},
userRepo,
&announcementUserSubRepoCapture{},
)
handler := NewAnnouncementHandler(svc)
router := gin.New()
router.GET("/admin/announcements", handler.List)
router.GET("/admin/announcements/:id/read-status", handler.ListReadStatus)
return router
}
func TestAdminAnnouncementListSortParams(t *testing.T) {
announcementRepo := &announcementRepoCapture{}
userRepo := &announcementUserRepoCapture{}
router := newAnnouncementSortTestRouter(announcementRepo, userRepo)
req := httptest.NewRequest(http.MethodGet, "/admin/announcements?sort_by=title&sort_order=ASC", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "title", announcementRepo.listParams.SortBy)
require.Equal(t, "ASC", announcementRepo.listParams.SortOrder)
}
func TestAdminAnnouncementListSortDefaults(t *testing.T) {
announcementRepo := &announcementRepoCapture{}
userRepo := &announcementUserRepoCapture{}
router := newAnnouncementSortTestRouter(announcementRepo, userRepo)
req := httptest.NewRequest(http.MethodGet, "/admin/announcements", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "created_at", announcementRepo.listParams.SortBy)
require.Equal(t, "desc", announcementRepo.listParams.SortOrder)
}
func TestAdminAnnouncementReadStatusSortParams(t *testing.T) {
announcementRepo := &announcementRepoCapture{}
userRepo := &announcementUserRepoCapture{}
router := newAnnouncementSortTestRouter(announcementRepo, userRepo)
req := httptest.NewRequest(http.MethodGet, "/admin/announcements/1/read-status?sort_by=balance&sort_order=DESC", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "balance", userRepo.listParams.SortBy)
require.Equal(t, "DESC", userRepo.listParams.SortOrder)
}
func TestAdminAnnouncementReadStatusSortDefaults(t *testing.T) {
announcementRepo := &announcementRepoCapture{}
userRepo := &announcementUserRepoCapture{}
router := newAnnouncementSortTestRouter(announcementRepo, userRepo)
req := httptest.NewRequest(http.MethodGet, "/admin/announcements/1/read-status", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "email", userRepo.listParams.SortBy)
require.Equal(t, "asc", userRepo.listParams.SortOrder)
}

View File

@@ -245,7 +245,12 @@ func (h *ChannelHandler) List(c *gin.Context) {
search = search[:100]
}
channels, pag, err := h.channelService.List(c.Request.Context(), pagination.PaginationParams{Page: page, PageSize: pageSize}, status, search)
channels, pag, err := h.channelService.List(c.Request.Context(), pagination.PaginationParams{
Page: page,
PageSize: pageSize,
SortBy: c.DefaultQuery("sort_by", "created_at"),
SortOrder: c.DefaultQuery("sort_order", "desc"),
}, status, search)
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -105,10 +105,11 @@ type CreateGroupRequest struct {
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes []string `json:"supported_model_scopes"`
// OpenAI Messages 调度配置(仅 openai 平台使用)
AllowMessagesDispatch bool `json:"allow_messages_dispatch"`
RequireOAuthOnly bool `json:"require_oauth_only"`
RequirePrivacySet bool `json:"require_privacy_set"`
DefaultMappedModel string `json:"default_mapped_model"`
AllowMessagesDispatch bool `json:"allow_messages_dispatch"`
RequireOAuthOnly bool `json:"require_oauth_only"`
RequirePrivacySet bool `json:"require_privacy_set"`
DefaultMappedModel string `json:"default_mapped_model"`
MessagesDispatchModelConfig service.OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config"`
// 从指定分组复制账号(创建后自动绑定)
CopyAccountsFromGroupIDs []int64 `json:"copy_accounts_from_group_ids"`
}
@@ -139,10 +140,11 @@ type UpdateGroupRequest struct {
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes *[]string `json:"supported_model_scopes"`
// OpenAI Messages 调度配置(仅 openai 平台使用)
AllowMessagesDispatch *bool `json:"allow_messages_dispatch"`
RequireOAuthOnly *bool `json:"require_oauth_only"`
RequirePrivacySet *bool `json:"require_privacy_set"`
DefaultMappedModel *string `json:"default_mapped_model"`
AllowMessagesDispatch *bool `json:"allow_messages_dispatch"`
RequireOAuthOnly *bool `json:"require_oauth_only"`
RequirePrivacySet *bool `json:"require_privacy_set"`
DefaultMappedModel *string `json:"default_mapped_model"`
MessagesDispatchModelConfig *service.OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config"`
// 从指定分组复制账号(同步操作:先清空当前分组的账号绑定,再绑定源分组的账号)
CopyAccountsFromGroupIDs []int64 `json:"copy_accounts_from_group_ids"`
}
@@ -160,6 +162,8 @@ func (h *GroupHandler) List(c *gin.Context) {
search = search[:100]
}
isExclusiveStr := c.Query("is_exclusive")
sortBy := c.DefaultQuery("sort_by", "sort_order")
sortOrder := c.DefaultQuery("sort_order", "asc")
var isExclusive *bool
if isExclusiveStr != "" {
@@ -167,7 +171,7 @@ func (h *GroupHandler) List(c *gin.Context) {
isExclusive = &val
}
groups, total, err := h.adminService.ListGroups(c.Request.Context(), page, pageSize, platform, status, search, isExclusive)
groups, total, err := h.adminService.ListGroups(c.Request.Context(), page, pageSize, platform, status, search, isExclusive, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -257,6 +261,7 @@ func (h *GroupHandler) Create(c *gin.Context) {
RequireOAuthOnly: req.RequireOAuthOnly,
RequirePrivacySet: req.RequirePrivacySet,
DefaultMappedModel: req.DefaultMappedModel,
MessagesDispatchModelConfig: req.MessagesDispatchModelConfig,
CopyAccountsFromGroupIDs: req.CopyAccountsFromGroupIDs,
})
if err != nil {
@@ -307,6 +312,7 @@ func (h *GroupHandler) Update(c *gin.Context) {
RequireOAuthOnly: req.RequireOAuthOnly,
RequirePrivacySet: req.RequirePrivacySet,
DefaultMappedModel: req.DefaultMappedModel,
MessagesDispatchModelConfig: req.MessagesDispatchModelConfig,
CopyAccountsFromGroupIDs: req.CopyAccountsFromGroupIDs,
})
if err != nil {

View File

@@ -0,0 +1,323 @@
package admin
import (
"strconv"
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
)
// PaymentHandler handles admin payment management.
type PaymentHandler struct {
paymentService *service.PaymentService
configService *service.PaymentConfigService
}
// NewPaymentHandler creates a new admin PaymentHandler.
func NewPaymentHandler(paymentService *service.PaymentService, configService *service.PaymentConfigService) *PaymentHandler {
return &PaymentHandler{
paymentService: paymentService,
configService: configService,
}
}
// --- Dashboard ---
// GetDashboard returns payment dashboard statistics.
// GET /api/v1/admin/payment/dashboard
func (h *PaymentHandler) GetDashboard(c *gin.Context) {
days := 30
if d := c.Query("days"); d != "" {
if v, err := strconv.Atoi(d); err == nil && v > 0 {
days = v
}
}
stats, err := h.paymentService.GetDashboardStats(c.Request.Context(), days)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, stats)
}
// --- Orders ---
// ListOrders returns a paginated list of all payment orders.
// GET /api/v1/admin/payment/orders
func (h *PaymentHandler) ListOrders(c *gin.Context) {
page, pageSize := response.ParsePagination(c)
var userID int64
if uid := c.Query("user_id"); uid != "" {
if v, err := strconv.ParseInt(uid, 10, 64); err == nil {
userID = v
}
}
orders, total, err := h.paymentService.AdminListOrders(c.Request.Context(), userID, service.OrderListParams{
Page: page,
PageSize: pageSize,
Status: c.Query("status"),
OrderType: c.Query("order_type"),
PaymentType: c.Query("payment_type"),
Keyword: c.Query("keyword"),
})
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Paginated(c, orders, int64(total), page, pageSize)
}
// GetOrderDetail returns detailed information about a single order.
// GET /api/v1/admin/payment/orders/:id
func (h *PaymentHandler) GetOrderDetail(c *gin.Context) {
orderID, ok := parseIDParam(c, "id")
if !ok {
return
}
order, err := h.paymentService.GetOrderByID(c.Request.Context(), orderID)
if err != nil {
response.ErrorFrom(c, err)
return
}
auditLogs, _ := h.paymentService.GetOrderAuditLogs(c.Request.Context(), orderID)
response.Success(c, gin.H{"order": order, "auditLogs": auditLogs})
}
// CancelOrder cancels a pending order (admin).
// POST /api/v1/admin/payment/orders/:id/cancel
func (h *PaymentHandler) CancelOrder(c *gin.Context) {
orderID, ok := parseIDParam(c, "id")
if !ok {
return
}
msg, err := h.paymentService.AdminCancelOrder(c.Request.Context(), orderID)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{"message": msg})
}
// RetryFulfillment retries fulfillment for a paid order.
// POST /api/v1/admin/payment/orders/:id/retry
func (h *PaymentHandler) RetryFulfillment(c *gin.Context) {
orderID, ok := parseIDParam(c, "id")
if !ok {
return
}
if err := h.paymentService.RetryFulfillment(c.Request.Context(), orderID); err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{"message": "fulfillment retried"})
}
// AdminProcessRefundRequest is the request body for admin refund processing.
type AdminProcessRefundRequest struct {
Amount float64 `json:"amount"`
Reason string `json:"reason"`
Force bool `json:"force"`
DeductBalance bool `json:"deduct_balance"`
}
// ProcessRefund processes a refund for an order (admin).
// POST /api/v1/admin/payment/orders/:id/refund
func (h *PaymentHandler) ProcessRefund(c *gin.Context) {
orderID, ok := parseIDParam(c, "id")
if !ok {
return
}
var req AdminProcessRefundRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
plan, earlyResult, err := h.paymentService.PrepareRefund(c.Request.Context(), orderID, req.Amount, req.Reason, req.Force, req.DeductBalance)
if err != nil {
response.ErrorFrom(c, err)
return
}
if earlyResult != nil {
response.Success(c, earlyResult)
return
}
result, err := h.paymentService.ExecuteRefund(c.Request.Context(), plan)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, result)
}
// --- Subscription Plans ---
// ListPlans returns all subscription plans.
// GET /api/v1/admin/payment/plans
func (h *PaymentHandler) ListPlans(c *gin.Context) {
plans, err := h.configService.ListPlans(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, plans)
}
// CreatePlan creates a new subscription plan.
// POST /api/v1/admin/payment/plans
func (h *PaymentHandler) CreatePlan(c *gin.Context) {
var req service.CreatePlanRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
plan, err := h.configService.CreatePlan(c.Request.Context(), req)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Created(c, plan)
}
// UpdatePlan updates an existing subscription plan.
// PUT /api/v1/admin/payment/plans/:id
func (h *PaymentHandler) UpdatePlan(c *gin.Context) {
id, ok := parseIDParam(c, "id")
if !ok {
return
}
var req service.UpdatePlanRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
plan, err := h.configService.UpdatePlan(c.Request.Context(), id, req)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, plan)
}
// DeletePlan deletes a subscription plan.
// DELETE /api/v1/admin/payment/plans/:id
func (h *PaymentHandler) DeletePlan(c *gin.Context) {
id, ok := parseIDParam(c, "id")
if !ok {
return
}
if err := h.configService.DeletePlan(c.Request.Context(), id); err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{"message": "deleted"})
}
// --- Provider Instances ---
// ListProviders returns all payment provider instances.
// GET /api/v1/admin/payment/providers
func (h *PaymentHandler) ListProviders(c *gin.Context) {
providers, err := h.configService.ListProviderInstancesWithConfig(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, providers)
}
// CreateProvider creates a new payment provider instance.
// POST /api/v1/admin/payment/providers
func (h *PaymentHandler) CreateProvider(c *gin.Context) {
var req service.CreateProviderInstanceRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
inst, err := h.configService.CreateProviderInstance(c.Request.Context(), req)
if err != nil {
response.ErrorFrom(c, err)
return
}
h.paymentService.RefreshProviders(c.Request.Context())
response.Created(c, inst)
}
// UpdateProvider updates an existing payment provider instance.
// PUT /api/v1/admin/payment/providers/:id
func (h *PaymentHandler) UpdateProvider(c *gin.Context) {
id, ok := parseIDParam(c, "id")
if !ok {
return
}
var req service.UpdateProviderInstanceRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
inst, err := h.configService.UpdateProviderInstance(c.Request.Context(), id, req)
if err != nil {
response.ErrorFrom(c, err)
return
}
h.paymentService.RefreshProviders(c.Request.Context())
response.Success(c, inst)
}
// DeleteProvider deletes a payment provider instance.
// DELETE /api/v1/admin/payment/providers/:id
func (h *PaymentHandler) DeleteProvider(c *gin.Context) {
id, ok := parseIDParam(c, "id")
if !ok {
return
}
if err := h.configService.DeleteProviderInstance(c.Request.Context(), id); err != nil {
response.ErrorFrom(c, err)
return
}
h.paymentService.RefreshProviders(c.Request.Context())
response.Success(c, gin.H{"message": "deleted"})
}
// parseIDParam parses an int64 path parameter.
// Returns the parsed ID and true on success; on failure it writes a BadRequest response and returns false.
func parseIDParam(c *gin.Context, paramName string) (int64, bool) {
id, err := strconv.ParseInt(c.Param(paramName), 10, 64)
if err != nil {
response.BadRequest(c, "Invalid "+paramName)
return 0, false
}
return id, true
}
// --- Config ---
// GetConfig returns the payment configuration (admin view).
// GET /api/v1/admin/payment/config
func (h *PaymentHandler) GetConfig(c *gin.Context) {
cfg, err := h.configService.GetPaymentConfig(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, cfg)
}
// UpdateConfig updates the payment configuration.
// PUT /api/v1/admin/payment/config
func (h *PaymentHandler) UpdateConfig(c *gin.Context) {
var req service.UpdatePaymentConfigRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
if err := h.configService.UpdatePaymentConfig(c.Request.Context(), req); err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{"message": "updated"})
}

View File

@@ -55,8 +55,10 @@ func (h *PromoHandler) List(c *gin.Context) {
}
params := pagination.PaginationParams{
Page: page,
PageSize: pageSize,
Page: page,
PageSize: pageSize,
SortBy: c.DefaultQuery("sort_by", "created_at"),
SortOrder: c.DefaultQuery("sort_order", "desc"),
}
codes, paginationResult, err := h.promoService.List(c.Request.Context(), params, status, search)

View File

@@ -33,11 +33,13 @@ func (h *ProxyHandler) ExportData(c *gin.Context) {
protocol := c.Query("protocol")
status := c.Query("status")
search := strings.TrimSpace(c.Query("search"))
sortBy := c.DefaultQuery("sort_by", "id")
sortOrder := c.DefaultQuery("sort_order", "desc")
if len(search) > 100 {
search = search[:100]
}
proxies, err = h.listProxiesFiltered(ctx, protocol, status, search)
proxies, err = h.listProxiesFiltered(ctx, protocol, status, search, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -89,7 +91,7 @@ func (h *ProxyHandler) ImportData(c *gin.Context) {
ctx := c.Request.Context()
result := DataImportResult{}
existingProxies, err := h.listProxiesFiltered(ctx, "", "", "")
existingProxies, err := h.listProxiesFiltered(ctx, "", "", "", "id", "desc")
if err != nil {
response.ErrorFrom(c, err)
return
@@ -220,18 +222,33 @@ func parseProxyIDs(c *gin.Context) ([]int64, error) {
return ids, nil
}
func (h *ProxyHandler) listProxiesFiltered(ctx context.Context, protocol, status, search string) ([]service.Proxy, error) {
func (h *ProxyHandler) listProxiesFiltered(ctx context.Context, protocol, status, search, sortBy, sortOrder string) ([]service.Proxy, error) {
page := 1
pageSize := dataPageCap
var out []service.Proxy
sortBy = strings.TrimSpace(sortBy)
useAccountCountSort := strings.EqualFold(sortBy, "account_count")
for {
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, protocol, status, search)
if err != nil {
return nil, err
}
out = append(out, items...)
if len(out) >= int(total) || len(items) == 0 {
break
if useAccountCountSort {
items, total, err := h.adminService.ListProxiesWithAccountCount(ctx, page, pageSize, protocol, status, search, sortBy, sortOrder)
if err != nil {
return nil, err
}
for i := range items {
out = append(out, items[i].Proxy)
}
if len(out) >= int(total) || len(items) == 0 {
break
}
} else {
items, total, err := h.adminService.ListProxies(ctx, page, pageSize, protocol, status, search, sortBy, sortOrder)
if err != nil {
return nil, err
}
out = append(out, items...)
if len(out) >= int(total) || len(items) == 0 {
break
}
}
page++
}

View File

@@ -74,6 +74,10 @@ func TestProxyExportDataRespectsFilters(t *testing.T) {
require.Len(t, resp.Data.Proxies, 1)
require.Len(t, resp.Data.Accounts, 0)
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
require.Equal(t, 1, adminSvc.lastListProxies.calls)
require.Equal(t, "https", adminSvc.lastListProxies.protocol)
require.Equal(t, "id", adminSvc.lastListProxies.sortBy)
require.Equal(t, "desc", adminSvc.lastListProxies.sortOrder)
}
func TestProxyExportDataWithSelectedIDs(t *testing.T) {
@@ -113,6 +117,96 @@ func TestProxyExportDataWithSelectedIDs(t *testing.T) {
require.Len(t, resp.Data.Proxies, 1)
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
require.Equal(t, "10.0.0.2", resp.Data.Proxies[0].Host)
require.Equal(t, 0, adminSvc.lastListProxies.calls)
}
func TestProxyExportDataPassesSortParams(t *testing.T) {
router, adminSvc := setupProxyDataRouter()
adminSvc.proxies = []service.Proxy{
{
ID: 1,
Name: "proxy-a",
Protocol: "http",
Host: "127.0.0.1",
Port: 8080,
Username: "user",
Password: "pass",
Status: service.StatusActive,
},
}
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/proxies/data?protocol=http&status=active&search=proxy&sort_by=name&sort_order=asc", nil)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, 1, adminSvc.lastListProxies.calls)
require.Equal(t, "http", adminSvc.lastListProxies.protocol)
require.Equal(t, "active", adminSvc.lastListProxies.status)
require.Equal(t, "proxy", adminSvc.lastListProxies.search)
require.Equal(t, "name", adminSvc.lastListProxies.sortBy)
require.Equal(t, "asc", adminSvc.lastListProxies.sortOrder)
}
func TestProxyExportDataSortByAccountCountUsesAccountCountListing(t *testing.T) {
router, adminSvc := setupProxyDataRouter()
adminSvc.proxies = []service.Proxy{
{
ID: 1,
Name: "proxy-id-1",
Protocol: "http",
Host: "127.0.0.1",
Port: 8080,
Status: service.StatusActive,
},
{
ID: 2,
Name: "proxy-id-2",
Protocol: "http",
Host: "127.0.0.2",
Port: 8081,
Status: service.StatusActive,
},
}
adminSvc.proxyCounts = []service.ProxyWithAccountCount{
{
Proxy: service.Proxy{
ID: 2,
Name: "proxy-count-high",
Protocol: "http",
Host: "127.0.0.2",
Port: 8081,
Status: service.StatusActive,
},
AccountCount: 9,
},
{
Proxy: service.Proxy{
ID: 1,
Name: "proxy-count-low",
Protocol: "http",
Host: "127.0.0.1",
Port: 8080,
Status: service.StatusActive,
},
AccountCount: 1,
},
}
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/proxies/data?sort_by=account_count&sort_order=desc", nil)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
var resp proxyDataResponse
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
require.Equal(t, 0, resp.Code)
require.Len(t, resp.Data.Proxies, 2)
require.Equal(t, "proxy-count-high", resp.Data.Proxies[0].Name)
require.Equal(t, "proxy-count-low", resp.Data.Proxies[1].Name)
require.Equal(t, 0, adminSvc.lastListProxies.calls)
}
func TestProxyImportDataReusesAndTriggersLatencyProbe(t *testing.T) {

View File

@@ -52,13 +52,15 @@ func (h *ProxyHandler) List(c *gin.Context) {
protocol := c.Query("protocol")
status := c.Query("status")
search := c.Query("search")
sortBy := c.DefaultQuery("sort_by", "id")
sortOrder := c.DefaultQuery("sort_order", "desc")
// 标准化和验证 search 参数
search = strings.TrimSpace(search)
if len(search) > 100 {
search = search[:100]
}
proxies, total, err := h.adminService.ListProxiesWithAccountCount(c.Request.Context(), page, pageSize, protocol, status, search)
proxies, total, err := h.adminService.ListProxiesWithAccountCount(c.Request.Context(), page, pageSize, protocol, status, search, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -0,0 +1,49 @@
package admin
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
)
func setupRedeemExportRouter() (*gin.Engine, *stubAdminService) {
gin.SetMode(gin.TestMode)
router := gin.New()
adminSvc := newStubAdminService()
h := NewRedeemHandler(adminSvc, nil)
router.GET("/api/v1/admin/redeem-codes/export", h.Export)
return router, adminSvc
}
func TestRedeemExportPassesSearchAndSort(t *testing.T) {
router, adminSvc := setupRedeemExportRouter()
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/redeem-codes/export?type=balance&status=unused&search=ABC&sort_by=value&sort_order=asc", nil)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, 1, adminSvc.lastListRedeemCodes.calls)
require.Equal(t, "balance", adminSvc.lastListRedeemCodes.codeType)
require.Equal(t, "unused", adminSvc.lastListRedeemCodes.status)
require.Equal(t, "ABC", adminSvc.lastListRedeemCodes.search)
require.Equal(t, "value", adminSvc.lastListRedeemCodes.sortBy)
require.Equal(t, "asc", adminSvc.lastListRedeemCodes.sortOrder)
}
func TestRedeemExportSortDefaults(t *testing.T) {
router, adminSvc := setupRedeemExportRouter()
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/redeem-codes/export", nil)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, 1, adminSvc.lastListRedeemCodes.calls)
require.Equal(t, "id", adminSvc.lastListRedeemCodes.sortBy)
require.Equal(t, "desc", adminSvc.lastListRedeemCodes.sortOrder)
}

View File

@@ -59,13 +59,15 @@ func (h *RedeemHandler) List(c *gin.Context) {
codeType := c.Query("type")
status := c.Query("status")
search := c.Query("search")
sortBy := c.DefaultQuery("sort_by", "id")
sortOrder := c.DefaultQuery("sort_order", "desc")
// 标准化和验证 search 参数
search = strings.TrimSpace(search)
if len(search) > 100 {
search = search[:100]
}
codes, total, err := h.adminService.ListRedeemCodes(c.Request.Context(), page, pageSize, codeType, status, search)
codes, total, err := h.adminService.ListRedeemCodes(c.Request.Context(), page, pageSize, codeType, status, search, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -300,9 +302,15 @@ func (h *RedeemHandler) GetStats(c *gin.Context) {
func (h *RedeemHandler) Export(c *gin.Context) {
codeType := c.Query("type")
status := c.Query("status")
search := strings.TrimSpace(c.Query("search"))
sortBy := c.DefaultQuery("sort_by", "id")
sortOrder := c.DefaultQuery("sort_order", "desc")
if len(search) > 100 {
search = search[:100]
}
// Get all codes without pagination (use large page size)
codes, _, err := h.adminService.ListRedeemCodes(c.Request.Context(), 1, 10000, codeType, status, "")
codes, _, err := h.adminService.ListRedeemCodes(c.Request.Context(), 1, 10000, codeType, status, search, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -35,21 +35,34 @@ func generateMenuItemID() (string, error) {
return hex.EncodeToString(b), nil
}
func scopesContainOpenID(scopes string) bool {
for _, scope := range strings.Fields(strings.ToLower(strings.TrimSpace(scopes))) {
if scope == "openid" {
return true
}
}
return false
}
// SettingHandler 系统设置处理器
type SettingHandler struct {
settingService *service.SettingService
emailService *service.EmailService
turnstileService *service.TurnstileService
opsService *service.OpsService
settingService *service.SettingService
emailService *service.EmailService
turnstileService *service.TurnstileService
opsService *service.OpsService
paymentConfigService *service.PaymentConfigService
paymentService *service.PaymentService
}
// NewSettingHandler 创建系统设置处理器
func NewSettingHandler(settingService *service.SettingService, emailService *service.EmailService, turnstileService *service.TurnstileService, opsService *service.OpsService) *SettingHandler {
func NewSettingHandler(settingService *service.SettingService, emailService *service.EmailService, turnstileService *service.TurnstileService, opsService *service.OpsService, paymentConfigService *service.PaymentConfigService, paymentService *service.PaymentService) *SettingHandler {
return &SettingHandler{
settingService: settingService,
emailService: emailService,
turnstileService: turnstileService,
opsService: opsService,
settingService: settingService,
emailService: emailService,
turnstileService: turnstileService,
opsService: opsService,
paymentConfigService: paymentConfigService,
paymentService: paymentService,
}
}
@@ -72,6 +85,15 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
})
}
// Load payment config
var paymentCfg *service.PaymentConfig
if h.paymentConfigService != nil {
paymentCfg, _ = h.paymentConfigService.GetPaymentConfig(c.Request.Context())
}
if paymentCfg == nil {
paymentCfg = &service.PaymentConfig{}
}
response.Success(c, dto.SystemSettings{
RegistrationEnabled: settings.RegistrationEnabled,
EmailVerifyEnabled: settings.EmailVerifyEnabled,
@@ -96,6 +118,28 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
LinuxDoConnectClientID: settings.LinuxDoConnectClientID,
LinuxDoConnectClientSecretConfigured: settings.LinuxDoConnectClientSecretConfigured,
LinuxDoConnectRedirectURL: settings.LinuxDoConnectRedirectURL,
OIDCConnectEnabled: settings.OIDCConnectEnabled,
OIDCConnectProviderName: settings.OIDCConnectProviderName,
OIDCConnectClientID: settings.OIDCConnectClientID,
OIDCConnectClientSecretConfigured: settings.OIDCConnectClientSecretConfigured,
OIDCConnectIssuerURL: settings.OIDCConnectIssuerURL,
OIDCConnectDiscoveryURL: settings.OIDCConnectDiscoveryURL,
OIDCConnectAuthorizeURL: settings.OIDCConnectAuthorizeURL,
OIDCConnectTokenURL: settings.OIDCConnectTokenURL,
OIDCConnectUserInfoURL: settings.OIDCConnectUserInfoURL,
OIDCConnectJWKSURL: settings.OIDCConnectJWKSURL,
OIDCConnectScopes: settings.OIDCConnectScopes,
OIDCConnectRedirectURL: settings.OIDCConnectRedirectURL,
OIDCConnectFrontendRedirectURL: settings.OIDCConnectFrontendRedirectURL,
OIDCConnectTokenAuthMethod: settings.OIDCConnectTokenAuthMethod,
OIDCConnectUsePKCE: settings.OIDCConnectUsePKCE,
OIDCConnectValidateIDToken: settings.OIDCConnectValidateIDToken,
OIDCConnectAllowedSigningAlgs: settings.OIDCConnectAllowedSigningAlgs,
OIDCConnectClockSkewSeconds: settings.OIDCConnectClockSkewSeconds,
OIDCConnectRequireEmailVerified: settings.OIDCConnectRequireEmailVerified,
OIDCConnectUserInfoEmailPath: settings.OIDCConnectUserInfoEmailPath,
OIDCConnectUserInfoIDPath: settings.OIDCConnectUserInfoIDPath,
OIDCConnectUserInfoUsernamePath: settings.OIDCConnectUserInfoUsernamePath,
SiteName: settings.SiteName,
SiteLogo: settings.SiteLogo,
SiteSubtitle: settings.SiteSubtitle,
@@ -106,6 +150,8 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
HideCcsImportButton: settings.HideCcsImportButton,
PurchaseSubscriptionEnabled: settings.PurchaseSubscriptionEnabled,
PurchaseSubscriptionURL: settings.PurchaseSubscriptionURL,
TableDefaultPageSize: settings.TableDefaultPageSize,
TablePageSizeOptions: settings.TablePageSizeOptions,
CustomMenuItems: dto.ParseCustomMenuItems(settings.CustomMenuItems),
CustomEndpoints: dto.ParseCustomEndpoints(settings.CustomEndpoints),
DefaultConcurrency: settings.DefaultConcurrency,
@@ -129,6 +175,24 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
EnableFingerprintUnification: settings.EnableFingerprintUnification,
EnableMetadataPassthrough: settings.EnableMetadataPassthrough,
EnableCCHSigning: settings.EnableCCHSigning,
PaymentEnabled: paymentCfg.Enabled,
PaymentMinAmount: paymentCfg.MinAmount,
PaymentMaxAmount: paymentCfg.MaxAmount,
PaymentDailyLimit: paymentCfg.DailyLimit,
PaymentOrderTimeoutMin: paymentCfg.OrderTimeoutMin,
PaymentMaxPendingOrders: paymentCfg.MaxPendingOrders,
PaymentEnabledTypes: paymentCfg.EnabledTypes,
PaymentBalanceDisabled: paymentCfg.BalanceDisabled,
PaymentLoadBalanceStrat: paymentCfg.LoadBalanceStrategy,
PaymentProductNamePrefix: paymentCfg.ProductNamePrefix,
PaymentProductNameSuffix: paymentCfg.ProductNameSuffix,
PaymentHelpImageURL: paymentCfg.HelpImageURL,
PaymentHelpText: paymentCfg.HelpText,
PaymentCancelRateLimitEnabled: paymentCfg.CancelRateLimitEnabled,
PaymentCancelRateLimitMax: paymentCfg.CancelRateLimitMax,
PaymentCancelRateLimitWindow: paymentCfg.CancelRateLimitWindow,
PaymentCancelRateLimitUnit: paymentCfg.CancelRateLimitUnit,
PaymentCancelRateLimitMode: paymentCfg.CancelRateLimitMode,
})
}
@@ -164,6 +228,30 @@ type UpdateSettingsRequest struct {
LinuxDoConnectClientSecret string `json:"linuxdo_connect_client_secret"`
LinuxDoConnectRedirectURL string `json:"linuxdo_connect_redirect_url"`
// Generic OIDC OAuth 登录
OIDCConnectEnabled bool `json:"oidc_connect_enabled"`
OIDCConnectProviderName string `json:"oidc_connect_provider_name"`
OIDCConnectClientID string `json:"oidc_connect_client_id"`
OIDCConnectClientSecret string `json:"oidc_connect_client_secret"`
OIDCConnectIssuerURL string `json:"oidc_connect_issuer_url"`
OIDCConnectDiscoveryURL string `json:"oidc_connect_discovery_url"`
OIDCConnectAuthorizeURL string `json:"oidc_connect_authorize_url"`
OIDCConnectTokenURL string `json:"oidc_connect_token_url"`
OIDCConnectUserInfoURL string `json:"oidc_connect_userinfo_url"`
OIDCConnectJWKSURL string `json:"oidc_connect_jwks_url"`
OIDCConnectScopes string `json:"oidc_connect_scopes"`
OIDCConnectRedirectURL string `json:"oidc_connect_redirect_url"`
OIDCConnectFrontendRedirectURL string `json:"oidc_connect_frontend_redirect_url"`
OIDCConnectTokenAuthMethod string `json:"oidc_connect_token_auth_method"`
OIDCConnectUsePKCE bool `json:"oidc_connect_use_pkce"`
OIDCConnectValidateIDToken bool `json:"oidc_connect_validate_id_token"`
OIDCConnectAllowedSigningAlgs string `json:"oidc_connect_allowed_signing_algs"`
OIDCConnectClockSkewSeconds int `json:"oidc_connect_clock_skew_seconds"`
OIDCConnectRequireEmailVerified bool `json:"oidc_connect_require_email_verified"`
OIDCConnectUserInfoEmailPath string `json:"oidc_connect_userinfo_email_path"`
OIDCConnectUserInfoIDPath string `json:"oidc_connect_userinfo_id_path"`
OIDCConnectUserInfoUsernamePath string `json:"oidc_connect_userinfo_username_path"`
// OEM设置
SiteName string `json:"site_name"`
SiteLogo string `json:"site_logo"`
@@ -175,6 +263,8 @@ type UpdateSettingsRequest struct {
HideCcsImportButton bool `json:"hide_ccs_import_button"`
PurchaseSubscriptionEnabled *bool `json:"purchase_subscription_enabled"`
PurchaseSubscriptionURL *string `json:"purchase_subscription_url"`
TableDefaultPageSize int `json:"table_default_page_size"`
TablePageSizeOptions []int `json:"table_page_size_options"`
CustomMenuItems *[]dto.CustomMenuItem `json:"custom_menu_items"`
CustomEndpoints *[]dto.CustomEndpoint `json:"custom_endpoints"`
@@ -213,6 +303,28 @@ type UpdateSettingsRequest struct {
EnableFingerprintUnification *bool `json:"enable_fingerprint_unification"`
EnableMetadataPassthrough *bool `json:"enable_metadata_passthrough"`
EnableCCHSigning *bool `json:"enable_cch_signing"`
// Payment configuration (integrated into settings, full replace)
PaymentEnabled *bool `json:"payment_enabled"`
PaymentMinAmount *float64 `json:"payment_min_amount"`
PaymentMaxAmount *float64 `json:"payment_max_amount"`
PaymentDailyLimit *float64 `json:"payment_daily_limit"`
PaymentOrderTimeoutMin *int `json:"payment_order_timeout_minutes"`
PaymentMaxPendingOrders *int `json:"payment_max_pending_orders"`
PaymentEnabledTypes []string `json:"payment_enabled_types"`
PaymentBalanceDisabled *bool `json:"payment_balance_disabled"`
PaymentLoadBalanceStrat *string `json:"payment_load_balance_strategy"`
PaymentProductNamePrefix *string `json:"payment_product_name_prefix"`
PaymentProductNameSuffix *string `json:"payment_product_name_suffix"`
PaymentHelpImageURL *string `json:"payment_help_image_url"`
PaymentHelpText *string `json:"payment_help_text"`
// Cancel rate limit
PaymentCancelRateLimitEnabled *bool `json:"payment_cancel_rate_limit_enabled"`
PaymentCancelRateLimitMax *int `json:"payment_cancel_rate_limit_max"`
PaymentCancelRateLimitWindow *int `json:"payment_cancel_rate_limit_window"`
PaymentCancelRateLimitUnit *string `json:"payment_cancel_rate_limit_unit"`
PaymentCancelRateLimitMode *string `json:"payment_cancel_rate_limit_window_mode"`
}
// UpdateSettings 更新系统设置
@@ -237,6 +349,13 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
if req.DefaultBalance < 0 {
req.DefaultBalance = 0
}
// 通用表格配置:兼容旧客户端未传字段时保留当前值。
if req.TableDefaultPageSize <= 0 {
req.TableDefaultPageSize = previousSettings.TableDefaultPageSize
}
if req.TablePageSizeOptions == nil {
req.TablePageSizeOptions = previousSettings.TablePageSizeOptions
}
req.SMTPHost = strings.TrimSpace(req.SMTPHost)
req.SMTPUsername = strings.TrimSpace(req.SMTPUsername)
req.SMTPPassword = strings.TrimSpace(req.SMTPPassword)
@@ -324,6 +443,122 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
}
}
// Generic OIDC 参数验证
if req.OIDCConnectEnabled {
req.OIDCConnectProviderName = strings.TrimSpace(req.OIDCConnectProviderName)
req.OIDCConnectClientID = strings.TrimSpace(req.OIDCConnectClientID)
req.OIDCConnectClientSecret = strings.TrimSpace(req.OIDCConnectClientSecret)
req.OIDCConnectIssuerURL = strings.TrimSpace(req.OIDCConnectIssuerURL)
req.OIDCConnectDiscoveryURL = strings.TrimSpace(req.OIDCConnectDiscoveryURL)
req.OIDCConnectAuthorizeURL = strings.TrimSpace(req.OIDCConnectAuthorizeURL)
req.OIDCConnectTokenURL = strings.TrimSpace(req.OIDCConnectTokenURL)
req.OIDCConnectUserInfoURL = strings.TrimSpace(req.OIDCConnectUserInfoURL)
req.OIDCConnectJWKSURL = strings.TrimSpace(req.OIDCConnectJWKSURL)
req.OIDCConnectScopes = strings.TrimSpace(req.OIDCConnectScopes)
req.OIDCConnectRedirectURL = strings.TrimSpace(req.OIDCConnectRedirectURL)
req.OIDCConnectFrontendRedirectURL = strings.TrimSpace(req.OIDCConnectFrontendRedirectURL)
req.OIDCConnectTokenAuthMethod = strings.ToLower(strings.TrimSpace(req.OIDCConnectTokenAuthMethod))
req.OIDCConnectAllowedSigningAlgs = strings.TrimSpace(req.OIDCConnectAllowedSigningAlgs)
req.OIDCConnectUserInfoEmailPath = strings.TrimSpace(req.OIDCConnectUserInfoEmailPath)
req.OIDCConnectUserInfoIDPath = strings.TrimSpace(req.OIDCConnectUserInfoIDPath)
req.OIDCConnectUserInfoUsernamePath = strings.TrimSpace(req.OIDCConnectUserInfoUsernamePath)
if req.OIDCConnectProviderName == "" {
req.OIDCConnectProviderName = "OIDC"
}
if req.OIDCConnectClientID == "" {
response.BadRequest(c, "OIDC Client ID is required when enabled")
return
}
if req.OIDCConnectIssuerURL == "" {
response.BadRequest(c, "OIDC Issuer URL is required when enabled")
return
}
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectIssuerURL); err != nil {
response.BadRequest(c, "OIDC Issuer URL must be an absolute http(s) URL")
return
}
if req.OIDCConnectDiscoveryURL != "" {
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectDiscoveryURL); err != nil {
response.BadRequest(c, "OIDC Discovery URL must be an absolute http(s) URL")
return
}
}
if req.OIDCConnectAuthorizeURL != "" {
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectAuthorizeURL); err != nil {
response.BadRequest(c, "OIDC Authorize URL must be an absolute http(s) URL")
return
}
}
if req.OIDCConnectTokenURL != "" {
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectTokenURL); err != nil {
response.BadRequest(c, "OIDC Token URL must be an absolute http(s) URL")
return
}
}
if req.OIDCConnectUserInfoURL != "" {
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectUserInfoURL); err != nil {
response.BadRequest(c, "OIDC UserInfo URL must be an absolute http(s) URL")
return
}
}
if req.OIDCConnectRedirectURL == "" {
response.BadRequest(c, "OIDC Redirect URL is required when enabled")
return
}
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectRedirectURL); err != nil {
response.BadRequest(c, "OIDC Redirect URL must be an absolute http(s) URL")
return
}
if req.OIDCConnectFrontendRedirectURL == "" {
response.BadRequest(c, "OIDC Frontend Redirect URL is required when enabled")
return
}
if err := config.ValidateFrontendRedirectURL(req.OIDCConnectFrontendRedirectURL); err != nil {
response.BadRequest(c, "OIDC Frontend Redirect URL is invalid")
return
}
if !scopesContainOpenID(req.OIDCConnectScopes) {
response.BadRequest(c, "OIDC scopes must contain openid")
return
}
switch req.OIDCConnectTokenAuthMethod {
case "", "client_secret_post", "client_secret_basic", "none":
default:
response.BadRequest(c, "OIDC Token Auth Method must be one of client_secret_post/client_secret_basic/none")
return
}
if req.OIDCConnectTokenAuthMethod == "none" && !req.OIDCConnectUsePKCE {
response.BadRequest(c, "OIDC PKCE must be enabled when token_auth_method=none")
return
}
if req.OIDCConnectClockSkewSeconds < 0 || req.OIDCConnectClockSkewSeconds > 600 {
response.BadRequest(c, "OIDC clock skew seconds must be between 0 and 600")
return
}
if req.OIDCConnectValidateIDToken {
if req.OIDCConnectAllowedSigningAlgs == "" {
response.BadRequest(c, "OIDC Allowed Signing Algs is required when validate_id_token=true")
return
}
}
if req.OIDCConnectJWKSURL != "" {
if err := config.ValidateAbsoluteHTTPURL(req.OIDCConnectJWKSURL); err != nil {
response.BadRequest(c, "OIDC JWKS URL must be an absolute http(s) URL")
return
}
}
if req.OIDCConnectTokenAuthMethod == "" || req.OIDCConnectTokenAuthMethod == "client_secret_post" || req.OIDCConnectTokenAuthMethod == "client_secret_basic" {
if req.OIDCConnectClientSecret == "" {
if previousSettings.OIDCConnectClientSecret == "" {
response.BadRequest(c, "OIDC Client Secret is required when enabled")
return
}
req.OIDCConnectClientSecret = previousSettings.OIDCConnectClientSecret
}
}
}
// “购买订阅”页面配置验证
purchaseEnabled := previousSettings.PurchaseSubscriptionEnabled
if req.PurchaseSubscriptionEnabled != nil {
@@ -554,6 +789,28 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
LinuxDoConnectClientID: req.LinuxDoConnectClientID,
LinuxDoConnectClientSecret: req.LinuxDoConnectClientSecret,
LinuxDoConnectRedirectURL: req.LinuxDoConnectRedirectURL,
OIDCConnectEnabled: req.OIDCConnectEnabled,
OIDCConnectProviderName: req.OIDCConnectProviderName,
OIDCConnectClientID: req.OIDCConnectClientID,
OIDCConnectClientSecret: req.OIDCConnectClientSecret,
OIDCConnectIssuerURL: req.OIDCConnectIssuerURL,
OIDCConnectDiscoveryURL: req.OIDCConnectDiscoveryURL,
OIDCConnectAuthorizeURL: req.OIDCConnectAuthorizeURL,
OIDCConnectTokenURL: req.OIDCConnectTokenURL,
OIDCConnectUserInfoURL: req.OIDCConnectUserInfoURL,
OIDCConnectJWKSURL: req.OIDCConnectJWKSURL,
OIDCConnectScopes: req.OIDCConnectScopes,
OIDCConnectRedirectURL: req.OIDCConnectRedirectURL,
OIDCConnectFrontendRedirectURL: req.OIDCConnectFrontendRedirectURL,
OIDCConnectTokenAuthMethod: req.OIDCConnectTokenAuthMethod,
OIDCConnectUsePKCE: req.OIDCConnectUsePKCE,
OIDCConnectValidateIDToken: req.OIDCConnectValidateIDToken,
OIDCConnectAllowedSigningAlgs: req.OIDCConnectAllowedSigningAlgs,
OIDCConnectClockSkewSeconds: req.OIDCConnectClockSkewSeconds,
OIDCConnectRequireEmailVerified: req.OIDCConnectRequireEmailVerified,
OIDCConnectUserInfoEmailPath: req.OIDCConnectUserInfoEmailPath,
OIDCConnectUserInfoIDPath: req.OIDCConnectUserInfoIDPath,
OIDCConnectUserInfoUsernamePath: req.OIDCConnectUserInfoUsernamePath,
SiteName: req.SiteName,
SiteLogo: req.SiteLogo,
SiteSubtitle: req.SiteSubtitle,
@@ -564,6 +821,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
HideCcsImportButton: req.HideCcsImportButton,
PurchaseSubscriptionEnabled: purchaseEnabled,
PurchaseSubscriptionURL: purchaseURL,
TableDefaultPageSize: req.TableDefaultPageSize,
TablePageSizeOptions: req.TablePageSizeOptions,
CustomMenuItems: customMenuJSON,
CustomEndpoints: customEndpointsJSON,
DefaultConcurrency: req.DefaultConcurrency,
@@ -629,6 +888,39 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
return
}
// Update payment configuration (integrated into system settings).
// Skip if no payment fields were provided (prevents accidental wipe).
if h.paymentConfigService != nil && hasPaymentFields(req) {
paymentReq := service.UpdatePaymentConfigRequest{
Enabled: req.PaymentEnabled,
MinAmount: req.PaymentMinAmount,
MaxAmount: req.PaymentMaxAmount,
DailyLimit: req.PaymentDailyLimit,
OrderTimeoutMin: req.PaymentOrderTimeoutMin,
MaxPendingOrders: req.PaymentMaxPendingOrders,
EnabledTypes: req.PaymentEnabledTypes,
BalanceDisabled: req.PaymentBalanceDisabled,
LoadBalanceStrategy: req.PaymentLoadBalanceStrat,
ProductNamePrefix: req.PaymentProductNamePrefix,
ProductNameSuffix: req.PaymentProductNameSuffix,
HelpImageURL: req.PaymentHelpImageURL,
HelpText: req.PaymentHelpText,
CancelRateLimitEnabled: req.PaymentCancelRateLimitEnabled,
CancelRateLimitMax: req.PaymentCancelRateLimitMax,
CancelRateLimitWindow: req.PaymentCancelRateLimitWindow,
CancelRateLimitUnit: req.PaymentCancelRateLimitUnit,
CancelRateLimitMode: req.PaymentCancelRateLimitMode,
}
if err := h.paymentConfigService.UpdatePaymentConfig(c.Request.Context(), paymentReq); err != nil {
response.ErrorFrom(c, err)
return
}
// Refresh in-memory provider registry so config changes take effect immediately
if h.paymentService != nil {
h.paymentService.RefreshProviders(c.Request.Context())
}
}
h.auditSettingsUpdate(c, previousSettings, settings, req)
// 重新获取设置返回
@@ -645,6 +937,15 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
})
}
// Reload payment config for response
var updatedPaymentCfg *service.PaymentConfig
if h.paymentConfigService != nil {
updatedPaymentCfg, _ = h.paymentConfigService.GetPaymentConfig(c.Request.Context())
}
if updatedPaymentCfg == nil {
updatedPaymentCfg = &service.PaymentConfig{}
}
response.Success(c, dto.SystemSettings{
RegistrationEnabled: updatedSettings.RegistrationEnabled,
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
@@ -669,6 +970,28 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
LinuxDoConnectClientID: updatedSettings.LinuxDoConnectClientID,
LinuxDoConnectClientSecretConfigured: updatedSettings.LinuxDoConnectClientSecretConfigured,
LinuxDoConnectRedirectURL: updatedSettings.LinuxDoConnectRedirectURL,
OIDCConnectEnabled: updatedSettings.OIDCConnectEnabled,
OIDCConnectProviderName: updatedSettings.OIDCConnectProviderName,
OIDCConnectClientID: updatedSettings.OIDCConnectClientID,
OIDCConnectClientSecretConfigured: updatedSettings.OIDCConnectClientSecretConfigured,
OIDCConnectIssuerURL: updatedSettings.OIDCConnectIssuerURL,
OIDCConnectDiscoveryURL: updatedSettings.OIDCConnectDiscoveryURL,
OIDCConnectAuthorizeURL: updatedSettings.OIDCConnectAuthorizeURL,
OIDCConnectTokenURL: updatedSettings.OIDCConnectTokenURL,
OIDCConnectUserInfoURL: updatedSettings.OIDCConnectUserInfoURL,
OIDCConnectJWKSURL: updatedSettings.OIDCConnectJWKSURL,
OIDCConnectScopes: updatedSettings.OIDCConnectScopes,
OIDCConnectRedirectURL: updatedSettings.OIDCConnectRedirectURL,
OIDCConnectFrontendRedirectURL: updatedSettings.OIDCConnectFrontendRedirectURL,
OIDCConnectTokenAuthMethod: updatedSettings.OIDCConnectTokenAuthMethod,
OIDCConnectUsePKCE: updatedSettings.OIDCConnectUsePKCE,
OIDCConnectValidateIDToken: updatedSettings.OIDCConnectValidateIDToken,
OIDCConnectAllowedSigningAlgs: updatedSettings.OIDCConnectAllowedSigningAlgs,
OIDCConnectClockSkewSeconds: updatedSettings.OIDCConnectClockSkewSeconds,
OIDCConnectRequireEmailVerified: updatedSettings.OIDCConnectRequireEmailVerified,
OIDCConnectUserInfoEmailPath: updatedSettings.OIDCConnectUserInfoEmailPath,
OIDCConnectUserInfoIDPath: updatedSettings.OIDCConnectUserInfoIDPath,
OIDCConnectUserInfoUsernamePath: updatedSettings.OIDCConnectUserInfoUsernamePath,
SiteName: updatedSettings.SiteName,
SiteLogo: updatedSettings.SiteLogo,
SiteSubtitle: updatedSettings.SiteSubtitle,
@@ -679,6 +1002,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
HideCcsImportButton: updatedSettings.HideCcsImportButton,
PurchaseSubscriptionEnabled: updatedSettings.PurchaseSubscriptionEnabled,
PurchaseSubscriptionURL: updatedSettings.PurchaseSubscriptionURL,
TableDefaultPageSize: updatedSettings.TableDefaultPageSize,
TablePageSizeOptions: updatedSettings.TablePageSizeOptions,
CustomMenuItems: dto.ParseCustomMenuItems(updatedSettings.CustomMenuItems),
CustomEndpoints: dto.ParseCustomEndpoints(updatedSettings.CustomEndpoints),
DefaultConcurrency: updatedSettings.DefaultConcurrency,
@@ -702,9 +1027,40 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
EnableFingerprintUnification: updatedSettings.EnableFingerprintUnification,
EnableMetadataPassthrough: updatedSettings.EnableMetadataPassthrough,
EnableCCHSigning: updatedSettings.EnableCCHSigning,
PaymentEnabled: updatedPaymentCfg.Enabled,
PaymentMinAmount: updatedPaymentCfg.MinAmount,
PaymentMaxAmount: updatedPaymentCfg.MaxAmount,
PaymentDailyLimit: updatedPaymentCfg.DailyLimit,
PaymentOrderTimeoutMin: updatedPaymentCfg.OrderTimeoutMin,
PaymentMaxPendingOrders: updatedPaymentCfg.MaxPendingOrders,
PaymentEnabledTypes: updatedPaymentCfg.EnabledTypes,
PaymentBalanceDisabled: updatedPaymentCfg.BalanceDisabled,
PaymentLoadBalanceStrat: updatedPaymentCfg.LoadBalanceStrategy,
PaymentProductNamePrefix: updatedPaymentCfg.ProductNamePrefix,
PaymentProductNameSuffix: updatedPaymentCfg.ProductNameSuffix,
PaymentHelpImageURL: updatedPaymentCfg.HelpImageURL,
PaymentHelpText: updatedPaymentCfg.HelpText,
PaymentCancelRateLimitEnabled: updatedPaymentCfg.CancelRateLimitEnabled,
PaymentCancelRateLimitMax: updatedPaymentCfg.CancelRateLimitMax,
PaymentCancelRateLimitWindow: updatedPaymentCfg.CancelRateLimitWindow,
PaymentCancelRateLimitUnit: updatedPaymentCfg.CancelRateLimitUnit,
PaymentCancelRateLimitMode: updatedPaymentCfg.CancelRateLimitMode,
})
}
// hasPaymentFields returns true if any payment-related field was explicitly provided.
func hasPaymentFields(req UpdateSettingsRequest) bool {
return req.PaymentEnabled != nil || req.PaymentMinAmount != nil ||
req.PaymentMaxAmount != nil || req.PaymentDailyLimit != nil ||
req.PaymentOrderTimeoutMin != nil || req.PaymentMaxPendingOrders != nil ||
req.PaymentEnabledTypes != nil || req.PaymentBalanceDisabled != nil ||
req.PaymentLoadBalanceStrat != nil || req.PaymentProductNamePrefix != nil ||
req.PaymentProductNameSuffix != nil || req.PaymentHelpImageURL != nil ||
req.PaymentHelpText != nil || req.PaymentCancelRateLimitEnabled != nil ||
req.PaymentCancelRateLimitMax != nil || req.PaymentCancelRateLimitWindow != nil ||
req.PaymentCancelRateLimitUnit != nil || req.PaymentCancelRateLimitMode != nil
}
func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) {
if before == nil || after == nil {
return
@@ -787,6 +1143,72 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
if before.LinuxDoConnectRedirectURL != after.LinuxDoConnectRedirectURL {
changed = append(changed, "linuxdo_connect_redirect_url")
}
if before.OIDCConnectEnabled != after.OIDCConnectEnabled {
changed = append(changed, "oidc_connect_enabled")
}
if before.OIDCConnectProviderName != after.OIDCConnectProviderName {
changed = append(changed, "oidc_connect_provider_name")
}
if before.OIDCConnectClientID != after.OIDCConnectClientID {
changed = append(changed, "oidc_connect_client_id")
}
if req.OIDCConnectClientSecret != "" {
changed = append(changed, "oidc_connect_client_secret")
}
if before.OIDCConnectIssuerURL != after.OIDCConnectIssuerURL {
changed = append(changed, "oidc_connect_issuer_url")
}
if before.OIDCConnectDiscoveryURL != after.OIDCConnectDiscoveryURL {
changed = append(changed, "oidc_connect_discovery_url")
}
if before.OIDCConnectAuthorizeURL != after.OIDCConnectAuthorizeURL {
changed = append(changed, "oidc_connect_authorize_url")
}
if before.OIDCConnectTokenURL != after.OIDCConnectTokenURL {
changed = append(changed, "oidc_connect_token_url")
}
if before.OIDCConnectUserInfoURL != after.OIDCConnectUserInfoURL {
changed = append(changed, "oidc_connect_userinfo_url")
}
if before.OIDCConnectJWKSURL != after.OIDCConnectJWKSURL {
changed = append(changed, "oidc_connect_jwks_url")
}
if before.OIDCConnectScopes != after.OIDCConnectScopes {
changed = append(changed, "oidc_connect_scopes")
}
if before.OIDCConnectRedirectURL != after.OIDCConnectRedirectURL {
changed = append(changed, "oidc_connect_redirect_url")
}
if before.OIDCConnectFrontendRedirectURL != after.OIDCConnectFrontendRedirectURL {
changed = append(changed, "oidc_connect_frontend_redirect_url")
}
if before.OIDCConnectTokenAuthMethod != after.OIDCConnectTokenAuthMethod {
changed = append(changed, "oidc_connect_token_auth_method")
}
if before.OIDCConnectUsePKCE != after.OIDCConnectUsePKCE {
changed = append(changed, "oidc_connect_use_pkce")
}
if before.OIDCConnectValidateIDToken != after.OIDCConnectValidateIDToken {
changed = append(changed, "oidc_connect_validate_id_token")
}
if before.OIDCConnectAllowedSigningAlgs != after.OIDCConnectAllowedSigningAlgs {
changed = append(changed, "oidc_connect_allowed_signing_algs")
}
if before.OIDCConnectClockSkewSeconds != after.OIDCConnectClockSkewSeconds {
changed = append(changed, "oidc_connect_clock_skew_seconds")
}
if before.OIDCConnectRequireEmailVerified != after.OIDCConnectRequireEmailVerified {
changed = append(changed, "oidc_connect_require_email_verified")
}
if before.OIDCConnectUserInfoEmailPath != after.OIDCConnectUserInfoEmailPath {
changed = append(changed, "oidc_connect_userinfo_email_path")
}
if before.OIDCConnectUserInfoIDPath != after.OIDCConnectUserInfoIDPath {
changed = append(changed, "oidc_connect_userinfo_id_path")
}
if before.OIDCConnectUserInfoUsernamePath != after.OIDCConnectUserInfoUsernamePath {
changed = append(changed, "oidc_connect_userinfo_username_path")
}
if before.SiteName != after.SiteName {
changed = append(changed, "site_name")
}
@@ -871,6 +1293,12 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
if before.PurchaseSubscriptionURL != after.PurchaseSubscriptionURL {
changed = append(changed, "purchase_subscription_url")
}
if before.TableDefaultPageSize != after.TableDefaultPageSize {
changed = append(changed, "table_default_page_size")
}
if !equalIntSlice(before.TablePageSizeOptions, after.TablePageSizeOptions) {
changed = append(changed, "table_page_size_options")
}
if before.CustomMenuItems != after.CustomMenuItems {
changed = append(changed, "custom_menu_items")
}
@@ -927,6 +1355,18 @@ func equalDefaultSubscriptions(a, b []service.DefaultSubscriptionSetting) bool {
return true
}
func equalIntSlice(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
// TestSMTPRequest 测试SMTP连接请求
type TestSMTPRequest struct {
SMTPHost string `json:"smtp_host"`

View File

@@ -165,7 +165,12 @@ func (h *UsageHandler) List(c *gin.Context) {
endTime = &t
}
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
params := pagination.PaginationParams{
Page: page,
PageSize: pageSize,
SortBy: c.DefaultQuery("sort_by", "created_at"),
SortOrder: c.DefaultQuery("sort_order", "desc"),
}
filters := usagestats.UsageLogFilters{
UserID: userID,
APIKeyID: apiKeyID,
@@ -339,7 +344,7 @@ func (h *UsageHandler) SearchUsers(c *gin.Context) {
}
// Limit to 30 results
users, _, err := h.adminService.ListUsers(c.Request.Context(), 1, 30, service.UserListFilters{Search: keyword})
users, _, err := h.adminService.ListUsers(c.Request.Context(), 1, 30, service.UserListFilters{Search: keyword}, "email", "asc")
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -15,11 +15,13 @@ import (
type adminUsageRepoCapture struct {
service.UsageLogRepository
listParams pagination.PaginationParams
listFilters usagestats.UsageLogFilters
statsFilters usagestats.UsageLogFilters
}
func (s *adminUsageRepoCapture) ListWithFilters(ctx context.Context, params pagination.PaginationParams, filters usagestats.UsageLogFilters) ([]service.UsageLog, *pagination.PaginationResult, error) {
s.listParams = params
s.listFilters = filters
return []service.UsageLog{}, &pagination.PaginationResult{
Total: 0,

View File

@@ -0,0 +1,35 @@
package admin
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
)
func TestAdminUsageListSortParams(t *testing.T) {
repo := &adminUsageRepoCapture{}
router := newAdminUsageRequestTypeTestRouter(repo)
req := httptest.NewRequest(http.MethodGet, "/admin/usage?sort_by=model&sort_order=ASC", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "model", repo.listParams.SortBy)
require.Equal(t, "ASC", repo.listParams.SortOrder)
}
func TestAdminUsageListSortDefaults(t *testing.T) {
repo := &adminUsageRepoCapture{}
router := newAdminUsageRequestTypeTestRouter(repo)
req := httptest.NewRequest(http.MethodGet, "/admin/usage", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, "created_at", repo.listParams.SortBy)
require.Equal(t, "desc", repo.listParams.SortOrder)
}

View File

@@ -91,12 +91,14 @@ func (h *UserHandler) List(c *gin.Context) {
GroupName: strings.TrimSpace(c.Query("group_name")),
Attributes: parseAttributeFilters(c),
}
sortBy := c.DefaultQuery("sort_by", "created_at")
sortOrder := c.DefaultQuery("sort_order", "desc")
if raw, ok := c.GetQuery("include_subscriptions"); ok {
includeSubscriptions := parseBoolQueryWithDefault(raw, true)
filters.IncludeSubscriptions = &includeSubscriptions
}
users, total, err := h.adminService.ListUsers(c.Request.Context(), page, pageSize, filters)
users, total, err := h.adminService.ListUsers(c.Request.Context(), page, pageSize, filters, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return
@@ -290,8 +292,10 @@ func (h *UserHandler) GetUserAPIKeys(c *gin.Context) {
}
page, pageSize := response.ParsePagination(c)
sortBy := c.DefaultQuery("sort_by", "created_at")
sortOrder := c.DefaultQuery("sort_order", "desc")
keys, total, err := h.adminService.GetUserAPIKeys(c.Request.Context(), userID, page, pageSize)
keys, total, err := h.adminService.GetUserAPIKeys(c.Request.Context(), userID, page, pageSize, sortBy, sortOrder)
if err != nil {
response.ErrorFrom(c, err)
return

View File

@@ -72,7 +72,12 @@ func (h *APIKeyHandler) List(c *gin.Context) {
}
page, pageSize := response.ParsePagination(c)
params := pagination.PaginationParams{Page: page, PageSize: pageSize}
params := pagination.PaginationParams{
Page: page,
PageSize: pageSize,
SortBy: c.DefaultQuery("sort_by", "created_at"),
SortOrder: c.DefaultQuery("sort_order", "desc"),
}
// Parse filter parameters
var filters service.APIKeyListFilters

View File

@@ -0,0 +1,873 @@
package handler
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"log"
"math/big"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
"github.com/Wei-Shaw/sub2api/internal/pkg/oauth"
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"github.com/imroc/req/v3"
"github.com/tidwall/gjson"
)
const (
oidcOAuthCookiePath = "/api/v1/auth/oauth/oidc"
oidcOAuthStateCookieName = "oidc_oauth_state"
oidcOAuthVerifierCookie = "oidc_oauth_verifier"
oidcOAuthRedirectCookie = "oidc_oauth_redirect"
oidcOAuthNonceCookie = "oidc_oauth_nonce"
oidcOAuthCookieMaxAgeSec = 10 * 60 // 10 minutes
oidcOAuthDefaultRedirectTo = "/dashboard"
oidcOAuthDefaultFrontendCB = "/auth/oidc/callback"
)
type oidcTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int64 `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
IDToken string `json:"id_token,omitempty"`
}
type oidcTokenExchangeError struct {
StatusCode int
ProviderError string
ProviderDescription string
Body string
}
func (e *oidcTokenExchangeError) Error() string {
if e == nil {
return ""
}
parts := []string{fmt.Sprintf("token exchange status=%d", e.StatusCode)}
if strings.TrimSpace(e.ProviderError) != "" {
parts = append(parts, "error="+strings.TrimSpace(e.ProviderError))
}
if strings.TrimSpace(e.ProviderDescription) != "" {
parts = append(parts, "error_description="+strings.TrimSpace(e.ProviderDescription))
}
return strings.Join(parts, " ")
}
type oidcIDTokenClaims struct {
Email string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
Name string `json:"name,omitempty"`
Nonce string `json:"nonce,omitempty"`
Azp string `json:"azp,omitempty"`
jwt.RegisteredClaims
}
type oidcUserInfoClaims struct {
Email string
Username string
Subject string
EmailVerified *bool
}
type oidcJWKSet struct {
Keys []oidcJWK `json:"keys"`
}
type oidcJWK struct {
Kty string `json:"kty"`
Kid string `json:"kid"`
Use string `json:"use"`
Alg string `json:"alg"`
N string `json:"n"`
E string `json:"e"`
Crv string `json:"crv"`
X string `json:"x"`
Y string `json:"y"`
}
// OIDCOAuthStart 启动通用 OIDC OAuth 登录流程。
// GET /api/v1/auth/oauth/oidc/start?redirect=/dashboard
func (h *AuthHandler) OIDCOAuthStart(c *gin.Context) {
cfg, err := h.getOIDCOAuthConfig(c.Request.Context())
if err != nil {
response.ErrorFrom(c, err)
return
}
state, err := oauth.GenerateState()
if err != nil {
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_STATE_GEN_FAILED", "failed to generate oauth state").WithCause(err))
return
}
redirectTo := sanitizeFrontendRedirectPath(c.Query("redirect"))
if redirectTo == "" {
redirectTo = oidcOAuthDefaultRedirectTo
}
secureCookie := isRequestHTTPS(c)
oidcSetCookie(c, oidcOAuthStateCookieName, encodeCookieValue(state), oidcOAuthCookieMaxAgeSec, secureCookie)
oidcSetCookie(c, oidcOAuthRedirectCookie, encodeCookieValue(redirectTo), oidcOAuthCookieMaxAgeSec, secureCookie)
codeChallenge := ""
if cfg.UsePKCE {
verifier, genErr := oauth.GenerateCodeVerifier()
if genErr != nil {
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_PKCE_GEN_FAILED", "failed to generate pkce verifier").WithCause(genErr))
return
}
codeChallenge = oauth.GenerateCodeChallenge(verifier)
oidcSetCookie(c, oidcOAuthVerifierCookie, encodeCookieValue(verifier), oidcOAuthCookieMaxAgeSec, secureCookie)
}
nonce := ""
if cfg.ValidateIDToken {
nonce, err = oauth.GenerateState()
if err != nil {
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_NONCE_GEN_FAILED", "failed to generate oauth nonce").WithCause(err))
return
}
oidcSetCookie(c, oidcOAuthNonceCookie, encodeCookieValue(nonce), oidcOAuthCookieMaxAgeSec, secureCookie)
}
redirectURI := strings.TrimSpace(cfg.RedirectURL)
if redirectURI == "" {
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_CONFIG_INVALID", "oauth redirect url not configured"))
return
}
authURL, err := buildOIDCAuthorizeURL(cfg, state, nonce, codeChallenge, redirectURI)
if err != nil {
response.ErrorFrom(c, infraerrors.InternalServer("OAUTH_BUILD_URL_FAILED", "failed to build oauth authorization url").WithCause(err))
return
}
c.Redirect(http.StatusFound, authURL)
}
// OIDCOAuthCallback 处理 OIDC 回调:校验 id_token、创建/登录用户并重定向到前端。
// GET /api/v1/auth/oauth/oidc/callback?code=...&state=...
func (h *AuthHandler) OIDCOAuthCallback(c *gin.Context) {
cfg, cfgErr := h.getOIDCOAuthConfig(c.Request.Context())
if cfgErr != nil {
response.ErrorFrom(c, cfgErr)
return
}
frontendCallback := strings.TrimSpace(cfg.FrontendRedirectURL)
if frontendCallback == "" {
frontendCallback = oidcOAuthDefaultFrontendCB
}
if providerErr := strings.TrimSpace(c.Query("error")); providerErr != "" {
redirectOAuthError(c, frontendCallback, "provider_error", providerErr, c.Query("error_description"))
return
}
code := strings.TrimSpace(c.Query("code"))
state := strings.TrimSpace(c.Query("state"))
if code == "" || state == "" {
redirectOAuthError(c, frontendCallback, "missing_params", "missing code/state", "")
return
}
secureCookie := isRequestHTTPS(c)
defer func() {
oidcClearCookie(c, oidcOAuthStateCookieName, secureCookie)
oidcClearCookie(c, oidcOAuthVerifierCookie, secureCookie)
oidcClearCookie(c, oidcOAuthRedirectCookie, secureCookie)
oidcClearCookie(c, oidcOAuthNonceCookie, secureCookie)
}()
expectedState, err := readCookieDecoded(c, oidcOAuthStateCookieName)
if err != nil || expectedState == "" || state != expectedState {
redirectOAuthError(c, frontendCallback, "invalid_state", "invalid oauth state", "")
return
}
redirectTo, _ := readCookieDecoded(c, oidcOAuthRedirectCookie)
redirectTo = sanitizeFrontendRedirectPath(redirectTo)
if redirectTo == "" {
redirectTo = oidcOAuthDefaultRedirectTo
}
codeVerifier := ""
if cfg.UsePKCE {
codeVerifier, _ = readCookieDecoded(c, oidcOAuthVerifierCookie)
if codeVerifier == "" {
redirectOAuthError(c, frontendCallback, "missing_verifier", "missing pkce verifier", "")
return
}
}
expectedNonce := ""
if cfg.ValidateIDToken {
expectedNonce, _ = readCookieDecoded(c, oidcOAuthNonceCookie)
if expectedNonce == "" {
redirectOAuthError(c, frontendCallback, "missing_nonce", "missing oauth nonce", "")
return
}
}
redirectURI := strings.TrimSpace(cfg.RedirectURL)
if redirectURI == "" {
redirectOAuthError(c, frontendCallback, "config_error", "oauth redirect url not configured", "")
return
}
tokenResp, err := oidcExchangeCode(c.Request.Context(), cfg, code, redirectURI, codeVerifier)
if err != nil {
description := ""
var exchangeErr *oidcTokenExchangeError
if errors.As(err, &exchangeErr) && exchangeErr != nil {
log.Printf(
"[OIDC OAuth] token exchange failed: status=%d provider_error=%q provider_description=%q body=%s",
exchangeErr.StatusCode,
exchangeErr.ProviderError,
exchangeErr.ProviderDescription,
truncateLogValue(exchangeErr.Body, 2048),
)
description = exchangeErr.Error()
} else {
log.Printf("[OIDC OAuth] token exchange failed: %v", err)
description = err.Error()
}
redirectOAuthError(c, frontendCallback, "token_exchange_failed", "failed to exchange oauth code", singleLine(description))
return
}
if cfg.ValidateIDToken && strings.TrimSpace(tokenResp.IDToken) == "" {
redirectOAuthError(c, frontendCallback, "missing_id_token", "missing id_token", "")
return
}
idClaims, err := oidcParseAndValidateIDToken(c.Request.Context(), cfg, tokenResp.IDToken, expectedNonce)
if err != nil {
log.Printf("[OIDC OAuth] id_token validation failed: %v", err)
redirectOAuthError(c, frontendCallback, "invalid_id_token", "failed to validate id_token", "")
return
}
userInfoClaims, err := oidcFetchUserInfo(c.Request.Context(), cfg, tokenResp)
if err != nil {
log.Printf("[OIDC OAuth] userinfo fetch failed: %v", err)
redirectOAuthError(c, frontendCallback, "userinfo_failed", "failed to fetch user info", "")
return
}
subject := strings.TrimSpace(idClaims.Subject)
if subject == "" {
subject = strings.TrimSpace(userInfoClaims.Subject)
}
if subject == "" {
redirectOAuthError(c, frontendCallback, "missing_subject", "missing subject claim", "")
return
}
issuer := strings.TrimSpace(idClaims.Issuer)
if issuer == "" {
issuer = strings.TrimSpace(cfg.IssuerURL)
}
if issuer == "" {
redirectOAuthError(c, frontendCallback, "missing_issuer", "missing issuer claim", "")
return
}
emailVerified := userInfoClaims.EmailVerified
if emailVerified == nil {
emailVerified = idClaims.EmailVerified
}
if cfg.RequireEmailVerified {
if emailVerified == nil || !*emailVerified {
redirectOAuthError(c, frontendCallback, "email_not_verified", "email is not verified", "")
return
}
}
identityKey := oidcIdentityKey(issuer, subject)
email := oidcSelectLoginEmail(userInfoClaims.Email, idClaims.Email, identityKey)
username := firstNonEmpty(
userInfoClaims.Username,
idClaims.PreferredUsername,
idClaims.Name,
oidcFallbackUsername(subject),
)
// 传入空邀请码;如果需要邀请码,服务层返回 ErrOAuthInvitationRequired
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, "")
if err != nil {
if errors.Is(err, service.ErrOAuthInvitationRequired) {
pendingToken, tokenErr := h.authService.CreatePendingOAuthToken(email, username)
if tokenErr != nil {
redirectOAuthError(c, frontendCallback, "login_failed", "service_error", "")
return
}
fragment := url.Values{}
fragment.Set("error", "invitation_required")
fragment.Set("pending_oauth_token", pendingToken)
fragment.Set("redirect", redirectTo)
redirectWithFragment(c, frontendCallback, fragment)
return
}
redirectOAuthError(c, frontendCallback, "login_failed", infraerrors.Reason(err), infraerrors.Message(err))
return
}
fragment := url.Values{}
fragment.Set("access_token", tokenPair.AccessToken)
fragment.Set("refresh_token", tokenPair.RefreshToken)
fragment.Set("expires_in", fmt.Sprintf("%d", tokenPair.ExpiresIn))
fragment.Set("token_type", "Bearer")
fragment.Set("redirect", redirectTo)
redirectWithFragment(c, frontendCallback, fragment)
}
type completeOIDCOAuthRequest struct {
PendingOAuthToken string `json:"pending_oauth_token" binding:"required"`
InvitationCode string `json:"invitation_code" binding:"required"`
}
// CompleteOIDCOAuthRegistration completes a pending OAuth registration by validating
// the invitation code and creating the user account.
// POST /api/v1/auth/oauth/oidc/complete-registration
func (h *AuthHandler) CompleteOIDCOAuthRegistration(c *gin.Context) {
var req completeOIDCOAuthRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "INVALID_REQUEST", "message": err.Error()})
return
}
email, username, err := h.authService.VerifyPendingOAuthToken(req.PendingOAuthToken)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "INVALID_TOKEN", "message": "invalid or expired registration token"})
return
}
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
if err != nil {
response.ErrorFrom(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"access_token": tokenPair.AccessToken,
"refresh_token": tokenPair.RefreshToken,
"expires_in": tokenPair.ExpiresIn,
"token_type": "Bearer",
})
}
func (h *AuthHandler) getOIDCOAuthConfig(ctx context.Context) (config.OIDCConnectConfig, error) {
if h != nil && h.settingSvc != nil {
return h.settingSvc.GetOIDCConnectOAuthConfig(ctx)
}
if h == nil || h.cfg == nil {
return config.OIDCConnectConfig{}, infraerrors.ServiceUnavailable("CONFIG_NOT_READY", "config not loaded")
}
if !h.cfg.OIDC.Enabled {
return config.OIDCConnectConfig{}, infraerrors.NotFound("OAUTH_DISABLED", "oauth login is disabled")
}
return h.cfg.OIDC, nil
}
func oidcExchangeCode(
ctx context.Context,
cfg config.OIDCConnectConfig,
code string,
redirectURI string,
codeVerifier string,
) (*oidcTokenResponse, error) {
client := req.C().SetTimeout(30 * time.Second)
form := url.Values{}
form.Set("grant_type", "authorization_code")
form.Set("client_id", cfg.ClientID)
form.Set("code", code)
form.Set("redirect_uri", redirectURI)
if cfg.UsePKCE {
form.Set("code_verifier", codeVerifier)
}
r := client.R().
SetContext(ctx).
SetHeader("Accept", "application/json")
switch strings.ToLower(strings.TrimSpace(cfg.TokenAuthMethod)) {
case "", "client_secret_post":
form.Set("client_secret", cfg.ClientSecret)
case "client_secret_basic":
r.SetBasicAuth(cfg.ClientID, cfg.ClientSecret)
case "none":
default:
return nil, fmt.Errorf("unsupported token_auth_method: %s", cfg.TokenAuthMethod)
}
resp, err := r.SetFormDataFromValues(form).Post(cfg.TokenURL)
if err != nil {
return nil, fmt.Errorf("request token: %w", err)
}
body := strings.TrimSpace(resp.String())
if !resp.IsSuccessState() {
providerErr, providerDesc := parseOAuthProviderError(body)
return nil, &oidcTokenExchangeError{
StatusCode: resp.StatusCode,
ProviderError: providerErr,
ProviderDescription: providerDesc,
Body: body,
}
}
tokenResp, ok := oidcParseTokenResponse(body)
if !ok {
return nil, &oidcTokenExchangeError{StatusCode: resp.StatusCode, Body: body}
}
if strings.TrimSpace(tokenResp.TokenType) == "" {
tokenResp.TokenType = "Bearer"
}
if strings.TrimSpace(tokenResp.AccessToken) == "" && strings.TrimSpace(tokenResp.IDToken) == "" {
return nil, &oidcTokenExchangeError{StatusCode: resp.StatusCode, Body: body}
}
return tokenResp, nil
}
func oidcParseTokenResponse(body string) (*oidcTokenResponse, bool) {
body = strings.TrimSpace(body)
if body == "" {
return nil, false
}
accessToken := strings.TrimSpace(getGJSON(body, "access_token"))
idToken := strings.TrimSpace(getGJSON(body, "id_token"))
if accessToken != "" || idToken != "" {
tokenType := strings.TrimSpace(getGJSON(body, "token_type"))
refreshToken := strings.TrimSpace(getGJSON(body, "refresh_token"))
scope := strings.TrimSpace(getGJSON(body, "scope"))
expiresIn := gjson.Get(body, "expires_in").Int()
return &oidcTokenResponse{
AccessToken: accessToken,
TokenType: tokenType,
ExpiresIn: expiresIn,
RefreshToken: refreshToken,
Scope: scope,
IDToken: idToken,
}, true
}
values, err := url.ParseQuery(body)
if err != nil {
return nil, false
}
accessToken = strings.TrimSpace(values.Get("access_token"))
idToken = strings.TrimSpace(values.Get("id_token"))
if accessToken == "" && idToken == "" {
return nil, false
}
expiresIn := int64(0)
if raw := strings.TrimSpace(values.Get("expires_in")); raw != "" {
if v, parseErr := strconv.ParseInt(raw, 10, 64); parseErr == nil {
expiresIn = v
}
}
return &oidcTokenResponse{
AccessToken: accessToken,
TokenType: strings.TrimSpace(values.Get("token_type")),
ExpiresIn: expiresIn,
RefreshToken: strings.TrimSpace(values.Get("refresh_token")),
Scope: strings.TrimSpace(values.Get("scope")),
IDToken: idToken,
}, true
}
func oidcFetchUserInfo(
ctx context.Context,
cfg config.OIDCConnectConfig,
token *oidcTokenResponse,
) (*oidcUserInfoClaims, error) {
if strings.TrimSpace(cfg.UserInfoURL) == "" {
return &oidcUserInfoClaims{}, nil
}
if token == nil || strings.TrimSpace(token.AccessToken) == "" {
return nil, errors.New("missing access_token for userinfo request")
}
client := req.C().SetTimeout(30 * time.Second)
authorization, err := buildBearerAuthorization(token.TokenType, token.AccessToken)
if err != nil {
return nil, fmt.Errorf("invalid token for userinfo request: %w", err)
}
resp, err := client.R().
SetContext(ctx).
SetHeader("Accept", "application/json").
SetHeader("Authorization", authorization).
Get(cfg.UserInfoURL)
if err != nil {
return nil, fmt.Errorf("request userinfo: %w", err)
}
if !resp.IsSuccessState() {
return nil, fmt.Errorf("userinfo status=%d", resp.StatusCode)
}
return oidcParseUserInfo(resp.String(), cfg), nil
}
func oidcParseUserInfo(body string, cfg config.OIDCConnectConfig) *oidcUserInfoClaims {
claims := &oidcUserInfoClaims{}
claims.Email = firstNonEmpty(
getGJSON(body, cfg.UserInfoEmailPath),
getGJSON(body, "email"),
getGJSON(body, "user.email"),
getGJSON(body, "data.email"),
getGJSON(body, "attributes.email"),
)
claims.Username = firstNonEmpty(
getGJSON(body, cfg.UserInfoUsernamePath),
getGJSON(body, "preferred_username"),
getGJSON(body, "username"),
getGJSON(body, "name"),
getGJSON(body, "user.username"),
getGJSON(body, "user.name"),
)
claims.Subject = firstNonEmpty(
getGJSON(body, cfg.UserInfoIDPath),
getGJSON(body, "sub"),
getGJSON(body, "id"),
getGJSON(body, "user_id"),
getGJSON(body, "uid"),
getGJSON(body, "user.id"),
)
if verified, ok := getGJSONBool(body, "email_verified"); ok {
claims.EmailVerified = &verified
}
claims.Email = strings.TrimSpace(claims.Email)
claims.Username = strings.TrimSpace(claims.Username)
claims.Subject = strings.TrimSpace(claims.Subject)
return claims
}
func getGJSONBool(body string, path string) (bool, bool) {
path = strings.TrimSpace(path)
if path == "" {
return false, false
}
res := gjson.Get(body, path)
if !res.Exists() {
return false, false
}
return res.Bool(), true
}
func buildOIDCAuthorizeURL(cfg config.OIDCConnectConfig, state, nonce, codeChallenge, redirectURI string) (string, error) {
u, err := url.Parse(cfg.AuthorizeURL)
if err != nil {
return "", fmt.Errorf("parse authorize_url: %w", err)
}
q := u.Query()
q.Set("response_type", "code")
q.Set("client_id", cfg.ClientID)
q.Set("redirect_uri", redirectURI)
if strings.TrimSpace(cfg.Scopes) != "" {
q.Set("scope", cfg.Scopes)
}
q.Set("state", state)
if strings.TrimSpace(nonce) != "" {
q.Set("nonce", nonce)
}
if cfg.UsePKCE {
q.Set("code_challenge", codeChallenge)
q.Set("code_challenge_method", "S256")
}
u.RawQuery = q.Encode()
return u.String(), nil
}
func oidcParseAndValidateIDToken(ctx context.Context, cfg config.OIDCConnectConfig, idToken string, expectedNonce string) (*oidcIDTokenClaims, error) {
idToken = strings.TrimSpace(idToken)
if idToken == "" {
return nil, errors.New("missing id_token")
}
allowed := oidcAllowedSigningAlgs(cfg.AllowedSigningAlgs)
if len(allowed) == 0 {
return nil, errors.New("empty allowed signing algorithms")
}
jwks, err := oidcFetchJWKSet(ctx, cfg.JWKSURL)
if err != nil {
return nil, err
}
leeway := time.Duration(cfg.ClockSkewSeconds) * time.Second
claims := &oidcIDTokenClaims{}
parsed, err := jwt.ParseWithClaims(
idToken,
claims,
func(token *jwt.Token) (any, error) {
alg := strings.TrimSpace(token.Method.Alg())
if !containsString(allowed, alg) {
return nil, fmt.Errorf("unexpected signing algorithm: %s", alg)
}
kid, _ := token.Header["kid"].(string)
return oidcFindPublicKey(jwks, strings.TrimSpace(kid), alg)
},
jwt.WithValidMethods(allowed),
jwt.WithAudience(cfg.ClientID),
jwt.WithIssuer(cfg.IssuerURL),
jwt.WithLeeway(leeway),
)
if err != nil {
return nil, err
}
if !parsed.Valid {
return nil, errors.New("id_token invalid")
}
if strings.TrimSpace(claims.Subject) == "" {
return nil, errors.New("id_token missing sub")
}
if expectedNonce != "" && strings.TrimSpace(claims.Nonce) != strings.TrimSpace(expectedNonce) {
return nil, errors.New("id_token nonce mismatch")
}
if len(claims.Audience) > 1 {
if strings.TrimSpace(claims.Azp) == "" || strings.TrimSpace(claims.Azp) != strings.TrimSpace(cfg.ClientID) {
return nil, errors.New("id_token azp mismatch")
}
}
return claims, nil
}
func oidcAllowedSigningAlgs(raw string) []string {
if strings.TrimSpace(raw) == "" {
return []string{"RS256", "ES256", "PS256"}
}
seen := make(map[string]struct{})
out := make([]string, 0, 4)
for _, part := range strings.Split(raw, ",") {
alg := strings.ToUpper(strings.TrimSpace(part))
if alg == "" {
continue
}
if _, ok := seen[alg]; ok {
continue
}
seen[alg] = struct{}{}
out = append(out, alg)
}
return out
}
func oidcFetchJWKSet(ctx context.Context, jwksURL string) (*oidcJWKSet, error) {
jwksURL = strings.TrimSpace(jwksURL)
if jwksURL == "" {
return nil, errors.New("missing jwks_url")
}
resp, err := req.C().
SetTimeout(30*time.Second).
R().
SetContext(ctx).
SetHeader("Accept", "application/json").
Get(jwksURL)
if err != nil {
return nil, fmt.Errorf("request jwks: %w", err)
}
if !resp.IsSuccessState() {
return nil, fmt.Errorf("jwks status=%d", resp.StatusCode)
}
set := &oidcJWKSet{}
if err := json.Unmarshal(resp.Bytes(), set); err != nil {
return nil, fmt.Errorf("parse jwks: %w", err)
}
if len(set.Keys) == 0 {
return nil, errors.New("jwks empty keys")
}
return set, nil
}
func oidcFindPublicKey(set *oidcJWKSet, kid, alg string) (any, error) {
if set == nil {
return nil, errors.New("jwks not loaded")
}
alg = strings.ToUpper(strings.TrimSpace(alg))
kid = strings.TrimSpace(kid)
var lastErr error
for i := range set.Keys {
k := set.Keys[i]
if strings.TrimSpace(k.Use) != "" && !strings.EqualFold(strings.TrimSpace(k.Use), "sig") {
continue
}
if kid != "" && strings.TrimSpace(k.Kid) != kid {
continue
}
if strings.TrimSpace(k.Alg) != "" && !strings.EqualFold(strings.TrimSpace(k.Alg), alg) {
continue
}
pk, err := k.publicKey()
if err != nil {
lastErr = err
continue
}
if pk != nil {
return pk, nil
}
}
if lastErr != nil {
return nil, lastErr
}
if kid != "" {
return nil, fmt.Errorf("jwk not found for kid=%s", kid)
}
return nil, errors.New("jwk not found")
}
func (k oidcJWK) publicKey() (any, error) {
switch strings.ToUpper(strings.TrimSpace(k.Kty)) {
case "RSA":
n, err := decodeBase64URLBigInt(k.N)
if err != nil {
return nil, fmt.Errorf("decode rsa n: %w", err)
}
eBytes, err := base64.RawURLEncoding.DecodeString(strings.TrimSpace(k.E))
if err != nil {
return nil, fmt.Errorf("decode rsa e: %w", err)
}
if len(eBytes) == 0 {
return nil, errors.New("empty rsa e")
}
e := 0
for _, b := range eBytes {
e = (e << 8) | int(b)
}
if e <= 0 {
return nil, errors.New("invalid rsa exponent")
}
if n.Sign() <= 0 {
return nil, errors.New("invalid rsa modulus")
}
return &rsa.PublicKey{N: n, E: e}, nil
case "EC":
var curve elliptic.Curve
switch strings.TrimSpace(k.Crv) {
case "P-256":
curve = elliptic.P256()
case "P-384":
curve = elliptic.P384()
case "P-521":
curve = elliptic.P521()
default:
return nil, fmt.Errorf("unsupported ec curve: %s", k.Crv)
}
x, err := decodeBase64URLBigInt(k.X)
if err != nil {
return nil, fmt.Errorf("decode ec x: %w", err)
}
y, err := decodeBase64URLBigInt(k.Y)
if err != nil {
return nil, fmt.Errorf("decode ec y: %w", err)
}
if !curve.IsOnCurve(x, y) {
return nil, errors.New("ec point is not on curve")
}
return &ecdsa.PublicKey{Curve: curve, X: x, Y: y}, nil
default:
return nil, fmt.Errorf("unsupported jwk kty: %s", k.Kty)
}
}
func decodeBase64URLBigInt(raw string) (*big.Int, error) {
buf, err := base64.RawURLEncoding.DecodeString(strings.TrimSpace(raw))
if err != nil {
return nil, err
}
if len(buf) == 0 {
return nil, errors.New("empty value")
}
return new(big.Int).SetBytes(buf), nil
}
func containsString(values []string, target string) bool {
target = strings.TrimSpace(target)
for _, v := range values {
if strings.EqualFold(strings.TrimSpace(v), target) {
return true
}
}
return false
}
func oidcIdentityKey(issuer, subject string) string {
issuer = strings.TrimSpace(strings.ToLower(issuer))
subject = strings.TrimSpace(subject)
return issuer + "\x1f" + subject
}
func oidcSyntheticEmailFromIdentityKey(identityKey string) string {
identityKey = strings.TrimSpace(identityKey)
if identityKey == "" {
return ""
}
sum := sha256.Sum256([]byte(identityKey))
return "oidc-" + hex.EncodeToString(sum[:16]) + service.OIDCConnectSyntheticEmailDomain
}
func oidcSelectLoginEmail(userInfoEmail, idTokenEmail, identityKey string) string {
email := strings.TrimSpace(firstNonEmpty(userInfoEmail, idTokenEmail))
if email != "" {
return email
}
return oidcSyntheticEmailFromIdentityKey(identityKey)
}
func oidcFallbackUsername(subject string) string {
subject = strings.TrimSpace(subject)
if subject == "" {
return "oidc_user"
}
sum := sha256.Sum256([]byte(subject))
return "oidc_" + hex.EncodeToString(sum[:])[:12]
}
func oidcSetCookie(c *gin.Context, name, value string, maxAgeSec int, secure bool) {
http.SetCookie(c.Writer, &http.Cookie{
Name: name,
Value: value,
Path: oidcOAuthCookiePath,
MaxAge: maxAgeSec,
HttpOnly: true,
Secure: secure,
SameSite: http.SameSiteLaxMode,
})
}
func oidcClearCookie(c *gin.Context, name string, secure bool) {
http.SetCookie(c.Writer, &http.Cookie{
Name: name,
Value: "",
Path: oidcOAuthCookiePath,
MaxAge: -1,
HttpOnly: true,
Secure: secure,
SameSite: http.SameSiteLaxMode,
})
}

View File

@@ -0,0 +1,120 @@
package handler
import (
"context"
"crypto/rand"
"crypto/rsa"
"encoding/base64"
"encoding/json"
"math/big"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/require"
)
func TestOIDCSyntheticEmailStableAndDistinct(t *testing.T) {
k1 := oidcIdentityKey("https://issuer.example.com", "subject-a")
k2 := oidcIdentityKey("https://issuer.example.com", "subject-b")
e1 := oidcSyntheticEmailFromIdentityKey(k1)
e1Again := oidcSyntheticEmailFromIdentityKey(k1)
e2 := oidcSyntheticEmailFromIdentityKey(k2)
require.Equal(t, e1, e1Again)
require.NotEqual(t, e1, e2)
require.Contains(t, e1, "@oidc-connect.invalid")
}
func TestOIDCSelectLoginEmailPrefersRealEmail(t *testing.T) {
identityKey := oidcIdentityKey("https://issuer.example.com", "subject-a")
email := oidcSelectLoginEmail("user@example.com", "idtoken@example.com", identityKey)
require.Equal(t, "user@example.com", email)
email = oidcSelectLoginEmail("", "idtoken@example.com", identityKey)
require.Equal(t, "idtoken@example.com", email)
email = oidcSelectLoginEmail("", "", identityKey)
require.Contains(t, email, "@oidc-connect.invalid")
require.Equal(t, oidcSyntheticEmailFromIdentityKey(identityKey), email)
}
func TestBuildOIDCAuthorizeURLIncludesNonceAndPKCE(t *testing.T) {
cfg := config.OIDCConnectConfig{
AuthorizeURL: "https://issuer.example.com/auth",
ClientID: "cid",
Scopes: "openid email profile",
UsePKCE: true,
}
u, err := buildOIDCAuthorizeURL(cfg, "state123", "nonce123", "challenge123", "https://app.example.com/callback")
require.NoError(t, err)
require.Contains(t, u, "nonce=nonce123")
require.Contains(t, u, "code_challenge=challenge123")
require.Contains(t, u, "code_challenge_method=S256")
require.Contains(t, u, "scope=openid+email+profile")
}
func TestOIDCParseAndValidateIDToken(t *testing.T) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)
kid := "kid-1"
jwks := oidcJWKSet{Keys: []oidcJWK{buildRSAJWK(kid, &priv.PublicKey)}}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, json.NewEncoder(w).Encode(jwks))
}))
defer srv.Close()
now := time.Now()
claims := oidcIDTokenClaims{
Nonce: "nonce-ok",
Azp: "client-1",
RegisteredClaims: jwt.RegisteredClaims{
Issuer: "https://issuer.example.com",
Subject: "subject-1",
Audience: jwt.ClaimStrings{"client-1", "another-aud"},
IssuedAt: jwt.NewNumericDate(now),
NotBefore: jwt.NewNumericDate(now.Add(-30 * time.Second)),
ExpiresAt: jwt.NewNumericDate(now.Add(5 * time.Minute)),
},
}
tok := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
tok.Header["kid"] = kid
signed, err := tok.SignedString(priv)
require.NoError(t, err)
cfg := config.OIDCConnectConfig{
ClientID: "client-1",
IssuerURL: "https://issuer.example.com",
JWKSURL: srv.URL,
AllowedSigningAlgs: "RS256",
ClockSkewSeconds: 120,
}
parsed, err := oidcParseAndValidateIDToken(context.Background(), cfg, signed, "nonce-ok")
require.NoError(t, err)
require.Equal(t, "subject-1", parsed.Subject)
require.Equal(t, "https://issuer.example.com", parsed.Issuer)
_, err = oidcParseAndValidateIDToken(context.Background(), cfg, signed, "bad-nonce")
require.Error(t, err)
}
func buildRSAJWK(kid string, pub *rsa.PublicKey) oidcJWK {
n := base64.RawURLEncoding.EncodeToString(pub.N.Bytes())
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pub.E)).Bytes())
return oidcJWK{
Kty: "RSA",
Kid: kid,
Use: "sig",
Alg: "RS256",
N: n,
E: e,
}
}

View File

@@ -133,16 +133,17 @@ func GroupFromServiceAdmin(g *service.Group) *AdminGroup {
return nil
}
out := &AdminGroup{
Group: groupFromServiceBase(g),
ModelRouting: g.ModelRouting,
ModelRoutingEnabled: g.ModelRoutingEnabled,
MCPXMLInject: g.MCPXMLInject,
DefaultMappedModel: g.DefaultMappedModel,
SupportedModelScopes: g.SupportedModelScopes,
AccountCount: g.AccountCount,
ActiveAccountCount: g.ActiveAccountCount,
RateLimitedAccountCount: g.RateLimitedAccountCount,
SortOrder: g.SortOrder,
Group: groupFromServiceBase(g),
ModelRouting: g.ModelRouting,
ModelRoutingEnabled: g.ModelRoutingEnabled,
MCPXMLInject: g.MCPXMLInject,
DefaultMappedModel: g.DefaultMappedModel,
MessagesDispatchModelConfig: g.MessagesDispatchModelConfig,
SupportedModelScopes: g.SupportedModelScopes,
AccountCount: g.AccountCount,
ActiveAccountCount: g.ActiveAccountCount,
RateLimitedAccountCount: g.RateLimitedAccountCount,
SortOrder: g.SortOrder,
}
if len(g.AccountGroups) > 0 {
out.AccountGroups = make([]AccountGroup, 0, len(g.AccountGroups))

View File

@@ -51,6 +51,29 @@ type SystemSettings struct {
LinuxDoConnectClientSecretConfigured bool `json:"linuxdo_connect_client_secret_configured"`
LinuxDoConnectRedirectURL string `json:"linuxdo_connect_redirect_url"`
OIDCConnectEnabled bool `json:"oidc_connect_enabled"`
OIDCConnectProviderName string `json:"oidc_connect_provider_name"`
OIDCConnectClientID string `json:"oidc_connect_client_id"`
OIDCConnectClientSecretConfigured bool `json:"oidc_connect_client_secret_configured"`
OIDCConnectIssuerURL string `json:"oidc_connect_issuer_url"`
OIDCConnectDiscoveryURL string `json:"oidc_connect_discovery_url"`
OIDCConnectAuthorizeURL string `json:"oidc_connect_authorize_url"`
OIDCConnectTokenURL string `json:"oidc_connect_token_url"`
OIDCConnectUserInfoURL string `json:"oidc_connect_userinfo_url"`
OIDCConnectJWKSURL string `json:"oidc_connect_jwks_url"`
OIDCConnectScopes string `json:"oidc_connect_scopes"`
OIDCConnectRedirectURL string `json:"oidc_connect_redirect_url"`
OIDCConnectFrontendRedirectURL string `json:"oidc_connect_frontend_redirect_url"`
OIDCConnectTokenAuthMethod string `json:"oidc_connect_token_auth_method"`
OIDCConnectUsePKCE bool `json:"oidc_connect_use_pkce"`
OIDCConnectValidateIDToken bool `json:"oidc_connect_validate_id_token"`
OIDCConnectAllowedSigningAlgs string `json:"oidc_connect_allowed_signing_algs"`
OIDCConnectClockSkewSeconds int `json:"oidc_connect_clock_skew_seconds"`
OIDCConnectRequireEmailVerified bool `json:"oidc_connect_require_email_verified"`
OIDCConnectUserInfoEmailPath string `json:"oidc_connect_userinfo_email_path"`
OIDCConnectUserInfoIDPath string `json:"oidc_connect_userinfo_id_path"`
OIDCConnectUserInfoUsernamePath string `json:"oidc_connect_userinfo_username_path"`
SiteName string `json:"site_name"`
SiteLogo string `json:"site_logo"`
SiteSubtitle string `json:"site_subtitle"`
@@ -61,6 +84,8 @@ type SystemSettings struct {
HideCcsImportButton bool `json:"hide_ccs_import_button"`
PurchaseSubscriptionEnabled bool `json:"purchase_subscription_enabled"`
PurchaseSubscriptionURL string `json:"purchase_subscription_url"`
TableDefaultPageSize int `json:"table_default_page_size"`
TablePageSizeOptions []int `json:"table_page_size_options"`
CustomMenuItems []CustomMenuItem `json:"custom_menu_items"`
CustomEndpoints []CustomEndpoint `json:"custom_endpoints"`
@@ -98,6 +123,28 @@ type SystemSettings struct {
EnableFingerprintUnification bool `json:"enable_fingerprint_unification"`
EnableMetadataPassthrough bool `json:"enable_metadata_passthrough"`
EnableCCHSigning bool `json:"enable_cch_signing"`
// Payment configuration
PaymentEnabled bool `json:"payment_enabled"`
PaymentMinAmount float64 `json:"payment_min_amount"`
PaymentMaxAmount float64 `json:"payment_max_amount"`
PaymentDailyLimit float64 `json:"payment_daily_limit"`
PaymentOrderTimeoutMin int `json:"payment_order_timeout_minutes"`
PaymentMaxPendingOrders int `json:"payment_max_pending_orders"`
PaymentEnabledTypes []string `json:"payment_enabled_types"`
PaymentBalanceDisabled bool `json:"payment_balance_disabled"`
PaymentLoadBalanceStrat string `json:"payment_load_balance_strategy"`
PaymentProductNamePrefix string `json:"payment_product_name_prefix"`
PaymentProductNameSuffix string `json:"payment_product_name_suffix"`
PaymentHelpImageURL string `json:"payment_help_image_url"`
PaymentHelpText string `json:"payment_help_text"`
// Cancel rate limit
PaymentCancelRateLimitEnabled bool `json:"payment_cancel_rate_limit_enabled"`
PaymentCancelRateLimitMax int `json:"payment_cancel_rate_limit_max"`
PaymentCancelRateLimitWindow int `json:"payment_cancel_rate_limit_window"`
PaymentCancelRateLimitUnit string `json:"payment_cancel_rate_limit_unit"`
PaymentCancelRateLimitMode string `json:"payment_cancel_rate_limit_window_mode"`
}
type DefaultSubscriptionSetting struct {
@@ -125,10 +172,16 @@ type PublicSettings struct {
HideCcsImportButton bool `json:"hide_ccs_import_button"`
PurchaseSubscriptionEnabled bool `json:"purchase_subscription_enabled"`
PurchaseSubscriptionURL string `json:"purchase_subscription_url"`
TableDefaultPageSize int `json:"table_default_page_size"`
TablePageSizeOptions []int `json:"table_page_size_options"`
CustomMenuItems []CustomMenuItem `json:"custom_menu_items"`
CustomEndpoints []CustomEndpoint `json:"custom_endpoints"`
LinuxDoOAuthEnabled bool `json:"linuxdo_oauth_enabled"`
OIDCOAuthEnabled bool `json:"oidc_oauth_enabled"`
OIDCOAuthProviderName string `json:"oidc_oauth_provider_name"`
SoraClientEnabled bool `json:"sora_client_enabled"`
BackendModeEnabled bool `json:"backend_mode_enabled"`
PaymentEnabled bool `json:"payment_enabled"`
Version string `json:"version"`
}

View File

@@ -1,6 +1,10 @@
package dto
import "time"
import (
"time"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
type User struct {
ID int64 `json:"id"`
@@ -112,7 +116,8 @@ type AdminGroup struct {
MCPXMLInject bool `json:"mcp_xml_inject"`
// OpenAI Messages 调度配置(仅 openai 平台使用)
DefaultMappedModel string `json:"default_mapped_model"`
DefaultMappedModel string `json:"default_mapped_model"`
MessagesDispatchModelConfig domain.OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config"`
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes []string `json:"supported_model_scopes"`

View File

@@ -34,7 +34,12 @@ func (f *fakeSchedulerCache) GetSnapshot(_ context.Context, _ service.SchedulerB
func (f *fakeSchedulerCache) SetSnapshot(_ context.Context, _ service.SchedulerBucket, _ []service.Account) error {
return nil
}
func (f *fakeSchedulerCache) GetAccount(_ context.Context, _ int64) (*service.Account, error) {
func (f *fakeSchedulerCache) GetAccount(_ context.Context, id int64) (*service.Account, error) {
for _, account := range f.accounts {
if account != nil && account.ID == id {
return account, nil
}
}
return nil, nil
}
func (f *fakeSchedulerCache) SetAccount(_ context.Context, _ *service.Account) error { return nil }

View File

@@ -31,22 +31,25 @@ type AdminHandlers struct {
APIKey *admin.AdminAPIKeyHandler
ScheduledTest *admin.ScheduledTestHandler
Channel *admin.ChannelHandler
Payment *admin.PaymentHandler
}
// Handlers contains all HTTP handlers
type Handlers struct {
Auth *AuthHandler
User *UserHandler
APIKey *APIKeyHandler
Usage *UsageHandler
Redeem *RedeemHandler
Subscription *SubscriptionHandler
Announcement *AnnouncementHandler
Admin *AdminHandlers
Gateway *GatewayHandler
OpenAIGateway *OpenAIGatewayHandler
Setting *SettingHandler
Totp *TotpHandler
Auth *AuthHandler
User *UserHandler
APIKey *APIKeyHandler
Usage *UsageHandler
Redeem *RedeemHandler
Subscription *SubscriptionHandler
Announcement *AnnouncementHandler
Admin *AdminHandlers
Gateway *GatewayHandler
OpenAIGateway *OpenAIGatewayHandler
Setting *SettingHandler
Totp *TotpHandler
Payment *PaymentHandler
PaymentWebhook *PaymentWebhookHandler
}
// BuildInfo contains build-time information

View File

@@ -47,6 +47,13 @@ func resolveOpenAIForwardDefaultMappedModel(apiKey *service.APIKey, fallbackMode
return strings.TrimSpace(apiKey.Group.DefaultMappedModel)
}
func resolveOpenAIMessagesDispatchMappedModel(apiKey *service.APIKey, requestedModel string) string {
if apiKey == nil || apiKey.Group == nil {
return ""
}
return strings.TrimSpace(apiKey.Group.ResolveMessagesDispatchModel(requestedModel))
}
// NewOpenAIGatewayHandler creates a new OpenAIGatewayHandler
func NewOpenAIGatewayHandler(
gatewayService *service.OpenAIGatewayService,
@@ -551,6 +558,7 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
}
reqModel := modelResult.String()
routingModel := service.NormalizeOpenAICompatRequestedModel(reqModel)
preferredMappedModel := resolveOpenAIMessagesDispatchMappedModel(apiKey, reqModel)
reqStream := gjson.GetBytes(body, "stream").Bool()
reqLog = reqLog.With(zap.String("model", reqModel), zap.Bool("stream", reqStream))
@@ -609,17 +617,20 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
failedAccountIDs := make(map[int64]struct{})
sameAccountRetryCount := make(map[int64]int)
var lastFailoverErr *service.UpstreamFailoverError
effectiveMappedModel := preferredMappedModel
for {
// 清除上一次迭代的降级模型标记,避免残留影响本次迭代
c.Set("openai_messages_fallback_model", "")
currentRoutingModel := routingModel
if effectiveMappedModel != "" {
currentRoutingModel = effectiveMappedModel
}
reqLog.Debug("openai_messages.account_selecting", zap.Int("excluded_account_count", len(failedAccountIDs)))
selection, scheduleDecision, err := h.gatewayService.SelectAccountWithScheduler(
c.Request.Context(),
apiKey.GroupID,
"", // no previous_response_id
sessionHash,
routingModel,
currentRoutingModel,
failedAccountIDs,
service.OpenAIUpstreamTransportAny,
)
@@ -628,29 +639,7 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
zap.Error(err),
zap.Int("excluded_account_count", len(failedAccountIDs)),
)
// 首次调度失败 + 有默认映射模型 → 用默认模型重试
if len(failedAccountIDs) == 0 {
defaultModel := ""
if apiKey.Group != nil {
defaultModel = apiKey.Group.DefaultMappedModel
}
if defaultModel != "" && defaultModel != routingModel {
reqLog.Info("openai_messages.fallback_to_default_model",
zap.String("default_mapped_model", defaultModel),
)
selection, scheduleDecision, err = h.gatewayService.SelectAccountWithScheduler(
c.Request.Context(),
apiKey.GroupID,
"",
sessionHash,
defaultModel,
failedAccountIDs,
service.OpenAIUpstreamTransportAny,
)
if err == nil && selection != nil {
c.Set("openai_messages_fallback_model", defaultModel)
}
}
if err != nil {
h.anthropicStreamingAwareError(c, http.StatusServiceUnavailable, "api_error", "Service temporarily unavailable", streamStarted)
return
@@ -682,9 +671,7 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
service.SetOpsLatencyMs(c, service.OpsRoutingLatencyMsKey, time.Since(routingStart).Milliseconds())
forwardStart := time.Now()
// Forward 层需要始终拿到 group 默认映射模型,这样未命中账号级映射的
// Claude 兼容模型才不会在后续 Codex 规范化中意外退化到 gpt-5.1。
defaultMappedModel := resolveOpenAIForwardDefaultMappedModel(apiKey, c.GetString("openai_messages_fallback_model"))
defaultMappedModel := strings.TrimSpace(effectiveMappedModel)
// 应用渠道模型映射到请求体
forwardBody := body
if channelMappingMsg.Mapped {

View File

@@ -360,7 +360,7 @@ func TestResolveOpenAIForwardDefaultMappedModel(t *testing.T) {
require.Equal(t, "gpt-5.2", resolveOpenAIForwardDefaultMappedModel(apiKey, " gpt-5.2 "))
})
t.Run("uses_group_default_on_normal_path", func(t *testing.T) {
t.Run("uses_group_default_when_explicit_fallback_absent", func(t *testing.T) {
apiKey := &service.APIKey{
Group: &service.Group{DefaultMappedModel: "gpt-5.4"},
}
@@ -376,6 +376,45 @@ func TestResolveOpenAIForwardDefaultMappedModel(t *testing.T) {
})
}
func TestResolveOpenAIMessagesDispatchMappedModel(t *testing.T) {
t.Run("exact_claude_model_override_wins", func(t *testing.T) {
apiKey := &service.APIKey{
Group: &service.Group{
MessagesDispatchModelConfig: service.OpenAIMessagesDispatchModelConfig{
SonnetMappedModel: "gpt-5.2",
ExactModelMappings: map[string]string{
"claude-sonnet-4-5-20250929": "gpt-5.4-mini-high",
},
},
},
}
require.Equal(t, "gpt-5.4-mini", resolveOpenAIMessagesDispatchMappedModel(apiKey, "claude-sonnet-4-5-20250929"))
})
t.Run("uses_family_default_when_no_override", func(t *testing.T) {
apiKey := &service.APIKey{Group: &service.Group{}}
require.Equal(t, "gpt-5.4", resolveOpenAIMessagesDispatchMappedModel(apiKey, "claude-opus-4-6"))
require.Equal(t, "gpt-5.3-codex", resolveOpenAIMessagesDispatchMappedModel(apiKey, "claude-sonnet-4-5-20250929"))
require.Equal(t, "gpt-5.4-mini", resolveOpenAIMessagesDispatchMappedModel(apiKey, "claude-haiku-4-5-20251001"))
})
t.Run("returns_empty_for_non_claude_or_missing_group", func(t *testing.T) {
require.Empty(t, resolveOpenAIMessagesDispatchMappedModel(nil, "claude-sonnet-4-5-20250929"))
require.Empty(t, resolveOpenAIMessagesDispatchMappedModel(&service.APIKey{}, "claude-sonnet-4-5-20250929"))
require.Empty(t, resolveOpenAIMessagesDispatchMappedModel(&service.APIKey{Group: &service.Group{}}, "gpt-5.4"))
})
t.Run("does_not_fall_back_to_group_default_mapped_model", func(t *testing.T) {
apiKey := &service.APIKey{
Group: &service.Group{
DefaultMappedModel: "gpt-5.4",
},
}
require.Empty(t, resolveOpenAIMessagesDispatchMappedModel(apiKey, "gpt-5.4"))
require.Equal(t, "gpt-5.3-codex", resolveOpenAIMessagesDispatchMappedModel(apiKey, "claude-sonnet-4-5-20250929"))
})
}
func TestOpenAIResponses_MissingDependencies_ReturnsServiceUnavailable(t *testing.T) {
gin.SetMode(gin.TestMode)

Some files were not shown because too many files have changed in this diff Show More