zjz-cli 0.0.1__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.
zjz_cli-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: zjz_cli
3
+ Version: 0.0.1
4
+ Summary: 自记账的工具箱
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: annotated-doc>=0.0.4
8
+ Requires-Dist: anyio>=4.0.0
9
+ Requires-Dist: certifi>=2024.2.25
10
+ Requires-Dist: click>=8.3.1
11
+ Requires-Dist: h11>=0.16.0
12
+ Requires-Dist: httpcore>=1.0.9
13
+ Requires-Dist: httpx>=0.28.1
14
+ Requires-Dist: idna>=3.0
15
+ Requires-Dist: markdown-it-py>=4.0.0
16
+ Requires-Dist: mdurl>=0.1.2
17
+ Requires-Dist: packaging>=24.0
18
+ Requires-Dist: Pygments>=2.10.0
19
+ Requires-Dist: rich>=14.3.3
20
+ Requires-Dist: shellingham>=1.5.4
21
+ Requires-Dist: typer>=0.24.1
22
+ Requires-Dist: typing_extensions>=4.12.0
23
+
24
+ ## zjz_cli
25
+
26
+ Cli tool for zjz
27
+
28
+ ### Use VENV
29
+
30
+ ```shell
31
+ mkdir .venv
32
+ cd .venv
33
+ python3.12 -m venv .
34
+ source .venv/bin/activate
35
+ ```
36
+
37
+ ### Install dependence
38
+
39
+ ```shell
40
+ pip install -r requirements.txt
41
+ ```
42
+
43
+ ### Build
44
+
45
+ ```shell
46
+ pyinstaller --onefile --name zjz_cli --clean --noupx main.py
47
+ ```
48
+
49
+ ### Dependence
50
+
51
+ If you add dependence, add here
52
+
53
+ ```shell
54
+ pip install typer
55
+ pip install pyinstaller
56
+ pip install httpx
57
+ ```
58
+
59
+ ### Export requirements
60
+
61
+ If you add dependence, export it
62
+
63
+ ```shell
64
+ pip freeze > requirements.txt
65
+ ```
@@ -0,0 +1,42 @@
1
+ ## zjz_cli
2
+
3
+ Cli tool for zjz
4
+
5
+ ### Use VENV
6
+
7
+ ```shell
8
+ mkdir .venv
9
+ cd .venv
10
+ python3.12 -m venv .
11
+ source .venv/bin/activate
12
+ ```
13
+
14
+ ### Install dependence
15
+
16
+ ```shell
17
+ pip install -r requirements.txt
18
+ ```
19
+
20
+ ### Build
21
+
22
+ ```shell
23
+ pyinstaller --onefile --name zjz_cli --clean --noupx main.py
24
+ ```
25
+
26
+ ### Dependence
27
+
28
+ If you add dependence, add here
29
+
30
+ ```shell
31
+ pip install typer
32
+ pip install pyinstaller
33
+ pip install httpx
34
+ ```
35
+
36
+ ### Export requirements
37
+
38
+ If you add dependence, export it
39
+
40
+ ```shell
41
+ pip freeze > requirements.txt
42
+ ```
File without changes
File without changes
@@ -0,0 +1,184 @@
1
+ from app.api.zjz_req import zjz_req
2
+
3
+
4
+ def sms_verify_code(phone: str) -> dict:
5
+ return zjz_req.get_client().post_json('login/sms', {
6
+ 'phone': phone,
7
+ })
8
+
9
+
10
+ def verify_sms_code(phone: str, code: str) -> dict:
11
+ return zjz_req.get_client().post_json('login/sms-2-token', {
12
+ 'phone': phone,
13
+ 'sms': code,
14
+ })
15
+
16
+
17
+ def get_employee_list(uid: str = None, keyword: str = '', page: int = 1) -> dict:
18
+ if not page or page < 1:
19
+ page = 1
20
+ return zjz_req.get_client().get('ryxx', params={
21
+ 'uid': uid,
22
+ 'keyword': keyword,
23
+ 'page': page
24
+ })
25
+
26
+
27
+ def add_employee(uid: str, data: dict) -> dict:
28
+ data['uid'] = uid
29
+ return zjz_req.get_client().post_json('ryxx', data)
30
+
31
+
32
+ def update_employee(employee_id: str, data: dict) -> dict:
33
+ return zjz_req.get_client().put('ryxx', {
34
+ 'id': employee_id,
35
+ 'data': data,
36
+ })
37
+
38
+
39
+ def get_payroll(uid: str, year: int, month: int) -> dict:
40
+ month_str = f"{year}-{month:02d}"
41
+ return zjz_req.get_client().get('payroll', params={
42
+ 'uid': uid,
43
+ 'month': month_str
44
+ })
45
+
46
+
47
+ def get_payroll_creation_status(uid: str, year: int, month: int) -> dict:
48
+ month_str = f"{year}-{month:02d}"
49
+ return zjz_req.get_client().get('payroll/creation-status', params={
50
+ 'uid': uid,
51
+ 'month': month_str
52
+ })
53
+
54
+
55
+ def get_preview_payroll(uid: str, year: int, month: int) -> dict:
56
+ month_str = f"{year}-{month:02d}"
57
+ return zjz_req.get_client().get('payroll/preview', params={
58
+ 'uid': uid,
59
+ 'month': month_str
60
+ })
61
+
62
+
63
+ def create_payroll(uid: str, year: int, month: int, data: list) -> dict:
64
+ month_str = f"{year}-{month:02d}"
65
+ return zjz_req.get_client().post_json('payroll', {
66
+ 'uid': uid,
67
+ 'month': month_str,
68
+ 'data': data
69
+ })
70
+
71
+
72
+ 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:
73
+ return zjz_req.get_client().get('invoice/sales_invoice_data_list', params={
74
+ 'uid': uid,
75
+ 'current': current,
76
+ 'invoice_number': invoice_number,
77
+ 'invoice_date_begin': invoice_date_begin,
78
+ 'invoice_date_end': invoice_date_end,
79
+ 'status': status,
80
+ })
81
+
82
+
83
+ def set_month_no_sales_invoice(uid: str, year: int, month: int) -> dict:
84
+ return zjz_req.get_client().post_json('invoice/set_month_no_sales_invoice', {
85
+ 'uid': uid,
86
+ 'year': year,
87
+ 'month': month,
88
+ })
89
+
90
+
91
+ 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:
92
+ return zjz_req.get_client().get('invoice/income_invoice_data_list', params={
93
+ 'uid': uid,
94
+ 'current': current,
95
+ 'invoice_number': invoice_number,
96
+ 'invoice_date_begin': invoice_date_begin,
97
+ 'invoice_date_end': invoice_date_end,
98
+ 'status': status,
99
+ })
100
+
101
+
102
+ def set_month_no_invoice(uid: str, year: int, month: int) -> dict:
103
+ return zjz_req.get_client().post_json('invoice/set_month_no_invoice', {
104
+ 'uid': uid,
105
+ 'year': year,
106
+ 'month': month,
107
+ })
108
+
109
+
110
+ def invoice_can_choose_use_list(uid: str, goods_name: str, total_tax_price: str, total_money: str) -> dict:
111
+ return zjz_req.get_client().get('invoice/invoice_can_choose_use_list', params={
112
+ 'uid': uid,
113
+ 'goods_name': goods_name,
114
+ 'total_tax_price': total_tax_price,
115
+ 'total_money': total_money,
116
+ })
117
+
118
+
119
+ def invoice_choose_use(uid: str, invoice_id: int, category: str, is_pay: str, payee: str) -> dict:
120
+ return zjz_req.get_client().post_json('invoice/invoice_choose_use', {
121
+ 'uid': uid,
122
+ 'invoice_id': invoice_id,
123
+ 'category': category,
124
+ 'is_pay': is_pay,
125
+ 'payee': payee,
126
+ })
127
+
128
+
129
+ def get_todo_list(uid: str = '') -> dict:
130
+ params = {}
131
+ if uid:
132
+ params['uid'] = uid
133
+ return zjz_req.get_client().get('todo-list', params=params)
134
+
135
+
136
+ def before_set_month_audited(year: int, month: int, uid: str = '') -> dict:
137
+ params = {
138
+ 'year': year,
139
+ 'month': month,
140
+ }
141
+ if uid:
142
+ params['uid'] = uid
143
+ return zjz_req.get_client().get('audit/before_set_month_audited', params=params)
144
+
145
+
146
+ def set_month_audited(year: int, month: int, uid: str = '') -> dict:
147
+ payload = {
148
+ 'year': year,
149
+ 'month': month,
150
+ }
151
+ if uid:
152
+ payload['uid'] = uid
153
+ return zjz_req.get_client().post_json('audit/set_month_audited', payload)
154
+
155
+
156
+ def get_bank_bill_data_list(uid: str, current: int = 1, date_begin: str = '', date_end: str = '') -> dict:
157
+ params = {
158
+ 'current': current,
159
+ 'date_begin': date_begin,
160
+ 'date_end': date_end,
161
+ }
162
+ if uid:
163
+ params['uid'] = uid
164
+ return zjz_req.get_client().get('bank/bill_data_list', params=params)
165
+
166
+
167
+ def choose_bank_use(uid: str, bill_id: int, rule_text: str) -> dict:
168
+ payload = {
169
+ 'id': bill_id,
170
+ 'rule_text': rule_text,
171
+ }
172
+ if uid:
173
+ payload['uid'] = uid
174
+ return zjz_req.get_client().post_json('bank/bank_bill_choose_use', payload)
175
+
176
+
177
+ def set_month_bank_no_water(uid: str, year: int, month: int) -> dict:
178
+ payload = {
179
+ 'year': year,
180
+ 'month': month,
181
+ }
182
+ if uid:
183
+ payload['uid'] = uid
184
+ return zjz_req.get_client().post_json('bank/set_month_no_water', payload)
@@ -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,47 @@
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
+ def get_sms_verify_code(phone: str = typer.Argument(..., help='自记账的登录手机号')):
14
+ service = AccountService()
15
+ res = service.sms_verify_code(phone)
16
+ echo_util.echo_http_res(res)
17
+
18
+
19
+ @account_app.command(
20
+ name='verify_sms_code',
21
+ help='通过短信验证码登录',
22
+ no_args_is_help=True)
23
+ def verify_sms_code(
24
+ phone: str = typer.Argument(..., help='手机号'),
25
+ code: str = typer.Argument(..., help='短信验证码')):
26
+ service = AccountService()
27
+ res = service.sms_code_login(phone, code)
28
+ echo_util.echo_http_res(res)
29
+
30
+
31
+ @account_app.command(
32
+ name='get_switchable_users',
33
+ help='获取可切换的公司列表')
34
+ def get_switchable_users():
35
+ service = AccountService()
36
+ res = service.get_switchable_user()
37
+ echo_util.echo_http_res(res)
38
+
39
+
40
+ @account_app.command(
41
+ name='switch_to',
42
+ help='切换公司',
43
+ no_args_is_help=True)
44
+ def switch_to(uid: str = typer.Argument(..., help='公司唯一标识uid')):
45
+ service = AccountService()
46
+ res = service.switch_to(uid)
47
+ echo_util.echo_http_res(res)
@@ -0,0 +1,49 @@
1
+ import typer
2
+
3
+ from app.service.bank_service import BankService
4
+ from app.util import echo_util
5
+
6
+ bank_app = typer.Typer()
7
+
8
+
9
+ @bank_app.command(
10
+ name='get_bank_bill_data_list',
11
+ help="获取银行回单/流水列表")
12
+ def get_bank_bill_data_list(
13
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
14
+ current: int = typer.Option(1, '--current', help='页码,默认 1'),
15
+ date_begin: str = typer.Option('', '--date_begin', help='交易日期开始(YYYY-MM-DD;如需使用需与 date_end 同时传)'),
16
+ date_end: str = typer.Option('', '--date_end', help='交易日期结束(YYYY-MM-DD;如需使用需与 date_begin 同时传)'),
17
+ ):
18
+ service = BankService()
19
+ res = service.get_bank_bill_data_list(uid, current, date_begin, date_end)
20
+ echo_util.echo_http_res(res)
21
+
22
+
23
+ @bank_app.command(
24
+ name='choose_bank_use',
25
+ help="回单选择用途/入账",
26
+ no_args_is_help=True)
27
+ def choose_bank_use(
28
+ bill_id: int = typer.Argument(...,help='回单单据 id(来自 get_bank_bill_data_list 返回 bill_list[].id)'),
29
+ rule_text: str = typer.Argument(..., help='用途文本(建议从 bill_list[].use_list 中选择)'),
30
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
31
+ ):
32
+ service = BankService()
33
+ res = service.choose_bank_use(uid, bill_id, rule_text)
34
+ echo_util.echo_http_res(res)
35
+
36
+
37
+ @bank_app.command(
38
+ name='set_month_bank_no_water',
39
+ help="标记某个月份无银行回单/流水",
40
+ no_args_is_help=True)
41
+ def set_month_bank_no_water(
42
+ year: int = typer.Argument(..., help='年份,如 2026'),
43
+ month: int = typer.Argument(..., help='月份(1-12),如 3'),
44
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
45
+ ):
46
+ service = BankService()
47
+ res = service.set_month_bank_no_water(uid, year, month)
48
+ echo_util.echo_http_res(res)
49
+
@@ -0,0 +1,48 @@
1
+ import json
2
+ import typer
3
+
4
+ from app.service.employee_service import EmployeeService
5
+ from app.util import echo_util
6
+
7
+ employee_app = typer.Typer()
8
+
9
+
10
+ @employee_app.command(
11
+ name='get_employee_list',
12
+ help="获取员工列表",
13
+ epilog="""使用示例\n\nzjz_cli employee get_employee_list""")
14
+ def get_employee_list(
15
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid'),
16
+ keyword: str = typer.Option('', '--keyword', help='姓名/证件号码 关键字,支持模糊搜索,如果为空则查询全部')
17
+ ):
18
+ service = EmployeeService()
19
+ res = service.get_employee_list(uid, keyword)
20
+ echo_util.echo_http_res(res)
21
+
22
+
23
+ @employee_app.command(
24
+ name='add_employee',
25
+ help="添加员工",
26
+ no_args_is_help=True)
27
+ def add_employee(
28
+ data: str = typer.Argument(..., help='员工信息的json字符串'),
29
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid')
30
+ ):
31
+ data_obj = json.loads(data)
32
+ service = EmployeeService()
33
+ res = service.add_employee(uid, data_obj)
34
+ echo_util.echo_http_res(res)
35
+
36
+
37
+ @employee_app.command(
38
+ name='update_employee',
39
+ help='更新员工信息',
40
+ no_args_is_help=True)
41
+ def update_employee(
42
+ employee_id: str = typer.Argument(..., help='员工id'),
43
+ data: str = typer.Argument(..., help='需要更新信息的json字符串')
44
+ ):
45
+ data_obj = json.loads(data)
46
+ service = EmployeeService()
47
+ res = service.update_employee(employee_id, data_obj)
48
+ echo_util.echo_http_res(res)
@@ -0,0 +1,96 @@
1
+ import typer
2
+
3
+ from app.service.invoice_service import InvoiceService
4
+ from app.util import echo_util
5
+
6
+ invoice_app = typer.Typer()
7
+
8
+
9
+ @invoice_app.command(
10
+ name='get_sales_invoice_data_list',
11
+ help="获取销项发票列表")
12
+ def get_sales_invoice_data_list(
13
+ uid: str = typer.Option('', '--uid', help='用户uid'),
14
+ current: int = typer.Option(1, '--current', help='页码'),
15
+ invoice_number: str = typer.Option('', '--invoice_number', help='发票号码 关键字,指定发票号码查询,如果为空则查询全部'),
16
+ invoice_date_begin: str = typer.Option('', '--invoice_date_begin', help='发票日期开始 关键字,指定发票日期开始查询(如果要使用,invoice_date_begin和invoice_date_end两个都需要),如果为空则不限制,日期格式为YYYY-MM-DD,例如2024-01-01'),
17
+ invoice_date_end: str = typer.Option('', '--invoice_date_end', help='发票日期结束 关键字,指定发票日期结束查询(如果要使用,invoice_date_begin和invoice_date_end两个都需要),如果为空则不限制,日期格式为YYYY-MM-DD,例如2024-01-31'),
18
+ ):
19
+ service = InvoiceService()
20
+ res = service.get_sales_invoice_data_list(uid, current, invoice_number, invoice_date_begin, invoice_date_end)
21
+ echo_util.echo_http_res(res)
22
+
23
+
24
+ @invoice_app.command(
25
+ name='get_income_invoice_data_list',
26
+ help="获取进项/收到的发票列表")
27
+ def get_income_invoice_data_list(
28
+ uid: str = typer.Option('', '--uid', help='用户uid'),
29
+ current: int = typer.Option(1, '--current', help='页码'),
30
+ invoice_number: str = typer.Option('', '--invoice_number', help='发票号码关键字(精确匹配),不传则查询全部'),
31
+ invoice_date_begin: str = typer.Option('', '--invoice_date_begin', help='开票日期开始(YYYY-MM-DD;如需使用需与 invoice_date_end 同时传)'),
32
+ invoice_date_end: str = typer.Option('', '--invoice_date_end', help='开票日期结束(YYYY-MM-DD;如需使用需与 invoice_date_begin 同时传)'),
33
+ status: str = typer.Option('', '--status', help='发票状态(审核中/待确认/已拒绝/已入账),不传则查询全部'),
34
+ ):
35
+ service = InvoiceService()
36
+ res = service.get_income_invoice_data_list(uid, current, invoice_number, invoice_date_begin, invoice_date_end, status)
37
+ echo_util.echo_http_res(res)
38
+
39
+
40
+ @invoice_app.command(
41
+ name='set_month_no_sales_invoice',
42
+ help="标记某个月份无销项/开出的发票",
43
+ no_args_is_help=True)
44
+ def set_month_no_sales_invoice(
45
+ uid: str = typer.Option('', '--uid', help='用户uid'),
46
+ year: int = typer.Argument(..., help='年份,如 2026'),
47
+ month: int = typer.Argument(..., help='月份(1-12),如 3'),
48
+ ):
49
+ service = InvoiceService()
50
+ res = service.set_month_no_sales_invoice(uid, year, month)
51
+ echo_util.echo_http_res(res)
52
+
53
+
54
+ @invoice_app.command(
55
+ name='set_month_no_invoice',
56
+ help="标记某个月份无进项/收到的发票",
57
+ no_args_is_help=True)
58
+ def set_month_no_invoice(
59
+ uid: str = typer.Option('', '--uid', help='用户uid'),
60
+ year: int = typer.Argument(..., help='年份,如 2026'),
61
+ month: int = typer.Argument(..., help='月份(1-12),如 3'),
62
+ ):
63
+ service = InvoiceService()
64
+ res = service.set_month_no_invoice(uid, year, month)
65
+ echo_util.echo_http_res(res)
66
+
67
+
68
+ @invoice_app.command(
69
+ name='invoice_can_choose_use_list',
70
+ help="进项发票:查询可选用途列表",
71
+ no_args_is_help=True)
72
+ def invoice_can_choose_use_list(
73
+ uid: str = typer.Option('', '--uid', help='用户uid(不传则使用当前已切换在用的 uid)'),
74
+ goods_name: str = typer.Option(..., '--goods_name', help='货物/服务名称(用于推荐用途)'),
75
+ total_tax_price: str = typer.Option(..., '--total_tax_price', help='价税合计(建议传“元”,如 113.00)'),
76
+ total_money: str = typer.Option(..., '--total_money', help='不含税金额(建议传“元”,如 100.00)'),
77
+ ):
78
+ service = InvoiceService()
79
+ res = service.invoice_can_choose_use_list(uid, goods_name, total_tax_price, total_money)
80
+ echo_util.echo_http_res(res)
81
+
82
+
83
+ @invoice_app.command(
84
+ name='invoice_choose_use',
85
+ help="进项发票:选择用途并入账",
86
+ no_args_is_help=True)
87
+ def invoice_choose_use(
88
+ uid: str = typer.Option('', '--uid', help='用户uid(不传则使用当前已切换在用的 uid)'),
89
+ invoice_id: int = typer.Option(..., '--invoice_id', help='发票 id'),
90
+ category: str = typer.Option(..., '--category', help='用途/类目(来自 invoice_can_choose_use_list.items[].id'),
91
+ is_pay: str = typer.Option(..., '--is_pay', help='支付方式(对公银行支付/员工垫付/老板垫付/现金支付)'),
92
+ payee: str = typer.Option(..., '--payee', help='垫付人/收款人(服务端会按支付方式校验)'),
93
+ ):
94
+ service = InvoiceService()
95
+ res = service.invoice_choose_use(uid, invoice_id, category, is_pay, payee)
96
+ echo_util.echo_http_res(res)
@@ -0,0 +1,79 @@
1
+ import json
2
+ import typer
3
+
4
+ from app.service.payroll_service import PayrollService
5
+ from app.util import echo_util
6
+
7
+ payroll_app = typer.Typer()
8
+
9
+
10
+ def parse_month(month_str: str) -> tuple:
11
+ try:
12
+ parts = month_str.split('-')
13
+ if len(parts) != 2:
14
+ raise typer.BadParameter("格式必须为 yyyy-mm,例如 2026-04")
15
+ year = int(parts[0])
16
+ month_val = int(parts[1])
17
+ if not (1 <= month_val <= 12):
18
+ raise typer.BadParameter("月份必须在 1 到 12 之间")
19
+ return year, month_val
20
+ except ValueError:
21
+ raise typer.BadParameter("年份和月份必须是数字,例如 2026-04")
22
+
23
+
24
+ @payroll_app.command(
25
+ name='get_payroll',
26
+ help="获取工资单",
27
+ epilog="""使用示例\n\nzjz_cli payroll get_payroll 2026-04""")
28
+ def get_payroll(
29
+ month: str = typer.Argument(..., help='工资单月份,如 2026-04'),
30
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid')
31
+ ):
32
+ req_year, req_month = parse_month(month)
33
+ service = PayrollService()
34
+ res = service.get_payroll(uid, req_year, req_month)
35
+ echo_util.echo_http_res(res)
36
+
37
+
38
+ @payroll_app.command(
39
+ name='get_payroll_creation_status',
40
+ help="获取工资单创建状态",
41
+ no_args_is_help=True)
42
+ def get_payroll_creation_status(
43
+ month: str = typer.Argument(..., help='按月时间,如 2026-04'),
44
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid')
45
+ ):
46
+ req_year, req_month = parse_month(month)
47
+ service = PayrollService()
48
+ res = service.get_payroll_creation_status(uid, req_year, req_month)
49
+ echo_util.echo_http_res(res)
50
+
51
+
52
+ @payroll_app.command(
53
+ name='get_preview_payroll',
54
+ help="获取预览工资单",
55
+ no_args_is_help=True)
56
+ def get_preview_payroll(
57
+ month: str = typer.Argument(..., help='工资单月份,如 2026-04'),
58
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid')
59
+ ):
60
+ req_year, req_month = parse_month(month)
61
+ service = PayrollService()
62
+ res = service.get_preview_payroll(uid, req_year, req_month)
63
+ echo_util.echo_http_res(res)
64
+
65
+
66
+ @payroll_app.command(
67
+ name='create_payroll',
68
+ help='创建工资单',
69
+ no_args_is_help=True)
70
+ def create_payroll(
71
+ month: str = typer.Argument(..., help='工资单月份,如 2026-04'),
72
+ data: str = typer.Argument(..., help='工资单列表的json字符串'),
73
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid')
74
+ ):
75
+ req_year, req_month = parse_month(month)
76
+ data_obj = json.loads(data)
77
+ service = PayrollService()
78
+ res = service.create_payroll(uid, req_year, req_month, data_obj)
79
+ echo_util.echo_http_res(res)
@@ -0,0 +1,45 @@
1
+ import typer
2
+
3
+ from app.service.todo_service import TodoService
4
+ from app.util import echo_util
5
+
6
+ todo_app = typer.Typer()
7
+
8
+
9
+ @todo_app.command(
10
+ name='get_todo_list',
11
+ help="获取代办列表")
12
+ def get_todo_list(
13
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
14
+ ):
15
+ service = TodoService()
16
+ res = service.get_todo_list(uid)
17
+ echo_util.echo_http_res(res)
18
+
19
+
20
+ @todo_app.command(
21
+ name='before_set_month_audited',
22
+ help="提交审账前确认",
23
+ no_args_is_help=True)
24
+ def before_set_month_audited(
25
+ year: int = typer.Argument(..., help='年份,如 2026'),
26
+ month: int = typer.Argument(..., help='月份(1-12),如 3'),
27
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
28
+ ):
29
+ service = TodoService()
30
+ res = service.before_set_month_audited(year, month, uid)
31
+ echo_util.echo_http_res(res)
32
+
33
+
34
+ @todo_app.command(
35
+ name='set_month_audited',
36
+ help="提交审账",
37
+ no_args_is_help=True)
38
+ def set_month_audited(
39
+ year: int = typer.Argument(..., help='年份,如 2026'),
40
+ month: int = typer.Argument(..., help='月份(1-12),如 3'),
41
+ uid: str = typer.Option('', '--uid', help='公司唯一标识uid(不传则使用当前已切换在用的 uid)'),
42
+ ):
43
+ service = TodoService()
44
+ res = service.set_month_audited(year, month, uid)
45
+ echo_util.echo_http_res(res)