@shundoo-ai/dsh-cosmic 1.0.19 → 1.0.21
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.
- package/cordis.patch.yml +5 -5
- package/package.json +1 -1
- package/skills/cosmic-build/CHANGELOG.md +4 -0
- package/skills/cosmic-build/LOCAL-PATCHES.md +91 -40
- package/skills/cosmic-build/SKILL.md +46 -13
- package/skills/cosmic-build/assets/platform-report-filters/TypedReportFilterFields.java +169 -0
- package/skills/cosmic-build/assets/platform-report-filters/platform.patch +98 -0
- package/skills/cosmic-build/assets/report-algo-benchmark/ReportAlgoBenchmark.java +48 -0
- package/skills/cosmic-build/assets/report-algo-benchmark/ReportBenchmarkLogFactory.java +7 -0
- package/skills/cosmic-build/examples/java-rules/CosmicEntryQuery.java +26 -0
- package/skills/cosmic-build/examples/java-rules/CosmicReportAggregation.java +35 -0
- package/skills/cosmic-build/examples/java-rules/CosmicReportFilters.java +77 -0
- package/skills/cosmic-build/examples/java-rules/CosmicTimeAdapter.java +25 -0
- package/skills/cosmic-build/examples/java-rules/CosmicTimeAdapterCheck.java +26 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/api/algo/GroupbyDataSet.md +47 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/api/entity/report/FilterInfo.md +12 -12
- package/skills/cosmic-build/knowledge/cosmic/platform/api/entity/report/FilterItemInfo.md +2 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/form-plugin.md +2 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/java-type-contracts.md +11 -2
- package/skills/cosmic-build/knowledge/cosmic/platform/list-plugin.md +18 -14
- package/skills/cosmic-build/knowledge/cosmic/platform/operation-plugin.md +4 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/reportlistdata-plugin.md +17 -9
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/cross-entity-aggregate-writeback.md +2 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/pre-post-operation.md +15 -7
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-algo.md +24 -68
- package/skills/cosmic-build/knowledge/cosmic/platform/workflow-plugin.md +2 -7
- package/skills/cosmic-build/references/application-context.md +35 -1
- package/skills/cosmic-build/references/common-reference.md +1 -1
- package/skills/cosmic-build/references/compile-guide.md +55 -68
- package/skills/cosmic-build/references/delivery.md +59 -7
- package/skills/cosmic-build/references/execution-contract.md +38 -0
- package/skills/cosmic-build/references/form-discovery.md +7 -1
- package/skills/cosmic-build/references/java-plugin-delivery.md +32 -162
- package/skills/cosmic-build/references/operation-dispatch.md +17 -0
- package/skills/cosmic-build/references/plugin-handoff-input.md +131 -0
- package/skills/cosmic-build/references/plugin-runtime-routing.md +1 -1
- package/skills/cosmic-build/references/report-filter-contract.md +78 -0
- package/skills/cosmic-build/references/sdk-inspection.md +23 -0
- package/skills/cosmic-build/schemas/data-model-authoring.schema.json +2 -3
- package/skills/cosmic-build/scripts/_http_client.py +55 -55
- package/skills/cosmic-build/scripts/appconfig_load.py +2 -2
- package/skills/cosmic-build/scripts/apply_report_filter_extension.py +39 -0
- package/skills/cosmic-build/scripts/bootstrap_cosmic_context.py +37 -2
- package/skills/cosmic-build/scripts/compile_plugin_source.py +279 -156
- package/skills/cosmic-build/scripts/execution_binding.py +40 -0
- package/skills/cosmic-build/scripts/inspect_platform_sdk.py +169 -0
- package/skills/cosmic-build/scripts/kd_api.py +23 -22
- package/skills/cosmic-build/scripts/kd_auth.py +1 -1
- package/skills/cosmic-build/scripts/kd_env_loader.py +19 -10
- package/skills/cosmic-build/scripts/kd_token_cache.py +2 -2
- package/skills/cosmic-build/scripts/kingscript_sdk_sync.py +350 -0
- package/skills/cosmic-build/scripts/kingscript_source_gate.py +11 -8
- package/skills/cosmic-build/scripts/platform_api_contract.py +246 -11
- package/skills/cosmic-build/scripts/plugin_corpus/build_index.py +403 -0
- package/skills/cosmic-build/scripts/plugin_corpus/jvm_classfile.py +281 -0
- package/skills/cosmic-build/scripts/plugin_corpus/measure_api_usage.py +446 -0
- package/skills/cosmic-build/scripts/plugin_source_gate.py +48 -7
- package/skills/cosmic-build/scripts/plugin_target_sdk.py +45 -0
- package/skills/cosmic-build/scripts/prepare_plugin_handoff.py +493 -47
- package/skills/cosmic-build/scripts/preview_url.py +35 -6
- package/skills/cosmic-build/scripts/query_plugin_handoff.py +250 -0
- package/skills/cosmic-build/scripts/register_plugins.py +28 -2
- package/skills/cosmic-build/scripts/render_output_cards.py +42 -9
- package/skills/cosmic-build/scripts/report_algo_benchmark.py +46 -0
- package/skills/cosmic-build/scripts/run.py +2 -2
- package/skills/cosmic-build/scripts/sync_generated_locale_assets.py +43 -0
- package/skills/cosmic-build/scripts/test/fixtures/ReportSdkCheck.java +64 -0
- package/skills/cosmic-build/scripts/test/fixtures/java_context_booking_native.json +541 -0
- package/skills/cosmic-build/scripts/test/test_add_rule_business_contract.py +85 -14
- package/skills/cosmic-build/scripts/test/test_batch5_drift_governance.py +12 -3
- package/skills/cosmic-build/scripts/test/test_build_meta_order.py +0 -16
- package/skills/cosmic-build/scripts/test/test_cli_continuation.py +87 -0
- package/skills/cosmic-build/scripts/test/test_compile_plugin_source.py +224 -3
- package/skills/cosmic-build/scripts/test/test_control_authoring.py +123 -4
- package/skills/cosmic-build/scripts/test/test_cosmic_sdk_examples.py +141 -0
- package/skills/cosmic-build/scripts/test/test_data_model_contract.py +30 -5
- package/skills/cosmic-build/scripts/test/test_delivery_stage_boundary.py +2 -10
- package/skills/cosmic-build/scripts/test/test_dym_sync_background.py +11 -0
- package/skills/cosmic-build/scripts/test/test_dynamic_form_metadata_only_contract.py +59 -1
- package/skills/cosmic-build/scripts/test/test_guide_skeleton_contract.py +87 -43
- package/skills/cosmic-build/scripts/test/test_inspect_platform_sdk.py +71 -0
- package/skills/cosmic-build/scripts/test/test_kd_api.py +67 -19
- package/skills/cosmic-build/scripts/test/test_kingscript_sdk_sync.py +221 -0
- package/skills/cosmic-build/scripts/test/test_kingscript_source_gate.py +10 -0
- package/skills/cosmic-build/scripts/test/test_list_configuration_closure.py +18 -0
- package/skills/cosmic-build/scripts/test/test_long_session_regressions.py +116 -0
- package/skills/cosmic-build/scripts/test/test_mcp_cli.py +524 -0
- package/skills/cosmic-build/scripts/test/test_modeling_input_recovery.py +141 -0
- package/skills/cosmic-build/scripts/test/test_open_world_cli_catalog.py +36 -2
- package/skills/cosmic-build/scripts/test/test_platform_api_contract.py +161 -1
- package/skills/cosmic-build/scripts/test/test_plugin_business_contract.py +91 -0
- package/skills/cosmic-build/scripts/test/test_plugin_corpus.py +195 -0
- package/skills/cosmic-build/scripts/test/test_plugin_handoff.py +346 -1
- package/skills/cosmic-build/scripts/test/test_plugin_target_sdk.py +70 -0
- package/skills/cosmic-build/scripts/test/test_preview_url.py +44 -1
- package/skills/cosmic-build/scripts/test/test_property_batch.py +22 -0
- package/skills/cosmic-build/scripts/test/test_property_input_discovery.py +13 -11
- package/skills/cosmic-build/scripts/test/test_query_plugin_handoff.py +160 -0
- package/skills/cosmic-build/scripts/test/test_register_plugins.py +31 -1
- package/skills/cosmic-build/scripts/test/test_render_output_cards.py +50 -4
- package/skills/cosmic-build/scripts/test/test_report_business_contract.py +27 -0
- package/skills/cosmic-build/scripts/test/test_report_doc_contract_sync.py +5 -4
- package/skills/cosmic-build/scripts/test/test_report_sdk_optimization.py +36 -0
- package/skills/cosmic-build/scripts/test/test_rule_batch_evidence.py +1 -1
- package/skills/cosmic-build/scripts/test/test_rule_domain_contract.py +20 -0
- package/skills/cosmic-build/scripts/test/test_rule_function_formula.py +16 -6
- package/skills/cosmic-build/scripts/test/test_skill_entry_contract.py +1 -0
- package/skills/cosmic-build/scripts/test/test_test_environment.py +45 -0
- package/skills/cosmic-build/scripts/test/test_verify_plugin_loading.py +79 -0
- package/skills/cosmic-build/scripts/test_environment.py +49 -0
- package/skills/cosmic-build/scripts/verify_plugin_loading.py +71 -0
- package/skills/cosmic-build/skills/cosmic-coding-impl/SKILL.md +86 -162
- package/skills/cosmic-build/skills/cosmic-coding-script/ATTRIBUTION.md +1 -1
- package/skills/cosmic-build/skills/cosmic-coding-script/SKILL.md +45 -14
- package/skills/cosmic-build/skills/cosmic-coding-script/references/kwc-controller-authoring.md +6 -0
- package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/README.md +29 -19
- package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/docs//350/204/232/346/234/254SDK.md +3 -4
- package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/indexes/package-index.md +1 -1
- package/skills/cosmic-build/skills/cosmic-coding-script/references/sdk/strategy.md +27 -18
- package/skills/cosmic-build/skills/cosmic-meta-api/SKILL.md +11 -17
- package/skills/cosmic-build/skills/cosmic-meta-api/apis/ai_meta.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/apis/app_menu.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/apis/meta_log.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/control-authoring.json +45 -4
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/form-control-traits.json +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/layout-ui.json +18 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/menu-publish.json +8 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/property-batch.json +7 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/property-input-index.json +3 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/report-write-contracts.json +1 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-domain.json +37 -5
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-event-contract.json +24 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/run-build-meta.json +61 -12
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/dropdown-menu.schema.json +69 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/report-write.schema.json +2 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/rule-set.schema.json +1 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/rule-write.schema.json +14 -7
- package/skills/cosmic-build/skills/cosmic-meta-api/docs/api-summary.md +2 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/app-action/SKILL.md +6 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/develop/SKILL.md +1 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/export/SKILL.md +5 -6
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/init/SKILL.md +13 -36
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/SKILL.md +8 -9
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/config.json.example +5 -15
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/reset/SKILL.md +6 -6
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/usage/SKILL.md +20 -148
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/verify/SKILL.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/build_receipts.py +171 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_apps.py +25 -6
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_controls.py +55 -21
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_fields.py +10 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_formactions.py +63 -6
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_forms.py +59 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_listui.py +8 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_metaops.py +36 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_plugins.py +115 -90
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_properties.py +666 -4
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_rules.py +1415 -87
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/commands.py +6 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/config.py +28 -15
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/execution_errors.py +40 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/formatters.py +32 -5
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/property_policy_contract.py +6 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/report_ops.py +113 -17
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/reset.py +3 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/rule_contract.py +107 -26
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/build_meta_order.py +50 -49
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py +856 -150
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/field_decorator.py +47 -14
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_receipt_resume.py +374 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_cli_failure_contract.py +24 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_creation_identity_boundary.py +4 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_dropdown_menu_contract.py +382 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_existing_form_ui.py +0 -25
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_field_decorator.py +50 -6
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_functional_group_resolution.py +83 -16
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_identity_template_resolution.py +103 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_plugin_contract.py +28 -2
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_readback_derivation.py +22 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_typed_filters.py +65 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_write_closure.py +1041 -15
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_post_build_recovery.py +65 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_verification_evidence.py +17 -0
- package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/api-param-checklist.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/rule-modeling-guide.md +7 -4
- package/skills/cosmic-build/skills/cosmic-meta-modeling/SKILL.md +61 -13
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/app-menu/SKILL.md +8 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/formtemplate/SKILL.md +5 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/formtemplate/dynamic-form-artifact-schema.md +5 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/SKILL.md +21 -9
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-entity-graphs.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-storage-constraints.md +5 -3
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-ui-composition.md +6 -3
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/creation-recovery.md +13 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/parse-core.md +3 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_contract.py +6 -1
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_emit.py +135 -87
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/field_type_registry.py +11 -1
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/isv_resolver.py +1 -3
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/report_validator.py +29 -0
- package/skills/cosmic-build/skills/cosmic-meta-modifier/SKILL.md +4 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/context/SKILL.md +2 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/execute/SKILL.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/SKILL.md +5 -4
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/operation-write.md +6 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/validation.md +2 -0
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/SKILL.md +20 -5
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/complex-apis.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/policy-grammar.md +4 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/report-op/SKILL.md +9 -0
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/SKILL.md +61 -4
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/raw-rule-authoring.md +3 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/rule-actions.md +2 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/rule-reference.md +6 -6
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/state.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/unit/SKILL.md +6 -3
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/verify/usage-guide.md +4 -4
- package/skills/cosmic-build/skills/cosmic-meta-modifier/references/list-filter-modification.md +4 -1
- package/skills/cosmic-build/skills/cosmic-meta-ui/SKILL.md +9 -1
- package/skills/cosmic-build/skills/cosmic-meta-ui/modules/button/SKILL.md +3 -0
- package/skills/cosmic-build/skills/mcp-server/SKILL.md +210 -0
- package/skills/cosmic-build/skills/mcp-server/scripts/mcp_cli.py +431 -0
- package/skills/cosmic-build/skills/openapi-gen/SKILL.md +3 -3
- package/skills/cosmic-build/skills/openapi-gen/scripts/api/gen_runner.py +2 -2
- package/skills/cosmic-dev-best-practices/references/bill-dev-convention.md +19 -9
- package/skills/cosmic-dev-best-practices/references/cosmic-meta-api.md +14 -11
- package/skills/cosmic-dev-best-practices/references/design-examples/basedata-design-example.md +1 -1
- package/skills/cosmic-dev-best-practices/references/design-examples/bill-design-example.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/AssistantField.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/BasedataField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/BasedataPropField.md +3 -3
- package/skills/cosmic-dev-best-practices/references/elements/CreaterField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/CurrencyField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/CustomerField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/FlexField.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/MaterielField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/OrgField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/SupplierField.md +2 -2
- package/skills/cosmic-dev-best-practices/references/elements/UnitField.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/UserField.md +3 -3
- package/skills/cosmic-dev-best-practices/references/elements/common-field-property-conventions.md +16 -11
- package/skills/cosmic-dev-best-practices/references/layout-control-convention.md +5 -4
- package/skills/erp-analysis/references/delivery-contract.md +4 -2
- package/skills/erp-analysis/templates/AGENTS.template.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/.dsh/cosmic/.kd/config.json +0 -21
package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_functional_group_resolution.py
CHANGED
|
@@ -360,7 +360,35 @@ def _add_receipt(unit_id: str = "ABCDEF1234", number: str | None = None) -> dict
|
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
|
|
363
|
-
def
|
|
363
|
+
def test_add_unit_missing_code_stops_before_platform_write():
|
|
364
|
+
with mock.patch.object(cmd_apps, "_api_call") as write:
|
|
365
|
+
failure = cmd_apps.do_add_unit({}, "token", biz_app_id="APP-1", name="Group A")
|
|
366
|
+
assert failure["errorCode"] == "FUNCTIONAL_GROUP_CODE_REQUIRED"
|
|
367
|
+
assert failure["writeAttempted"] is False
|
|
368
|
+
write.assert_not_called()
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_add_unit_binds_app_root_and_validates_explicit_application(tmp_path):
|
|
372
|
+
runtime = tmp_path / "_runtime/cosmic-metadata"
|
|
373
|
+
runtime.mkdir(parents=True)
|
|
374
|
+
(tmp_path / "archive.json").write_text(json.dumps({"appCode": "uhyl_zlgl", "appId": "APP-1"}), encoding="utf-8")
|
|
375
|
+
(runtime / "workspace.json").write_text(json.dumps({"appNumber": "uhyl_zlgl", "bizAppId": "APP-1"}), encoding="utf-8")
|
|
376
|
+
assert cosmic_api._unit_app_target(str(tmp_path)) == ("APP-1", None)
|
|
377
|
+
with pytest.raises(RuntimeError, match="APP_TARGET_MISMATCH"):
|
|
378
|
+
cosmic_api._unit_app_target(str(tmp_path), "OTHER-APP")
|
|
379
|
+
receipt = _add_receipt("UNIT-1", "quality_master_data")
|
|
380
|
+
readback = _units_envelope([{"id": "UNIT-1", "number": "quality_master_data", "name": "基础数据"}])
|
|
381
|
+
with mock.patch.object(cmd_apps, "_api_call", return_value=receipt) as write, \
|
|
382
|
+
mock.patch.object(cmd_apps, "do_list_units", return_value=readback):
|
|
383
|
+
result = cosmic_api._dispatch_serve({}, "token", "addUnit", {
|
|
384
|
+
"appRoot": str(tmp_path), "name": "基础数据", "number": "quality_master_data", "seq": 2,
|
|
385
|
+
})
|
|
386
|
+
assert result["status"] is True
|
|
387
|
+
assert write.call_args.args[3] == {"bizAppId": "APP-1", "name": "基础数据",
|
|
388
|
+
"number": "quality_master_data", "description": "基础数据", "seq": 2}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def test_add_unit_explicit_code_defaults_description_and_verifies_root() -> None:
|
|
364
392
|
receipt = _add_receipt()
|
|
365
393
|
readback = {
|
|
366
394
|
"status": True,
|
|
@@ -380,12 +408,12 @@ def test_add_unit_name_only_omits_defaulted_fields_and_verifies_root() -> None:
|
|
|
380
408
|
mock.patch.object(cmd_apps, "do_list_units", return_value=readback) as list_units,
|
|
381
409
|
):
|
|
382
410
|
result = cmd_apps.do_add_unit(
|
|
383
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
411
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
384
412
|
)
|
|
385
413
|
|
|
386
414
|
assert api_call.call_args.args[2:] == (
|
|
387
415
|
"app/unit/add",
|
|
388
|
-
{"bizAppId": "APP-1", "name": "Group A"},
|
|
416
|
+
{"bizAppId": "APP-1", "name": "Group A", "number": "lingee_abcdef1234", "description": "Group A", "seq": 2},
|
|
389
417
|
)
|
|
390
418
|
assert api_call.call_args.kwargs == {"method": "POST"}
|
|
391
419
|
list_units.assert_called_once_with(
|
|
@@ -399,6 +427,45 @@ def test_add_unit_name_only_omits_defaulted_fields_and_verifies_root() -> None:
|
|
|
399
427
|
}
|
|
400
428
|
|
|
401
429
|
|
|
430
|
+
def test_add_unit_without_seq_appends_after_verified_existing_groups() -> None:
|
|
431
|
+
before = _units_envelope([{"id": "HOME", "name": "首页", "number": "MainPage", "seq": 1}])
|
|
432
|
+
after = _units_envelope([
|
|
433
|
+
{"id": "HOME", "name": "首页", "number": "MainPage", "seq": 1},
|
|
434
|
+
{"id": "ABCDEF1234", "name": "Group A", "number": "lingee_abcdef1234", "seq": 2},
|
|
435
|
+
])
|
|
436
|
+
with (
|
|
437
|
+
mock.patch.object(cmd_apps, "_api_call", return_value=_add_receipt()) as write,
|
|
438
|
+
mock.patch.object(cmd_apps, "do_list_units", side_effect=[before, after]) as list_units,
|
|
439
|
+
):
|
|
440
|
+
result = cmd_apps.do_add_unit({}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234")
|
|
441
|
+
assert result["status"] is True
|
|
442
|
+
assert write.call_args.args[3]["seq"] == 2
|
|
443
|
+
assert list_units.call_count == 2
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def test_add_unit_without_verified_sequence_stops_before_write() -> None:
|
|
447
|
+
with (
|
|
448
|
+
mock.patch.object(cmd_apps, "_api_call") as write,
|
|
449
|
+
mock.patch.object(cmd_apps, "do_list_units", return_value=_units_envelope([{"id": "HOME", "name": "首页"}])),
|
|
450
|
+
):
|
|
451
|
+
result = cmd_apps.do_add_unit({}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234")
|
|
452
|
+
assert result["errorCode"] == "FUNCTIONAL_GROUP_SEQ_UNAVAILABLE"
|
|
453
|
+
assert result["writeAttempted"] is False
|
|
454
|
+
write.assert_not_called()
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def test_nested_add_unit_requires_a_sibling_sequence_before_write() -> None:
|
|
458
|
+
with (
|
|
459
|
+
mock.patch.object(cmd_apps, "_api_call") as write,
|
|
460
|
+
mock.patch.object(cmd_apps, "do_list_units") as list_units,
|
|
461
|
+
):
|
|
462
|
+
result = cmd_apps.do_add_unit({}, "token", biz_app_id="APP-1", name="Child", number="child", parent_unit_id="PARENT")
|
|
463
|
+
assert result["errorCode"] == "FUNCTIONAL_GROUP_SEQ_UNAVAILABLE"
|
|
464
|
+
assert result["writeAttempted"] is False
|
|
465
|
+
write.assert_not_called()
|
|
466
|
+
list_units.assert_not_called()
|
|
467
|
+
|
|
468
|
+
|
|
402
469
|
def test_add_unit_full_payload_is_preserved_and_verified() -> None:
|
|
403
470
|
receipt = _add_receipt("UNIT-1", "group_a")
|
|
404
471
|
readback = {
|
|
@@ -444,7 +511,7 @@ def test_add_unit_write_failure_does_not_read_back() -> None:
|
|
|
444
511
|
mock.patch.object(cmd_apps, "do_list_units") as list_units,
|
|
445
512
|
):
|
|
446
513
|
result = cmd_apps.do_add_unit(
|
|
447
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
514
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
448
515
|
)
|
|
449
516
|
|
|
450
517
|
assert result is failed
|
|
@@ -467,7 +534,7 @@ def test_add_unit_readback_failure_is_unknown_after_write(
|
|
|
467
534
|
mock.patch.object(cmd_apps, "do_list_units", return_value=readback),
|
|
468
535
|
):
|
|
469
536
|
result = cmd_apps.do_add_unit(
|
|
470
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
537
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
471
538
|
)
|
|
472
539
|
|
|
473
540
|
assert result["status"] is False
|
|
@@ -505,7 +572,7 @@ def test_add_unit_nested_child_is_not_accepted_as_first_level_readback() -> None
|
|
|
505
572
|
mock.patch.object(cmd_apps, "do_list_units", return_value=readback),
|
|
506
573
|
):
|
|
507
574
|
result = cmd_apps.do_add_unit(
|
|
508
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
575
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
509
576
|
)
|
|
510
577
|
|
|
511
578
|
assert result["errorCode"] == "ADD_UNIT_READBACK_MISMATCH"
|
|
@@ -528,7 +595,7 @@ def test_add_unit_duplicate_or_different_id_readback_fails_closed() -> None:
|
|
|
528
595
|
mock.patch.object(cmd_apps, "do_list_units", return_value=duplicate),
|
|
529
596
|
):
|
|
530
597
|
result = cmd_apps.do_add_unit(
|
|
531
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
598
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
532
599
|
)
|
|
533
600
|
assert result["data"]["verification"]["reason"] == "candidate_count_mismatch"
|
|
534
601
|
|
|
@@ -546,7 +613,7 @@ def test_add_unit_duplicate_or_different_id_readback_fails_closed() -> None:
|
|
|
546
613
|
mock.patch.object(cmd_apps, "do_list_units", return_value=different),
|
|
547
614
|
):
|
|
548
615
|
result = cmd_apps.do_add_unit(
|
|
549
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
616
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
550
617
|
)
|
|
551
618
|
assert result["data"]["verification"]["reason"] == "unit_id_mismatch"
|
|
552
619
|
assert "unitId" not in result["data"]
|
|
@@ -560,7 +627,7 @@ def test_add_unit_readback_exception_fails_closed() -> None:
|
|
|
560
627
|
),
|
|
561
628
|
):
|
|
562
629
|
result = cmd_apps.do_add_unit(
|
|
563
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
630
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
564
631
|
)
|
|
565
632
|
|
|
566
633
|
assert result["errorCode"] == "ADD_UNIT_READBACK_FAILED"
|
|
@@ -574,7 +641,7 @@ def test_add_unit_invalid_default_receipt_fails_before_readback() -> None:
|
|
|
574
641
|
mock.patch.object(cmd_apps, "do_list_units") as list_units,
|
|
575
642
|
):
|
|
576
643
|
result = cmd_apps.do_add_unit(
|
|
577
|
-
{}, "token", biz_app_id="APP-1", name="Group A"
|
|
644
|
+
{}, "token", biz_app_id="APP-1", name="Group A", number="lingee_abcdef1234", seq=2
|
|
578
645
|
)
|
|
579
646
|
|
|
580
647
|
assert result["errorCode"] == "ADD_UNIT_READBACK_MISMATCH"
|
|
@@ -582,11 +649,11 @@ def test_add_unit_invalid_default_receipt_fails_before_readback() -> None:
|
|
|
582
649
|
list_units.assert_not_called()
|
|
583
650
|
|
|
584
651
|
|
|
585
|
-
def
|
|
652
|
+
def test_add_unit_cli_accepts_explicit_code(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
586
653
|
monkeypatch.setattr(
|
|
587
654
|
sys,
|
|
588
655
|
"argv",
|
|
589
|
-
["cosmic_api.py", "addUnit", "--bizAppId", "APP-1", "--name", "Group A"],
|
|
656
|
+
["cosmic_api.py", "addUnit", "--bizAppId", "APP-1", "--name", "Group A", "--number", "group_a"],
|
|
590
657
|
)
|
|
591
658
|
with (
|
|
592
659
|
mock.patch.object(cosmic_api, "load_config", return_value={}),
|
|
@@ -604,7 +671,7 @@ def test_add_unit_cli_accepts_name_only(monkeypatch: pytest.MonkeyPatch) -> None
|
|
|
604
671
|
biz_app_id="APP-1",
|
|
605
672
|
biz_app_number=None,
|
|
606
673
|
name="Group A",
|
|
607
|
-
number=
|
|
674
|
+
number="group_a",
|
|
608
675
|
description=None,
|
|
609
676
|
seq=None,
|
|
610
677
|
parent_unit_id=None,
|
|
@@ -612,12 +679,12 @@ def test_add_unit_cli_accepts_name_only(monkeypatch: pytest.MonkeyPatch) -> None
|
|
|
612
679
|
)
|
|
613
680
|
|
|
614
681
|
|
|
615
|
-
def
|
|
682
|
+
def test_serve_add_unit_uses_shared_implementation() -> None:
|
|
616
683
|
with mock.patch.object(
|
|
617
684
|
cosmic_api, "do_add_unit", return_value={"status": True}
|
|
618
685
|
) as add_unit:
|
|
619
686
|
result = cosmic_api._dispatch_serve(
|
|
620
|
-
{}, "token", "addUnit", {"bizAppId": "APP-1", "name": "Group A"}
|
|
687
|
+
{}, "token", "addUnit", {"bizAppId": "APP-1", "name": "Group A", "number": "group_a"}
|
|
621
688
|
)
|
|
622
689
|
|
|
623
690
|
assert result == {"status": True}
|
|
@@ -627,7 +694,7 @@ def test_serve_add_unit_name_only_uses_shared_implementation() -> None:
|
|
|
627
694
|
biz_app_id="APP-1",
|
|
628
695
|
biz_app_number=None,
|
|
629
696
|
name="Group A",
|
|
630
|
-
number=
|
|
697
|
+
number="group_a",
|
|
631
698
|
description=None,
|
|
632
699
|
seq=None,
|
|
633
700
|
parent_unit_id=None,
|
package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_identity_template_resolution.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import pytest
|
|
4
|
+
from types import SimpleNamespace
|
|
5
|
+
|
|
6
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
7
|
+
from _core import cmd_forms, cmd_properties
|
|
8
|
+
import cosmic_api
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_key_rename_uses_single_setter_and_new_key_readback(monkeypatch):
|
|
12
|
+
calls = []
|
|
13
|
+
monkeypatch.setattr(cmd_properties, "do_get_property_schema", lambda *args:
|
|
14
|
+
{"status": True, "data": [{"propertyName": "Key", "editable": True,
|
|
15
|
+
"complexity": "simple", "editorType": "text"}]})
|
|
16
|
+
def write(cfg, token, form, key, properties):
|
|
17
|
+
calls.append(("write", key, properties))
|
|
18
|
+
return {"status": True, "data": {}}
|
|
19
|
+
def read(cfg, token, form, key, names):
|
|
20
|
+
calls.append(("read", key, names))
|
|
21
|
+
return {"status": True, "data": {"Key": key}}
|
|
22
|
+
monkeypatch.setattr(cmd_properties, "do_set_properties", write)
|
|
23
|
+
monkeypatch.setattr(cmd_properties, "do_get_properties", read)
|
|
24
|
+
result = cmd_properties.do_set_properties_verified({}, "", "form", "acme_old", {"Key": "acme_new"})
|
|
25
|
+
assert result["verification"]["verified"]
|
|
26
|
+
assert calls == [("write", "acme_old", {"Key": "acme_new"}), ("read", "acme_new", ["Key"])]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_cli_key_rename_applies_developer_prefix_once(monkeypatch, tmp_path):
|
|
30
|
+
monkeypatch.setattr(cosmic_api, "_load_workspace_at",
|
|
31
|
+
lambda root: {"isv": "uhyl", "standard": False})
|
|
32
|
+
args = SimpleNamespace(app_root=str(tmp_path))
|
|
33
|
+
assert cosmic_api._normalize_key_property(args, {"Key": "sample_description"})["Key"] == "uhyl_sample_description"
|
|
34
|
+
assert cosmic_api._normalize_key_property(args, {"Key": "uhyl_sample_description"})["Key"] == "uhyl_sample_description"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_rename_element_key_migrates_rules_and_preserves_layout(monkeypatch, tmp_path):
|
|
38
|
+
args = SimpleNamespace(formNumber="form", element="申请说明",
|
|
39
|
+
new_key="sample_description", app_root=str(tmp_path))
|
|
40
|
+
monkeypatch.setattr(cosmic_api, "_load_workspace_at",
|
|
41
|
+
lambda root: {"isv": "uhyl", "standard": False})
|
|
42
|
+
monkeypatch.setattr(cosmic_api, "resolve_element_selector",
|
|
43
|
+
lambda *args: "uhyl_apply_note")
|
|
44
|
+
before = {"key": "uhyl_apply_note", "name": "申请说明", "type": "TextField",
|
|
45
|
+
"parentKey": "head", "index": 4}
|
|
46
|
+
after = {**before, "key": "uhyl_sample_description"}
|
|
47
|
+
element_reads = iter([
|
|
48
|
+
{"status": True, "data": [before]},
|
|
49
|
+
{"status": True, "data": [after]},
|
|
50
|
+
])
|
|
51
|
+
monkeypatch.setattr(cosmic_api, "do_list_elements", lambda *args: next(element_reads))
|
|
52
|
+
rule_before = {"ruleId": "r1", "ruleType": "formRule",
|
|
53
|
+
"preCondition": "uhyl_apply_note = '加急'",
|
|
54
|
+
"triggerField": "申请说明(uhyl_apply_note)"}
|
|
55
|
+
rule_after = {**rule_before, "preCondition": "uhyl_sample_description = '加急'",
|
|
56
|
+
"triggerField": "申请说明(uhyl_sample_description)"}
|
|
57
|
+
rule_reads = iter([
|
|
58
|
+
{"status": True, "data": {"rules": [rule_before]}},
|
|
59
|
+
{"status": True, "data": {"rules": [rule_after]}},
|
|
60
|
+
])
|
|
61
|
+
monkeypatch.setattr(cosmic_api, "do_list_rules", lambda *args: next(rule_reads))
|
|
62
|
+
writes = []
|
|
63
|
+
monkeypatch.setattr(cosmic_api, "do_set_properties_verified",
|
|
64
|
+
lambda cfg, token, form, key, props:
|
|
65
|
+
writes.append((key, props)) or
|
|
66
|
+
{"status": True, "verification": {"verified": True}})
|
|
67
|
+
patches = []
|
|
68
|
+
monkeypatch.setattr(cosmic_api, "do_update_rule_verified",
|
|
69
|
+
lambda cfg, token, form, patch:
|
|
70
|
+
patches.append(patch) or
|
|
71
|
+
{"status": True, "verification": {"verified": True}})
|
|
72
|
+
result = cosmic_api._rename_element_key({}, "", args)
|
|
73
|
+
assert result["verification"] == {
|
|
74
|
+
"verified": True, "preservationVerified": True,
|
|
75
|
+
"oldKeyAbsent": True, "newKeyPresent": True, "staleRuleIds": [],
|
|
76
|
+
}
|
|
77
|
+
assert writes == [("uhyl_apply_note", {"Key": "uhyl_sample_description"})]
|
|
78
|
+
assert patches == [{"ruleType": "formRule", "ruleId": "r1",
|
|
79
|
+
"preCondition": "uhyl_sample_description = '加急'",
|
|
80
|
+
"triggerField": "申请说明(uhyl_sample_description)"}]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_template_code_and_name_use_same_live_identity():
|
|
84
|
+
rows = [{"number": "vendor_tpl", "name": "单据带组织模板", "modelType": "BillFormModel"}]
|
|
85
|
+
for selector in ("vendor_tpl", "单据带组织模板", "单据带组织模版"):
|
|
86
|
+
assert cmd_forms.resolve_template_selector(selector, rows, "BillFormModel") == "vendor_tpl"
|
|
87
|
+
assert cmd_forms.resolve_template_selector("单据带组织模版",
|
|
88
|
+
[dict(rows[0], name="单据(带组织)")], "BillFormModel") == "vendor_tpl"
|
|
89
|
+
with pytest.raises(ValueError, match="TEMPLATE_NAME_AMBIGUOUS"):
|
|
90
|
+
cmd_forms.resolve_template_selector("单据带组织模板", rows + [
|
|
91
|
+
dict(rows[0], number="other_tpl")], "BillFormModel")
|
|
92
|
+
with pytest.raises(ValueError, match="TEMPLATE_NOT_FOUND"):
|
|
93
|
+
cmd_forms.resolve_template_selector("单据带组织模板", rows, "BaseFormModel")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_ascii_template_name_still_uses_live_directory(monkeypatch):
|
|
97
|
+
monkeypatch.setattr(cmd_forms, "do_get_template_list", lambda *args, **kwargs:
|
|
98
|
+
[{"number": "vendor_tpl", "name": "OrganizationTemplate",
|
|
99
|
+
"modelType": "BillFormModel"}])
|
|
100
|
+
assert cmd_forms.resolve_template_input({}, "", "OrganizationTemplate",
|
|
101
|
+
model_type="BillFormModel") == "vendor_tpl"
|
|
102
|
+
assert cmd_forms.resolve_template_input({}, "", "bos_billorgtpl",
|
|
103
|
+
model_type="BillFormModel") == "bos_billorgtpl"
|
package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_plugin_contract.py
CHANGED
|
@@ -211,7 +211,7 @@ class CompileReportPluginContractTest(unittest.TestCase):
|
|
|
211
211
|
)
|
|
212
212
|
requirements = {row["requirement"] for row in contract["filterEnforcement"]}
|
|
213
213
|
self.assertEqual(requirements, {"compare", "mustInput", "defaultValue"})
|
|
214
|
-
self.assertIn('
|
|
214
|
+
self.assertIn('getFilterItems()', contract["filterEnforcement"][0]["java"])
|
|
215
215
|
|
|
216
216
|
def test_every_filter_carries_its_comparison_as_a_requirement(self):
|
|
217
217
|
"""compare is not persisted at all, so query() is the only place it can be applied.
|
|
@@ -231,7 +231,33 @@ class CompileReportPluginContractTest(unittest.TestCase):
|
|
|
231
231
|
if row["requirement"] == "compare"]
|
|
232
232
|
self.assertEqual([(row["filterKey"], row["value"]) for row in compares],
|
|
233
233
|
[("flt_date", "between"), ("flt_sup", "in")])
|
|
234
|
-
self.assertIn('
|
|
234
|
+
self.assertIn('getValue("flt_sup")', compares[1]["java"])
|
|
235
|
+
|
|
236
|
+
def test_filter_contract_keeps_explicit_source_mapping_without_claiming_runtime_proof(self):
|
|
237
|
+
contract = report_ops.compile_report_plugin_contract({
|
|
238
|
+
"reportFilters": [{"fieldPath": "flt_sourcearea", "compare": "in"},
|
|
239
|
+
{"fieldPath": "flt_date", "compare": "between"}],
|
|
240
|
+
"reportProperties": {"filterFieldConfig": [{"key": "flt_sourcearea",
|
|
241
|
+
"fieldName": "shfz_admindivision", "dataSourceId": "arrival-form-id"}]},
|
|
242
|
+
}, "test_report")
|
|
243
|
+
area, dates = contract["filterValueContracts"]
|
|
244
|
+
self.assertEqual(area["candidateValueKeys"], ["shfz_admindivision", "flt_sourcearea", "shfz_sourcearea"])
|
|
245
|
+
self.assertFalse(area["runtimeKeysVerified"])
|
|
246
|
+
self.assertEqual(area["sourceBinding"], {"fieldName": "shfz_admindivision", "dataSourceId": "arrival-form-id"})
|
|
247
|
+
self.assertEqual(dates["valueChannel"], "getFilterItems")
|
|
248
|
+
self.assertEqual(dates["rangeItemKeys"], {"start": "flt_date_startdate", "end": "flt_date_enddate"})
|
|
249
|
+
self.assertEqual(contract["permissionFilterChannel"], "getQFilters")
|
|
250
|
+
|
|
251
|
+
def test_compatibility_candidates_do_not_invent_a_project_namespace(self):
|
|
252
|
+
contract = report_ops.compile_report_plugin_contract({
|
|
253
|
+
"reportFilters": [{"fieldPath": "flt_supplier", "compare": "in"}],
|
|
254
|
+
}, "acme_report")
|
|
255
|
+
self.assertEqual(contract["filterValueContracts"][0]["candidateValueKeys"], ["flt_supplier"])
|
|
256
|
+
contract = report_ops.compile_report_plugin_contract({
|
|
257
|
+
"reportFilters": [{"fieldPath": "flt_area", "compare": "in"}],
|
|
258
|
+
"reportProperties": {"filterFieldConfig": [{"key": "flt_area", "fieldName": "acme_region"}]},
|
|
259
|
+
}, "acme_report")
|
|
260
|
+
self.assertEqual(contract["filterValueContracts"][0]["candidateValueKeys"], ["acme_region", "flt_area", "acme_area"])
|
|
235
261
|
|
|
236
262
|
def test_default_valued_filter_properties_are_not_requirements(self):
|
|
237
263
|
contract = _compile(
|
package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_readback_derivation.py
CHANGED
|
@@ -108,6 +108,28 @@ class TestColumnsFromLayout(unittest.TestCase):
|
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
class TestFiltersFromLayout(unittest.TestCase):
|
|
111
|
+
def test_fieldap_filters_read_actual_entity_types(self):
|
|
112
|
+
layout = _layout()
|
|
113
|
+
layout["children"][1]["children"][0]["children"] = [
|
|
114
|
+
{"key": key, "type": "FieldAp", "name": key}
|
|
115
|
+
for key in ("startdate", "orgscope", "resultms")
|
|
116
|
+
] + [{"key": "label", "type": "LabelAp", "name": "Label"}]
|
|
117
|
+
schema_text = "### Entity: kdtest_rpt (Report) [ReportEntity]\n" + "\n".join([
|
|
118
|
+
"Field: startdate (Start Date) Type=DateField",
|
|
119
|
+
"Field: orgscope (Organizations) Type=MulBaseDataField",
|
|
120
|
+
"Field: resultms (Result) Type=ComboListField",
|
|
121
|
+
"Field: column_only (Column Only) Type=TextField",
|
|
122
|
+
])
|
|
123
|
+
filters = _filters_from_layout(layout, schema_text)
|
|
124
|
+
self.assertEqual(["startdate", "orgscope", "resultms"], [row["fieldPath"] for row in filters])
|
|
125
|
+
self.assertEqual(["DateField", "MulBaseDataField", "ComboListField"], [row["fieldType"] for row in filters])
|
|
126
|
+
self.assertTrue(all(row["controlType"] == "FieldAp" for row in filters))
|
|
127
|
+
|
|
128
|
+
def test_fieldap_without_entity_evidence_does_not_guess_text(self):
|
|
129
|
+
layout = _layout()
|
|
130
|
+
layout["children"][1]["children"][0]["children"] = [{"key": "date", "type": "FieldAp", "name": "Date"}]
|
|
131
|
+
self.assertEqual([{"fieldPath": "date", "displayName": "Date", "controlType": "FieldAp"}], _filters_from_layout(layout))
|
|
132
|
+
|
|
111
133
|
def test_filter_controls_are_derived_with_control_type(self):
|
|
112
134
|
filters = _filters_from_layout(_layout())
|
|
113
135
|
self.assertEqual(["biz_date", "sup_number"], [item["fieldPath"] for item in filters])
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
6
|
+
from _core import report_ops
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def request():
|
|
10
|
+
return report_ops.normalize_report_filters_input([{
|
|
11
|
+
"fieldPath": "flt_supplier", "displayName": "Supplier", "compare": "in",
|
|
12
|
+
"source": {"formNumber": "purchase", "fieldKey": "supplier"},
|
|
13
|
+
}])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_source_is_typed_input_and_not_an_arbitrary_field_selector():
|
|
17
|
+
item = request()[0]
|
|
18
|
+
assert report_ops._build_filters_payload([item])[0]["source"] == item["source"]
|
|
19
|
+
with pytest.raises(ValueError):
|
|
20
|
+
report_ops.normalize_report_filters_input([{**item, "source": {"formNumber": "purchase", "fieldType": "TextField"}}])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_legacy_platform_rejected_before_write_and_never_falls_back(monkeypatch):
|
|
24
|
+
writes = []
|
|
25
|
+
monkeypatch.setattr(report_ops, "_get_schema", lambda *args: {"data": {"schemaText": "legacy"}})
|
|
26
|
+
monkeypatch.setattr(report_ops, "_set_complex", lambda *args: writes.append(args))
|
|
27
|
+
with pytest.raises(RuntimeError, match="PLATFORM_UNSUPPORTED"):
|
|
28
|
+
report_ops.set_report_filters({}, "token", "report", request(), form_number="report")
|
|
29
|
+
assert writes == []
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_typed_source_uses_dedicated_route(monkeypatch):
|
|
33
|
+
calls = []
|
|
34
|
+
monkeypatch.setattr(report_ops, "_get_schema", lambda *args: {"data": {"fieldSchemas": [
|
|
35
|
+
{"fieldPath": "supplier", "fieldType": "BasedataField", "referenceEntityId": "bd_supplier"}]}})
|
|
36
|
+
monkeypatch.setattr(report_ops, "_assert_report_entity_writable", lambda *args, **kwargs: None)
|
|
37
|
+
monkeypatch.setattr(report_ops, "_set_complex", lambda *args: calls.append(args) or {"success": True})
|
|
38
|
+
report_ops.set_report_filters({}, "token", "report", request(), form_number="report")
|
|
39
|
+
assert calls[0][3] == "ReportFilters.typed"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_readback_compares_fresh_source_reference_and_enum_configuration(monkeypatch):
|
|
43
|
+
source = {"fieldPath": "supplier", "fieldType": "BasedataField", "referenceEntityId": "bd_supplier", "displayProp": "name"}
|
|
44
|
+
monkeypatch.setattr(report_ops, "_get_schema", lambda *args: {"data": {"fieldSchemas": [source]}})
|
|
45
|
+
schema = {"readBackAvailable": True, "readBackSource": "formLayout", "typedFiltersReadBack": True,
|
|
46
|
+
"undecidableFilterProperties": ["compare", "defaultValue", "visible"],
|
|
47
|
+
"filterSourceExpectations": report_ops.report_filter_source_expectations({}, "token", request()),
|
|
48
|
+
"reportFilters": [{**source, "fieldPath": "flt_supplier", "displayName": "Supplier"}]}
|
|
49
|
+
assert report_ops.report_readback_verification("filters", request(), schema)["verified"]
|
|
50
|
+
schema["reportFilters"][0]["referenceEntityId"] = "wrong-reference"
|
|
51
|
+
assert not report_ops.report_readback_verification("filters", request(), schema)["verified"]
|
|
52
|
+
schema["reportFilters"][0]["referenceEntityId"] = "bd_supplier"
|
|
53
|
+
del schema["typedFiltersReadBack"]
|
|
54
|
+
assert not report_ops.report_readback_verification("filters", request(), schema)["verified"]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_date_range_and_ambiguous_source_fail_closed(monkeypatch):
|
|
58
|
+
items = [{"fieldPath": "flt_date", "compare": "between", "source": {"formNumber": "purchase", "fieldKey": "date"}}]
|
|
59
|
+
monkeypatch.setattr(report_ops, "_get_schema", lambda *args: {"data": {"fieldSchemas": [
|
|
60
|
+
{"fieldPath": "date", "fieldType": "DateField", "timeZoneTransType": 0}]}})
|
|
61
|
+
assert report_ops.report_filter_source_expectations({}, "token", items)["flt_date"]["fieldType"] == "DateRangeField"
|
|
62
|
+
monkeypatch.setattr(report_ops, "_get_schema", lambda *args: {"data": {"fieldSchemas": [
|
|
63
|
+
{"fieldPath": "date", "fieldType": "TextField"}]}})
|
|
64
|
+
with pytest.raises(ValueError, match="RANGE_TYPE_UNSUPPORTED"):
|
|
65
|
+
report_ops.report_filter_source_expectations({}, "token", items)
|