# Enterprise Python Plugin

Enterprise Python plugin work is enabled only when the user explicitly asks for a Python plugin, IronPython, or a BOS/Enterprise Python script. Normal enterprise plugin requests use the C# BOS stack.

## Runtime And Scope

Kingdee Cloud Enterprise Python plugins run through IronPython inside BOS and call .NET assemblies such as `Kingdee.BOS`, `Kingdee.BOS.Core`, `Kingdee.BOS.App`, `Kingdee.BOS.Contracts`, and `Kingdee.BOS.ServiceHelper`.

Use Python plugins for form/list/operation/report/convert scripting when BOS registration supports it. Do not use Python for server interfaces, scheduled execution plans, or scenarios that require inheriting and overriding standard C# plugins; those remain C# work.

## Required Planning Facts

Before coding, confirm:

- The user explicitly requested a Python plugin, IronPython, or a BOS/Enterprise Python script.
- Plugin type: bill/form, list, operation service, report service, report form, or convert plugin.
- Target FormId, bill/entity, field keys, entity keys, operation code, and lifecycle event.
- Whether the script will be registered in BOS and where the project stores Python scripts.
- How to test in a BOS test data center.

## Common References

Typical imports:

```python
import clr
clr.AddReference('System')
clr.AddReference('System.Data')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.BOS.App')
clr.AddReference('Kingdee.BOS.Contracts')
clr.AddReference('Kingdee.BOS.ServiceHelper')

from Kingdee.BOS import *
from Kingdee.BOS.Core import *
from Kingdee.BOS.Core.Bill import *
from Kingdee.BOS.Core.DynamicForm.PlugIn import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.Args import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel import *
from Kingdee.BOS.App.Data import *
from Kingdee.BOS.ServiceHelper import *
from System.Collections.Generic import List
```

Use English punctuation and strict indentation. IronPython code does not use `new`; instantiate with `TypeName()`. Generic lists use forms such as `List[object]()` or `List[DynamicObject]()`.

## DynamicObject Patterns

Form plugins can read the current bill data from:

```python
billObj = this.View.Model.DataObject
```

Base data fields return `DynamicObject`; read properties such as `Number`, `Name`, or `Id`. Base data ID fields often use the suffix `_Id`.

Entry entities are usually `DynamicObjectCollection`:

```python
entryRows = billObj["POOrderEntry"]
for row in entryRows:
    materialId = row["MaterialId_Id"]
    qty = row["Qty"]
```

When assigning base data, set both the ID and the data object when required:

```python
field = this.View.BillBusinessInfo.GetField("FMaterialId")
material = BusinessDataServiceHelper.LoadSingle(this.Context, materialId, field.RefFormDynamicObjectType)
row["MaterialId_Id"] = materialId
row["MaterialId"] = material
```

Refresh only the necessary view areas with `this.View.UpdateView("FFieldKey")` or the entity key.

## Form And Bill Plugin Events

Common bill/form plugin events:

- `AfterCreateModelData`: initialize default values after new bill data is created.
- `AfterBindData`: UI state changes after data binding.
- `BarItemClick`: toolbar/menu click handling.
- `ButtonClick`: button or hyperlink handling.
- `EntityRowClick` / `EntityRowDoubleClick`: entry row interactions.
- `DataChanged`: field value linkage when immediate trigger is enabled in BOS.
- `BeforeF7Select`: dynamic F7 filter.
- `BeforeDoOperation`: validate before an operation.
- `AfterDoOperation`: handle after an operation.

For UI messages in form/list plugins, use `this.View.ShowMessage`, `ShowWarnningMessage`, or `ShowErrMessage`.

## Operation Service Plugin Events

Operation service plugins do not have `this.View`.

Common events:

- `OnPreparePropertys`: declare required fields before loading data.
- `OnAddValidators`: register validators.
- `BeforeExecuteOperationTransaction`: before platform transaction execution.
- `BeginOperationTransaction`: transaction begins.
- `EndOperationTransaction`: transaction has completed and data is updated.
- `AfterExecuteOperationTransaction`: after transaction execution.

For service/report/convert plugins, raise an exception for blocking messages:

```python
raise Exception("提示信息")
```

Avoid independent save calls inside platform transaction hooks unless the plan explicitly accepts the transaction risk. Prefer modifying the data entities passed by the platform.

## Query And Save Patterns

Use platform helpers:

- `MetaDataServiceHelper.Load` or `GetFormMetaData` for form metadata.
- `BusinessDataServiceHelper.LoadSingle`, `Load`, `Save`, `Submit`, `Audit`, and `DoNothing`.
- `QueryServiceHelper.GetDynamicObjectCollection` for query builder results.
- `DBUtils.ExecuteDataSet` or `ExecuteDynamicObject` when direct SQL is required.

When writing SQL, use platform-safe patterns and avoid user-input string concatenation. Mark SQL dialect intentionally when using dialect SQL.

## Verification

Python plugin verification is usually BOS registration plus functional testing in a test data center. The plan and verification record should include:

- Script file path.
- Plugin type and BOS registration target.
- FormId, field keys, entity keys, and operation code evidence.
- Test data and operation steps.
- Runtime error or message evidence.
