deepfos 1.1.66__tar.gz → 1.1.67__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.
- {deepfos-1.1.66 → deepfos-1.1.67}/CHANGELOG.md +12 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/PKG-INFO +1 -1
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/_version.py +3 -3
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/deepmodel.py +126 -123
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/dimension.py +2 -2
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/finmodel.py +23 -4
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/journal.py +19 -8
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/PKG-INFO +1 -1
- {deepfos-1.1.66 → deepfos-1.1.67}/.gitattributes +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/.gitee/ISSUE_GUIDELINES.md +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/.gitee/ISSUE_TEMPLATE.md +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/.gitignore +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/MANIFEST.in +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/README.md +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/algo/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/algo/graph.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/business_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/models/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/models/business_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_1/models/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_2/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_2/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_2/models/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/V1_2/models/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/account.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/accounting_engines.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/app.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/approval_process.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/base.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/business_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/consolidation.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/consolidation_process.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/datatable.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/deep_pipeline.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/deepconnector.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/deepfos_task.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/deepmodel.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/financial_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/journal_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/journal_template.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/memory_financial_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/account.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/accounting_engines.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/app.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/approval_process.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/base.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/business_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/consolidation.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/consolidation_process.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/datatable_mysql.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/deep_pipeline.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/deepconnector.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/deepfos_task.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/deepmodel.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/financial_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/journal_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/journal_template.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/memory_financial_model.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/platform.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/python.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/reconciliation_engine.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/reconciliation_report.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/role_strategy.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/smartlist.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/space.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/system.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/variable.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/models/workflow.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/platform.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/python.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/reconciliation_engine.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/reconciliation_report.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/role_strategy.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/smartlist.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/space.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/system.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/variable.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/api/workflow.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/jstream.c +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/jstream.pyx +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/pandas.c +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/pandas.pyx +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/py_jstream.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/boost/py_pandas.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/cache.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/config.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/_base.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/constants.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/cube.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/formula.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/syscube.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/typing.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/cube/utils.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/_base.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/dimcreator.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/dimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/dimexpr.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/dimmember.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/eledimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/filters.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/dimension/sysdimension.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/_cache.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/_operator.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/nodemixin.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/sqlcondition.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/core/logictable/tablemodel.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/cipher.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/clickhouse.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/connector.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/daclickhouse.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/dameng.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/damysql.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/dbkits.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/deepengine.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/deepmodel.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/deepmodel_kingbase.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/edb.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/gauss.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/kingbase.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/mysql.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/oracle.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/postgresql.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/sqlserver.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/db/utils.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/accounting.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/apvlprocess.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/base.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/bizmodel.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/datatable.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/deep_pipeline.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/deepconnector.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/fact_table.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/journal_template.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/pyscript.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/reconciliation.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/rolestrategy.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/smartlist.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/variable.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/element/workflow.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/exceptions/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/exceptions/hook.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lazy.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/__init__.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/_javaobj.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/asynchronous.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/concurrency.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/constant.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/decorator.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/deepchart.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/deepux.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/discovery.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/edb_lexer.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/eureka.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/filterparser.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/httpcli.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/jsonstreamer.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/msg.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/nacos.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/patch.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/redis.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/serutils.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/stopwatch.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/subtask.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/sysutils.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/lib/utils.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/local.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/options.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos/translation.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/SOURCES.txt +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/dependency_links.txt +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/not-zip-safe +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/requires.txt +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/deepfos.egg-info/top_level.txt +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/requirements.txt +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/setup.cfg +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/setup.py +0 -0
- {deepfos-1.1.66 → deepfos-1.1.67}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-07-
|
|
11
|
+
"date": "2025-07-22T03:24:23+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.1.
|
|
14
|
+
"full-revisionid": "61559f9a44520b8bcfced0acc40f356ed3c1e6d7",
|
|
15
|
+
"version": "1.1.67"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -7,7 +7,7 @@ import json
|
|
|
7
7
|
import uuid
|
|
8
8
|
from contextlib import asynccontextmanager, contextmanager
|
|
9
9
|
from contextvars import ContextVar
|
|
10
|
-
from itertools import count
|
|
10
|
+
from itertools import count, chain
|
|
11
11
|
from typing import (
|
|
12
12
|
List, TYPE_CHECKING, Any, Dict, Union, NamedTuple,
|
|
13
13
|
Iterable, Optional, Literal
|
|
@@ -37,7 +37,7 @@ from deepfos.lib import serutils
|
|
|
37
37
|
from deepfos.lib.asynchronous import future_property, evloop
|
|
38
38
|
from deepfos.lib.decorator import flagmethod, cached_property, lru_cache
|
|
39
39
|
from deepfos.lib.utils import (
|
|
40
|
-
AliasGenerator, to_version_tuple,
|
|
40
|
+
AliasGenerator, to_version_tuple,
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
__all__ = ['AsyncDeepModel', 'DeepModel', 'to_fields', 'QueryWithArgs']
|
|
@@ -793,8 +793,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
793
793
|
self,
|
|
794
794
|
direct_access: bool = True,
|
|
795
795
|
pg_dsn: str = None,
|
|
796
|
-
|
|
797
|
-
after_chunk: ChunkAlert = None,
|
|
796
|
+
**kwargs
|
|
798
797
|
):
|
|
799
798
|
self._txn_ = ContextVar('QLTXN')
|
|
800
799
|
self.appmodule = f"app{OPTION.api.header['app']}"
|
|
@@ -805,8 +804,6 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
805
804
|
self.alias = AliasGenerator()
|
|
806
805
|
self.pg_dsn = pg_dsn
|
|
807
806
|
self._globals = None
|
|
808
|
-
self.before_chunk = before_chunk
|
|
809
|
-
self.after_chunk = after_chunk
|
|
810
807
|
self._clients = threading.local()
|
|
811
808
|
|
|
812
809
|
@future_property
|
|
@@ -1099,6 +1096,10 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1099
1096
|
会自动用作所有string形式ql的参数
|
|
1100
1097
|
|
|
1101
1098
|
"""
|
|
1099
|
+
qls_with_args = self._collect_execute_qls(qls, kwargs)
|
|
1100
|
+
return await self._maybe_exec_qls(qls_with_args)
|
|
1101
|
+
|
|
1102
|
+
def _collect_execute_qls(self, qls, kwargs):
|
|
1102
1103
|
self._ensure_client()
|
|
1103
1104
|
if isinstance(qls, str):
|
|
1104
1105
|
qls_with_args = [QueryWithArgs(
|
|
@@ -1126,8 +1127,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1126
1127
|
))
|
|
1127
1128
|
else:
|
|
1128
1129
|
raise TypeError(f'qls参数中出现类型非法成员:{type(ql)}')
|
|
1129
|
-
|
|
1130
|
-
return await self._maybe_exec_qls(qls_with_args)
|
|
1130
|
+
return qls_with_args
|
|
1131
1131
|
|
|
1132
1132
|
execute.__doc__ = execute.__doc__ + DOC_ARGS_KWARGS
|
|
1133
1133
|
|
|
@@ -1312,30 +1312,17 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1312
1312
|
tgt_main_field[name] = MainField(tgt_bkey, is_multi, link_props)
|
|
1313
1313
|
return field_info, tgt_main_field
|
|
1314
1314
|
|
|
1315
|
-
def
|
|
1316
|
-
self,
|
|
1317
|
-
data: pd.DataFrame,
|
|
1318
|
-
ql: str,
|
|
1319
|
-
chunksize: int,
|
|
1320
|
-
qls: List[QueryWithArgs]
|
|
1321
|
-
):
|
|
1315
|
+
def _ql_payload(self, data: pd.DataFrame, ql: str,):
|
|
1322
1316
|
self._ensure_client()
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
),
|
|
1333
|
-
kwargs={kw_name: part.to_json(
|
|
1334
|
-
orient='records', double_precision=15,
|
|
1335
|
-
force_ascii=False, default_handler=str
|
|
1336
|
-
)},
|
|
1337
|
-
globals=self._globals
|
|
1338
|
-
))
|
|
1317
|
+
kw_name = self.alias.get(BATCH_INSERT_KW)
|
|
1318
|
+
return QueryWithArgs(
|
|
1319
|
+
commands=ql.replace(f'${BATCH_INSERT_KW}', f'${kw_name}'),
|
|
1320
|
+
kwargs={kw_name: data.to_json(
|
|
1321
|
+
orient='records', double_precision=15,
|
|
1322
|
+
force_ascii=False, default_handler=str
|
|
1323
|
+
)},
|
|
1324
|
+
globals=self._globals,
|
|
1325
|
+
)
|
|
1339
1326
|
|
|
1340
1327
|
@staticmethod
|
|
1341
1328
|
def _split_self_link(data, relation, structure, bkey):
|
|
@@ -1391,6 +1378,87 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1391
1378
|
data = data.join(link.to_frame(name), on=bkey)
|
|
1392
1379
|
return data
|
|
1393
1380
|
|
|
1381
|
+
async def _collect_bulk_qls(
|
|
1382
|
+
self,
|
|
1383
|
+
object_name: str,
|
|
1384
|
+
data: pd.DataFrame,
|
|
1385
|
+
relation: Dict[str, pd.DataFrame] = None,
|
|
1386
|
+
chunk_size: int = 500,
|
|
1387
|
+
enable_upsert: bool = False,
|
|
1388
|
+
update_fields: Iterable[str] = None,
|
|
1389
|
+
exclusive_fields: Iterable[str] = None,
|
|
1390
|
+
match_fields: Iterable[str] = None,
|
|
1391
|
+
insert: bool = True
|
|
1392
|
+
) -> List[List[QueryWithArgs]]:
|
|
1393
|
+
if object_name in self.objects:
|
|
1394
|
+
obj = self.objects[object_name]
|
|
1395
|
+
else:
|
|
1396
|
+
raise ObjectNotExist(
|
|
1397
|
+
f'DeepModel对象[{object_name}]在当前应用不存在,无法插入数据'
|
|
1398
|
+
)
|
|
1399
|
+
if obj.external:
|
|
1400
|
+
raise ExternalObjectReadOnly('外部对象只可读')
|
|
1401
|
+
|
|
1402
|
+
structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
|
|
1403
|
+
self._valid_data(data, object_name, relation, structure, check_required=insert)
|
|
1404
|
+
|
|
1405
|
+
relation = relation or {}
|
|
1406
|
+
bkey = await self._get_bkey(obj)
|
|
1407
|
+
if bkey not in data.columns:
|
|
1408
|
+
raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
|
|
1409
|
+
|
|
1410
|
+
# data拼接relation df
|
|
1411
|
+
data = self._merge_relation(data, relation, structure, bkey)
|
|
1412
|
+
# 从data中分离出self-link更新信息
|
|
1413
|
+
data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
|
|
1414
|
+
field_info, tgt_main_field = await self._collect_bulk_field_info(
|
|
1415
|
+
object_name, structure, data, relation
|
|
1416
|
+
)
|
|
1417
|
+
field_names = set(map(lambda f: f.name, field_info))
|
|
1418
|
+
if insert:
|
|
1419
|
+
if enable_upsert:
|
|
1420
|
+
self._valid_upsert(obj, field_names, bkey, exclusive_fields, update_fields)
|
|
1421
|
+
|
|
1422
|
+
exclusive_fields = set(exclusive_fields or {bkey}) & set(field_names)
|
|
1423
|
+
update_fields = set(update_fields or (field_names - {bkey})) & set(field_names)
|
|
1424
|
+
if enable_upsert and update_fields:
|
|
1425
|
+
bulk_ql = bulk_upsert_by_fields(
|
|
1426
|
+
object_name, field_info, tgt_main_field,
|
|
1427
|
+
exclusive_fields, update_fields
|
|
1428
|
+
)
|
|
1429
|
+
else:
|
|
1430
|
+
bulk_ql = bulk_insert_by_fields(object_name, field_info, tgt_main_field)
|
|
1431
|
+
else:
|
|
1432
|
+
if missing := (set(match_fields or [bkey]) - set(field_names)):
|
|
1433
|
+
raise ValueError(f"match fields: {missing} 不在提供的数据中")
|
|
1434
|
+
|
|
1435
|
+
match_fields = set(match_fields or [bkey]) & set(field_names)
|
|
1436
|
+
if to_upd := (field_names - match_fields):
|
|
1437
|
+
bulk_ql = bulk_update_by_fields(
|
|
1438
|
+
object_name, field_info, tgt_main_field,
|
|
1439
|
+
match_fields, to_upd
|
|
1440
|
+
)
|
|
1441
|
+
else:
|
|
1442
|
+
bulk_ql = None
|
|
1443
|
+
qls = []
|
|
1444
|
+
self._ensure_client()
|
|
1445
|
+
for i in range(0, len(data), chunk_size):
|
|
1446
|
+
part = structure.fit(data.iloc[i: i + chunk_size])
|
|
1447
|
+
ql_chunk = []
|
|
1448
|
+
# Ignore bulk_ql when only update multi links
|
|
1449
|
+
if bulk_ql is not None:
|
|
1450
|
+
ql_chunk = [self._ql_payload(part, bulk_ql)]
|
|
1451
|
+
for update_field, (update_df, main_field) in self_link_dfs.items():
|
|
1452
|
+
field = structure.fields[update_field]
|
|
1453
|
+
update_ql = bulk_update_by_fields(
|
|
1454
|
+
object_name, [field], {update_field: main_field},
|
|
1455
|
+
[bkey], [update_field]
|
|
1456
|
+
)
|
|
1457
|
+
update_part = update_df.iloc[i: i + chunk_size]
|
|
1458
|
+
ql_chunk.append(self._ql_payload(update_part, update_ql))
|
|
1459
|
+
qls.append(ql_chunk)
|
|
1460
|
+
return qls
|
|
1461
|
+
|
|
1394
1462
|
@txn_support
|
|
1395
1463
|
async def insert_df(
|
|
1396
1464
|
self,
|
|
@@ -1401,6 +1469,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1401
1469
|
enable_upsert: bool = False,
|
|
1402
1470
|
update_fields: Iterable[str] = None,
|
|
1403
1471
|
exclusive_fields: Iterable[str] = None,
|
|
1472
|
+
commit_per_chunk: bool = False,
|
|
1404
1473
|
) -> None:
|
|
1405
1474
|
"""以事务执行基于DataFrame字段信息的批量插入数据
|
|
1406
1475
|
|
|
@@ -1421,6 +1490,9 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1421
1490
|
exclusive_fields: upsert句式下update的exclusive fields列表,
|
|
1422
1491
|
涉及的fields需出现在data或relation中,
|
|
1423
1492
|
默认为业务主键
|
|
1493
|
+
commit_per_chunk: 每次插入后是否提交事务,
|
|
1494
|
+
默认为False,即所有数据插入后再提交事务
|
|
1495
|
+
该参数仅在非start transaction上下文中生效
|
|
1424
1496
|
|
|
1425
1497
|
Notes:
|
|
1426
1498
|
|
|
@@ -1493,54 +1565,16 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1493
1565
|
logger.info("data为空,无DML执行")
|
|
1494
1566
|
return
|
|
1495
1567
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
f'DeepModel对象[{object_name}]在当前应用不存在,无法插入数据'
|
|
1501
|
-
)
|
|
1502
|
-
if obj.external:
|
|
1503
|
-
raise ExternalObjectReadOnly('外部对象只可读')
|
|
1504
|
-
|
|
1505
|
-
structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
|
|
1506
|
-
|
|
1507
|
-
self._valid_data(data, object_name, relation, structure)
|
|
1508
|
-
|
|
1509
|
-
relation = relation or {}
|
|
1510
|
-
bkey = await self._get_bkey(obj)
|
|
1511
|
-
# data拼接relation df
|
|
1512
|
-
data = self._merge_relation(data, relation, structure, bkey)
|
|
1513
|
-
# 从data中分离出self-link更新信息
|
|
1514
|
-
data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
|
|
1515
|
-
field_info, tgt_main_field = await self._collect_bulk_field_info(
|
|
1516
|
-
object_name, structure, data, relation
|
|
1568
|
+
qls = await self._collect_bulk_qls(
|
|
1569
|
+
object_name, data, relation, chunksize,
|
|
1570
|
+
enable_upsert, update_fields, exclusive_fields,
|
|
1571
|
+
insert=True
|
|
1517
1572
|
)
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
exclusive_fields = set(exclusive_fields or {bkey}) & set(field_names)
|
|
1523
|
-
update_fields = set(update_fields or (field_names - {bkey})) & set(field_names)
|
|
1524
|
-
if enable_upsert and update_fields:
|
|
1525
|
-
insert_ql = bulk_upsert_by_fields(
|
|
1526
|
-
object_name, field_info, tgt_main_field,
|
|
1527
|
-
exclusive_fields, update_fields
|
|
1528
|
-
)
|
|
1573
|
+
if commit_per_chunk:
|
|
1574
|
+
for ql_chunk in qls:
|
|
1575
|
+
await self.execute(ql_chunk)
|
|
1529
1576
|
else:
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
qls = []
|
|
1533
|
-
self._collect_qls(structure.fit(data), insert_ql, chunksize, qls)
|
|
1534
|
-
if self_link_dfs:
|
|
1535
|
-
for update_field, (update_df, main_field) in self_link_dfs.items():
|
|
1536
|
-
field = structure.fields[update_field]
|
|
1537
|
-
update_ql = bulk_update_by_fields(
|
|
1538
|
-
object_name, [field], {update_field: main_field},
|
|
1539
|
-
[bkey], [update_field]
|
|
1540
|
-
)
|
|
1541
|
-
self._collect_qls(update_df, update_ql, chunksize, qls)
|
|
1542
|
-
|
|
1543
|
-
await self.execute(qls)
|
|
1577
|
+
await self.execute(list(chain(*qls)))
|
|
1544
1578
|
|
|
1545
1579
|
async def get_object(
|
|
1546
1580
|
self,
|
|
@@ -1693,6 +1727,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1693
1727
|
relation: Dict[str, pd.DataFrame] = None,
|
|
1694
1728
|
chunksize: int = 500,
|
|
1695
1729
|
match_fields: Iterable[str] = None,
|
|
1730
|
+
commit_per_chunk: bool = False,
|
|
1696
1731
|
) -> None:
|
|
1697
1732
|
"""以事务执行基于DataFrame字段信息的批量更新数据
|
|
1698
1733
|
|
|
@@ -1709,57 +1744,23 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1709
1744
|
若有link property,则以property名为列名,提供在除source和target的列中
|
|
1710
1745
|
chunksize: 单次最大行数
|
|
1711
1746
|
match_fields: update的匹配列表,涉及的fields需出现在data或relation中,默认为业务主键
|
|
1747
|
+
commit_per_chunk: 每次插入后是否提交事务,
|
|
1748
|
+
默认为False,即所有数据插入后再提交事务
|
|
1749
|
+
该参数仅在非start transaction上下文中生效
|
|
1712
1750
|
"""
|
|
1713
1751
|
if data.empty:
|
|
1714
1752
|
logger.info("data为空,无DML执行")
|
|
1715
1753
|
return
|
|
1716
1754
|
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
raise ObjectNotExist(
|
|
1721
|
-
f'DeepModel对象[{object_name}]在当前应用不存在,无法更新数据'
|
|
1722
|
-
)
|
|
1723
|
-
if obj.external:
|
|
1724
|
-
raise ExternalObjectReadOnly('外部对象只可读')
|
|
1725
|
-
|
|
1726
|
-
structure = ObjectStructure(name=obj.name, structure=obj.fields.values())
|
|
1727
|
-
self._valid_data(data, object_name, relation, structure, check_required=False)
|
|
1728
|
-
relation = relation or {}
|
|
1729
|
-
bkey = await self._get_bkey(obj)
|
|
1730
|
-
if bkey not in data.columns:
|
|
1731
|
-
raise RequiredFieldUnfilled(f'缺少业务主键[{bkey}]')
|
|
1732
|
-
# data拼接relation df
|
|
1733
|
-
data = self._merge_relation(data, relation, structure, bkey)
|
|
1734
|
-
# 从data中分离出self-link更新信息
|
|
1735
|
-
data, self_link_dfs = self._split_self_link(data, relation, structure, bkey)
|
|
1736
|
-
field_info, tgt_main_field = await self._collect_bulk_field_info(
|
|
1737
|
-
object_name, structure, data, relation
|
|
1738
|
-
)
|
|
1739
|
-
field_names = set(map(lambda f: f.name, field_info))
|
|
1740
|
-
|
|
1741
|
-
if missing := (set(match_fields or [bkey]) - set(field_names)):
|
|
1742
|
-
raise ValueError(f"match fields: {missing} 不在提供的数据中")
|
|
1743
|
-
|
|
1744
|
-
match_fields = set(match_fields or [bkey]) & set(field_names)
|
|
1745
|
-
update_ql = bulk_update_by_fields(
|
|
1746
|
-
object_name, field_info, tgt_main_field,
|
|
1747
|
-
match_fields, field_names - match_fields
|
|
1755
|
+
qls = await self._collect_bulk_qls(
|
|
1756
|
+
object_name, data, relation, chunksize,
|
|
1757
|
+
match_fields=match_fields, insert=False
|
|
1748
1758
|
)
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
update_ql = bulk_update_by_fields(
|
|
1755
|
-
object_name, [field],
|
|
1756
|
-
{update_field: main_field},
|
|
1757
|
-
[bkey],
|
|
1758
|
-
[update_field]
|
|
1759
|
-
)
|
|
1760
|
-
self._collect_qls(update_df, update_ql, chunksize, qls)
|
|
1761
|
-
|
|
1762
|
-
await self.execute(qls)
|
|
1759
|
+
if commit_per_chunk:
|
|
1760
|
+
for ql_chunk in qls:
|
|
1761
|
+
await self.execute(ql_chunk)
|
|
1762
|
+
else:
|
|
1763
|
+
await self.execute(list(chain(*qls)))
|
|
1763
1764
|
|
|
1764
1765
|
@asynccontextmanager
|
|
1765
1766
|
async def start_transaction(self, flatten: bool = False):
|
|
@@ -1799,7 +1800,7 @@ class AsyncDeepModel(ElementBase[DeepModelAPI]):
|
|
|
1799
1800
|
|
|
1800
1801
|
Important:
|
|
1801
1802
|
|
|
1802
|
-
仅 :func:`insert_df` :func:`execute` 方法支持在事务中执行
|
|
1803
|
+
仅 :func:`insert_df` :func:`update_df` :func:`execute` 方法支持在事务中执行
|
|
1803
1804
|
|
|
1804
1805
|
"""
|
|
1805
1806
|
try:
|
|
@@ -1913,6 +1914,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
|
|
|
1913
1914
|
enable_upsert: bool = False,
|
|
1914
1915
|
update_fields: Iterable[str] = None,
|
|
1915
1916
|
exclusive_fields: Iterable[str] = None,
|
|
1917
|
+
commit_per_chunk: bool = False,
|
|
1916
1918
|
) -> None:
|
|
1917
1919
|
...
|
|
1918
1920
|
|
|
@@ -1934,6 +1936,7 @@ class DeepModel(AsyncDeepModel, metaclass=SyncMeta):
|
|
|
1934
1936
|
relation: Dict[str, pd.DataFrame] = None,
|
|
1935
1937
|
chunksize: int = 500,
|
|
1936
1938
|
match_fields: Iterable[str] = None,
|
|
1939
|
+
commit_per_chunk: bool = False,
|
|
1937
1940
|
) -> None:
|
|
1938
1941
|
...
|
|
1939
1942
|
|
|
@@ -956,7 +956,7 @@ class AsyncDimension(ElementBase[DimensionAPI]):
|
|
|
956
956
|
|
|
957
957
|
# -----------------------------------------------------------------------------
|
|
958
958
|
# has shared member
|
|
959
|
-
df_shared: pd.DataFrame = df[df[shared_mbr_col]]
|
|
959
|
+
df_shared: pd.DataFrame = df[df[shared_mbr_col].astype(bool)]
|
|
960
960
|
if self._strict:
|
|
961
961
|
existed_mbrs = self._member_memo
|
|
962
962
|
|
|
@@ -989,7 +989,7 @@ class AsyncDimension(ElementBase[DimensionAPI]):
|
|
|
989
989
|
# 在df中丢弃系统中已存在的共享节点
|
|
990
990
|
df_shared_remain = df_shared[~df_shared.index.isin(dup_sharedmbrs)]
|
|
991
991
|
|
|
992
|
-
df_not_shared = df[~df[shared_mbr_col]]
|
|
992
|
+
df_not_shared = df[~df[shared_mbr_col].astype(bool)]
|
|
993
993
|
existed_idx = df_not_shared[DFLT_NAME_COLUMN].isin(existed_mbrs)
|
|
994
994
|
return df_not_shared.loc[existed_idx], \
|
|
995
995
|
pd.concat([df_not_shared.loc[~existed_idx], df_shared_remain])
|
|
@@ -390,6 +390,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
390
390
|
verify_access: bool = False,
|
|
391
391
|
include_ignored: bool = False,
|
|
392
392
|
normalize_view: bool = False,
|
|
393
|
+
pivot_members: List[str] = None,
|
|
393
394
|
) -> Union[pd.DataFrame, Tuple[pd.DataFrame, Dict[str, str]]]:
|
|
394
395
|
"""
|
|
395
396
|
根据维度表达式以及pov获取cube数据
|
|
@@ -403,6 +404,7 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
403
404
|
verify_access: 是否带权限查询
|
|
404
405
|
include_ignored: 包含多版本实体维时,是否在结果中包含无效数据(即i列为1的数据)
|
|
405
406
|
normalize_view: 是否把大小写View统一成"View"
|
|
407
|
+
pivot_members: 如有透视维度,可指定透视成员列表,在透视列成员不存在时补全列
|
|
406
408
|
|
|
407
409
|
.. admonition:: 示例
|
|
408
410
|
|
|
@@ -432,7 +434,9 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
432
434
|
|
|
433
435
|
"""
|
|
434
436
|
pov = self._resolve_pov_as_dict(pov, validate_expr)
|
|
435
|
-
expression, full_pov = self._split_expr(
|
|
437
|
+
expression, full_pov = self._split_expr(
|
|
438
|
+
expression, pov, validate_expr=validate_expr
|
|
439
|
+
)
|
|
436
440
|
pov_expr = dict_to_expr(full_pov)
|
|
437
441
|
|
|
438
442
|
if not expression: # only pov
|
|
@@ -469,10 +473,17 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
469
473
|
|
|
470
474
|
if pivot_dim is not None:
|
|
471
475
|
pivot_col = self._get_column_from_dim(pivot_dim)
|
|
472
|
-
|
|
476
|
+
has_mbrs = isinstance(pivot_members, list)
|
|
477
|
+
if has_mbrs and any(not isinstance(c, str) for c in pivot_members):
|
|
478
|
+
raise ValueError(
|
|
479
|
+
f"Pivot members must be a list of string, got: {pivot_members}"
|
|
480
|
+
)
|
|
473
481
|
if pivot_col in full_pov:
|
|
474
482
|
val = full_pov.pop(pivot_col)
|
|
475
|
-
|
|
483
|
+
if not has_mbrs or val in pivot_members:
|
|
484
|
+
data = data.rename(columns={DFLT_DATA_COLUMN: val})
|
|
485
|
+
else:
|
|
486
|
+
data = data.drop(columns=[DFLT_DATA_COLUMN])
|
|
476
487
|
elif pivot_col not in data.columns:
|
|
477
488
|
raise ValueError(
|
|
478
489
|
f"Pivot dimension: {pivot_dim} does not "
|
|
@@ -488,7 +499,14 @@ class AsyncFinancialCube(ElementBase[FinancialModelAPI]):
|
|
|
488
499
|
columns=pivot_col, aggfunc='first', fill_value=None
|
|
489
500
|
).reset_index(drop=drop_index)
|
|
490
501
|
data.columns.name = None
|
|
491
|
-
|
|
502
|
+
if has_mbrs:
|
|
503
|
+
data = data.drop(columns=filter(
|
|
504
|
+
lambda c: c not in pivot_members and c not in index,
|
|
505
|
+
data.columns
|
|
506
|
+
))
|
|
507
|
+
if has_mbrs:
|
|
508
|
+
mbr_assigns = {m: None for m in pivot_members if m not in data.columns}
|
|
509
|
+
data = data.assign(**mbr_assigns)
|
|
492
510
|
if not compact:
|
|
493
511
|
return data.assign(**full_pov)
|
|
494
512
|
return data, full_pov
|
|
@@ -1573,6 +1591,7 @@ class FinancialCube(AsyncFinancialCube, metaclass=SyncMeta):
|
|
|
1573
1591
|
verify_access: bool = False,
|
|
1574
1592
|
include_ignored: bool = False,
|
|
1575
1593
|
normalize_view: bool = False,
|
|
1594
|
+
pivot_members: List[str] = None,
|
|
1576
1595
|
) -> Union[pd.DataFrame, Tuple[pd.DataFrame, Dict[str, str]]]:
|
|
1577
1596
|
...
|
|
1578
1597
|
|
|
@@ -122,8 +122,7 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
122
122
|
line_df: pd.DataFrame,
|
|
123
123
|
callback: Union[Dict, CallbackInfo] = None,
|
|
124
124
|
relation_field: str = 'journal_id',
|
|
125
|
-
id_col: str =
|
|
126
|
-
operate_type: Literal['EDIT', 'ADD'] = 'ADD',
|
|
125
|
+
id_col: str = MAIN_ID,
|
|
127
126
|
enable_create: bool = True,
|
|
128
127
|
enable_default_value: bool = True,
|
|
129
128
|
enable_repeat_check: bool = True,
|
|
@@ -131,9 +130,10 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
131
130
|
enable_valid_range: bool = True,
|
|
132
131
|
enable_all_errors: bool = True,
|
|
133
132
|
enable_need_one_line: bool = True,
|
|
133
|
+
header_operate: Literal['EDIT', 'ADD', 'DELETE_ADD'] = 'ADD',
|
|
134
|
+
line_operate: Literal['EDIT', 'ADD', 'DELETE', 'DELETE_ADD'] = 'ADD',
|
|
134
135
|
):
|
|
135
136
|
errors = set()
|
|
136
|
-
is_editing = operate_type == 'EDIT'
|
|
137
137
|
|
|
138
138
|
if head_df.empty:
|
|
139
139
|
errors.add('凭证头表数据DataFrame不能为空')
|
|
@@ -143,6 +143,7 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
143
143
|
errors.add('凭证头行表的关联字段relation_field不能为空')
|
|
144
144
|
|
|
145
145
|
self._maybe_raise_errors(errors)
|
|
146
|
+
is_editing = not (header_operate == 'ADD' and line_operate == 'ADD')
|
|
146
147
|
|
|
147
148
|
if is_editing:
|
|
148
149
|
head_required_fields = [relation_field, '_type', id_col]
|
|
@@ -201,7 +202,7 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
201
202
|
index=head_data.index
|
|
202
203
|
)
|
|
203
204
|
)
|
|
204
|
-
head_data = head_data.assign(operateType=
|
|
205
|
+
head_data = head_data.assign(operateType=header_operate)
|
|
205
206
|
|
|
206
207
|
# NB: replace twice in case of infer None to nan happened
|
|
207
208
|
head_df = head_df.replace({None: np.nan})
|
|
@@ -227,7 +228,7 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
227
228
|
self._maybe_raise_errors(errors)
|
|
228
229
|
|
|
229
230
|
line_data = line_df[line_required_fields]
|
|
230
|
-
line_data = line_data.assign(operateType=
|
|
231
|
+
line_data = line_data.assign(operateType=line_operate)
|
|
231
232
|
|
|
232
233
|
# generate lineMainId
|
|
233
234
|
if is_editing:
|
|
@@ -301,7 +302,7 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
301
302
|
enable_need_one_line: bool = True,
|
|
302
303
|
sync: bool = True
|
|
303
304
|
) -> CommonResultDTO:
|
|
304
|
-
"""
|
|
305
|
+
"""凭证模型数据新增
|
|
305
306
|
|
|
306
307
|
Args:
|
|
307
308
|
head_df: 凭证头表的数据(字段名与凭证模型上头表的字段名对应)
|
|
@@ -471,6 +472,8 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
471
472
|
enable_valid_range: bool = True,
|
|
472
473
|
enable_all_errors: bool = True,
|
|
473
474
|
enable_need_one_line: bool = True,
|
|
475
|
+
header_operate: Literal['EDIT', 'DELETE_ADD'] = 'EDIT',
|
|
476
|
+
line_operate: Literal['EDIT', 'ADD', 'DELETE', 'DELETE_ADD'] = 'EDIT',
|
|
474
477
|
) -> CommonResultDTO:
|
|
475
478
|
"""凭证模型数据更新
|
|
476
479
|
|
|
@@ -491,6 +494,10 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
491
494
|
enable_valid_range: 是否启用有效性范围的校验,默认为True
|
|
492
495
|
enable_all_errors: 是否启用一次性校验所有规则和数据,默认为True
|
|
493
496
|
enable_need_one_line: 是否启用凭证行表至少需要一条数据的校验,默认为True
|
|
497
|
+
header_operate: 凭证头表的操作类型,默认为EDIT
|
|
498
|
+
line_operate: 凭证行表的操作类型,默认为EDIT
|
|
499
|
+
头表EDIT, 行表可以ADD/EDIT/DELETE
|
|
500
|
+
头表DELETE_ADD, 头表update,行表全删全增,行表只能为DELETE_ADD
|
|
494
501
|
|
|
495
502
|
Returns:
|
|
496
503
|
接口返回信息(CommonResultDTO的success为true 表示成功,如false 则错误在errors集合里)
|
|
@@ -500,14 +507,16 @@ class AsyncJournalModel(ElementBase[JournalModelAPI]):
|
|
|
500
507
|
batch = self._gen_batch_payload(
|
|
501
508
|
head_df=head_df, line_df=line_df,
|
|
502
509
|
callback=callback, relation_field=relation_field,
|
|
503
|
-
id_col=MAIN_ID,
|
|
510
|
+
id_col=MAIN_ID,
|
|
504
511
|
enable_create=enable_create,
|
|
505
512
|
enable_default_value=enable_default_value,
|
|
506
513
|
enable_repeat_check=enable_repeat_check,
|
|
507
514
|
enable_required=enable_required,
|
|
508
515
|
enable_valid_range=enable_valid_range,
|
|
509
516
|
enable_all_errors=enable_all_errors,
|
|
510
|
-
enable_need_one_line=enable_need_one_line
|
|
517
|
+
enable_need_one_line=enable_need_one_line,
|
|
518
|
+
header_operate=header_operate,
|
|
519
|
+
line_operate=line_operate,
|
|
511
520
|
)
|
|
512
521
|
resp = await self.async_api.journal_model_data.update(batch)
|
|
513
522
|
|
|
@@ -814,6 +823,8 @@ class JournalModel(AsyncJournalModel, metaclass=SyncMeta):
|
|
|
814
823
|
enable_valid_range: bool = True,
|
|
815
824
|
enable_all_errors: bool = True,
|
|
816
825
|
enable_need_one_line: bool = True,
|
|
826
|
+
header_operate: Literal['EDIT', 'DELETE_ADD'] = 'EDIT',
|
|
827
|
+
line_operate: Literal['EDIT', 'ADD', 'DELETE', 'DELETE_ADD'] = 'EDIT',
|
|
817
828
|
) -> CommonResultDTO:
|
|
818
829
|
...
|
|
819
830
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|