zijizhang-cli 0.0.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. zijizhang_cli-0.0.11/PKG-INFO +141 -0
  2. zijizhang_cli-0.0.11/README.md +118 -0
  3. zijizhang_cli-0.0.11/app/__init__.py +0 -0
  4. zijizhang_cli-0.0.11/app/api/__init__.py +0 -0
  5. zijizhang_cli-0.0.11/app/api/zjz_api.py +267 -0
  6. zijizhang_cli-0.0.11/app/api/zjz_req.py +22 -0
  7. zijizhang_cli-0.0.11/app/module/__init__.py +0 -0
  8. zijizhang_cli-0.0.11/app/module/account.py +59 -0
  9. zijizhang_cli-0.0.11/app/module/bank.py +141 -0
  10. zijizhang_cli-0.0.11/app/module/employee.py +60 -0
  11. zijizhang_cli-0.0.11/app/module/invoice.py +156 -0
  12. zijizhang_cli-0.0.11/app/module/payroll.py +91 -0
  13. zijizhang_cli-0.0.11/app/module/todo.py +54 -0
  14. zijizhang_cli-0.0.11/app/service/__init__.py +0 -0
  15. zijizhang_cli-0.0.11/app/service/account_service.py +103 -0
  16. zijizhang_cli-0.0.11/app/service/bank_service.py +318 -0
  17. zijizhang_cli-0.0.11/app/service/config_manager.py +92 -0
  18. zijizhang_cli-0.0.11/app/service/employee_service.py +63 -0
  19. zijizhang_cli-0.0.11/app/service/invoice_service.py +303 -0
  20. zijizhang_cli-0.0.11/app/service/payroll_service.py +56 -0
  21. zijizhang_cli-0.0.11/app/service/todo_service.py +85 -0
  22. zijizhang_cli-0.0.11/app/util/__init__.py +0 -0
  23. zijizhang_cli-0.0.11/app/util/echo_util.py +9 -0
  24. zijizhang_cli-0.0.11/app/util/http_client.py +80 -0
  25. zijizhang_cli-0.0.11/main.py +45 -0
  26. zijizhang_cli-0.0.11/pyproject.toml +24 -0
  27. zijizhang_cli-0.0.11/requirements.txt +16 -0
  28. zijizhang_cli-0.0.11/setup.cfg +4 -0
  29. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/PKG-INFO +141 -0
  30. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/SOURCES.txt +32 -0
  31. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/dependency_links.txt +1 -0
  32. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/entry_points.txt +2 -0
  33. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/requires.txt +16 -0
  34. zijizhang_cli-0.0.11/zijizhang_cli.egg-info/top_level.txt +2 -0
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: zijizhang-cli
3
+ Version: 0.0.11
4
+ Summary: Cli tool for zijizhang
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: annotated-doc==0.0.4
8
+ Requires-Dist: anyio==4.12.1
9
+ Requires-Dist: certifi==2026.2.25
10
+ Requires-Dist: click==8.1.8
11
+ Requires-Dist: exceptiongroup==1.3.1
12
+ Requires-Dist: h11==0.16.0
13
+ Requires-Dist: httpcore==1.0.9
14
+ Requires-Dist: httpx==0.28.1
15
+ Requires-Dist: idna==3.11
16
+ Requires-Dist: markdown-it-py==3.0.0
17
+ Requires-Dist: mdurl==0.1.2
18
+ Requires-Dist: Pygments==2.20.0
19
+ Requires-Dist: rich==14.3.3
20
+ Requires-Dist: shellingham==1.5.4
21
+ Requires-Dist: typer==0.23.2
22
+ Requires-Dist: typing_extensions==4.15.0
23
+
24
+ # zjz-cli
25
+
26
+ Cli tool for zjz
27
+
28
+ ## Requirements
29
+
30
+ - Python 3 or higher – [Download Python](https://www.python.org/downloads/)
31
+
32
+ ## Installation
33
+
34
+ It is **strongly recommended** to install this tool inside a Python virtual environment to avoid dependency conflicts with other Python projects on your system.
35
+
36
+ You can choose **one** of the following installation methods:
37
+
38
+ - Use Python's built-in `venv`
39
+ - Use `uv`
40
+
41
+ You only need to follow one method, not both.
42
+
43
+ ### Option 1: Install with `venv`
44
+
45
+ #### Step 1: Create a virtual environment
46
+
47
+ Open your terminal and choose a location for the environment. A common practice is to place it in your home directory as a hidden folder (e.g., `~/.my-cli-tool-env`). Run:
48
+
49
+ ```shell
50
+ python3 -m venv ~/.my-cli-tool-env
51
+ ```
52
+
53
+ #### Step 2: Activate the virtual environment
54
+
55
+ - Linux / macOS:
56
+
57
+ ```shell
58
+ source ~/.my-cli-tool-env/bin/activate
59
+ ```
60
+
61
+ - Windows (Command Prompt):
62
+
63
+ ```bash
64
+ .my-cli-tool-env\Scripts\activate.bat
65
+ ```
66
+
67
+ - Windows (PowerShell):
68
+
69
+ ```bash
70
+ .my-cli-tool-env\Scripts\Activate.ps1
71
+ ```
72
+
73
+ You will see (`.my-cli-tool-env`) appear at the beginning of your command prompt, indicating the virtual environment is active.
74
+
75
+ #### Step 3: Install the tool
76
+
77
+ With the virtual environment activated, install the package from PyPI:
78
+
79
+ ```shell
80
+ pip install --upgrade zjz-cli
81
+ ```
82
+
83
+ That's it! The CLI command `zjz-cli` is now available inside this virtual environment.
84
+
85
+ ### Option 2: Install with `uv`
86
+
87
+ If you prefer using `uv`, you can create and manage the virtual environment with it instead.
88
+
89
+ #### Step 1: Install `uv`
90
+
91
+ Follow the official guide to install `uv`:
92
+
93
+ [Install uv](https://docs.astral.sh/uv/getting-started/installation/)
94
+
95
+ #### Step 2: Create a virtual environment
96
+
97
+ ```shell
98
+ uv venv ~/.my-cli-tool-env
99
+ ```
100
+
101
+ #### Step 3: Activate the virtual environment
102
+
103
+ - Linux / macOS:
104
+
105
+ ```shell
106
+ source ~/.my-cli-tool-env/bin/activate
107
+ ```
108
+
109
+ - Windows (Command Prompt):
110
+
111
+ ```bash
112
+ .my-cli-tool-env\Scripts\activate.bat
113
+ ```
114
+
115
+ - Windows (PowerShell):
116
+
117
+ ```bash
118
+ .my-cli-tool-env\Scripts\Activate.ps1
119
+ ```
120
+
121
+ #### Step 4: Install the tool
122
+
123
+ With the virtual environment activated, install the package with `uv`:
124
+
125
+ ```shell
126
+ uv pip install --upgrade zjz-cli
127
+ ```
128
+
129
+ That's it! The CLI command `zjz-cli` is now available inside this virtual environment.
130
+
131
+ ### Usage
132
+
133
+ Once the virtual environment is activated, you can run the tool:
134
+
135
+ ```shell
136
+ zjz-cli --help
137
+ ```
138
+
139
+ ## Why a virtual environment?
140
+
141
+ Using a virtual environment prevents version clashes between Python packages required by this tool and other Python applications on your system. It also keeps your global Python installation clean. For more background, see [Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/).
@@ -0,0 +1,118 @@
1
+ # zjz-cli
2
+
3
+ Cli tool for zjz
4
+
5
+ ## Requirements
6
+
7
+ - Python 3 or higher – [Download Python](https://www.python.org/downloads/)
8
+
9
+ ## Installation
10
+
11
+ It is **strongly recommended** to install this tool inside a Python virtual environment to avoid dependency conflicts with other Python projects on your system.
12
+
13
+ You can choose **one** of the following installation methods:
14
+
15
+ - Use Python's built-in `venv`
16
+ - Use `uv`
17
+
18
+ You only need to follow one method, not both.
19
+
20
+ ### Option 1: Install with `venv`
21
+
22
+ #### Step 1: Create a virtual environment
23
+
24
+ Open your terminal and choose a location for the environment. A common practice is to place it in your home directory as a hidden folder (e.g., `~/.my-cli-tool-env`). Run:
25
+
26
+ ```shell
27
+ python3 -m venv ~/.my-cli-tool-env
28
+ ```
29
+
30
+ #### Step 2: Activate the virtual environment
31
+
32
+ - Linux / macOS:
33
+
34
+ ```shell
35
+ source ~/.my-cli-tool-env/bin/activate
36
+ ```
37
+
38
+ - Windows (Command Prompt):
39
+
40
+ ```bash
41
+ .my-cli-tool-env\Scripts\activate.bat
42
+ ```
43
+
44
+ - Windows (PowerShell):
45
+
46
+ ```bash
47
+ .my-cli-tool-env\Scripts\Activate.ps1
48
+ ```
49
+
50
+ You will see (`.my-cli-tool-env`) appear at the beginning of your command prompt, indicating the virtual environment is active.
51
+
52
+ #### Step 3: Install the tool
53
+
54
+ With the virtual environment activated, install the package from PyPI:
55
+
56
+ ```shell
57
+ pip install --upgrade zjz-cli
58
+ ```
59
+
60
+ That's it! The CLI command `zjz-cli` is now available inside this virtual environment.
61
+
62
+ ### Option 2: Install with `uv`
63
+
64
+ If you prefer using `uv`, you can create and manage the virtual environment with it instead.
65
+
66
+ #### Step 1: Install `uv`
67
+
68
+ Follow the official guide to install `uv`:
69
+
70
+ [Install uv](https://docs.astral.sh/uv/getting-started/installation/)
71
+
72
+ #### Step 2: Create a virtual environment
73
+
74
+ ```shell
75
+ uv venv ~/.my-cli-tool-env
76
+ ```
77
+
78
+ #### Step 3: Activate the virtual environment
79
+
80
+ - Linux / macOS:
81
+
82
+ ```shell
83
+ source ~/.my-cli-tool-env/bin/activate
84
+ ```
85
+
86
+ - Windows (Command Prompt):
87
+
88
+ ```bash
89
+ .my-cli-tool-env\Scripts\activate.bat
90
+ ```
91
+
92
+ - Windows (PowerShell):
93
+
94
+ ```bash
95
+ .my-cli-tool-env\Scripts\Activate.ps1
96
+ ```
97
+
98
+ #### Step 4: Install the tool
99
+
100
+ With the virtual environment activated, install the package with `uv`:
101
+
102
+ ```shell
103
+ uv pip install --upgrade zjz-cli
104
+ ```
105
+
106
+ That's it! The CLI command `zjz-cli` is now available inside this virtual environment.
107
+
108
+ ### Usage
109
+
110
+ Once the virtual environment is activated, you can run the tool:
111
+
112
+ ```shell
113
+ zjz-cli --help
114
+ ```
115
+
116
+ ## Why a virtual environment?
117
+
118
+ Using a virtual environment prevents version clashes between Python packages required by this tool and other Python applications on your system. It also keeps your global Python installation clean. For more background, see [Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/).
File without changes
File without changes
@@ -0,0 +1,267 @@
1
+ from app.api.zjz_req import zjz_req
2
+ from pathlib import Path
3
+
4
+
5
+ def sms_verify_code(phone: str) -> dict:
6
+ return zjz_req.get_client().post_json('login/sms', {
7
+ 'phone': phone,
8
+ })
9
+
10
+
11
+ def verify_sms_code(phone: str, code: str) -> dict:
12
+ return zjz_req.get_client().post_json('login/sms-2-token', {
13
+ 'phone': phone,
14
+ 'sms': code,
15
+ })
16
+
17
+
18
+ def get_employee_list(uid: str = None, keyword: str = '', page: int = 1) -> dict:
19
+ if not page or page < 1:
20
+ page = 1
21
+ return zjz_req.get_client().get('ryxx', params={
22
+ 'uid': uid,
23
+ 'keyword': keyword,
24
+ 'page': page
25
+ })
26
+
27
+
28
+ def add_employee(uid: str, data: dict) -> dict:
29
+ data['uid'] = uid
30
+ return zjz_req.get_client().post_json('ryxx', data)
31
+
32
+
33
+ def update_employee(employee_id: str, data: dict) -> dict:
34
+ return zjz_req.get_client().put('ryxx', {
35
+ 'id': employee_id,
36
+ 'data': data,
37
+ })
38
+
39
+
40
+ def get_payroll(uid: str, year: int, month: int) -> dict:
41
+ month_str = f"{year}-{month:02d}"
42
+ return zjz_req.get_client().get('payroll', params={
43
+ 'uid': uid,
44
+ 'month': month_str
45
+ })
46
+
47
+
48
+ def get_payroll_creation_status(uid: str, year: int, month: int) -> dict:
49
+ month_str = f"{year}-{month:02d}"
50
+ return zjz_req.get_client().get('payroll/creation-status', params={
51
+ 'uid': uid,
52
+ 'month': month_str
53
+ })
54
+
55
+
56
+ def get_preview_payroll(uid: str, year: int, month: int) -> dict:
57
+ month_str = f"{year}-{month:02d}"
58
+ return zjz_req.get_client().get('payroll/preview', params={
59
+ 'uid': uid,
60
+ 'month': month_str
61
+ })
62
+
63
+
64
+ def create_payroll(uid: str, year: int, month: int, data: list) -> dict:
65
+ month_str = f"{year}-{month:02d}"
66
+ return zjz_req.get_client().post_json('payroll', {
67
+ 'uid': uid,
68
+ 'month': month_str,
69
+ 'data': data
70
+ })
71
+
72
+
73
+ def get_sales_invoice_data_list(uid: str, current: int = 1, invoice_number: str = '', invoice_date_begin: str = '', invoice_date_end: str = '', status: str = '') -> dict:
74
+ return zjz_req.get_client().get('invoice/sales_invoice_data_list', params={
75
+ 'uid': uid,
76
+ 'current': current,
77
+ 'invoice_number': invoice_number,
78
+ 'invoice_date_begin': invoice_date_begin,
79
+ 'invoice_date_end': invoice_date_end,
80
+ 'status': status,
81
+ })
82
+
83
+
84
+ def set_month_no_sales_invoice(uid: str, year: int, month: int) -> dict:
85
+ return zjz_req.get_client().post_json('invoice/set_month_no_sales_invoice', {
86
+ 'uid': uid,
87
+ 'year': year,
88
+ 'month': month,
89
+ })
90
+
91
+
92
+ def get_income_invoice_data_list(uid: str, current: int = 1, invoice_number: str = '', invoice_date_begin: str = '', invoice_date_end: str = '', status: str = '') -> dict:
93
+ return zjz_req.get_client().get('invoice/income_invoice_data_list', params={
94
+ 'uid': uid,
95
+ 'current': current,
96
+ 'invoice_number': invoice_number,
97
+ 'invoice_date_begin': invoice_date_begin,
98
+ 'invoice_date_end': invoice_date_end,
99
+ 'status': status,
100
+ })
101
+
102
+
103
+ def set_month_no_invoice(uid: str, year: int, month: int) -> dict:
104
+ return zjz_req.get_client().post_json('invoice/set_month_no_invoice', {
105
+ 'uid': uid,
106
+ 'year': year,
107
+ 'month': month,
108
+ })
109
+
110
+
111
+ def invoice_can_choose_use_list(uid: str, goods_name: str, total_tax_price: str, total_money: str) -> dict:
112
+ return zjz_req.get_client().get('invoice/invoice_can_choose_use_list', params={
113
+ 'uid': uid,
114
+ 'goods_name': goods_name,
115
+ 'total_tax_price': total_tax_price,
116
+ 'total_money': total_money,
117
+ })
118
+
119
+
120
+ def invoice_choose_use(uid: str, invoice_id: int, category: str, is_pay: str, payee: str) -> dict:
121
+ return zjz_req.get_client().post_json('invoice/invoice_choose_use', {
122
+ 'uid': uid,
123
+ 'invoice_id': invoice_id,
124
+ 'category': category,
125
+ 'is_pay': is_pay,
126
+ 'payee': payee,
127
+ })
128
+
129
+
130
+ def upload_invoice_file(uid: str, file_path: str) -> dict:
131
+ p = Path(file_path)
132
+ suffix = p.suffix.lower()
133
+ content_type = 'application/octet-stream'
134
+ if suffix == '.pdf':
135
+ content_type = 'application/pdf'
136
+ elif suffix == '.ofd':
137
+ content_type = 'application/ofd'
138
+
139
+ with p.open('rb') as f:
140
+ return zjz_req.get_client().post_file('invoice/upload_invoice_file', files={
141
+ 'file': (p.name, f, content_type),
142
+ }, data={
143
+ 'uid': uid,
144
+ })
145
+
146
+
147
+ def invoice_file_list(uid: str, current: int = 1) -> dict:
148
+ if not current or current < 1:
149
+ current = 1
150
+ params = {
151
+ 'current': current,
152
+ 'uid': uid,
153
+ }
154
+ return zjz_req.get_client().get('invoice/invoice_file_list', params=params)
155
+
156
+
157
+ def get_todo_list(uid: str) -> dict:
158
+ params = {
159
+ 'uid': uid,
160
+ }
161
+ return zjz_req.get_client().get('todo-list', params=params)
162
+
163
+
164
+ def before_set_month_audited(year: int, month: int, uid: str) -> dict:
165
+ params = {
166
+ 'year': year,
167
+ 'month': month,
168
+ 'uid': uid,
169
+ }
170
+ return zjz_req.get_client().get('audit/before_set_month_audited', params=params)
171
+
172
+
173
+ def set_month_audited(year: int, month: int, uid: str) -> dict:
174
+ payload = {
175
+ 'year': year,
176
+ 'month': month,
177
+ 'uid': uid,
178
+ }
179
+ return zjz_req.get_client().post_json('audit/set_month_audited', payload)
180
+
181
+
182
+ def get_bank_bill_data_list(uid: str, current: int = 1, date_begin: str = '', date_end: str = '') -> dict:
183
+ params = {
184
+ 'current': current,
185
+ 'date_begin': date_begin,
186
+ 'date_end': date_end,
187
+ 'uid': uid,
188
+ }
189
+ return zjz_req.get_client().get('bank/bill_data_list', params=params)
190
+
191
+
192
+ def choose_bank_use(uid: str, bill_id: int, rule_text: str) -> dict:
193
+ payload = {
194
+ 'id': bill_id,
195
+ 'rule_text': rule_text,
196
+ 'uid': uid,
197
+ }
198
+ return zjz_req.get_client().post_json('bank/bank_bill_choose_use', payload)
199
+
200
+
201
+ def set_month_bank_no_water(uid: str, year: int, month: int) -> dict:
202
+ payload = {
203
+ 'year': year,
204
+ 'month': month,
205
+ 'uid': uid,
206
+ }
207
+ return zjz_req.get_client().post_json('bank/set_month_no_water', payload)
208
+
209
+
210
+ def support_bank_list() -> dict:
211
+ return zjz_req.get_client().get('bank/support_bank_list')
212
+
213
+
214
+ def bank_account_number_list(uid: str) -> dict:
215
+ params = {
216
+ 'uid': uid,
217
+ }
218
+ return zjz_req.get_client().get('bank/bank_account_number_list', params=params)
219
+
220
+
221
+ def add_bank_account_number(uid: str, bank_id: int, bank_number: str) -> dict:
222
+ payload = {
223
+ 'bank_id': bank_id,
224
+ 'bank_number': bank_number,
225
+ 'uid': uid,
226
+ }
227
+ return zjz_req.get_client().post_json('bank/add_bank_account_number', payload)
228
+
229
+
230
+ def del_bank_account_number(uid: str, bank_id: int, bank_number: str) -> dict:
231
+ payload = {
232
+ 'bank_id': bank_id,
233
+ 'bank_number': bank_number,
234
+ 'uid': uid,
235
+ }
236
+ return zjz_req.get_client().post_json('bank/del_bank_account_number', payload)
237
+
238
+
239
+ def bank_file_list(uid: str, current: int = 1) -> dict:
240
+ if not current or current < 1:
241
+ current = 1
242
+ params = {
243
+ 'current': current,
244
+ 'uid': uid,
245
+ }
246
+ return zjz_req.get_client().get('bank/bank_file_list', params=params)
247
+
248
+
249
+ def upload_bank_file(uid: str, file_path: str, file_type: str, bank_account_number_id: int, billing_cycle: str) -> dict:
250
+ p = Path(file_path)
251
+ suffix = p.suffix.lower()
252
+ content_type = 'application/octet-stream'
253
+ if suffix == '.pdf':
254
+ content_type = 'application/pdf'
255
+ elif suffix == '.xls':
256
+ content_type = 'application/vnd.ms-excel'
257
+ elif suffix == '.xlsx':
258
+ content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
259
+ with p.open('rb') as f:
260
+ return zjz_req.get_client().post_file('bank/upload_bank_file', files={
261
+ 'file': (p.name, f, content_type),
262
+ }, data={
263
+ 'uid': uid,
264
+ 'file_type': file_type,
265
+ 'bank_account_number_id': str(bank_account_number_id),
266
+ 'billing_cycle': billing_cycle,
267
+ })
@@ -0,0 +1,22 @@
1
+ from app.service.config_manager import cfg_mgr
2
+ from app.util.http_client import HttpClient
3
+
4
+
5
+ class ZjzReq:
6
+ def __init__(self):
7
+ self.headers = {}
8
+ self.base_url: str = "https://www.zijizhang.com/ai/skill"
9
+ self.client = None
10
+
11
+ def get_client(self):
12
+ auth_token = self.headers.get('Authorization')
13
+ if not auth_token:
14
+ token = cfg_mgr.get_config('token')
15
+ if token:
16
+ self.headers['Authorization'] = f'Bearer {token}'
17
+ self.client = None
18
+ if not self.client:
19
+ self.client = HttpClient(base_url=self.base_url, headers=self.headers)
20
+ return self.client
21
+
22
+ zjz_req = ZjzReq()
File without changes
@@ -0,0 +1,59 @@
1
+ import typer
2
+
3
+ from app.service.account_service import AccountService
4
+ from app.util import echo_util
5
+
6
+ account_app = typer.Typer()
7
+
8
+
9
+ @account_app.command(
10
+ name='get_sms_verify_code',
11
+ help='获取登录的短信验证码',
12
+ no_args_is_help=True,
13
+ epilog="""使用示例
14
+
15
+ zijizhang-cli account get_sms_verify_code 17199999999""")
16
+ def get_sms_verify_code(phone: str = typer.Argument(..., help='自记账的登录手机号')):
17
+ service = AccountService()
18
+ res = service.sms_verify_code(phone)
19
+ echo_util.echo_http_res(res)
20
+
21
+
22
+ @account_app.command(
23
+ name='verify_sms_code',
24
+ help='通过短信验证码登录',
25
+ no_args_is_help=True,
26
+ epilog="""使用示例
27
+
28
+ zijizhang-cli account verify_sms_code 17199999999 5799""")
29
+ def verify_sms_code(
30
+ phone: str = typer.Argument(..., help='手机号'),
31
+ code: str = typer.Argument(..., help='短信验证码')):
32
+ service = AccountService()
33
+ res = service.sms_code_login(phone, code)
34
+ echo_util.echo_http_res(res)
35
+
36
+
37
+ @account_app.command(
38
+ name='get_switchable_users',
39
+ help='获取可切换的公司列表',
40
+ epilog="""使用示例
41
+
42
+ zijizhang-cli account get_switchable_users""")
43
+ def get_switchable_users():
44
+ service = AccountService()
45
+ res = service.get_switchable_user()
46
+ echo_util.echo_http_res(res)
47
+
48
+
49
+ @account_app.command(
50
+ name='switch_to',
51
+ help='切换公司',
52
+ no_args_is_help=True,
53
+ epilog="""使用示例
54
+
55
+ zijizhang-cli account switch_to 123451c07f47435e12a34111""")
56
+ def switch_to(uid: str = typer.Argument(..., help='公司唯一标识uid')):
57
+ service = AccountService()
58
+ res = service.switch_to(uid)
59
+ echo_util.echo_http_res(res)