.claude/settings.local.json
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,9 @@ { "permissions": { "allow": [ "Bash(rm:*)", "Bash(git add:*)" ], "deny": [] } } CLAUDE.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,140 @@ # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a Manufacturing Execution System (MES) API application built with .NET 8, consisting of: - **MESApplication**: Main Web API project with controllers and middleware - **MES.Service**: Service layer containing business logic, data models, and database operations The system manages manufacturing operations including quality control (QC), warehouse management, inventory tracking, PLM integration, and ERP connectivity. ## Development Commands ### Build and Run ```bash # Build the solution dotnet build MESApplication.sln # Run the API (from MESApplication directory) cd MESApplication dotnet run # Run with specific environment dotnet run --environment Development ``` ### Development Server - API runs on: `http://localhost:5184` - Swagger UI available at: `http://localhost:5184/swagger` - IIS Express: `http://localhost:10054` ### Project Structure Commands ```bash # Restore NuGet packages dotnet restore # Clean build artifacts dotnet clean # Build specific project dotnet build MESApplication/MESApplication.csproj dotnet build MES.Service/MES.Service.csproj ``` ## Architecture ### Database Layer - **ORM**: SqlSugar for Oracle database connectivity - **Database**: Oracle (connection configured in appsettings.json) - **Patterns**: Repository pattern with generic DbContext<T> and specific managers - **Key Classes**: - `SqlSugarHelper.cs`: Database connection and transaction management - `DbContext<T>.cs`: Generic repository for CRUD operations - `Repository.cs`: Base repository implementation ### Service Layer (MES.Service) Organized by business domains: - **BasicData/**: Core master data (customers, suppliers, items, departments) - **QC/**: Quality control operations (inspections, testing, suspensions) - **Warehouse/**: Inventory management (stock, moves, receipts, shipments) - **PLM/**: Product lifecycle management integration - **SpotCheck/**: Equipment maintenance and spot checking ### API Layer (MESApplication) - **Controllers/**: REST endpoints organized by domain (matching service structure) - **Filter/**: Action filters for logging and error handling - **Authentication**: Not implemented (anonymous access) - **Serialization**: Newtonsoft.Json with camelCase naming ### Key Configuration - **Database**: Oracle connection string in `AppSettings.DataBaseConn` - **CORS**: Enabled for all origins during development - **Swagger**: Auto-generated API documentation with XML comments - **Logging**: Console logging with SQL query debugging enabled ### External Integrations - **Kingdee ERP**: Via WebService (configured URLs in AppSettings) - **PLM System**: Document and BOM management - **Real-time Inventory**: HTTP client for inventory queries ### Domain Models Major entity categories: - **Inventory**: `MesInvItem*` classes for stock management - **Quality**: `MesQa*` classes for quality control processes - **Manufacturing**: `Wom*` classes for work orders - **Purchasing**: `Purd*` classes for procurement - **Sales**: `SalesOrder*` classes for order management ### Data Transfer Objects (DTOs) - **service/**: Internal service communication DTOs - **webApi/**: External API integration DTOs (ERP, PLM) - **base/**: Common DTOs (pagination, login, settings) ## Testing and Quality ### Testing Commands ```bash # No automated tests currently configured # Manual testing via Swagger UI at http://localhost:5184/swagger ``` ### Common Development Tasks #### Adding New API Endpoints 1. Create model class in `MES.Service/Modes/` 2. Create service manager in `MES.Service/service/[Domain]/` 3. Create controller in `MESApplication/Controllers/[Domain]/` 4. Register dependencies in `Startup.cs` if needed #### Working with Database - All database operations use SqlSugar ORM with Oracle - Transaction support via `SqlSugarHelper.UseTransactionWithOracle()` - SQL queries are logged to console during development - Connection string configured in `appsettings.json` #### External System Integration - **ERP Integration**: Kingdee WebService calls configured in AppSettings - **PLM Integration**: Document management via HTTP clients - **Real-time Inventory**: Dedicated service for inventory queries ### Key Files to Understand - `MES.Service/DB/SqlSugarHelper.cs`: Database connection management - `MES.Service/DB/DbContext.cs`: Generic repository pattern - `MES.Service/util/AppsettingsUtility.cs`: Configuration access - `MESApplication/Startup.cs`: Application configuration and DI setup - `MESApplication/Filter/ActionFilter.cs`: Request/response logging ### Dependencies and Packages - **SqlSugarCore**: ORM for Oracle database operations - **Newtonsoft.Json**: JSON serialization with camelCase naming - **Swashbuckle.AspNetCore**: API documentation generation - **Oracle.EntityFrameworkCore**: Oracle database connectivity - **Kingdee.CDP.WebApi.SDK**: ERP system integration (local DLL) ### Configuration Management - Environment-specific settings in `appsettings.json` and `appsettings.Development.json` - Database connection in `AppSettings.DataBaseConn` - ERP URLs in `AppSettings.TestErpUrl` and `AppSettings.ProductionErpUrl` - CORS enabled for all origins in development mode MES.Service/Dto/service/OQCDto.cs
@@ -12,6 +12,8 @@ public decimal? MainId { get; set; } public string? ReleaseNo { get; set; } public string? OrderNo { get; set; } public List<MesInvItemStocks>? ItemBarCodeData { get; set; } MES.Service/Modes/MesLaboratory.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,111 @@ using SqlSugar; using System; namespace MES.Service.Modes { /// <summary> /// å®éªå®¤æ£æµæ°æ®è¡¨ /// </summary> [SugarTable("MES_LABORATORY")] public class MesLaboratory { /// <summary> /// 主é®ID /// </summary> [SugarColumn(ColumnName = "ID", OracleSequenceName = "SEQ_MES_LABORATORY", IsPrimaryKey = true)] public decimal Id { get; set; } /// <summary> /// å·¥åå· /// </summary> [SugarColumn(ColumnName = "BILL_NO", Length = 100)] public string? BillNo { get; set; } /// <summary> /// ç产线ä½ç¼ç /// </summary> [SugarColumn(ColumnName = "LINE_NO", Length = 100)] public string? LineNo { get; set; } /// <summary> /// ç©æid /// </summary> [SugarColumn(ColumnName = "ITEM_ID")] public int? ItemId { get; set; } /// <summary> /// ç©æç¼ç /// </summary> [SugarColumn(ColumnName = "ITEM_NO", Length = 64)] public string? ItemNo { get; set; } /// <summary> /// ç©æåç§° /// </summary> [SugarColumn(ColumnName = "ITEM_NAME", Length = 500)] public string? ItemName { get; set; } /// <summary> /// ç©æè§æ ¼ /// </summary> [SugarColumn(ColumnName = "ITEM_MODEL", Length = 3000)] public string? ItemModel { get; set; } /// <summary> /// ç产车é´id /// </summary> [SugarColumn(ColumnName = "DEPARTMENTID")] public int? DepartmentId { get; set; } /// <summary> /// ç产车é´ç¼ç /// </summary> [SugarColumn(ColumnName = "DEPARTMENTCODE", Length = 32)] public string? DepartmentCode { get; set; } /// <summary> /// éå®è®¢åå· /// </summary> [SugarColumn(ColumnName = "SALE_ORDER_NOC", Length = 50)] public string? SaleOrderNoc { get; set; } /// <summary> /// æ£éªç»æ /// </summary> [SugarColumn(ColumnName = "INSPECTION_RESULT", Length = 20)] public string? InspectionResult { get; set; } /// <summary> /// å建æ¶é´ /// </summary> [SugarColumn(ColumnName = "CREATE_TIME", InsertServerTime = true)] public DateTime? CreateTime { get; set; } /// <summary> /// å建人 /// </summary> [SugarColumn(ColumnName = "CREATE_BY", Length = 100)] public string? CreateBy { get; set; } /// <summary> /// æ£éªæ¶é´ /// </summary> [SugarColumn(ColumnName = "INSPECTION_TIME")] public DateTime? InspectionTime { get; set; } /// <summary> /// æ£éªäºº /// </summary> [SugarColumn(ColumnName = "INSPECTION_BY", Length = 100)] public string? InspectionBy { get; set; } [SugarColumn(IsIgnore = true)] public string? CreateUser { get; set; } //inspection [SugarColumn(IsIgnore = true)] public string? InspectionUser { get; set; } } } MES.Service/Modes/VLaboratory.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,72 @@ using SqlSugar; namespace MES.Service.Modes; /// <summary> /// å®éªå®¤æ£æµæ°æ®è¡¨ /// </summary> [SugarTable("V_LABORATORY")] public class VLaboratory { /// <summary> /// 主é®ID /// </summary> [SugarColumn(ColumnName = "ID", IsPrimaryKey = true)] public decimal Id { get; set; } /// <summary> /// å·¥åå· /// </summary> [SugarColumn(ColumnName = "BILL_NO")] public string? BillNo { get; set; } /// <summary> /// ç产线ä½ç¼ç /// </summary> [SugarColumn(ColumnName = "LINE_NO")] public string? LineNo { get; set; } /// <summary> /// ç©æid /// </summary> [SugarColumn(ColumnName = "ITEM_ID")] public int? ItemId { get; set; } /// <summary> /// ç©æç¼ç /// </summary> [SugarColumn(ColumnName = "ITEM_NO")] public string? ItemNo { get; set; } /// <summary> /// ç©æåç§° /// </summary> [SugarColumn(ColumnName = "ITEM_NAME")] public string? ItemName { get; set; } /// <summary> /// ç©æè§æ ¼ /// </summary> [SugarColumn(ColumnName = "ITEM_MODEL")] public string? ItemModel { get; set; } /// <summary> /// ç产车é´id /// </summary> [SugarColumn(ColumnName = "DEPARTMENTID")] public int? DepartmentId { get; set; } /// <summary> /// ç产车é´ç¼ç /// </summary> [SugarColumn(ColumnName = "DEPARTMENTCODE")] public string? DepartmentCode { get; set; } /// <summary> /// éå®è®¢åå· /// </summary> [SugarColumn(ColumnName = "SALE_ORDER_NOC")] public string? SaleOrderNoc { get; set; } } MES.Service/bin/Debug/net8.0/MES.Service.dllBinary files differ
MES.Service/bin/Debug/net8.0/MES.Service.pdbBinary files differ
MES.Service/service/QC/MesLaboratoryService.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,94 @@ using System.Data; using MES.Service.DB; using MES.Service.Dto.service; using MES.Service.Modes; using MES.Service.util; using SqlSugar; using DbType = System.Data.DbType; namespace MES.Service.service.QC; public class MesLaboratoryService : Repository<MesLaboratory> { //OQCDto public bool SaveLaboratory(OQCDto dto) { //1.æ ¹æ®BillNoæ¥è¯¢è§å¾VLaboratoryï¼ç¨dtoçOrderNoï¼ä½¿ç¨.First()åªè¿åä¸ä¸ªå¯¹è±¡ var vLaboratory = Context.Queryable<VLaboratory>() .Where(x => x.BillNo == dto.OrderNo) .First(); //2.å°æ¥è¯¢åºæ¥çVLaboratory转æ¢ä¸ºMesLaboratory var mesLaboratory = new MesLaboratory { BillNo = vLaboratory.BillNo, LineNo = vLaboratory.LineNo, ItemId = vLaboratory.ItemId, ItemNo = vLaboratory.ItemNo, ItemName = vLaboratory.ItemName, ItemModel = vLaboratory.ItemModel, DepartmentId = vLaboratory.DepartmentId, DepartmentCode = vLaboratory.DepartmentCode, SaleOrderNoc = vLaboratory.SaleOrderNoc, CreateBy = dto.CreateUser, CreateTime = DateTime.Now }; //3.æå ¥å°æ°æ®åºä¸ return Context.Insertable(mesLaboratory) .IgnoreColumns(ignoreNullColumn: true) .ExecuteCommand() > 0; } public new object InsertReturnIdentity(MesLaboratory data) { return base.InsertReturnIdentity(data); } public (List<MesLaboratory> item, int TotalCount) GetPage( XJPageResult queryObj) { if (queryObj == null) throw new ArgumentNullException(nameof(queryObj)); var db = Db; var totalCount = 0; if (!decimal.TryParse(queryObj.id, out var id)) id = 0; var pageList = db .Queryable<MesLaboratory, SysUser, SysUser>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.CreateBy == b.Fcode, JoinType.Left, a.InspectionBy == c.Fcode )) .WhereIF(id > 0, (a, b, c) => a.Id == id) .Select((a, b, c) => new MesLaboratory() { CreateUser = b.Fname, InspectionUser = c.Fname, DepartmentId = a.DepartmentId, }, true) .OrderByDescending(a => a.Id) .ToPageList(queryObj.PageIndex, queryObj.Limit, ref totalCount); return (pageList, totalCount); } /// <summary> /// å½å ¥æ£éªç»æ /// </summary> /// <param name="data">å®éªå®¤æ£æµæ°æ®</param> /// <returns></returns> public bool UpdateInspectionResult(MesLaboratory data) { return Context.Updateable<MesLaboratory>() .SetColumnsIF(!string.IsNullOrEmpty(data.InspectionResult), x => x.InspectionResult == data.InspectionResult) .SetColumnsIF(!string.IsNullOrEmpty(data.InspectionBy), x => x.InspectionBy == data.InspectionBy) .SetColumns(x => x.InspectionTime == DateTime.Now) .Where(x => x.Id == data.Id) .ExecuteCommand() > 0; } } MESApplication/Controllers/QC/MesLaboratoryController.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,231 @@ using System.Dynamic; using MES.Service.Dto.service; using MES.Service.Modes; using MES.Service.service.QC; using MES.Service.util; using Microsoft.AspNetCore.Mvc; namespace MESApplication.Controllers.QC; [Route("api/[controller]")] [ApiController] public class MesLaboratoryController : ControllerBase { private readonly MesLaboratoryService m = new(); [HttpPost("saveLaboratory")] public ResponseResult SaveLaboratory([FromBody] OQCDto dto) { try { dynamic resultInfos = new ExpandoObject(); var result = m.SaveLaboratory(dto); resultInfos.result = result; return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// è·åææ /// </summary> /// <returns></returns> [HttpPost("GetList")] public ResponseResult GetList() { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.GetList(); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// æ ¹æ®ä¸»é®è·å /// </summary> /// <returns></returns> [HttpPost("GetById")] public ResponseResult GetById(decimal id) { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.GetById(id); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// æ ¹æ®ä¸»é®å é¤ /// </summary> /// <returns></returns> [HttpPost("DeleteByIds")] public ResponseResult DeleteByIds([FromBody] object[] ids) { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.DeleteByIds(ids); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// æ·»å /// </summary> /// <returns></returns> [HttpPost("Insert")] public ResponseResult Add([FromBody] MesLaboratory data) { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.Insert(data); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// æ·»å è¿åèªå¢ /// </summary> /// <returns></returns> [HttpPost("InsertReturnIdentity")] public ResponseResult InsertReturnIdentity([FromBody] MesLaboratory data) { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.InsertReturnIdentity(data); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// ä¿®æ¹ /// </summary> /// <returns></returns> [HttpPost("Update")] public ResponseResult Update([FromBody] MesLaboratory data) { try { dynamic resultInfos = new ExpandoObject(); resultInfos.tbBillList = m.Update(data); return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// å页æ¥è¯¢ /// </summary> /// <returns></returns> [HttpPost("GetPage")] public ResponseResult GetPage([FromBody] XJPageResult queryObj) { try { dynamic resultInfos = new ExpandoObject(); var (items, totalCount) = m.GetPage(queryObj); resultInfos.tbBillList = items; resultInfos.totalCount = totalCount; return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } /// <summary> /// å½å ¥æ£éªç»æ /// </summary> /// <returns></returns> [HttpPost("UpdateInspectionResult")] public ResponseResult UpdateInspectionResult([FromBody] MesLaboratory data) { try { dynamic resultInfos = new ExpandoObject(); var result = m.UpdateInspectionResult(data); resultInfos.result = result; return new ResponseResult { status = 0, message = "OK", data = resultInfos }; } catch (Exception ex) { return ResponseResult.ResponseError(ex); } } } MESApplication/bin/Debug/net8.0/MES.Service.dllBinary files differ
MESApplication/bin/Debug/net8.0/MES.Service.pdbBinary files differ
MESApplication/bin/Debug/net8.0/MESApplication.dllBinary files differ
MESApplication/bin/Debug/net8.0/MESApplication.exeBinary files differ
MESApplication/bin/Debug/net8.0/MESApplication.pdbBinary files differ
MESApplication/bin/Debug/net8.0/MESApplication.xml
@@ -757,6 +757,61 @@ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.BaseController.getLljAllImgByFid(Newtonsoft.Json.Linq.JObject)"> <summary> è·åæ¥ææ£å个æ£éªåä¸ä¼ çææå¾ç </summary> <param name="data"></param> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.GetList"> <summary> è·åææ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.GetById(System.Decimal)"> <summary> æ ¹æ®ä¸»é®è·å </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.DeleteByIds(System.Object[])"> <summary> æ ¹æ®ä¸»é®å é¤ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.Add(MES.Service.Modes.MesLaboratory)"> <summary> æ·»å </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.InsertReturnIdentity(MES.Service.Modes.MesLaboratory)"> <summary> æ·»å è¿åèªå¢ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.Update(MES.Service.Modes.MesLaboratory)"> <summary> ä¿®æ¹ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.GetPage(MES.Service.Dto.service.XJPageResult)"> <summary> å页æ¥è¯¢ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLaboratoryController.UpdateInspectionResult(MES.Service.Modes.MesLaboratory)"> <summary> å½å ¥æ£éªç»æ </summary> <returns></returns> </member> <member name="M:MESApplication.Controllers.QC.MesLineUserController.GetList"> <summary> è·åææ