/install biolims-skill
\r \r
Bio-LIMS (v2.0)\r
\r
A skill for calling Bio-LIMS backend APIs. All API calls are made through scripts/biolims.mjs, with automatic token management.\r
\r
Module Features:\r
- Order Management\r
- Sample Receive\r
- Sample Type Query\r
- Experiment Template Management\r \r
Quick Start\r
\r
# Script path (absolute path)\r
SCRIPT="/home/biolims/.openclaw/workspace/skills/biolims/scripts/biolims.mjs"\r
\r
# Query order details\r
node "$SCRIPT" order ORDER202401180001\r
\r
# Paginated query of order list (default page 1, 10 per page)\r
bash "$SCRIPT" order-list\r
bash "$SCRIPT" order-list 1 20 # Page 1, 20 per page\r
\r
# Query order sample list\r
bash "$SCRIPT" order-samples ORDER202401180001\r
\r
# Query order fee information\r
bash "$SCRIPT" order-fees ORDER202401180001\r
\r
# Create new order (Note: field names must be exact!)\r
# sampleOrderItem cannot be written as samples!\r
# crmConsumeRmarkets cannot be written as fees!\r
bash "$SCRIPT" create-order '{\r
"order": {\r
"name": "John Smith",\r
"productId": "PROD001",\r
"productName": "Genetic Testing"\r
},\r
"sampleOrderItem": [\r
{\r
"slideCode": "BC123",\r
"sampleTypeId": "T250724002",\r
"sampleType": "Whole Blood",\r
"productId": "PROD001",\r
"productName": "Genetic Testing"\r
}\r
],\r
"crmConsumeRmarkets": [\r
{\r
"fee": 3500.00,\r
"feeWay": "Bank Transfer",\r
"isFee": "1"\r
}\r
]\r
}'\r
\r
# Update order\r
bash "$SCRIPT" update-order '{"order":{"id":"ORDER123","name":"Jane Smith",...}}'\r
\r
# Complete order\r
bash "$SCRIPT" complete-order ORDER202401180001\r
\r
# Cancel order\r
bash "$SCRIPT" cancel-order ORDER202401180001\r
\r
# Query all sample types\r
bash "$SCRIPT" sample-types\r
\r
# Search sample types (fuzzy match by name)\r
bash "$SCRIPT" search-sample-type "Blood"\r
\r
# ==================== Sample Receive Commands ====================\r
\r
# Query receive order list\r
bash "$SCRIPT" receive-list\r
bash "$SCRIPT" receive-list 1 20 # Page 1, 20 per page\r
\r
# Query single receive order details\r
bash "$SCRIPT" receive SR202401180001\r
\r
# Query receive order sample detail list\r
bash "$SCRIPT" receive-samples SR202401180001\r
bash "$SCRIPT" receive-samples SR202401180001 1 50 # Page 1, 50 per page\r
\r
# Scan barcode to get sample info (receive_id is required, must create receive order first)\r
# Input format: { "sampleReceive": { "id": "...", "name": "...", "acceptDate": "...", "isBoard": "..." }, "barCode": "..." }\r
bash "$SCRIPT" scan-barcode BC20240118001 SR202401180001\r
\r
# Scan order number to get unreceived samples\r
bash "$SCRIPT" scan-order ORD202401180001\r
bash "$SCRIPT" scan-order ORD202401180001 SR202401180001 # Specify receive order ID\r
\r
# Create receive order (Note: field names must be exact!)\r
# sampleReceiveItems cannot be written as samples!\r
# addBoardInfo cannot be written as boardInfo!\r
bash "$SCRIPT" create-receive '{\r
"sampleReceive": {\r
"name": "Clinical Sample Receive",\r
"acceptDate": "2024-01-18 10:00",\r
"expressNum": "SF1234567890",\r
"expressCompanyId": "EC001",\r
"expressCompanyName": "SF Express",\r
"transportTypeId": "TT001",\r
"transportTypeName": "Cold Chain Transport",\r
"isBoard": "1"\r
},\r
"sampleReceiveItems": [\r
{\r
"sampleCode": "S001",\r
"barCode": "BC001",\r
"orderCode": "ORD001",\r
"patientName": "John Smith",\r
"gender": "1",\r
"dicSampleType": "Whole Blood",\r
"dicSampleTypeId": "T250724002",\r
"productName": "Genetic Testing",\r
"sampleNum": "5",\r
"unit": "ml",\r
"isGood": "1",\r
"nextFlow": "Warehousing"\r
}\r
],\r
"addBoardInfo": "{\"banHao\":\"P001\",\"rowNum\":8,\"colNum\":12}"\r
}'\r
\r
# Update receive order (uses same API as create-receive)\r
bash "$SCRIPT" update-receive '{"sampleReceive":{"id":"SR202401180001",...},...}'\r
\r
# Complete receive order\r
bash "$SCRIPT" complete-receive SR202401180001\r
\r
# Delete sample receive detail items\r
bash "$SCRIPT" delete-receive-item SR202401180001 "ITEM001,ITEM002"\r
\r
# Get available order list (for order number mode selection)\r
bash "$SCRIPT" get-orders-for-receive\r
bash "$SCRIPT" get-orders-for-receive 1 10 # Page 1, 10 per page\r
\r
# ==================== Experiment Template Commands ====================\r
\r
# Query experiment template list\r
bash "$SCRIPT" et-list\r
bash "$SCRIPT" et-list 1 20 # Page 1, 20 per page\r
bash "$SCRIPT" et-list 1 10 "PCR" # Fuzzy search by template name\r
\r
# Query template details (three-layer structure: template -> steps -> components)\r
bash "$SCRIPT" et-detail ET2024000001\r
bash "$SCRIPT" et-detail ET2024000001 edit # Edit mode\r
\r
# Create template (pass JSON directly or read from file)\r
bash "$SCRIPT" et-create '{"templateName":"...","stepDetails":[...]}'\r
bash "$SCRIPT" et-create @/tmp/template.json\r
\r
# Copy template (deep copy, including attachments)\r
bash "$SCRIPT" et-copy ET2024000001\r
\r
# Cancel template (supports multiple IDs)\r
bash "$SCRIPT" et-cancel ET2024000001\r
bash "$SCRIPT" et-cancel ET001 ET002 ET003\r
\r
# Complete template (workflow callback, state -> 1)\r
bash "$SCRIPT" et-complete ET2024000001\r
\r
# Query all completed templates (for selection by other modules)\r
bash "$SCRIPT" et-all-completed\r
\r
# Query experiment types (query available types before creating template)\r
bash "$SCRIPT" et-exp-types\r
bash "$SCRIPT" et-exp-types-search "PCR"\r
\r
# Query approver list\r
bash "$SCRIPT" et-approvers \x3Cgroup_id>\r
\r
# Query experiment group list\r
bash "$SCRIPT" et-groups\r
```\r
\r
## Common Usage Scenarios\r
\r
### Scenario 1: User asks about order information\r
\r
**User**: "Help me check order ORDER202401180001"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" order ORDER202401180001`\r
2. Parse the returned JSON, extract key information\r
3. Reply to user in a clear list format\r
\r
**Reply Example** (strictly follow field mapping):\r
```\r
OK, found the information for order ORDER202401180001:\r
\r
=== Patient Information ===\r
Order ID: ORDER202401180001\r
Patient Name: John Smith\r
Gender: Male\r
Age: 35\r
Date of Birth: 1989-05-15\r
Phone Number: [phone_number]\r
Email: [email]\r
ZIP Code: 200000\r
\r
=== Product & Test Information ===\r
Test Item ID: PROD001\r
Test Item(s): Genetic Testing Panel\r
Barcode: BC123456789\r
Clinical Diagnosis: Cancer Stage II\r
\r
=== Order Status ===\r
Status: Complete\r
Order Progress: Clinical Sample Registration\r
\r
=== Creator & Approver ===\r
Created by: HX\r
Created at: 2024-01-18 10:30:00\r
Approved by: Dr. Wang\r
Completed at: 2024-01-18 15:00:00\r
\r
=== Hospital & Medical Information ===\r
Medical Institutions: Shanghai General Hospital\r
Clinical Department: Oncology\r
Attending Physician: Dr. Wang\r
Physician Contact No.: [phone_number]\r
Province: Shanghai\r
```\r
\r
**Important Reminders**:\r
- Use English field display names (e.g., "Patient Name", not Chinese equivalents)\r
- Patient name is a single field `name`, do not split it for display\r
- Display by field groups (Patient Information, Product Information, etc.)\r
- Only show fields that have values\r
- This system **does not use** firstName/lastName, only the `name` field\r
\r
### Scenario 2: Query order list\r
\r
**User**: "What are the recent orders?"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" order-list 1 10`\r
2. Parse the returned list\r
3. Display recent orders\r
\r
**Reply Example** (list mode, simplified display):\r
```\r
Recent 10 orders (72 total):\r
\r
1. Order ID: DD2602030022\r
Patient Name: John Smith\r
Test Item(s): LymphDetect\r
Status: COMPLETE\r
Created at: 2026-02-03 05:47:02\r
\r
2. Order ID: DD2602030021\r
Patient Name: Jane Doe\r
Test Item(s): Genetic Panel\r
Status: NEW\r
Created at: 2026-02-02 10:30:00\r
\r
3. Order ID: DD2602030020\r
Patient Name: Bob Wilson\r
Test Item(s): Cancer Screening\r
Status: Submitted\r
Created at: 2026-02-01 14:20:00\r
\r
...\r
\r
To view details of a specific order, please provide the order number.\r
```\r
\r
**Important**: List mode only shows key fields, uses English display names, patient name uses single `name` field\r
\r
### Scenario 3: View order samples\r
\r
**User**: "What samples does order ORDER202401180001 have?"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" order-samples ORDER202401180001`\r
2. Display sample list\r
\r
**Reply Example**:\r
```\r
Sample list for order ORDER202401180001:\r
\r
1. Blood Sample\r
- Barcode: BC202401180001\r
- Type: Whole Blood\r
- Sampling Time: 2024-01-18 09:30\r
- Status: Received\r
\r
2. Saliva Sample\r
- Barcode: BC202401180002\r
- Type: Saliva\r
- Sampling Time: 2024-01-18 09:35\r
- Status: Processing\r
```\r
\r
### Scenario 4: Query sample types\r
\r
**User**: "What sample types are available?" or "I need the type ID for blood samples"\r
\r
**AI Actions**:\r
1. If user provided a specific name (e.g., "Blood"), call: `bash "$SCRIPT" search-sample-type "Blood"`\r
2. If user did not provide a name, call: `bash "$SCRIPT" sample-types`\r
3. Display sample type list including ID, name, and code\r
\r
**Reply Example**:\r
```\r
Found 1 matching sample type:\r
\r
Name: Whole Blood\r
ID: T250724002\r
Code: WB\r
Status: Valid\r
\r
When creating samples, use:\r
- sampleTypeId: "T250724002"\r
- sampleType: "Whole Blood"\r
```\r
\r
### Scenario 5: Create order\r
\r
**User**: "Help me create an order, patient name is John Smith, test item is LymphDetect, need one blood sample"\r
\r
**AI Actions**:\r
1. Collect required info: name (patient name), productId, productName\r
2. If user mentions sample type, use `search-sample-type` to query sample type ID\r
3. Build complete JSON (**must use correct field names**)\r
4. **Use file method to pass large JSON** (avoid command line escaping issues)\r
5. Call create order command\r
\r
**Key Notes for Creating Orders**:\r
\r
1. **Use file method to pass JSON** (strongly recommended):\r
- Windows PowerShell has issues with command line JSON escaping\r
- Write JSON to a temp file, then pass using `@filepath`\r
```bash\r
# First write JSON to file\r
# Then call:\r
node biolims.mjs create-order "@C:\path o\order.json"\r
```\r
\r
2. **productId must be a system ID**:\r
- Wrong: `"productId": "LymphDetect"` (using product name directly)\r
- Correct: `"productId": "CP2511240001"` (system product ID)\r
- If you don't know the productId, first query existing orders to get the correct ID\r
\r
3. **Samples must also include productId and productName**:\r
- Each sampleOrderItem must include productId and productName\r
- Otherwise the server will return a 400 error\r
\r
**Critically Important - Field Names**:\r
```json\r
{\r
"order": { ... },\r
"sampleOrderItem": [ ... ], \x3C- Must be sampleOrderItem, NOT samples!\r
"crmConsumeRmarkets": [ ... ] \x3C- Must be crmConsumeRmarkets, NOT fees!\r
}\r
```\r
\r
**Complete JSON Example**:\r
```json\r
{\r
"order": {\r
"name": "John Smith",\r
"gender": "1",\r
"phone": "[phone_number]",\r
"email": "[email]",\r
"productId": "CP2511240001",\r
"productName": "LymphDetect",\r
"crmCustomerId": "HOSP001",\r
"crmCustomerName": "Shanghai Hospital",\r
"diagnosis": "Lymphoma"\r
},\r
"sampleOrderItem": [\r
{\r
"slideCode": "BC202401180001",\r
"sampleTypeId": "T250724002",\r
"sampleType": "Whole Blood",\r
"productId": "CP2511240001",\r
"productName": "LymphDetect"\r
}\r
],\r
"crmConsumeRmarkets": [\r
{\r
"fee": 3500.00,\r
"feeWay": "Bank Transfer",\r
"isFee": "1",\r
"consumptionTime": "2024-01-18 10:00"\r
}\r
]\r
}\r
```\r
\r
**Common Product ID Mapping**:\r
| Product Name | productId |\r
|-------------|-----------|\r
| LymphDetect | CP2511240001 |\r
\r
(Other product IDs can be obtained by querying existing orders)\r
\r
**Reply Example**:\r
```\r
Order created successfully!\r
\r
Order ID: DD2602030023\r
Patient Name: John Smith\r
Test Item: LymphDetect\r
Sample: Whole Blood (BC202401180001)\r
Status: NEW\r
\r
Order has been saved to the system.\r
```\r
\r
## Response Handling\r
\r
**Key Rules:**\r
1. **Must check status field**: Only `status === 200` indicates success\r
2. **order-list response structure**: `{"status":200,"data":{"result":[order array],"total":count}}`\r
- Order list is in `data.result`, not directly in `data`\r
3. **Single order response structure**: `{"status":200,"data":{"result":{order object}}}`\r
4. **Error response**: `{"status":403/401,"msg":"error message"}`\r
\r
**Response Handling Steps:**\r
```javascript\r
1. Parse JSON\r
2. Check if response.status is 200\r
3. If 200, extract data from response.data.result\r
4. If not 200, check response.msg for error reason\r
5. Format output\r
```\r
\r
**Display Rules (Very Important):**\r
1. **Use English field display names**:\r
- Strictly follow the field mapping table using English names\r
- Example: `name` -> "Patient Name: John Smith"\r
- Example: `gender` -> "Gender: Female"\r
- Reference `references/field-mapping-quick-reference.md` for field mapping table\r
\r
2. **Correct use of name field**:\r
- This system uses a single `name` field for patient name, display as "Patient Name: John Smith"\r
- Do NOT look for firstName / lastName (these fields do not exist in this system)\r
- Do NOT split the name field into first and last name\r
\r
3. **Format Requirements**:\r
- Do not paste raw JSON directly\r
- Use list format for display (WhatsApp does not support markdown tables)\r
- Display by groups (Patient Information, Product Information, etc.)\r
- Only show fields with values (do not show null or empty strings)\r
\r
4. **Enum Value Conversion**:\r
- gender: 0->Female, 1->Male, 2->Unknown\r
- state: 0->Cancelled, 1->Complete, 3->NEW, 15->To Be Modified, 20->Submitted\r
- Sample status: 0->Cancel, 1->New, 2->To be received, 3->Received, 4->Scanned\r
\r
5. **Time Format**:\r
- Keep original format or convert to readable format\r
- Example: "2024-01-18 10:30:00"\r
\r
## Order Status Description\r
\r
- `0` - Cancelled\r
- `1` - Complete\r
- `3` - New\r
- `15` - To Be Modified\r
- `20` - Submitted\r
\r
## Gender Codes\r
\r
- `0` - Female\r
- `1` - Male\r
- `2` - Unknown\r
\r
## Important Notes\r
\r
1. **Token Management**: The script automatically handles login and token refresh; no manual intervention needed\r
2. **Error Handling**: If the API returns an error, explain the specific issue to the user (e.g., "order does not exist", "insufficient permissions", etc.)\r
3. **Data Format**: Creating/updating orders requires a complete JSON structure; refer to `references/api.md`\r
4. **Privacy Protection**: Be careful to protect privacy when displaying patient information; do not over-expose sensitive data\r
\r
## Field Mapping Reference\r
\r
### Fixed Field Mapping\r
\r
The JSON data returned by orders uses API internal field names (e.g., `name`, `productId`), which need to be mapped to page display names (e.g., "Patient Name", "Test Item ID").\r
\r
**Main Field Mapping**:\r
- `id` -> Order ID\r
- `name` -> Patient Name (**single field, NOT firstName/lastName**)\r
- `gender` -> Gender (0=Female, 1=Male, 2=Unknown)\r
- `age` -> Age\r
- `birthDate` -> Date of Birth\r
- `nation` -> Ethnicity\r
- `idCard` -> ID Card No.\r
- `phone` -> Phone Number\r
- `email` -> Email\r
- `medicalNumber` -> EMR ID\r
- `bedNo` -> Bed No.\r
- `hospitalPatientid` -> Inpatient/Outpatient No.\r
- `productId` -> Test Item ID\r
- `productName` -> Test Item(s)\r
- `barcode` -> Barcode\r
- `diagnosis` -> Clinical Diagnosis\r
- `medicalHistory` -> Health Condition\r
- `disease` -> Disease\r
- `stateName` -> Status\r
- `progress` -> Order Progress\r
- `creatorNickname` -> Created by\r
- `createTime` -> Created at\r
- `confirmerNickname` -> Approved by\r
- `confirmTime` -> Completed at\r
- `commissionerNickname` -> Sales\r
- `crmCustomerName` -> Medical Institutions\r
- `inspectionDepartmentName` -> Clinical Department\r
- `attendingDoctorName` -> Attending Physician\r
- `attendingDoctorPhone` -> Physician Contact No.\r
- `provinceName` -> Province\r
- `contractName` -> Contract Name\r
- `contractPrice` -> Contract Price\r
- `note` -> Remarks\r
\r
For the complete mapping table, refer to `references/field-mapping-quick-reference.md`.\r
\r
### Custom Field Handling\r
\r
Order data contains two types of custom fields:\r
\r
1. **Order main table custom fields** (`customFieldValue`)\r
- Storage location: `order.customFieldValue` (JSON string)\r
- Field mapping API: `GET /system/custom/selAllFields?flag=104-mainTable`\r
\r
2. **Sample sub-table custom fields** (`customFieldValue`)\r
- Storage location: `sampleOrderItem[n].customFieldValue` (JSON string)\r
- Field mapping API: `GET /system/custom/selAllFields?flag=104-sampleTable`\r
\r
**Processing Steps**:\r
1. Call field mapping API to get `{"Display Name": "apiFieldName"}` mapping\r
2. `JSON.parse()` to parse the `customFieldValue` string in the order\r
3. Use the mapping to convert API field names to display names\r
4. Display to user\r
\r
**Example**:\r
```javascript\r
// 1. Get field mapping\r
const mapping = await getCustomFields('104-mainTable');\r
// Returns: {"Patient Note": "patientNote", "Urgency Level": "urgencyLevel"}\r
\r
// 2. Parse custom fields\r
const customValues = JSON.parse(order.customFieldValue);\r
// customValues = {"patientNote": "Urgent case", "urgencyLevel": "High"}\r
\r
// 3. Convert to display names\r
// "Patient Note": "Urgent case"\r
// "Urgency Level": "High"\r
```\r
\r
---\r
\r
## Sample Receive Usage Scenarios\r
\r
### Scenario 6: Query receive order list\r
\r
**User**: "What are the recent sample receive orders?"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" receive-list 1 10`\r
2. Parse the returned list\r
3. Display recent receive orders\r
\r
**Reply Example** (list mode, simplified display):\r
```\r
Recent 10 receive orders (45 total):\r
\r
1. Registration ID: SR202401180001\r
Description: Clinical Sample Receive\r
Received At: 2024-01-18 10:00:00\r
Status: New\r
Created by: HX\r
Created at: 2024-01-18 09:30:00\r
Sample ID: S001,S002,S003\r
Barcode: BC001,BC002,BC003\r
\r
2. Registration ID: SR202401180002\r
Description: Research Sample Receive\r
Received At: 2024-01-18 14:00:00\r
Status: Complete\r
Created by: Wang\r
Created at: 2024-01-18 13:30:00\r
Sample ID: S004,S005\r
Barcode: BC004,BC005\r
\r
...\r
\r
To view details of a specific receive order, please provide the registration ID.\r
```\r
\r
### Scenario 7: Query receive order details\r
\r
**User**: "Help me check receive order SR202401180001"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" receive SR202401180001`\r
2. Parse the returned JSON, extract key information\r
3. Reply in a clear list format\r
\r
**Reply Example** (strictly follow field mapping, do not merge fields):\r
```\r
OK, found the information for receive order SR202401180001:\r
\r
=== Sample Receive Information ===\r
Registration ID: SR202401180001\r
Code: SR202401180001\r
Description: Clinical Sample Receive\r
Received At: 2024-01-18 10:00:00\r
In Plate: Yes\r
Project Name: Genetic Testing Project\r
Classify: Clinical\r
Type: Research\r
\r
=== Express & Transport Information ===\r
Express Bill No.: SF1234567890\r
Courier: SF Express\r
Transportation Method: Cold Chain Transport\r
\r
=== Receive Status ===\r
Status: New\r
Created by: HX\r
Created at: 2024-01-18 09:30:00\r
\r
To view sample details, use command: receive-samples SR202401180001\r
```\r
\r
**Important Reminders**:\r
- Use English field display names (e.g., "Registration ID", not Chinese equivalents)\r
- Do not merge fields (display each field separately)\r
- Display by field groups (Sample Receive Information, Express Information, etc.)\r
- Only show fields that have values\r
\r
### Scenario 8: Query receive order sample details\r
\r
**User**: "What samples does receive order SR202401180001 have?"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" receive-samples SR202401180001`\r
2. Display sample list\r
\r
**Reply Example**:\r
```\r
Sample details for receive order SR202401180001 (15 samples total):\r
\r
1. Sample ID: S001\r
Barcode: BC001\r
Order ID: ORD001\r
Name: John Smith\r
Gender: Male\r
Sample Type: Whole Blood\r
Test Item(s): Genetic Testing\r
Sampling Time: 2024-01-18 09:00:00\r
Sampling Volume: 5 ml\r
Normal: Yes\r
Result: Qualified\r
Next Step: Warehousing\r
Plate Number: P001\r
Sample Location: A01\r
\r
2. Sample ID: S002\r
Barcode: BC002\r
Order ID: ORD001\r
Name: Jane Doe\r
Gender: Female\r
Sample Type: Plasma\r
Test Item(s): Genetic Testing\r
Sampling Volume: 3 ml\r
Normal: Yes\r
Result: Qualified\r
Next Step: Warehousing\r
Plate Number: P001\r
Sample Location: A02\r
\r
...\r
```\r
\r
### Scenario 9: Scan barcode to receive sample\r
\r
**User**: "Scan barcode BC20240118001"\r
\r
**Important**: The `scan-barcode` command's `receive_id` is a **required parameter**; you must create a receive order first!\r
\r
**AI Actions**:\r
1. **First check if a receive order exists**:\r
- If user already provided a receive order ID -> use it directly\r
- If no receive order -> first call `create-receive` to create a new one\r
2. Call: `bash "$SCRIPT" scan-barcode BC20240118001 SR202401180001`\r
3. Parse the returned sample information\r
4. Display sample details\r
\r
**API Input Format**:\r
```json\r
{\r
"sampleReceive": {\r
"id": "SR202401180001",\r
"name": "Clinical Sample Receive",\r
"acceptDate": "2024-01-18 10:00",\r
"isBoard": "1"\r
},\r
"barCode": "BC20240118001"\r
}\r
```\r
\r
**Reply Example**:\r
```\r
Scanned barcode BC20240118001 sample information:\r
\r
Sample ID: S001\r
Barcode: BC20240118001\r
Order ID: ORD001\r
Name: John Smith\r
Gender: Male\r
Sample Type: Whole Blood\r
Test Item(s): Genetic Testing\r
\r
This sample has been added to receive order SR202401180001.\r
```\r
\r
**If barcode has already been received**:\r
```\r
Error: Barcode BC20240118001 has already been received in receive order SR202401170005.\r
```\r
\r
**If no receive order ID provided**:\r
```\r
Error: Scanning barcode requires creating a receive order first. Please use the create-receive command to create a receive order, or provide the receive order ID.\r
```\r
\r
### Scenario 10: Scan order number for batch receiving\r
\r
**User**: "Scan order ORD202401180001"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" scan-order ORD202401180001`\r
2. Parse the returned sample list\r
3. Display receivable samples\r
\r
**Reply Example**:\r
```\r
Order ORD202401180001 has 3 unreceived samples:\r
\r
1. Sample ID: S001\r
Barcode: BC001\r
Name: John Smith\r
Gender: Male\r
Sample Type: Whole Blood\r
Test Item(s): Genetic Testing\r
\r
2. Sample ID: S002\r
Barcode: BC002\r
Name: Jane Doe\r
Gender: Female\r
Sample Type: Plasma\r
Test Item(s): Genetic Testing\r
\r
3. Sample ID: S003\r
Barcode: BC003\r
Name: Bob Wilson\r
Gender: Male\r
Sample Type: Serum\r
Test Item(s): Genetic Testing\r
\r
These samples can be batch-added to a receive order.\r
```\r
\r
### Scenario 11: Create sample receive order\r
\r
**User**: "Create a sample receive order, receive time is today at 10am, express number SF1234567890, needs plating"\r
\r
**AI Actions**:\r
1. Collect required info: acceptDate (receive time), isBoard (whether to plate)\r
2. Build complete JSON (**must use correct field names**)\r
3. Call create receive order command\r
\r
**Critically Important - Field Names**:\r
```json\r
{\r
"sampleReceive": { ... }, \x3C- Receive order main table\r
"sampleReceiveItems": [ ... ], \x3C- Must be sampleReceiveItems, NOT samples!\r
"addBoardInfo": "..." \x3C- Must be addBoardInfo, NOT boardInfo!\r
}\r
```\r
\r
**Complete JSON Example**:\r
```json\r
{\r
"sampleReceive": {\r
"name": "Clinical Sample Receive",\r
"acceptDate": "2024-01-18 10:00",\r
"expressNum": "SF1234567890",\r
"expressCompanyId": "EC001",\r
"expressCompanyName": "SF Express",\r
"transportTypeId": "TT001",\r
"transportTypeName": "Cold Chain Transport",\r
"isBoard": "1"\r
},\r
"sampleReceiveItems": [\r
{\r
"sampleCode": "S001",\r
"barCode": "BC001",\r
"orderCode": "ORD001",\r
"patientName": "John Smith",\r
"gender": "1",\r
"dicSampleType": "Whole Blood",\r
"dicSampleTypeId": "T250724002",\r
"productName": "Genetic Testing",\r
"sampleNum": "5",\r
"unit": "ml",\r
"isGood": "1",\r
"nextFlow": "Warehousing"\r
}\r
],\r
"addBoardInfo": "{\"banHao\":\"P001\",\"rowNum\":8,\"colNum\":12}"\r
}\r
```\r
\r
**Reply Example**:\r
```\r
Receive order created successfully!\r
\r
Registration ID: SR202401180001\r
Description: Clinical Sample Receive\r
Received At: 2024-01-18 10:00:00\r
Express Bill No.: SF1234567890\r
Courier: SF Express\r
In Plate: Yes\r
Status: New\r
\r
Sample Details:\r
- Sample ID: S001, Barcode: BC001, Whole Blood, 5ml\r
\r
Receive order has been saved to the system.\r
```\r
\r
---\r
\r
### Scenario 12: Query receive order with custom fields\r
\r
**User**: "Query complete information for receive order SR202401180001, including custom fields"\r
\r
**AI Actions**:\r
1. Call `get-custom-fields 121-mainTable` to get main table custom field mapping\r
2. Call `get-custom-fields 121-receiveTable` to get sub-table custom field mapping\r
3. Call `receive SR202401180001` to query receive order data\r
4. Parse fixed fields (using field mapping table from TOOLS.md)\r
5. Parse enum values (Gender, Status, isGood, method, isBoard)\r
6. Parse `customFieldValue` JSON fields (main table and sub-table)\r
7. Format display (all fields use English display names)\r
\r
**Complete Workflow Example**:\r
\r
```bash\r
# Step 1: Get main table custom field mapping\r
bash "$SCRIPT" get-custom-fields 121-mainTable\r
# Returns: {"Storage Condition": "storageCondition", "Special Notes": "specialNotes"}\r
\r
# Step 2: Get sub-table custom field mapping\r
bash "$SCRIPT" get-custom-fields 121-receiveTable\r
# Returns: {"Sample Source": "sampleSource", "Quality Grade": "qualityGrade"}\r
\r
# Step 3: Query receive order data\r
bash "$SCRIPT" receive SR202401180001\r
```\r
\r
**Parsing Logic** (pseudocode):\r
```javascript\r
// 1. Parse fixed fields\r
const displayData = {\r
"Registration ID": data.sampleReceive.id,\r
"Received At": data.sampleReceive.acceptDate,\r
"Status": data.sampleReceive.state === 3 ? "New" : "Complete",\r
"Express Bill No.": data.sampleReceive.expressNum,\r
"Courier": data.sampleReceive.expressCompanyName,\r
"In Plate": data.sampleReceive.isBoard === "1" ? "Yes" : "No",\r
// ... other fixed fields ...\r
};\r
\r
// 2. Parse main table custom fields\r
if (data.sampleReceive.customFieldValue) {\r
const customFields = JSON.parse(data.sampleReceive.customFieldValue);\r
// customFields = {"storageCondition": "2-8C", "specialNotes": "Urgent"}\r
\r
// Use mapping from step 1 to convert field names\r
displayData["Storage Condition"] = customFields["storageCondition"]; // "2-8C"\r
displayData["Special Notes"] = customFields["specialNotes"]; // "Urgent"\r
}\r
\r
// 3. Parse sample details (including sub-table custom fields)\r
displayData.samples = data.sampleReceiveItems.map(item => {\r
const displayItem = {\r
"Sample ID": item.sampleCode,\r
"Barcode": item.barCode,\r
"Name": item.patientName,\r
"Gender": item.gender === 1 ? "Male" : item.gender === 0 ? "Female" : "Unknown",\r
"Sample Type": item.dicSampleType,\r
"Test Item(s)": item.productName,\r
"Sampling Volume": item.sampleNum,\r
"Unit": item.unit,\r
"Normal": item.isGood === "1" ? "Yes" : "No",\r
"Result": item.method === "1" ? "Qualified" : "Unqualified",\r
"Next Step": item.nextFlow,\r
// ... other fixed fields ...\r
};\r
\r
// Parse sample custom fields\r
if (item.customFieldValue) {\r
const customFields = JSON.parse(item.customFieldValue);\r
// customFields = {"sampleSource": "Hospital A", "qualityGrade": "Grade A"}\r
\r
// Use mapping from step 2 to convert field names\r
displayItem["Sample Source"] = customFields["sampleSource"]; // "Hospital A"\r
displayItem["Quality Grade"] = customFields["qualityGrade"]; // "Grade A"\r
}\r
\r
return displayItem;\r
});\r
```\r
\r
**Reply Example**:\r
```\r
Receive order details:\r
\r
Registration ID: SR202401180001\r
Received At: 2024-01-18 10:00:00\r
Status: New\r
Express Bill No.: SF1234567890\r
Courier: SF Express\r
In Plate: Yes\r
Storage Condition: 2-8C\r
Special Notes: Urgent\r
\r
Sample Details (2 samples):\r
\r
Sample #1:\r
- Sample ID: S001\r
- Barcode: BC001\r
- Name: John Smith\r
- Gender: Male\r
- Sample Type: Whole Blood\r
- Test Item(s): Genetic Testing\r
- Sampling Volume: 5\r
- Unit: ml\r
- Normal: Yes\r
- Result: Qualified\r
- Next Step: Warehousing\r
- Sample Source: Hospital A\r
- Quality Grade: Grade A\r
\r
Sample #2:\r
- Sample ID: S002\r
- Barcode: BC002\r
- Name: Jane Doe\r
- Gender: Female\r
- Sample Type: Serum\r
- Test Item(s): Protein Testing\r
- Sampling Volume: 3\r
- Unit: ml\r
- Normal: Yes\r
- Result: Qualified\r
- Next Step: Testing\r
- Sample Source: Hospital B\r
- Quality Grade: Grade A\r
```\r
\r
**Important Tips**:\r
- Custom field mappings may change dynamically; it is recommended to re-fetch them with each query\r
- `customFieldValue` is a JSON string that must be parsed with `JSON.parse()` first\r
- All fields must use English display names\r
- Only display fields with values; do not show empty fields\r
\r
---\r
\r
### Scenario 13: Query next step flow list\r
\r
**User**: "Query next step flow for product PROD001" or "Where does this sample go next?"\r
\r
**AI Actions**:\r
\r
**Key: This API requires a product ID; it will error without one**\r
\r
**Step 1: Confirm product ID**\r
- If user already provided product ID -> use it directly\r
- If user did not provide product ID -> **must ask or query first**\r
\r
**Step 2: Call API**\r
```bash\r
# Single product ID\r
bash "$SCRIPT" get-next-flows PROD001\r
\r
# Multiple product IDs (intersection)\r
bash "$SCRIPT" get-next-flows PROD001,PROD002\r
```\r
\r
**Step 3: Parse response**\r
```json\r
{\r
"status": 200,\r
"data": {\r
"result": [\r
{\r
"id": "FLOW001",\r
"name": "Warehousing",\r
"description": "Store sample in warehouse"\r
},\r
{\r
"id": "FLOW002",\r
"name": "Testing",\r
"description": "Enter testing workflow"\r
}\r
],\r
"total": 2\r
}\r
}\r
```\r
\r
**Reply Example 1 (with product ID)**:\r
```\r
Next step flow options for product PROD001:\r
\r
1. Warehousing (FLOW001)\r
- Store sample in warehouse\r
\r
2. Testing (FLOW002)\r
- Enter testing workflow\r
\r
2 flow options available.\r
```\r
\r
**Reply Example 2 (no product ID - must ask first)**:\r
```\r
To query next step flow, I need the product ID.\r
\r
You can:\r
1. Tell me the product ID directly (e.g., PROD001)\r
2. Or I can first help you query the available test item list\r
\r
Which would you prefer?\r
```\r
\r
**Common Errors (must avoid)**:\r
```bash\r
# Wrong: Calling without providing product ID\r
bash "$SCRIPT" get-next-flows\r
# Result: {"error":"Usage: biolims.sh get-next-flows \x3Cproduct_id1,product_id2,...>"}\r
\r
# Correct: Ask user first or get product ID from context\r
# AI: "Please provide the product ID, or shall I help you query available test items?"\r
```\r
\r
**Business Logic**:\r
- **Single product ID**: Returns all available next step flows for that product\r
- **Multiple product IDs**: Returns flows supported by all products (intersection)\r
- Example: PROD001 supports [A,B,C], PROD002 supports [B,C,D] -> Returns [B,C]\r
\r
**Rules AI Must Follow**:\r
1. **Never** call `get-next-flows` without a product ID\r
2. If user did not provide a product ID, **must ask first**: "Please provide the test item product ID"\r
3. Or proactively offer help: "I can first help you query the available test item list, would you like that?"\r
4. Only call the API after obtaining the product ID\r
\r
---\r
\r
### Scenario 14: Required field validation before completing receive order\r
\r
**User**: "Complete receive order SR202401180001"\r
\r
**AI Actions**:\r
\r
**Key: Must validate all required fields before completing**\r
\r
**Step 1: Query current receive order data**\r
```bash\r
bash "$SCRIPT" receive SR202401180001\r
```\r
\r
**Step 2: Validate required fields**\r
\r
**Main table required fields (2):**\r
- `acceptDate` (Received At) - Receive time\r
- `isBoard` (In Plate) - Whether to plate\r
\r
**Sample detail required fields (9 per sample):**\r
- `orderCode` (Order ID)\r
- `barCode` (Barcode)\r
- `productName` (Test Item(s))\r
- `dicSampleTypeId` (Sample Type ID)\r
- `sampleNum` (Sampling Volume)\r
- `unit` (Unit)\r
- `isGood` (Normal)\r
- `method` (Result)\r
- `nextFlow` (Next Step)\r
\r
**Step 3: Decide whether to complete based on validation results**\r
\r
**Case A - All fields present:**\r
```bash\r
bash "$SCRIPT" complete-receive SR202401180001\r
```\r
\r
Reply:\r
```\r
Receive order completed successfully!\r
\r
Registration ID: SR202401180001\r
Status: Complete\r
Received At: 2024-01-18 10:00:00\r
\r
Receive order is now locked and cannot be edited.\r
```\r
\r
**Case B - Missing fields (must list specific missing fields):**\r
\r
Reply:\r
```\r
Cannot complete receive order, the following required fields are not filled:\r
\r
Receive Order Main Table:\r
- Received At (acceptDate) - Receive time\r
\r
Sample Details:\r
Sample #1 (BC001):\r
- Next Step (nextFlow) - Next step flow\r
- Normal (isGood) - Whether normal\r
\r
Sample #2 (BC002):\r
- Result (method) - Test result\r
\r
Please fill in this information before completing the receive order.\r
\r
You can use the following command to update:\r
bash "$SCRIPT" update-receive '\x3Cjson>'\r
```\r
\r
**Things AI Must Never Do**:\r
1. Call `complete-receive` directly without validation\r
2. Assume fields are filled and skip validation\r
3. Only say "fields are missing" without listing specific fields\r
\r
---\r
\r
### Scenario 15: Duplicate barcode error handling\r
\r
**User**: "Create receive order with samples BC001 and BC001"\r
\r
**AI Actions**:\r
1. Build JSON\r
2. Call `create-receive`\r
3. Receive error response: `{"status": 400, "msg": "Save failed: duplicate barcode", "data": null}`\r
\r
**AI should reply like this**:\r
```\r
Save failed: duplicate barcode\r
\r
Duplicate barcode detected: BC001\r
\r
Barcodes must be unique within the same receive order. Please check:\r
1. Did you accidentally enter the same barcode twice\r
2. If there are indeed multiple samples, each sample needs a different barcode\r
\r
Please modify the duplicate barcode and try again.\r
```\r
\r
**Common barcode error scenarios**:\r
\r
**Scenario A - Duplicate within same receive order:**\r
```json\r
{\r
"sampleReceiveItems": [\r
{"barCode": "BC001", ...},\r
{"barCode": "BC001", ...} // Duplicate\r
]\r
}\r
```\r
Error: `"Save failed: duplicate barcode"`\r
\r
**Scenario B - Already received by another receive order:**\r
- Barcode BC001 is already in another receive order\r
- Scanning will indicate the sample has been received\r
\r
**AI Handling**:\r
- Parse error message\r
- Identify the specific duplicate barcode\r
- Provide clear resolution suggestions\r
\r
---\r
\r
### Scenario 16: Unified handling of API error responses\r
\r
**After all API calls, AI must check the status field:**\r
\r
```javascript\r
// Pseudocode example\r
const response = JSON.parse(apiResponse);\r
\r
if (response.status === 200) {\r
// Success - display data normally\r
displayData(response.data);\r
\r
} else if (response.status === 400) {\r
// Business error - display error in friendly manner\r
const errorMsg = response.msg;\r
\r
if (errorMsg.includes("duplicate barcode")) {\r
return `Save failed: duplicate barcode\
\
${provide resolution suggestions}`;\r
\r
} else if (errorMsg.includes("required field")) {\r
return `Save failed: missing required fields\
\
${list specific fields}`;\r
\r
} else {\r
return `Operation failed: ${errorMsg}\
\
Please check if the input data is correct.`;\r
}\r
\r
} else if (response.status === 401) {\r
// Script will auto-retry, AI does not need to handle\r
\r
} else if (response.status === 500) {\r
return "Server error, please try again later.";\r
}\r
```\r
\r
**Error response examples and AI replies:**\r
\r
| API Response | AI Reply |\r
|-------------|----------|\r
| `{"status":400,"msg":"Save failed: duplicate barcode"}` | Save failed: duplicate barcode. Duplicate barcode detected... Please modify and try again. |\r
| `{"status":400,"msg":"Required field not filled: acceptDate"}` | Save failed: missing required field - Received At (acceptDate). Please fill in and try again. |\r
| `{"status":500,"msg":"Internal error"}` | Server error, please try again later. |\r
\r
**Principles AI Must Follow**:\r
1. **Always check the status field** - Do not assume the call succeeded\r
2. **Display errors in a friendly manner** - Do not return raw error messages directly\r
3. **Provide resolution suggestions** - Tell the user how to fix the error\r
4. **List specific details** - Which field is missing? Which barcode is duplicated?\r
\r
---\r
\r
## Sample Receive Status Description\r
\r
### Receive Order Status\r
\r
- `3` - New - Editable, saveable, completable\r
- `1` - Complete - Read-only, not editable\r
\r
### Sample Qualification Status\r
\r
- `1` - Qualified\r
- `0` - Unqualified\r
\r
### In Plate\r
\r
- `1` - Yes\r
- `0` - No\r
\r
---\r
\r
## Experiment Template Usage Scenarios\r
\r
### Scenario 17: Query experiment template list\r
\r
**User**: "View experiment templates" / "Check latest experiment templates" / "What experiment templates are there"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" et-list 1 10`\r
2. Parse the returned `data.result` array, display key fields\r
\r
**Reply Example**:\r
```\r
Found 8 experiment templates (8 total):\r
\r
1. Template ID: ET2024000001\r
Template Name: PCR Testing Experiment Template\r
Experiment Type: PCR Amplification\r
Status: Complete\r
Created by: admin\r
Created at: 2024-01-15 10:30:00\r
\r
2. Template ID: ET2024000002\r
Template Name: Cell Culture Testing Template\r
Experiment Type: Cell Experiment\r
Status: New\r
Created by: lab_user\r
Created at: 2024-01-20 14:00:00\r
```\r
\r
**Status Value Conversion**:\r
- `3` -> New (editable)\r
- `20` -> In Workflow\r
- `15` -> To Be Modified\r
- `1` -> Complete\r
- `30` -> Cancelled (excluded from queries automatically)\r
\r
---\r
\r
### Scenario 18: Query experiment template details\r
\r
**User**: "View details of template ET2024000001" / "What steps does ET2024000001 have"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" et-detail ET2024000001 view`\r
2. Parse three-layer nested structure, display by step -> component hierarchy\r
\r
**Reply Example**:\r
```\r
Template Details: ET2024000001\r
\r
=== Basic Information ===\r
Template Name: PCR Testing Experiment Template\r
Experiment Type: PCR Amplification\r
Status: Complete\r
Created by: admin\r
Created at: 2024-01-15 10:30:00\r
Version: 1.0\r
\r
=== Step Structure (2 steps total) ===\r
\r
Step 1: Sample Preparation\r
- [detailTable] Sample Detail Table\r
- [input] Extraction Concentration (number)\r
- [input] Extraction Date (date)\r
- [attachment] Extraction Record\r
\r
Step 2: PCR Amplification\r
- [detailTable] Sample Detail Table\r
- [equipment] Instruments & Equipment\r
- [material] Reagents & Consumables\r
- [resultTable] Test Result Table\r
```\r
\r
---\r
\r
### Scenario 19: Create experiment template\r
\r
**User**: "Help me create an XXX testing template"\r
\r
**AI Actions**:\r
1. First query experiment types: `bash "$SCRIPT" et-exp-types`\r
2. First query experiment groups: `bash "$SCRIPT" et-groups`\r
3. Collect required info: templateName, experimentType, experimentGroup, auditor\r
4. Build JSON and write to temp file (avoid escaping issues)\r
5. Call: `bash "$SCRIPT" et-create @/tmp/template.json`\r
\r
**Create JSON Structure** (templateName required, stepDetails required):\r
```json\r
{\r
"templateName": "Template Name",\r
"experimentType": "Experiment Type ID",\r
"experimentTypeName": "Experiment Type Name",\r
"experimentGroup": "Experiment Group ID",\r
"experimentGroupName": "Experiment Group Name",\r
"auditor": "Approver ID",\r
"auditorName": "Approver Name",\r
"stepDetails": [\r
{\r
"name": "Step Name",\r
"keyId": 0,\r
"jsonDatas": [\r
{\r
"label": "Field Name",\r
"type": "input",\r
"size": "8",\r
"inputType": "text",\r
"exclusiveShow": "0"\r
}\r
]\r
}\r
]\r
}\r
```\r
\r
---\r
\r
### Scenario 20: Copy experiment template\r
\r
**User**: "Copy template ET2024000001" / "Create a new one based on template ET001"\r
\r
**AI Actions**:\r
1. Call: `bash "$SCRIPT" et-copy ET2024000001`\r
2. Display new template ID (auto-generated by system, status is New and editable)\r
\r
---\r
\r
### Scenario 21: Cancel experiment template\r
\r
**User**: "Cancel template ET2024000001"\r
\r
**AI Actions**:\r
1. **Must confirm first**: "Are you sure you want to cancel template ET2024000001? This action cannot be undone."\r
2. After user confirms: `bash "$SCRIPT" et-cancel ET2024000001`\r
\r
---\r
\r
## Detailed API Information\r
\r
### Order Module\r
\r
- Complete API documentation: `references/api.md`\r
- **Field mapping quick reference**: `references/field-mapping-quick-reference.md` \x3C- Must read when querying orders!\r
\r
### Sample Receive Module\r
\r
- Complete API documentation: `references/api-sample-receive.md`\r
- **Field mapping quick reference**: `references/field-mapping-sample-receive-quick-reference.md` \x3C- Must read when querying receive orders!\r
\r
### Experiment Template Module\r
\r
- Complete API documentation: `references/api-experiment-template.md` \x3C- Must read for experiment template operations!\r
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install biolims-skill - After installation, invoke the skill by name or use
/biolims-skill - Provide required inputs per the skill's parameter spec and get structured output
What is BioLIMS SKILL?
Call Bio-LIMS system APIs to manage orders, sample receiving, and experiment templates, including querying, creating, updating orders, sample receive managem... It is an AI Agent Skill for Claude Code / OpenClaw, with 109 downloads so far.
How do I install BioLIMS SKILL?
Run "/install biolims-skill" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is BioLIMS SKILL free?
Yes, BioLIMS SKILL is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does BioLIMS SKILL support?
BioLIMS SKILL is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created BioLIMS SKILL?
It is built and maintained by biolims (@biolims); the current version is v1.0.0.