# `Sp_productionPlanInfo_BtnEventCancelRelease` (procedure)

> 机台计划：取消下达


- **Type:** PROCEDURE
- **Deterministic:** NO
- **SQL data access:** CONTAINS SQL

## Parameters

| # | Mode | Name | Type |
|---|---|---|---|
| 1 | IN | `sProInParam` | `longtext` |
| 2 | IN | `sMakePerson` | `varchar(100)` |
| 3 | IN | `sBrId` | `varchar(100)` |
| 4 | IN | `sSuId` | `varchar(100)` |
| 5 | OUT | `sReturn` | `varchar(1000)` |
| 6 | OUT | `sCode` | `int` |

## Body

_Body is not pre-cached. To inspect: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE PROCEDURE `Sp_productionPlanInfo_BtnEventCancelRelease`'`._

## Narrative

**Business context:** 生产计划管理 → 生管主计划 / 生产排程 — 机台计划：取消下达 (per the COMMENT). Per-row inverse of the 下达 (release-to-floor) action: reverts a released `mftproductionplanslave` row back to its pre-release state so the planner can re-edit or reroute it. Skips frozen rows with a tracked-but-non-fatal `sCode=1` and `chooseData` / 冻结 messaging.

**What it does:** Parses the same `$.params[*].slave/slaveInfo[*].sId` shape used across the BtnEvent family. For each dash-separated `sId`: reads `bFrozen, sState, bLock` from `mftproductionplanslave`. If `bFrozen=1`, sets `sCode=1` and emits the "冻结的单子已跳过,请先解冻工单" message — the full body (truncated in this preview) then performs the actual cancel-release write: clearing `bEmploy`, `sEmployPerson`, `tEmploytime`, and rolling `sState` back to the unreleased value, plus the matching `mftproductionplanslavelock` cleanup when `bLock=1`.

**Invocation:** Dispatched dynamically by `GenericProcedureCallServiceImpl.doGenericProcedureCall()` from the 取消下达 toolbar action on 排程信息表 / 排程从表 / 机台计划执行情况 grids under 生产排程 (and the `Info`-suffixed `_BtnEvent_*` sibling family). xly-src `script/标版/30100101/schedule/Sp_productionPlanInfo_BtnEventCancelRelease.sql` ships the install copy. Related: `Sp_productionPlanInfo_BtnEventConfirm` (confirm) and `Sp_productionPlanInfo_BtnEventUnChange` (the actual release-trigger sibling) both reference this name in their bodies.
