From 2b82744eb86c59f177d1f8d076777798e58ea823 Mon Sep 17 00:00:00 2001 From: George Date: Mon, 5 Oct 2026 17:53:41 -0500 Subject: [PATCH] Commit inicial: ITCA_API_SAP_WMS (.NET Core 3.1) Co-Authored-By: Claude Sonnet 5.5 --- .gitignore | 22 + CLAUDE.md | 100 ++ ITCA_API_SAP_WMS.sln | 73 + .../Authenticate/Dto_AuthenticateRequest.cs | 22 + Net.Business.DTO/Net.Business.DTO.csproj | 16 + Net.Business.DTO/WMS/HojaRuta/Dto_HojaRuta.cs | 29 + .../WMS/HojaRuta/Dto_HojaRutaCreate.cs | 40 + .../WMS/Inventario/Dto_Inventario.cs | 35 + .../WMS/Picking/Dto_PickingRequest.cs | 60 + .../WMS/Recibo/Dto_ReciboRequest.cs | 51 + .../Dto_SolicitudTransferenciaPatchRequest.cs | 31 + .../Transferencia/Dto_TransferenciaRequest.cs | 48 + .../Authenticate/BE_AuthenticateRequest.cs | 12 + .../Authenticate/BE_AuthenticateResponse.cs | 12 + .../Authenticate/ModelCredential.cs | 12 + .../Email/BE_EmailSenderOptions.cs | 11 + .../Net.Business.Entities.csproj | 15 + .../BE_ResultadoTransaccion.cs | 45 + .../ServicesLayer/BE_BaseResponseSap.cs | 26 + .../ServicesLayer/BE_BusinessPartners.cs | 115 ++ .../CreditNotes/BE_CreditNotesBatchNumbers.cs | 12 + .../BE_CreditNotesDocumentReferences.cs | 14 + .../CreditNotes/BE_CreditNotesLine.cs | 23 + .../CreditNotes/BE_CreditNotesNotes.cs | 30 + .../Filtro/FE_BusinessPartners.cs | 17 + .../ServicesLayer/HR/BE_HojaRutaCreate.cs | 78 ++ .../HR/BE_HojaRutaCreateDetalle.cs | 12 + .../ServicesLayer/ITC_SOLINGMER.cs | 23 + .../ServicesLayer/ITC_SOLSALMER.cs | 23 + .../BE_InventoryGenEntries.cs | 22 + .../BE_InventoryGenEntriesBatchNumbers.cs | 12 + .../BE_InventoryGenEntriesLine.cs | 20 + .../InventoryGenExits/BE_InventoryGenExits.cs | 23 + .../BE_InventoryGenExitsBatchNumbers.cs | 12 + .../BE_InventoryGenExitsLine.cs | 20 + .../BE_InventoryTransferRequest.cs | 21 + .../ServicesLayer/Invoices/BE_Invoices.cs | 38 + .../Invoices/BE_InvoicesBatchNumbers.cs | 12 + .../ServicesLayer/Invoices/BE_InvoicesLine.cs | 20 + .../ServicesLayer/Items/BE_ItemStock.cs | 17 + .../BE_PurchaseDeliveryNotes.cs | 21 + .../BE_PurchaseDeliveryNotesBatchNumbers.cs | 12 + .../BE_PurchaseDeliveryNotesLine.cs | 22 + .../PurchaseInvoices/BE_PurchaseInvoices.cs | 19 + .../BE_PurchaseInvoicesBatchNumbers.cs | 12 + .../BE_PurchaseInvoicesLine.cs | 20 + .../PurchaseOrders/BE_PurchaseOrders.cs | 19 + .../BE_PurchaseOrdersBatchNumbers.cs | 12 + .../PurchaseOrders/BE_PurchaseOrdersLine.cs | 20 + .../ReturnRequest/BE_ReturnRequest.cs | 25 + .../BE_ReturnRequestBatchNumbers.cs | 12 + .../ReturnRequest/BE_ReturnRequestLine.cs | 21 + .../StockTransfer/BE_StockTransfer.cs | 39 + .../BE_StockTransferDocumentReferences.cs | 14 + .../StockTransfer/BE_StockTransferLine.cs | 18 + .../BE_StockTransferLineBatchNumber.cs | 12 + .../WMS/HojaRuta/BE_HojaRutaEntities.cs | 13 + .../WMS/Inventario/BE_Inventario.cs | 18 + .../WMS/Inventario/BE_InventarioItems.cs | 15 + .../WMS/Inventario/BE_InventarioItemsLotes.cs | 11 + .../WMS/Picking/BE_PickingDetalle.cs | 14 + .../WMS/Picking/BE_PickingRequest.cs | 32 + .../WMS/ProcesoPicking/BE_ProcesoPicking.cs | 10 + .../WMS/Recibo/BE_ReciboDetalle.cs | 11 + .../WMS/Recibo/BE_ReciboRequest.cs | 27 + .../BE_SolicitudTransferenciaPatchRequest.cs | 22 + .../Transferencia/BE_TransferenciaDetalle.cs | 12 + .../Transferencia/BE_TransferenciaRequest.cs | 26 + .../.config/dotnet-tools.json | 12 + .../Controllers/AuthenticateController.cs | 44 + .../Controllers/HojaRutaController.cs | 58 + .../Controllers/InventarioController.cs | 58 + .../Controllers/ItemController.cs | 37 + .../Controllers/PickingController.cs | 104 ++ .../Controllers/ReciboController.cs | 55 + .../SolicitudTransferenciaController.cs | 100 ++ .../Controllers/TransferenciaController.cs | 55 + .../ExceptionMiddlewareExtensions.cs | 45 + .../Extensions/ServiceExtensions.cs | 54 + Net.Business.Services/ITCA_API_SAP_WMS.xml | 20 + Net.Business.Services/Log/B_Log.cs | 35 + .../Net.Business.Services.csproj | 40 + Net.Business.Services/Program.cs | 47 + .../PublishProfiles/FolderProfile.pubxml | 21 + .../PublishProfiles/FolderProfile1.pubxml | 21 + .../PublishProfiles/FolderProfile2.pubxml | 21 + .../Properties/launchSettings.json | 38 + Net.Business.Services/Startup.cs | 141 ++ .../appsettings.example.json | 55 + .../resources/img/logo-prosemedic.png | Bin 0 -> 7139 bytes Net.Business.Services/web.config | 17 + Net.Connection.Attributes/ActionType.cs | 11 + Net.Connection.Attributes/DBParameter.cs | 64 + .../Net.Connection.Attributes.csproj | 7 + .../ConnectionServiceLayer.cs | 1216 +++++++++++++++++ .../Net.Connection.ServiceLayer.csproj | 17 + .../ResponseGetServiceLayer.cs | 9 + .../ResponseLoginServiceLayer.cs | 27 + Net.Connection/Connection/ConnectionSQL.cs | 372 +++++ Net.Connection/Connection/DbParametro.cs | 35 + Net.Connection/Connection/IConnectionSQL.cs | 17 + Net.Connection/Net.Connection.csproj | 18 + .../RepositoryBase/IRepositoryBase.cs | 14 + .../RepositoryBase/RepositoryBase.cs | 43 + Net.Constantes/Net.Constantes.csproj | 7 + Net.Constantes/StoreProcedure.cs | 146 ++ Net.CrossCotting/EncriptaHelper.cs | 223 +++ Net.CrossCotting/Net.CrossCotting.csproj | 15 + Net.CrossCotting/PageEventHelper.cs | 84 ++ Net.CrossCotting/ResultadoTransaccion.cs | 58 + Net.CrossCotting/Serializador.cs | 118 ++ Net.CrossCotting/Utils.cs | 65 + .../Authenticate/AuthenticateRepository.cs | 94 ++ .../Authenticate/IAuthenticateRepository.cs | 15 + .../DependencyInjection/IRepositoryWrapper.cs | 49 + .../DependencyInjection/RepositoryWrapper.cs | 326 +++++ .../Correlativo/HelperCorrelativo.cs | 35 + Net.Data/HelperData/HelperDB.cs | 27 + .../HelperData/HojaRuta/HelperHojaRuta.cs | 97 ++ .../HelperData/Inventario/HelperInventario.cs | 34 + Net.Data/HelperData/Invoices/HelperInvoice.cs | 34 + .../HelperProcesoPermitido.cs | 106 ++ .../ProcesoPiciking/HelperProcesoPiciking.cs | 54 + Net.Data/HelperData/Stock/HelperStock.cs | 85 ++ Net.Data/LocalData.cs | 37 + Net.Data/Net.Data.csproj | 21 + .../BusinessPartnersRepository.cs | 78 ++ .../IBusinessPartnersRepository.cs | 11 + .../CreditNotes/CreditNotesRepository.cs | 92 ++ .../CreditNotes/ICreditNotesRepository.cs | 13 + .../GlobalData/GlobalDataRepository.cs | 83 ++ .../GlobalData/IGlobalDataRepository.cs | 15 + Net.Data/ServicesLayer/HR/HRRepository.cs | 146 ++ Net.Data/ServicesLayer/HR/IHRRepository.cs | 14 + .../IInventoryGenEntriesRepository.cs | 13 + .../InventoryGenEntriesRepository.cs | 67 + .../IInventoryGenExitsRepository.cs | 14 + .../InventoryGenExitsRepository.cs | 68 + .../Invoice/IInvoiceRepository.cs | 17 + .../Invoice/InvoiceRepository.cs | 118 ++ .../IPurchaseDeliveryNotesRepository.cs | 13 + .../PurchaseDeliveryNotesRepository.cs | 78 ++ .../IPurchaseInvoicesRepository.cs | 13 + .../PurchaseInvoicesRepository.cs | 76 ++ .../IPurchaseOrdersRepository.cs | 15 + .../PurchaseOrdersRepository.cs | 79 ++ .../ReturnRequest/IReturnRequestRepository.cs | 13 + .../ReturnRequest/ReturnRequestRepository.cs | 77 ++ .../StockTransfer/IStockTransferRepository.cs | 11 + .../StockTransfer/StockTransferRepository.cs | 100 ++ Net.Data/TextFile1.txt | 5 + Net.Data/WMS/Enums/EnumRecibo.cs | 12 + .../WMS/Inventario/IInventarioRepository.cs | 11 + .../WMS/Inventario/InventarioRepository.cs | 601 ++++++++ Net.Data/WMS/Items/IItemsRepository.cs | 11 + Net.Data/WMS/Items/ItemsRepository.cs | 80 ++ Net.Data/WMS/Picking/IPickingRepository.cs | 14 + Net.Data/WMS/Picking/PickingRepository.cs | 794 +++++++++++ Net.Data/WMS/Recibo/IReciboRepository.cs | 12 + Net.Data/WMS/Recibo/ReciboRepository.cs | 642 +++++++++ .../ISolicitudTransferenciaRepository.cs | 12 + .../SolicitudTransferenciaRepository.cs | 109 ++ .../Transferencia/ITransferenciaRepository.cs | 11 + .../Transferencia/TransferenciaRepository.cs | 184 +++ README.md | 149 ++ docs/PICKING.md | 272 ++++ docs/PORTE_FUNCIONALIDAD_NUEVA.md | 231 ++++ docs/SOLICITUD_TRANSFERENCIA.md | 301 ++++ 168 files changed, 11066 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 ITCA_API_SAP_WMS.sln create mode 100644 Net.Business.DTO/Authenticate/Dto_AuthenticateRequest.cs create mode 100644 Net.Business.DTO/Net.Business.DTO.csproj create mode 100644 Net.Business.DTO/WMS/HojaRuta/Dto_HojaRuta.cs create mode 100644 Net.Business.DTO/WMS/HojaRuta/Dto_HojaRutaCreate.cs create mode 100644 Net.Business.DTO/WMS/Inventario/Dto_Inventario.cs create mode 100644 Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs create mode 100644 Net.Business.DTO/WMS/Recibo/Dto_ReciboRequest.cs create mode 100644 Net.Business.DTO/WMS/SolicitudTransferencia/Dto_SolicitudTransferenciaPatchRequest.cs create mode 100644 Net.Business.DTO/WMS/Transferencia/Dto_TransferenciaRequest.cs create mode 100644 Net.Business.Entities/Authenticate/BE_AuthenticateRequest.cs create mode 100644 Net.Business.Entities/Authenticate/BE_AuthenticateResponse.cs create mode 100644 Net.Business.Entities/Authenticate/ModelCredential.cs create mode 100644 Net.Business.Entities/Email/BE_EmailSenderOptions.cs create mode 100644 Net.Business.Entities/Net.Business.Entities.csproj create mode 100644 Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs create mode 100644 Net.Business.Entities/ServicesLayer/BE_BaseResponseSap.cs create mode 100644 Net.Business.Entities/ServicesLayer/BE_BusinessPartners.cs create mode 100644 Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesDocumentReferences.cs create mode 100644 Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesNotes.cs create mode 100644 Net.Business.Entities/ServicesLayer/Filtro/FE_BusinessPartners.cs create mode 100644 Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreate.cs create mode 100644 Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreateDetalle.cs create mode 100644 Net.Business.Entities/ServicesLayer/ITC_SOLINGMER.cs create mode 100644 Net.Business.Entities/ServicesLayer/ITC_SOLSALMER.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntries.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExits.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/InventoryTransferRequest/BE_InventoryTransferRequest.cs create mode 100644 Net.Business.Entities/ServicesLayer/Invoices/BE_Invoices.cs create mode 100644 Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/Items/BE_ItemStock.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotes.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoices.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrders.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequest.cs create mode 100644 Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestBatchNumbers.cs create mode 100644 Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransfer.cs create mode 100644 Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferDocumentReferences.cs create mode 100644 Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLine.cs create mode 100644 Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLineBatchNumber.cs create mode 100644 Net.Business.Entities/WMS/HojaRuta/BE_HojaRutaEntities.cs create mode 100644 Net.Business.Entities/WMS/Inventario/BE_Inventario.cs create mode 100644 Net.Business.Entities/WMS/Inventario/BE_InventarioItems.cs create mode 100644 Net.Business.Entities/WMS/Inventario/BE_InventarioItemsLotes.cs create mode 100644 Net.Business.Entities/WMS/Picking/BE_PickingDetalle.cs create mode 100644 Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs create mode 100644 Net.Business.Entities/WMS/ProcesoPicking/BE_ProcesoPicking.cs create mode 100644 Net.Business.Entities/WMS/Recibo/BE_ReciboDetalle.cs create mode 100644 Net.Business.Entities/WMS/Recibo/BE_ReciboRequest.cs create mode 100644 Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchRequest.cs create mode 100644 Net.Business.Entities/WMS/Transferencia/BE_TransferenciaDetalle.cs create mode 100644 Net.Business.Entities/WMS/Transferencia/BE_TransferenciaRequest.cs create mode 100644 Net.Business.Services/.config/dotnet-tools.json create mode 100644 Net.Business.Services/Controllers/AuthenticateController.cs create mode 100644 Net.Business.Services/Controllers/HojaRutaController.cs create mode 100644 Net.Business.Services/Controllers/InventarioController.cs create mode 100644 Net.Business.Services/Controllers/ItemController.cs create mode 100644 Net.Business.Services/Controllers/PickingController.cs create mode 100644 Net.Business.Services/Controllers/ReciboController.cs create mode 100644 Net.Business.Services/Controllers/SolicitudTransferenciaController.cs create mode 100644 Net.Business.Services/Controllers/TransferenciaController.cs create mode 100644 Net.Business.Services/Extensions/ExceptionMiddlewareExtensions.cs create mode 100644 Net.Business.Services/Extensions/ServiceExtensions.cs create mode 100644 Net.Business.Services/ITCA_API_SAP_WMS.xml create mode 100644 Net.Business.Services/Log/B_Log.cs create mode 100644 Net.Business.Services/Net.Business.Services.csproj create mode 100644 Net.Business.Services/Program.cs create mode 100644 Net.Business.Services/Properties/PublishProfiles/FolderProfile.pubxml create mode 100644 Net.Business.Services/Properties/PublishProfiles/FolderProfile1.pubxml create mode 100644 Net.Business.Services/Properties/PublishProfiles/FolderProfile2.pubxml create mode 100644 Net.Business.Services/Properties/launchSettings.json create mode 100644 Net.Business.Services/Startup.cs create mode 100644 Net.Business.Services/appsettings.example.json create mode 100644 Net.Business.Services/resources/img/logo-prosemedic.png create mode 100644 Net.Business.Services/web.config create mode 100644 Net.Connection.Attributes/ActionType.cs create mode 100644 Net.Connection.Attributes/DBParameter.cs create mode 100644 Net.Connection.Attributes/Net.Connection.Attributes.csproj create mode 100644 Net.Connection.ServiceLayer/ConnectionServiceLayer.cs create mode 100644 Net.Connection.ServiceLayer/Net.Connection.ServiceLayer.csproj create mode 100644 Net.Connection.ServiceLayer/ResponseGetServiceLayer.cs create mode 100644 Net.Connection.ServiceLayer/ResponseLoginServiceLayer.cs create mode 100644 Net.Connection/Connection/ConnectionSQL.cs create mode 100644 Net.Connection/Connection/DbParametro.cs create mode 100644 Net.Connection/Connection/IConnectionSQL.cs create mode 100644 Net.Connection/Net.Connection.csproj create mode 100644 Net.Connection/RepositoryBase/IRepositoryBase.cs create mode 100644 Net.Connection/RepositoryBase/RepositoryBase.cs create mode 100644 Net.Constantes/Net.Constantes.csproj create mode 100644 Net.Constantes/StoreProcedure.cs create mode 100644 Net.CrossCotting/EncriptaHelper.cs create mode 100644 Net.CrossCotting/Net.CrossCotting.csproj create mode 100644 Net.CrossCotting/PageEventHelper.cs create mode 100644 Net.CrossCotting/ResultadoTransaccion.cs create mode 100644 Net.CrossCotting/Serializador.cs create mode 100644 Net.CrossCotting/Utils.cs create mode 100644 Net.Data/Authenticate/AuthenticateRepository.cs create mode 100644 Net.Data/Authenticate/IAuthenticateRepository.cs create mode 100644 Net.Data/DependencyInjection/IRepositoryWrapper.cs create mode 100644 Net.Data/DependencyInjection/RepositoryWrapper.cs create mode 100644 Net.Data/HelperData/Correlativo/HelperCorrelativo.cs create mode 100644 Net.Data/HelperData/HelperDB.cs create mode 100644 Net.Data/HelperData/HojaRuta/HelperHojaRuta.cs create mode 100644 Net.Data/HelperData/Inventario/HelperInventario.cs create mode 100644 Net.Data/HelperData/Invoices/HelperInvoice.cs create mode 100644 Net.Data/HelperData/ProcesoPermitidos/HelperProcesoPermitido.cs create mode 100644 Net.Data/HelperData/ProcesoPiciking/HelperProcesoPiciking.cs create mode 100644 Net.Data/HelperData/Stock/HelperStock.cs create mode 100644 Net.Data/LocalData.cs create mode 100644 Net.Data/Net.Data.csproj create mode 100644 Net.Data/ServicesLayer/BusinessPartners/BusinessPartnersRepository.cs create mode 100644 Net.Data/ServicesLayer/BusinessPartners/IBusinessPartnersRepository.cs create mode 100644 Net.Data/ServicesLayer/CreditNotes/CreditNotesRepository.cs create mode 100644 Net.Data/ServicesLayer/CreditNotes/ICreditNotesRepository.cs create mode 100644 Net.Data/ServicesLayer/GlobalData/GlobalDataRepository.cs create mode 100644 Net.Data/ServicesLayer/GlobalData/IGlobalDataRepository.cs create mode 100644 Net.Data/ServicesLayer/HR/HRRepository.cs create mode 100644 Net.Data/ServicesLayer/HR/IHRRepository.cs create mode 100644 Net.Data/ServicesLayer/InventoryGenEntries/IInventoryGenEntriesRepository.cs create mode 100644 Net.Data/ServicesLayer/InventoryGenEntries/InventoryGenEntriesRepository.cs create mode 100644 Net.Data/ServicesLayer/InventoryGenExits/IInventoryGenExitsRepository.cs create mode 100644 Net.Data/ServicesLayer/InventoryGenExits/InventoryGenExitsRepository.cs create mode 100644 Net.Data/ServicesLayer/Invoice/IInvoiceRepository.cs create mode 100644 Net.Data/ServicesLayer/Invoice/InvoiceRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseDeliveryNotes/IPurchaseDeliveryNotesRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseDeliveryNotes/PurchaseDeliveryNotesRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseInvoices/IPurchaseInvoicesRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseInvoices/PurchaseInvoicesRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseOrders/IPurchaseOrdersRepository.cs create mode 100644 Net.Data/ServicesLayer/PurchaseOrders/PurchaseOrdersRepository.cs create mode 100644 Net.Data/ServicesLayer/ReturnRequest/IReturnRequestRepository.cs create mode 100644 Net.Data/ServicesLayer/ReturnRequest/ReturnRequestRepository.cs create mode 100644 Net.Data/ServicesLayer/StockTransfer/IStockTransferRepository.cs create mode 100644 Net.Data/ServicesLayer/StockTransfer/StockTransferRepository.cs create mode 100644 Net.Data/TextFile1.txt create mode 100644 Net.Data/WMS/Enums/EnumRecibo.cs create mode 100644 Net.Data/WMS/Inventario/IInventarioRepository.cs create mode 100644 Net.Data/WMS/Inventario/InventarioRepository.cs create mode 100644 Net.Data/WMS/Items/IItemsRepository.cs create mode 100644 Net.Data/WMS/Items/ItemsRepository.cs create mode 100644 Net.Data/WMS/Picking/IPickingRepository.cs create mode 100644 Net.Data/WMS/Picking/PickingRepository.cs create mode 100644 Net.Data/WMS/Recibo/IReciboRepository.cs create mode 100644 Net.Data/WMS/Recibo/ReciboRepository.cs create mode 100644 Net.Data/WMS/SolicitudTransferencia/ISolicitudTransferenciaRepository.cs create mode 100644 Net.Data/WMS/SolicitudTransferencia/SolicitudTransferenciaRepository.cs create mode 100644 Net.Data/WMS/Transferencia/ITransferenciaRepository.cs create mode 100644 Net.Data/WMS/Transferencia/TransferenciaRepository.cs create mode 100644 README.md create mode 100644 docs/PICKING.md create mode 100644 docs/PORTE_FUNCIONALIDAD_NUEVA.md create mode 100644 docs/SOLICITUD_TRANSFERENCIA.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..106ebfa --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Build +bin/ +obj/ +publish/ +*.user +*.suo + +# IDE +.vs/ +.vscode/ +.idea/ + +# OS +.DS_Store + +# Logs +*.log + +# Configuración con credenciales (usar appsettings.example.json como plantilla) +appsettings.json +appsettings.*.json +!appsettings.example.json diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0670445 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,100 @@ +# ITCA_API_SAP_WMS (.NET) — proyecto principal + +API de integración WMS ↔ SAP Business One, **ASP.NET Core 3.1**. Para +build/publish/despliegue en IIS ver [`README.md`](./README.md). + +Esta carpeta (`backend_octubre`) es **el proyecto vigente**. Antes existía +una copia paralela, `ITCA_API_SAP_WMS`, con la funcionalidad nueva portada +desde la reescritura Python; se portó aquí y esa copia quedó **archivada en un +comprimido (versión antigua)**. No hay `git` en esta carpeta. + +## Qué se portó desde `ITCA_API_SAP_WMS` (2026-10-05) + +Detalle técnico en `docs/PORTE_FUNCIONALIDAD_NUEVA.md`, +`docs/SOLICITUD_TRANSFERENCIA.md` y `docs/PICKING.md`. + +1. **SolicitudTransferencia**: `PATCH /api/SolicitudTransferencia/{docEntry}` y + `POST /api/SolicitudTransferencia/{docEntry}/cerrar`. +2. **Picking diurno/nocturno**: campo `Notificacion` (early-return en + `PickingRepository.Create` tras `HelperProcesoPiciking.Set`) y + `POST /api/Picking/HojaRuta/{docEntry}/Cerrar`. +3. **`ConnectionServiceLayer`**: `PatchNoContentAsync` y `PostActionAsync` + (métodos nuevos; los existentes no se tocaron). + +## Cambios de configuración y correcciones hechas en esta carpeta + +- **Credenciales y esquema HANA en `appsettings.json`**, sección `Hana` + (`server`, `user`, `password`, `schema` opcional), leída por + `LocalData.Configure` desde `Startup`. Antes estaban fijas en el código + (`LocalData.cs`, `Log/B_Log.cs`). El esquema sale de `Hana:schema` o, si no + está, de `SapServiceLayer:company`; **si falta la sección `Hana` o el + esquema, la app no arranca** (error claro). Ya no hay `DB_NAME` fijo. +- **Precio promedio solo en entradas** (`TipoMovimiento "01"`) en + `InventarioRepository.Create` (los dos chequeos: `SubAlmacen` y `Almacen`). + Si el artículo no tiene stock, se conserva el `PrecioPromedio` del request en + vez de abortar con *"No existe stock disponible para el articulo X"* (ese + error bloqueaba ingresos de artículos sin stock previo). En salidas ya no se + busca el promedio: `PriceAfterVAT` lleva el precio del request. El chequeo de + stock de la rama de **salida** de `PickingRepository` (~línea 363) no se tocó. +- **Lote de 100 líneas** (`InventarioRepository.Create`): `var Inventario = + entidad` reutilizaba el mismo objeto, y con más de 100 líneas se generaban N + documentos iguales con el último bloque. Ahora se crea una copia por bloque y + la rama de salida lee `entidad_inventario.Detalle`. +- **SQL injection**: parametrizadas las consultas de `HelperProcesoPiciking`, + `HelperStock`, `HelperInventario`, `HelperInvoice`, `HelperCorrelativo`, + `HelperHojaRuta` y `HelperProcesoPermitido` (`?` + `HanaParameter`). + El esquema sigue interpolado (viene de configuración, no del request). +- `ITCA_API_SAP_WMS.xml` ahora se genera también en Release (sin eso Swagger + revienta con `FileNotFoundException` en un `publish -c Release`). + +## Funcionalidad propia de esta carpeta (no existe en la copia antigua) + +Hoja de Ruta (`HojaRutaController`, `HRRepository`, `GlobalDataRepository`), +reapertura de facturas (`InvoiceRepository.ReOpen`, `PostReOpen`), notas de +crédito con documentos de referencia, cierre automático de la solicitud de +traslado en `Transferencia` (`PostClose`), `Latitud`/`Longitud` y reproceso en +Picking, columna `HORA` en `B_Log`. Lo que **no** se trajo: `Chatbots` y +`MessageController` (solo existen en la copia archivada). + +## Sin verificar + +- **Nada se probó contra SAP/HANA reales.** Solo se verificó que compila + (0 errores) y que el publish se genera. +- La sintaxis `CALL "esquema"."proc"(?, ?)` con parámetros no está probada con + el driver HANA 2.1; si falla con un error de parámetro, mirar primero ahí. +- Para probar el lote de 100: un inventario de >100 líneas (p. ej. 250) debe + generar 3 documentos (100/100/50) sin repetir ni perder líneas, tanto en + entradas como en salidas. + +## Bugs conocidos, sin corregir + +- `BE_ResultadoTransaccion.NombreEstacion`: setter con recursión infinita + (bomba de tiempo; hoy nada lo asigna). +- `ConnectionServiceLayer.PatchAsyncSBA`: con un `204` real devuelve `null` + sin marcar éxito. `Login()`/`LoginPost()` duplicados; `throw` inalcanzable + tras `return` en varios `catch`. +- `ValidarCertificado` acepta cualquier certificado TLS (siempre `true`). +- `HelperDB.SET(string query)` ejecuta SQL arbitrario; hoy sin llamadores + (candidato a borrar). +- `appsettings.json` versionado en texto plano con credenciales reales + (SAP Service Layer, **HANA `B1ADMIN`**, semilla JWT). Rotar la contraseña de + `B1ADMIN` (estuvo en el código fuente) y evaluar un usuario HANA de mínimos + permisos. + +## Despliegue + +Sitio IIS previsto: **`/integracion`** (antes `/integracion_wms`). Publicar con +el comando del README **sin pisar** el `appsettings.json` del servidor; agregar +a ese archivo la sección `Hana` y revisar `SapServiceLayer:company` (determina +contra qué base lee y escribe). El `web.config` generado por `dotnet publish` +usa `processPath=".\ITCA_API_SAP_WMS.exe"`; el del código fuente apunta a +`bin\Debug\...` (solo para sitios que corren desde el código compilado). + +## Pendiente + +- Probar en QA: endpoints nuevos (SolicitudTransferencia, `Notificacion`, + `HojaRuta/Cerrar`), un ingreso sin stock previo, el lote de 100 y las + consultas parametrizadas. +- Verificar que existan en el esquema del sitio los procedimientos `ITCA_*` + y las tablas `@ITCA_PROWMS`, `@SYP_MOTIVOS`, `@SYP_NUMDOC`. +- Decidir si se corrigen los bugs de la lista de arriba. diff --git a/ITCA_API_SAP_WMS.sln b/ITCA_API_SAP_WMS.sln new file mode 100644 index 0000000..4bfd9cb --- /dev/null +++ b/ITCA_API_SAP_WMS.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Business.DTO", "Net.Business.DTO\Net.Business.DTO.csproj", "{22BCC127-93B5-40DE-9678-A172AA8F542C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Business.Entities", "Net.Business.Entities\Net.Business.Entities.csproj", "{5B11F494-0091-4A4C-930A-90012AD4F695}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Connection", "Net.Connection\Net.Connection.csproj", "{F63F6FF0-BD00-4A28-84E7-ACA7CA40AC10}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Connection.Attributes", "Net.Connection.Attributes\Net.Connection.Attributes.csproj", "{540EEA77-9B44-4796-89EF-0ADDE3EE3825}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.CrossCotting", "Net.CrossCotting\Net.CrossCotting.csproj", "{CACDBD23-52C9-4533-B231-A7A59D0EDAF8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Data", "Net.Data\Net.Data.csproj", "{DC9B3CEE-7AF1-4421-8058-4D0244DD1CF5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Business.Services", "Net.Business.Services\Net.Business.Services.csproj", "{B4BE6148-6E1F-4BB9-B399-424C4E6BF4C0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Constantes", "Net.Constantes\Net.Constantes.csproj", "{05A306D4-ADBB-4205-A589-D692D1ACB954}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net.Connection.ServiceLayer", "Net.Connection.ServiceLayer\Net.Connection.ServiceLayer.csproj", "{21B28EDA-ED40-4886-B11F-37C5794A6E33}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {22BCC127-93B5-40DE-9678-A172AA8F542C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22BCC127-93B5-40DE-9678-A172AA8F542C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22BCC127-93B5-40DE-9678-A172AA8F542C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22BCC127-93B5-40DE-9678-A172AA8F542C}.Release|Any CPU.Build.0 = Release|Any CPU + {5B11F494-0091-4A4C-930A-90012AD4F695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B11F494-0091-4A4C-930A-90012AD4F695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B11F494-0091-4A4C-930A-90012AD4F695}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B11F494-0091-4A4C-930A-90012AD4F695}.Release|Any CPU.Build.0 = Release|Any CPU + {F63F6FF0-BD00-4A28-84E7-ACA7CA40AC10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F63F6FF0-BD00-4A28-84E7-ACA7CA40AC10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F63F6FF0-BD00-4A28-84E7-ACA7CA40AC10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F63F6FF0-BD00-4A28-84E7-ACA7CA40AC10}.Release|Any CPU.Build.0 = Release|Any CPU + {540EEA77-9B44-4796-89EF-0ADDE3EE3825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {540EEA77-9B44-4796-89EF-0ADDE3EE3825}.Debug|Any CPU.Build.0 = Debug|Any CPU + {540EEA77-9B44-4796-89EF-0ADDE3EE3825}.Release|Any CPU.ActiveCfg = Release|Any CPU + {540EEA77-9B44-4796-89EF-0ADDE3EE3825}.Release|Any CPU.Build.0 = Release|Any CPU + {CACDBD23-52C9-4533-B231-A7A59D0EDAF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CACDBD23-52C9-4533-B231-A7A59D0EDAF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CACDBD23-52C9-4533-B231-A7A59D0EDAF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CACDBD23-52C9-4533-B231-A7A59D0EDAF8}.Release|Any CPU.Build.0 = Release|Any CPU + {DC9B3CEE-7AF1-4421-8058-4D0244DD1CF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC9B3CEE-7AF1-4421-8058-4D0244DD1CF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC9B3CEE-7AF1-4421-8058-4D0244DD1CF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC9B3CEE-7AF1-4421-8058-4D0244DD1CF5}.Release|Any CPU.Build.0 = Release|Any CPU + {B4BE6148-6E1F-4BB9-B399-424C4E6BF4C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4BE6148-6E1F-4BB9-B399-424C4E6BF4C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4BE6148-6E1F-4BB9-B399-424C4E6BF4C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4BE6148-6E1F-4BB9-B399-424C4E6BF4C0}.Release|Any CPU.Build.0 = Release|Any CPU + {05A306D4-ADBB-4205-A589-D692D1ACB954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05A306D4-ADBB-4205-A589-D692D1ACB954}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05A306D4-ADBB-4205-A589-D692D1ACB954}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05A306D4-ADBB-4205-A589-D692D1ACB954}.Release|Any CPU.Build.0 = Release|Any CPU + {21B28EDA-ED40-4886-B11F-37C5794A6E33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21B28EDA-ED40-4886-B11F-37C5794A6E33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21B28EDA-ED40-4886-B11F-37C5794A6E33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21B28EDA-ED40-4886-B11F-37C5794A6E33}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {139784B0-0533-40EC-8A32-A4E3E7CA0A89} + EndGlobalSection +EndGlobal diff --git a/Net.Business.DTO/Authenticate/Dto_AuthenticateRequest.cs b/Net.Business.DTO/Authenticate/Dto_AuthenticateRequest.cs new file mode 100644 index 0000000..2252e92 --- /dev/null +++ b/Net.Business.DTO/Authenticate/Dto_AuthenticateRequest.cs @@ -0,0 +1,22 @@ +using Net.Business.Entities.Authenticate; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.DTO.Authenticate +{ + public class Dto_AuthenticateRequest + { + public string client_id { get; set; } + public string client_secret { get; set; } + + public BE_AuthenticateRequest RetornaModelo() + { + return new BE_AuthenticateRequest() + { + client_id = client_id, + client_secret = client_secret, + }; + } + } +} diff --git a/Net.Business.DTO/Net.Business.DTO.csproj b/Net.Business.DTO/Net.Business.DTO.csproj new file mode 100644 index 0000000..9ab9a0b --- /dev/null +++ b/Net.Business.DTO/Net.Business.DTO.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRuta.cs b/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRuta.cs new file mode 100644 index 0000000..15b2c02 --- /dev/null +++ b/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRuta.cs @@ -0,0 +1,29 @@ +using Net.Business.Entities.WMS.HojaRuta; + +namespace Net.Business.DTO.WMS.HojaRuta +{ + public class Dto_HojaRuta + { + public int DocEntry { get; set; } + public string CodEstado { get; set; } + public string Estado { get; set; } + public string Proceso { get; set; } + public int IdEstadoCubico { get; set; } + public string HoraInicio { get; set; } + public string FinRuta { get; set; } + public string CodMotivo { get; set; } + public BE_HojaRutaEntities RetornaModelo() + { + return new BE_HojaRutaEntities() + { + DocEntry = DocEntry, + IdEstadoCubico = IdEstadoCubico, + Estado = Estado, + Proceso = Proceso, + CodMotivo = CodMotivo, + FinRuta = FinRuta, + HoraInicio = HoraInicio + }; + } + } +} diff --git a/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRutaCreate.cs b/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRutaCreate.cs new file mode 100644 index 0000000..de4e02b --- /dev/null +++ b/Net.Business.DTO/WMS/HojaRuta/Dto_HojaRutaCreate.cs @@ -0,0 +1,40 @@ +using iTextSharp.text; +using Net.Business.Entities.ServicesLayer.HR; +using System; +using System.Collections.Generic; + +namespace Net.Business.DTO.WMS.HojaRuta +{ + public class Dto_HojaRutaCreate + { + public string ModalidadTransporte { get; set; } + public string Zona { get; set; } + public string Territorio { get; set; } + public string Despachador { get; set; } + public DateTime FechaDespacho { get; set; } + public string AgenciaTransporte { get; set; } + public string NombreConductor { get; set; } + public string LicenciaConductor { get; set; } + public string PlacaVehiculo { get; set; } + public string Estado { get; set; } + public List Detalle { get; set; } + + public BE_HojaRutaCreate RetornaModelo() + { + return new BE_HojaRutaCreate() + { + AgenciaTransporte = AgenciaTransporte, + Despachador = Despachador, + Detalle = Detalle, + Estado = Estado, + FechaDespacho = FechaDespacho, + LicenciaConductor = LicenciaConductor, + ModalidadTransporte = ModalidadTransporte, + NombreConductor = NombreConductor, + PlacaVehiculo = PlacaVehiculo, + Territorio = Territorio, + Zona = Zona + }; + } + } +} diff --git a/Net.Business.DTO/WMS/Inventario/Dto_Inventario.cs b/Net.Business.DTO/WMS/Inventario/Dto_Inventario.cs new file mode 100644 index 0000000..410304e --- /dev/null +++ b/Net.Business.DTO/WMS/Inventario/Dto_Inventario.cs @@ -0,0 +1,35 @@ +using Net.Business.Entities.WMS.Inventario; +using System; +using System.Collections.Generic; + +namespace Net.Business.DTO.WMS.Inventario +{ + public class Dto_Inventario + { + public DateTime Fecha { get; set; } + public DateTime FechaVencimiento { get; set; } + public string TipoMovimientoSAP { get; set; } + public string TipoMovimiento { get; set; } + public string TipoInventario { get; set; } + public string Almacen { get; set; } + public string SubAlmacen { get; set; } + public List Detalle { get; set; } + public string NroInventario { get; set; } + public BE_Inventario RetornaModelo() + { + return new BE_Inventario() + { + Almacen = Almacen, + Detalle = Detalle, + Fecha = Fecha, + FechaVencimiento = FechaVencimiento, + SubAlmacen = SubAlmacen, + TipoMovimiento = TipoMovimiento, + NroInventario = NroInventario, + TipoInventario = TipoInventario, + TipoMovimientoSAP = TipoMovimientoSAP, + + }; + } + } +} diff --git a/Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs b/Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs new file mode 100644 index 0000000..3d7c7e4 --- /dev/null +++ b/Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs @@ -0,0 +1,60 @@ +using Net.Business.Entities.WMS.Picking; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.DTO.WMS.Picking +{ + public class Dto_PickingRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public string FechaEntrega { get; set; } + public string CodigoAlmacen { get; set; } + public DateTime FechaLlegada { get; set; } + public string CodigoERPCliente { get; set; } + public string CodigoERPDireccion { get; set; } + public int IdTipo { get; set; } + public int IdTipoDoc { get; set; } + public string Observacion { get; set; } + public int IdCondicion { get; set; } + public int Accion { get; set; } + public int IdEstadoCubico { get; set; } + public int DocEntry { get; set; } + public string Proceso { get; set; } + public string CodMotivo { get; set; } + // "preliminar" | "cierre" - cualquier otro valor o ausente se trata como + // "preliminar" (default seguro, nunca crea documentos en SAP por accidente). + public string Notificacion { get; set; } + public List Detalle { get; set; } + + public decimal Longitud { get; set; } + public decimal Latitud { get; set; } + public BE_PickingRequest RetornaModelo() + { + return new BE_PickingRequest() + { + Accion = Accion, + CodigoAlmacen = CodigoAlmacen, + CodigoERPCliente = CodigoERPCliente, + IdEstadoCubico = IdEstadoCubico, + CodigoERPDireccion = CodigoERPDireccion, + Detalle = Detalle, + FechaEntrega = FechaEntrega, + FechaLlegada = FechaLlegada, + FechaOrden = FechaOrden, + IdCondicion = IdCondicion, + IdTipo = IdTipo, + IdTipoDoc = IdTipoDoc, + NumOrden = NumOrden, + Observacion = Observacion, + DocEntry = DocEntry, + Proceso = Proceso, + CodMotivo = CodMotivo, + Notificacion = Notificacion, + Latitud = Latitud, + Longitud = Longitud, + }; + } + } +} diff --git a/Net.Business.DTO/WMS/Recibo/Dto_ReciboRequest.cs b/Net.Business.DTO/WMS/Recibo/Dto_ReciboRequest.cs new file mode 100644 index 0000000..4cf2fe7 --- /dev/null +++ b/Net.Business.DTO/WMS/Recibo/Dto_ReciboRequest.cs @@ -0,0 +1,51 @@ +using Net.Business.Entities.WMS.Recibo; +using System; +using System.Collections.Generic; + +namespace Net.Business.DTO.WMS.Recibo +{ + public class Dto_ReciboRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public string CodigoAlmacen { get; set; } + public DateTime FechaLlegada { get; set; } + public string CodigoERPProveedor { get; set; } + public int IdTipo { get; set; } + public int IdTipoDoc { get; set; } + public string Observacion { get; set; } + public int IdCuenta { get; set; } + public int Accion { get; set; } + public int DocEntry { get; set; } + public string DocImportacion { get; set; } + public string U_SYP_MDTD { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public string Comentario { get; set; } + public List Detalle { get; set; } + + public BE_ReciboRequest RetornaModelo() + { + return new BE_ReciboRequest() + { + Accion = Accion, + CodigoAlmacen = CodigoAlmacen, + CodigoERPProveedor = CodigoERPProveedor, + Detalle = Detalle, + FechaLlegada = FechaLlegada, + FechaOrden = FechaOrden, + IdTipo = IdTipo, + IdTipoDoc = IdTipoDoc, + Observacion = Observacion, + IdCuenta = IdCuenta, + NumOrden = NumOrden, + DocEntry = DocEntry, + DocImportacion = DocImportacion, + Comentario = Comentario, + U_SYP_MDSD = U_SYP_MDSD, + U_SYP_MDCD = U_SYP_MDCD, + U_SYP_MDTD = U_SYP_MDTD + }; + } + } +} diff --git a/Net.Business.DTO/WMS/SolicitudTransferencia/Dto_SolicitudTransferenciaPatchRequest.cs b/Net.Business.DTO/WMS/SolicitudTransferencia/Dto_SolicitudTransferenciaPatchRequest.cs new file mode 100644 index 0000000..1de8f33 --- /dev/null +++ b/Net.Business.DTO/WMS/SolicitudTransferencia/Dto_SolicitudTransferenciaPatchRequest.cs @@ -0,0 +1,31 @@ +using Net.Business.Entities.WMS.SolicitudTransferencia; +using System.Collections.Generic; +using System.Linq; + +namespace Net.Business.DTO.WMS.SolicitudTransferencia +{ + public class Dto_SolicitudTransferenciaPatchDetalle + { + public int Linea { get; set; } + public double Cantidad { get; set; } + } + + public class Dto_SolicitudTransferenciaPatchRequest + { + public string NumOrden { get; set; } + public List Detalle { get; set; } + + public BE_SolicitudTransferenciaPatchRequest RetornaModelo() + { + return new BE_SolicitudTransferenciaPatchRequest() + { + NumOrden = NumOrden, + Detalle = Detalle?.Select(d => new BE_SolicitudTransferenciaPatchDetalle + { + Linea = d.Linea, + Cantidad = d.Cantidad, + }).ToList(), + }; + } + } +} diff --git a/Net.Business.DTO/WMS/Transferencia/Dto_TransferenciaRequest.cs b/Net.Business.DTO/WMS/Transferencia/Dto_TransferenciaRequest.cs new file mode 100644 index 0000000..038b672 --- /dev/null +++ b/Net.Business.DTO/WMS/Transferencia/Dto_TransferenciaRequest.cs @@ -0,0 +1,48 @@ +using Net.Business.Entities.WMS.Transferencia; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.DTO.WMS.Transferencia +{ + public class Dto_TransferenciaRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public int IdTipo { get; set; } + public string CodigoAlmacenOrigen { get; set; } + public string CodigoSubAlmacenOrigen { get; set; } + public int IdCondicionOrigen { get; set; } + public string CodigoAlmacenDestino { get; set; } + public string CodigoSubAlmacenDestino { get; set; } + public int IdCondicionDestino { get; set; } + public string Observacion { get; set; } + public int IdCuenta { get; set; } + public int Accion { get; set; } + public int DocEntry { get; set; } + public int DocEntryEM { get; set; } + public List Detalle { get; set; } + + public BE_TransferenciaRequest RetornaModelo() + { + return new BE_TransferenciaRequest() + { + Accion = Accion, + TransferenciaDetalles = Detalle, + CodigoAlmacenDestino = CodigoAlmacenDestino, + CodigoAlmacenOrigen = CodigoAlmacenOrigen, + CodigoSubAlmacenDestino = CodigoSubAlmacenDestino, + CodigoSubAlmacenOrigen = CodigoSubAlmacenOrigen, + FechaOrden = FechaOrden, + IdCondicionDestino = IdCondicionDestino, + IdCondicionOrigen = IdCondicionOrigen, + IdCuenta = IdCuenta, + IdTipo = IdTipo, + NumOrden = NumOrden, + Observacion = Observacion, + DocEntry = DocEntry, + DocEntryEM = DocEntryEM + }; + } + } +} diff --git a/Net.Business.Entities/Authenticate/BE_AuthenticateRequest.cs b/Net.Business.Entities/Authenticate/BE_AuthenticateRequest.cs new file mode 100644 index 0000000..4f81c4d --- /dev/null +++ b/Net.Business.Entities/Authenticate/BE_AuthenticateRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.Authenticate +{ + public class BE_AuthenticateRequest + { + public string client_id { get; set; } + public string client_secret { get; set; } + } +} diff --git a/Net.Business.Entities/Authenticate/BE_AuthenticateResponse.cs b/Net.Business.Entities/Authenticate/BE_AuthenticateResponse.cs new file mode 100644 index 0000000..02efc00 --- /dev/null +++ b/Net.Business.Entities/Authenticate/BE_AuthenticateResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.Authenticate +{ + public class BE_AuthenticateResponse + { + public string Token { get; set; } + public string Type { get; set; } + } +} diff --git a/Net.Business.Entities/Authenticate/ModelCredential.cs b/Net.Business.Entities/Authenticate/ModelCredential.cs new file mode 100644 index 0000000..f3e1cc3 --- /dev/null +++ b/Net.Business.Entities/Authenticate/ModelCredential.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.Authenticate +{ + public class ModelCredential + { + public string client_id { get; set; } + public string client_secret { get; set; } + } +} diff --git a/Net.Business.Entities/Email/BE_EmailSenderOptions.cs b/Net.Business.Entities/Email/BE_EmailSenderOptions.cs new file mode 100644 index 0000000..e114b05 --- /dev/null +++ b/Net.Business.Entities/Email/BE_EmailSenderOptions.cs @@ -0,0 +1,11 @@ +namespace Net.Business.Entities +{ + public class BE_EmailSenderOptions + { + public int Port { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public bool EnableSsl { get; set; } + public string Host { get; set; } + } +} diff --git a/Net.Business.Entities/Net.Business.Entities.csproj b/Net.Business.Entities/Net.Business.Entities.csproj new file mode 100644 index 0000000..031a0d1 --- /dev/null +++ b/Net.Business.Entities/Net.Business.Entities.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs b/Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs new file mode 100644 index 0000000..135c927 --- /dev/null +++ b/Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities +{ + public class BE_ResultadoTransaccion + { + /// + /// ID de un nuevo registro o Id de registro actualizar + /// + public int? DocEntry { get; set; } + + public string DocNum { get; set; } + /// + /// Resultado de Codigo, Obtenido de la Base de Datos + /// 0 => Correcto + /// -1 => Error + /// + public int StatusCode { get; set; } + /// + /// Descripcion de la acción al finalizar el metodo invocado + /// + public string Message { get; set; } + public string Error { get; set; } + /// + /// Nombre de la Aplicación + /// + public string AppName { get; set; } + /// + /// Nombre del Método + /// + public string MethodName { get; set; } + /// + /// Lista del Resultado al finalizar el método invocado + /// + public IEnumerable ListData { get; set; } + /// + /// Data Resultado al finalizar el método invocado + /// + public T Data { get; set; } + /// + /// Nombre de la estación de trabajo + /// + public string NombreEstacion { get => System.Environment.MachineName; set => NombreEstacion = System.Environment.MachineName; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/BE_BaseResponseSap.cs b/Net.Business.Entities/ServicesLayer/BE_BaseResponseSap.cs new file mode 100644 index 0000000..59798f2 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/BE_BaseResponseSap.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer +{ + public class BE_BaseResponseSap + { + public decimal DocTotal { get; set; } + public decimal DocTotalSys { get; set; } + public long? TransNum { get; set; } + public long? DocEntry { get; set; } + public long? AbsoluteEntry { get; set; } + public long TransId { get; set; } + public long Number { get; set; } + public long Original { get; set; } + public long DocNum { get; set; } + public bool Exito { get; set; } + public string Mensaje { get; set; } + public string CodigoHttp { get; set; } + public string U_BPP_MDCD { get; set; } + public string Currency { get; set; } + public string DocumentStatus { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/BE_BusinessPartners.cs b/Net.Business.Entities/ServicesLayer/BE_BusinessPartners.cs new file mode 100644 index 0000000..a3b88e4 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/BE_BusinessPartners.cs @@ -0,0 +1,115 @@ +using Net.Connection.Attributes; +using System.Data; + +namespace Net.Business.Entities.ServicesLayer +{ + public class BE_BusinessPartners + { + [DBParameter(SqlDbType.VarChar, 15, ActionType.Everything)] + public string CardCode { get; set; } + + [DBParameter(SqlDbType.VarChar, 100, ActionType.Everything)] + public string CardType { get; set; } + + + [DBParameter(SqlDbType.VarChar, 100, ActionType.Everything)] + public string CardName { get; set; } + + + [DBParameter(SqlDbType.VarChar, 32, ActionType.Everything)] + public string FederalTaxID { get; set; } + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Address { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string MailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string EmailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Phone1 { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string U_BPP_BPTD { get; set; } + + + + public string EstadoSocio { get; set; } + public string TablaEstadoSocioNegocio { get; set; } + public string EstadoSocioStyle { get; set; } + } + + + public class BE_BusinessPartnersCustomersUpdate + { + [DBParameter(SqlDbType.VarChar, 15, ActionType.Everything)] + public string CardCode { get; set; } + + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Address { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string MailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string EmailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Phone1 { get; set; } + + public int PriceListNum { get; set; } + + + } + + + public class BE_BusinessPartnersCustomers + { + [DBParameter(SqlDbType.VarChar, 15, ActionType.Everything)] + public string CardCode { get; set; } + + [DBParameter(SqlDbType.VarChar, 100, ActionType.Everything)] + public string CardType { get; set; } + + + [DBParameter(SqlDbType.VarChar, 100, ActionType.Everything)] + public string CardName { get; set; } + + + [DBParameter(SqlDbType.VarChar, 32, ActionType.Everything)] + public string FederalTaxID { get; set; } + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Address { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string MailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string EmailAddress { get; set; } + + + [DBParameter(SqlDbType.VarChar, 250, ActionType.Everything)] + public string Phone1 { get; set; } + + [DBParameter(SqlDbType.Int, 0, ActionType.Everything)] + public int U_BPP_BPTD { get; set; } + public int PriceListNum { get; set; } + //U_BPP_BPTD = 6, + + } + +} diff --git a/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesBatchNumbers.cs new file mode 100644 index 0000000..7cdfa00 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.CreditNotes +{ + public class BE_CreditNotesBatchNumbers + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesDocumentReferences.cs b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesDocumentReferences.cs new file mode 100644 index 0000000..83b8420 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesDocumentReferences.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.CreditNotes +{ + public class BE_CreditNotesDocumentReferences + { + public int RefDocEntr { get; set; } + public string RefObjType { get; set; } + public DateTime IssueDate { get; set; } + public string Remark { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesLine.cs b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesLine.cs new file mode 100644 index 0000000..02fb05f --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesLine.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.CreditNotes +{ + public class BE_CreditNotesLine + { + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public decimal Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public int? BaseType { get; set; } + public int? BaseEntry { get; set; } + public int? BaseLine { get; set; } + public int LineNum { get; set; } + public string U_ITC_ALMDES { get; set; } + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesNotes.cs b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesNotes.cs new file mode 100644 index 0000000..a25c260 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/CreditNotes/BE_CreditNotesNotes.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.CreditNotes +{ + public class BE_CreditNotesNotes + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public string NumAtCard { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public string U_SYP_MDTD { get; set; } + public string U_SYP_MDSO { get; set; } + public string U_SYP_MDCO { get; set; } + public string U_SYP_MDTO { get; set; } + public string U_SYP_FECHAREF { get; set; } + public string U_SYP_TPONC { get; set; } + public string U_SYP_MOTNC { get; set; } + public string U_SYP_FEESUNAT { get; set; } = "000"; + public string U_SYP_FEEST { get; set; } = "PE"; + public string U_SYP_FEMEX { get; set; } = "1"; + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/Filtro/FE_BusinessPartners.cs b/Net.Business.Entities/ServicesLayer/Filtro/FE_BusinessPartners.cs new file mode 100644 index 0000000..4f978f4 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/Filtro/FE_BusinessPartners.cs @@ -0,0 +1,17 @@ +using Net.Connection.Attributes; +using System.Data; + +namespace Net.Business.Entities.ServicesLayer +{ + public class FE_BusinessPartners + { + [DBParameter(SqlDbType.VarChar, 30, ActionType.Everything)] + public string CardCode { get; set; } + [DBParameter(SqlDbType.VarChar, 100, ActionType.Everything)] + public string CardName { get; set; } + [DBParameter(SqlDbType.VarChar, 32, ActionType.Everything)] + public string FederalTaxID { get; set; } + [DBParameter(SqlDbType.VarChar, 20, ActionType.Everything)] + public string Usuario { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreate.cs b/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreate.cs new file mode 100644 index 0000000..abe0ddd --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreate.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.HR +{ + public class BE_HojaRutaCreate + { + public string ModalidadTransporte { get; set; } + public string Zona { get; set; } + public string Territorio { get; set; } + public string Despachador { get; set; } + public DateTime FechaDespacho { get; set; } + public string AgenciaTransporte { get; set; } + public string NombreConductor { get; set; } + public string LicenciaConductor { get; set; } + public string PlacaVehiculo { get; set; } + public string Estado { get; set; } + public List Detalle { get; set; } + } + + public class HojaRutaSAP + { + //public int DocEntry { get; set; } + //public int DocNum { get; set; } + public int U_ARD_PHR_CNTDOC { get; set; } + public string U_ARD_PHR_PLACA { get; set; } + public string U_ARD_PHR_LICCON { get; set; } + public string U_ARD_PHR_NOMCON { get; set; } + public string U_ARD_PHR_MARVEH { get; set; } + public DateTime U_ARD_PHR_FECCRE { get; set; } + public string U_ARD_PHR_CERINS { get; set; } + public string U_ARD_PHR_PLATOL { get; set; } + public string U_ARD_PHR_NOMDESP { get; set; } + public string U_ARD_PHR_ESTDESP { get; set; } + public string U_ARD_PHR_OBSERVA { get; set; } + public string U_ARD_PHR_ZONDIS { get; set; } + public string U_ARD_PHR_TERRI { get; set; } + public string U_ARD_PHR_MODTRANSP { get; set; } + public string U_ARD_PHR_NOMAGENTRANS { get; set; } + public string U_ARD_PHR_CODAGENTRANS { get; set; } + public string U_ARD_PHR_RUCAGENTRANS { get; set; } + public double U_MSV_PKH_PESM { get; set; } + public string Object { get; set; } = "ARD_PHR"; + public string U_MSV_PKH_ORIG { get; set; } + public List ARD_PCK_HJRT_DETCollection { get; set; } + } + + public class HojaRutaDetailsEntities + { + public int DocEntry { get; set; } + public int LineId { get; set; } + public int VisOrder { get; set; } + public string U_ARD_PHR_NROPED { get; set; } + public string U_ARD_PHR_NOMCLI { get; set; } + public string U_ARD_PHR_RUCCLI { get; set; } + public string U_ARD_PHR_DIRDESP { get; set; } + public string U_ARD_PHR_FORPAG { get; set; } + public string U_ARD_PHR_NROGRE { get; set; } + public string U_ARD_PHR_NROFACT { get; set; } + public string U_ARD_PHR_ZONA { get; set; } + public string U_ARD_PHR_TERRIT { get; set; } + public DateTime U_ARD_PHR_FEENPED { get; set; } + public string U_ARD_PHR_MONED { get; set; } + public decimal U_ARD_TOTALFC { get; set; } + public decimal U_ARD_PHR_TOTALPD { get; set; } + public string U_MSV_PKH_DORV { get; set; } + public string U_MSV_PKH_DGRE { get; set; } + public string U_MSV_PKH_DCPE { get; set; } + public int U_MSV_PKH_PEOV { get; set; } + public string U_ITC_PHR_NOMVEN { get; set; } + public string U_MSV_PKH_CGUI { get; set; } + public string U_ARD_PHR_ESTDESP { get; set; } = "Embarcado"; + public string U_MSV_PKH_APLG { get; set; } + public string Object { get; set; } = "ARD_PHR"; + + } +} diff --git a/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreateDetalle.cs b/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreateDetalle.cs new file mode 100644 index 0000000..89333b0 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/HR/BE_HojaRutaCreateDetalle.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.HR +{ + public class BE_HojaRutaCreateDetalle + { + public string NumeroFactura { get; set; } + public string CodigoInterno { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/ITC_SOLINGMER.cs b/Net.Business.Entities/ServicesLayer/ITC_SOLINGMER.cs new file mode 100644 index 0000000..286e223 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/ITC_SOLINGMER.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer +{ + public class ITC_SOLINGMER + { + public string U_ITC_MDTI { get; set; } + public string U_ITC_MDWC { get; set; } + public string U_ITC_USRSOL { get; set; } + public string U_ITC_MDCM { get; set; } + public List ITC_SOLINGMERDETCollection { get; set; } + } + + public class ITC_SOLINGMER_Details + { + public int LineId { get; set; } + public string U_ITC_CCOSTO { get; set; } + public string U_ITC_ACCCODE { get; set; } + public string U_ITC_ITEMNAME { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/ITC_SOLSALMER.cs b/Net.Business.Entities/ServicesLayer/ITC_SOLSALMER.cs new file mode 100644 index 0000000..e40c152 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/ITC_SOLSALMER.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer +{ + public class ITC_SOLSALMER + { + public string U_ITC_MDTS { get; set; } + public string U_ITC_USRSOL { get; set; } + public string U_ITC_MDCM { get; set; } + public List ITCA_SOLSALMERDETCollection { get; set; } + } + + public class ITC_SOLSALMER_Details + { + public int LineId { get; set; } + public string U_ITC_CCOST { get; set; } + public string U_ITC_AccCode { get; set; } + public string U_ITC_ItemName { get; set; } + } + +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntries.cs b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntries.cs new file mode 100644 index 0000000..6188c55 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntries.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenEntries +{ + public class BE_InventoryGenEntries + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public double DocRate { get; set; } + public string U_SYP_TPOENTME { get; set; } + public string U_ITC_WMS_NUMINV { get; set; } + public string U_ARD_PERSOLIC { get; set; } + public string Comments { get; set; } + + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesBatchNumbers.cs new file mode 100644 index 0000000..5dcf7ed --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenEntries +{ + public class BE_InventoryGenEntriesBatchNumbers + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesLine.cs b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesLine.cs new file mode 100644 index 0000000..d161ce4 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenEntries/BE_InventoryGenEntriesLine.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenEntries +{ + public class BE_InventoryGenEntriesLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public double Quantity { get; set; } + public double PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public double LineTotal { get; set; } + public string AccountCode { get; set; } + public string CostingCode { get; set; } = ""; + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExits.cs b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExits.cs new file mode 100644 index 0000000..0b99ed7 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExits.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenExits +{ + public class BE_InventoryGenExits + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + + //public string DocObjectCode2 { get; set; } + public double DocRate { get; set; } + public string U_SYP_TPOSALME { get; set; } + public string U_ITC_WMS_NUMINV { get; set; } + public string U_ARD_PERSOLIC { get; set; } + public string Comments { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsBatchNumbers.cs new file mode 100644 index 0000000..72ae562 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenExits +{ + public class BE_InventoryGenExitsBatchNumbers + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsLine.cs b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsLine.cs new file mode 100644 index 0000000..c23a0c8 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryGenExits/BE_InventoryGenExitsLine.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.InventoryGenExits +{ + public class BE_InventoryGenExitsLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public double Quantity { get; set; } + public double PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public double LineTotal { get; set; } + public string AccountCode { get; set; } + public string CostingCode { get; set; } = ""; + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/InventoryTransferRequest/BE_InventoryTransferRequest.cs b/Net.Business.Entities/ServicesLayer/InventoryTransferRequest/BE_InventoryTransferRequest.cs new file mode 100644 index 0000000..8f02052 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/InventoryTransferRequest/BE_InventoryTransferRequest.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.InventoryTransferRequest +{ + // Shape minimo del GET InventoryTransferRequests({docEntry}) de Service Layer - + // solo lo que SolicitudTransferenciaRepository.Update necesita leer (el Rate + // real de cada linea antes del PATCH). Los campos del JSON de SAP que no estan + // mapeados aca se ignoran al deserializar (comportamiento default de + // Newtonsoft.Json), no hace falta mapear el documento completo. + public class BE_InventoryTransferRequest + { + public int DocEntry { get; set; } + public List StockTransferLines { get; set; } + } + + public class BE_InventoryTransferRequestLine + { + public int LineNum { get; set; } + public double Rate { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/Invoices/BE_Invoices.cs b/Net.Business.Entities/ServicesLayer/Invoices/BE_Invoices.cs new file mode 100644 index 0000000..b1613be --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/Invoices/BE_Invoices.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.Invoices +{ + public class BE_Invoices + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public int DocEntry { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public string U_SYP_MDTD { get; set; } + public List DocumentLines { get; set; } + } + public class BE_InvoicesConsulta + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public int DocEntry { get; set; } + public string DocumentStatus { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public string U_SYP_MDTD { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesBatchNumbers.cs new file mode 100644 index 0000000..7e581f9 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.Invoices +{ + public class BE_InvoicesBatchNumbers + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesLine.cs b/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesLine.cs new file mode 100644 index 0000000..55660ae --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/Invoices/BE_InvoicesLine.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.Invoices +{ + public class BE_InvoicesLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public decimal Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public int? BaseLine { get; set; } + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/Items/BE_ItemStock.cs b/Net.Business.Entities/ServicesLayer/Items/BE_ItemStock.cs new file mode 100644 index 0000000..72f6b28 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/Items/BE_ItemStock.cs @@ -0,0 +1,17 @@ +using System; + +namespace Net.Business.Entities.ServicesLayer.Items +{ + public class BE_ItemStock + { + public string ItemCode { get; set; } + public string ItemName { get; set; } + public string WhsCode { get; set; } + public string WhsName { get; set; } + public string DistNumber { get; set; } + public DateTime ExpDate { get; set; } + public string BinCode { get; set; } + public double OnHandQty { get; set; } + public double AvgPrice { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotes.cs b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotes.cs new file mode 100644 index 0000000..952baba --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotes.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes +{ + public class BE_PurchaseDeliveryNotes + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public string NumAtCard { get; set; } + public string U_SYP_MDTD { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesBatchNumbers.cs new file mode 100644 index 0000000..6f013a0 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes +{ + public class BE_PurchaseDeliveryNotesBatchNumbers + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesLine.cs b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesLine.cs new file mode 100644 index 0000000..f7ede16 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseDeliveryNotes/BE_PurchaseDeliveryNotesLine.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes +{ + public class BE_PurchaseDeliveryNotesLine + { + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public double Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public int? BaseType { get; set; } + public int? BaseEntry { get; set; } + public int? BaseLine { get; set; } + public int LineNum { get; set; } + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoices.cs b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoices.cs new file mode 100644 index 0000000..b315d9f --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoices.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseInvoices +{ + public class BE_PurchaseInvoices + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public int DocEntry { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesBatchNumbers.cs new file mode 100644 index 0000000..8f5fbca --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseInvoices +{ + public class BE_PurchaseInvoicesBatchNumbers + { + public string BatchNumber { get; set; } + public string Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesLine.cs b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesLine.cs new file mode 100644 index 0000000..36b56be --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseInvoices/BE_PurchaseInvoicesLine.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseInvoices +{ + public class BE_PurchaseInvoicesLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public decimal Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrders.cs b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrders.cs new file mode 100644 index 0000000..82ca5c4 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrders.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseOrders +{ + public class BE_PurchaseOrders + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public int DocEntry { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersBatchNumbers.cs new file mode 100644 index 0000000..e6d61c3 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseOrders +{ + public class BE_PurchaseOrdersBatchNumbers + { + public string BatchNumber { get; set; } + public string Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersLine.cs b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersLine.cs new file mode 100644 index 0000000..9fb61ca --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/PurchaseOrders/BE_PurchaseOrdersLine.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.PurchaseOrders +{ + public class BE_PurchaseOrdersLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public decimal Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequest.cs b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequest.cs new file mode 100644 index 0000000..e1a35ea --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.ReturnRequest +{ + public class BE_ReturnRequest + { + public DateTime DocDate { get; set; } + public DateTime DocDueDate { get; set; } + public string CardCode { get; set; } + public string CardName { get; set; } + public string DocCurrency { get; set; } + public string PaymentGroupCode { get; set; } + public string DocObjectCode { get; set; } + public int DocEntry { get; set; } + public string U_SYP_TPONC { get; set; } + public string U_SYP_MOTNC { get; set; } + public string U_SYP_MDSO { get; set; } + public string U_SYP_MDCO { get; set; } + public string U_SYP_MDTO { get; set; } + public DateTime U_SYP_FECHAREF { get; set; } + public List DocumentLines { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestBatchNumbers.cs b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestBatchNumbers.cs new file mode 100644 index 0000000..dfc5559 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestBatchNumbers.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.ReturnRequest +{ + public class BE_ReturnRequestBatchNumbers + { + public string BatchNumber { get; set; } + public string Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestLine.cs b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestLine.cs new file mode 100644 index 0000000..9a3515a --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/ReturnRequest/BE_ReturnRequestLine.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.ReturnRequest +{ + public class BE_ReturnRequestLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public decimal Quantity { get; set; } + public decimal PriceAfterVAT { get; set; } + public string WarehouseCode { get; set; } + public string Currency { get; set; } + public int? BaseEntry { get; set; } + public int? BaseLine { get; set; } + public int? BaseType { get; set; } + public string U_ITC_ALMDES { get;set; } + public List BatchNumbers { get; set; } + + } +} diff --git a/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransfer.cs b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransfer.cs new file mode 100644 index 0000000..eeecb77 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransfer.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.StockTransfer +{ + public class BE_StockTransfer + { + public DateTime DocDate { get; set; } + public DateTime DueDate { get; set; } + public string Comments { get; set; } + public string FromWarehouse { get; set; } + public string ToWarehouse { get; set; } + public DateTime TaxDate { get; set; } + public string U_SYP_MDTS { get; set; } + public string U_SYP_MDMT { get; set; } + public string U_ITC_WMS_NUMINV { get; set; } + public string U_SYP_TPOENTME { get; set; } + public List StockTransferLines { get; set; } + public List DocumentReferences { get; set; } + } + + public class BE_StockTransferAutomatico + { + public DateTime DocDate { get; set; } + public DateTime DueDate { get; set; } + public string Comments { get; set; } + public string FromWarehouse { get; set; } + public string ToWarehouse { get; set; } + public DateTime TaxDate { get; set; } + public string U_SYP_MDTS { get; set; } + public string U_SYP_MDMT { get; set; } + public string U_ITC_WMS_NUMINV { get; set; } + public string U_SYP_TPOENTME { get; set; } + public int PriceList { get; set; } + public List StockTransferLines { get; set; } + public List DocumentReferences { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferDocumentReferences.cs b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferDocumentReferences.cs new file mode 100644 index 0000000..13b8c4b --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferDocumentReferences.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.StockTransfer +{ + public class BE_StockTransferDocumentReferences + { + public int RefDocEntr { get; set; } + public string RefObjType { get; set; } + public string Remark { get; set; } + public DateTime IssueDate { get; set; } = DateTime.Now; + } +} diff --git a/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLine.cs b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLine.cs new file mode 100644 index 0000000..241a788 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLine.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.ServicesLayer.StockTransfer +{ + public class BE_StockTransferLine + { + public int LineNum { get; set; } + public string ItemCode { get; set; } + public string ItemDescription { get; set; } + public double Quantity { get; set; } + public string WarehouseCode { get; set; } + public string FromWarehouseCode { get; set; } + public int? BaseLine { get; set; } + public int? BaseEntry { get; set; } + public string BaseType { get; set; } + public List BatchNumbers { get; set; } + } +} diff --git a/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLineBatchNumber.cs b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLineBatchNumber.cs new file mode 100644 index 0000000..f5ef646 --- /dev/null +++ b/Net.Business.Entities/ServicesLayer/StockTransfer/BE_StockTransferLineBatchNumber.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.ServicesLayer.StockTransfer +{ + public class BE_StockTransferLineBatchNumber + { + public string BatchNumber { get; set; } + public double Quantity { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/HojaRuta/BE_HojaRutaEntities.cs b/Net.Business.Entities/WMS/HojaRuta/BE_HojaRutaEntities.cs new file mode 100644 index 0000000..57f89ff --- /dev/null +++ b/Net.Business.Entities/WMS/HojaRuta/BE_HojaRutaEntities.cs @@ -0,0 +1,13 @@ +namespace Net.Business.Entities.WMS.HojaRuta +{ + public class BE_HojaRutaEntities + { + public int DocEntry { get; set; } + public int IdEstadoCubico { get; set; } + public string Estado { get; set; } + public string Proceso { get; set; } + public string CodMotivo { get; set; } + public string HoraInicio { get; set; } + public string FinRuta { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Inventario/BE_Inventario.cs b/Net.Business.Entities/WMS/Inventario/BE_Inventario.cs new file mode 100644 index 0000000..cbd29a9 --- /dev/null +++ b/Net.Business.Entities/WMS/Inventario/BE_Inventario.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace Net.Business.Entities.WMS.Inventario +{ + public class BE_Inventario + { + public DateTime Fecha { get; set; } + public DateTime FechaVencimiento { get; set; } + public string TipoMovimientoSAP { get; set; } + public string TipoMovimiento { get; set; } + public string TipoInventario { get; set; } + public string Almacen { get; set; } + public string SubAlmacen { get; set; } + public string NroInventario { get; set; } + public List Detalle { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Inventario/BE_InventarioItems.cs b/Net.Business.Entities/WMS/Inventario/BE_InventarioItems.cs new file mode 100644 index 0000000..9eac915 --- /dev/null +++ b/Net.Business.Entities/WMS/Inventario/BE_InventarioItems.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.WMS.Inventario +{ + public class BE_InventarioItems + { + public string CodigoArticulo { get; set; } + public string DescripcionArticulo { get; set; } + public decimal Cantidad { get; set; } + public string UnidadMedida { get; set; } + public double PrecioPromedio { get; set; } + public string CentroCosto { get; set; } + public List Lotes { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Inventario/BE_InventarioItemsLotes.cs b/Net.Business.Entities/WMS/Inventario/BE_InventarioItemsLotes.cs new file mode 100644 index 0000000..562fbc9 --- /dev/null +++ b/Net.Business.Entities/WMS/Inventario/BE_InventarioItemsLotes.cs @@ -0,0 +1,11 @@ +using System; + +namespace Net.Business.Entities.WMS.Inventario +{ + public class BE_InventarioItemsLotes + { + public string Lote { get; set; } + public DateTime FechaVencimiento { get; set; } + public decimal Cantidad { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Picking/BE_PickingDetalle.cs b/Net.Business.Entities/WMS/Picking/BE_PickingDetalle.cs new file mode 100644 index 0000000..2d1f1b7 --- /dev/null +++ b/Net.Business.Entities/WMS/Picking/BE_PickingDetalle.cs @@ -0,0 +1,14 @@ +namespace Net.Business.Entities.WMS.Picking +{ + public class BE_PickingDetalle + { + public int Item { get; set; } + public string CodigoArticulo { get; set; } + public string CodigoUM { get; set; } + public string LoteProducto { get; set; } + public decimal CantidadPedida { get; set; } + public string CodigoSubAlmacen { get; set; } + public string Estado { get; set; } + public double PrecioPromedio { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs b/Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs new file mode 100644 index 0000000..82339a6 --- /dev/null +++ b/Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.WMS.Picking +{ + public class BE_PickingRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public string FechaEntrega { get; set; } + public string CodigoAlmacen { get; set; } + public DateTime FechaLlegada { get; set; } + public string CodigoERPCliente { get; set; } + public string CodigoERPDireccion { get; set; } + public int IdTipo { get; set; } + public int IdTipoDoc { get; set; } + public string Observacion { get; set; } + public int IdCondicion { get; set; } + public int Accion { get; set; } + public int DocEntry { get; set; } + public int IdEstadoCubico { get; set; } + public string Proceso { get; set; } + public string CodMotivo { get; set; } + // "preliminar" | "cierre" - cualquier otro valor o ausente se trata como + // "preliminar" (default seguro, nunca crea documentos en SAP por accidente). + public string Notificacion { get; set; } + public decimal Longitud { get; set; } + public decimal Latitud { get; set; } + public List Detalle { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/ProcesoPicking/BE_ProcesoPicking.cs b/Net.Business.Entities/WMS/ProcesoPicking/BE_ProcesoPicking.cs new file mode 100644 index 0000000..a73bbeb --- /dev/null +++ b/Net.Business.Entities/WMS/ProcesoPicking/BE_ProcesoPicking.cs @@ -0,0 +1,10 @@ +namespace Net.Business.Entities.WMS.ProcesoPicking +{ + public class BE_ProcesoPicking + { + public string Code { get; set; } + public string U_ITCA_PROCESO { get; set; } + public string U_ITCA_GNRPROC { get; set; } + public string U_ITCA_ESTADO { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Recibo/BE_ReciboDetalle.cs b/Net.Business.Entities/WMS/Recibo/BE_ReciboDetalle.cs new file mode 100644 index 0000000..89c7fc6 --- /dev/null +++ b/Net.Business.Entities/WMS/Recibo/BE_ReciboDetalle.cs @@ -0,0 +1,11 @@ +namespace Net.Business.Entities.WMS.Recibo +{ + public class BE_ReciboDetalle + { + public int Item { get; set; } + public string CodigoArticulo { get; set; } + public string CodigoUM { get; set; } + public string LoteProducto { get; set; } + public decimal CantidadPedida { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Recibo/BE_ReciboRequest.cs b/Net.Business.Entities/WMS/Recibo/BE_ReciboRequest.cs new file mode 100644 index 0000000..4c94298 --- /dev/null +++ b/Net.Business.Entities/WMS/Recibo/BE_ReciboRequest.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.WMS.Recibo +{ + public class BE_ReciboRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public string CodigoAlmacen { get; set; } + public DateTime FechaLlegada { get; set; } + public string CodigoERPProveedor { get; set; } + public int IdTipo { get; set; } + public int IdTipoDoc { get; set; } + public string Observacion { get; set; } + public int IdCuenta { get; set; } + public int DocEntry { get; set; } + public int Accion { get; set; } + public string DocImportacion { get; set; } + public string U_SYP_MDTD { get; set; } + public string U_SYP_MDSD { get; set; } + public string U_SYP_MDCD { get; set; } + public string Comentario { get; set; } + public List Detalle { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchRequest.cs b/Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchRequest.cs new file mode 100644 index 0000000..216b8a7 --- /dev/null +++ b/Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchRequest.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Net.Business.Entities.WMS.SolicitudTransferencia +{ + // Contrato propio del PATCH de SolicitudTransferencia - funcionalidad nueva, sin + // equivalente en el .NET original. El PATCH real SOLO actualiza cantidades de + // linea existentes en SAP (InventoryTransferRequests) y ELIMINA una linea + // cuando Cantidad = 0 - no toca fechas, almacenes ni ningun otro campo del + // documento, por eso no reusa BE_TransferenciaRequest. + public class BE_SolicitudTransferenciaPatchDetalle + { + public int Linea { get; set; } + public double Cantidad { get; set; } + } + + public class BE_SolicitudTransferenciaPatchRequest + { + // No se usa para el PATCH a SAP - solo trazabilidad en el log de auditoria. + public string NumOrden { get; set; } + public List Detalle { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaDetalle.cs b/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaDetalle.cs new file mode 100644 index 0000000..bd07c3f --- /dev/null +++ b/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaDetalle.cs @@ -0,0 +1,12 @@ +namespace Net.Business.Entities.WMS.Transferencia +{ + public class BE_TransferenciaDetalle + { + public int Item { get; set; } + public string CodigoArticulo { get; set; } + public string CodigoUM { get; set; } + public string LoteProducto { get; set; } + public decimal CantidadPedida { get; set; } + public int Accion { get; set; } + } +} diff --git a/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaRequest.cs b/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaRequest.cs new file mode 100644 index 0000000..2bff6b0 --- /dev/null +++ b/Net.Business.Entities/WMS/Transferencia/BE_TransferenciaRequest.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Net.Business.Entities.WMS.Transferencia +{ + public class BE_TransferenciaRequest + { + public string NumOrden { get; set; } + public DateTime FechaOrden { get; set; } + public int IdTipo { get; set; } + public string CodigoAlmacenOrigen { get; set; } + public string CodigoSubAlmacenOrigen { get; set; } + public int IdCondicionOrigen { get; set; } + public string CodigoAlmacenDestino { get; set; } + public string CodigoSubAlmacenDestino { get; set; } + public int IdCondicionDestino { get; set; } + public string Observacion { get; set; } + public int IdCuenta { get; set; } + public int Accion { get; set; } + public int DocEntry { get; set; } + public int DocEntryEM { get; set; } + + public List TransferenciaDetalles { get; set; } + } +} diff --git a/Net.Business.Services/.config/dotnet-tools.json b/Net.Business.Services/.config/dotnet-tools.json new file mode 100644 index 0000000..13fc3ec --- /dev/null +++ b/Net.Business.Services/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "5.0.8", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/Net.Business.Services/Controllers/AuthenticateController.cs b/Net.Business.Services/Controllers/AuthenticateController.cs new file mode 100644 index 0000000..50b4deb --- /dev/null +++ b/Net.Business.Services/Controllers/AuthenticateController.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO; +using Net.Business.DTO.Authenticate; +using Net.Data; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + public class AuthenticateController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public AuthenticateController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + /// + /// Obtiene Token de Acceso + /// + /// Parametros de filtros + /// Devuelve Token de Acceso + [HttpPost] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task Token([FromBody] Dto_AuthenticateRequest value) + { + + var objectGetAll = await _repository.Authenticate.GetToken(value.RetornaModelo()); + + if (objectGetAll.StatusCode == -1) + { + return BadRequest(objectGetAll); + } + + return Ok(objectGetAll.Data); + } + + } +} diff --git a/Net.Business.Services/Controllers/HojaRutaController.cs b/Net.Business.Services/Controllers/HojaRutaController.cs new file mode 100644 index 0000000..e75131e --- /dev/null +++ b/Net.Business.Services/Controllers/HojaRutaController.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.HojaRuta; +using Net.Business.DTO.WMS.Picking; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class HojaRutaController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public HojaRutaController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task POST([FromBody] Dto_HojaRutaCreate value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Hoja Ruta", "", "", "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Hoja Ruta", "", "", "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.HR.SetCreateHojaRuta(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", "", "", "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", "", "", ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + + + } +} diff --git a/Net.Business.Services/Controllers/InventarioController.cs b/Net.Business.Services/Controllers/InventarioController.cs new file mode 100644 index 0000000..690b152 --- /dev/null +++ b/Net.Business.Services/Controllers/InventarioController.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.Inventario; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class InventarioController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public InventarioController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + /// + /// Registra Proceso de Inventario + /// + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Inventario([FromBody] Dto_Inventario value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Inventario", "0", "0", "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Inventario", "0", "0", "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.Inventario.Create(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Inventario", "0", "0", "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Inventario", "0", "0", ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + } +} diff --git a/Net.Business.Services/Controllers/ItemController.cs b/Net.Business.Services/Controllers/ItemController.cs new file mode 100644 index 0000000..01efb4b --- /dev/null +++ b/Net.Business.Services/Controllers/ItemController.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Data; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class ItemController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public ItemController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + [HttpGet] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Stock() + { + var ObjectNew = await _repository.Items.GetStockItem(); + + if (ObjectNew.StatusCode != 0) + { + return BadRequest(ObjectNew); + } + return Ok(ObjectNew); + } + } +} diff --git a/Net.Business.Services/Controllers/PickingController.cs b/Net.Business.Services/Controllers/PickingController.cs new file mode 100644 index 0000000..d7c2ac3 --- /dev/null +++ b/Net.Business.Services/Controllers/PickingController.cs @@ -0,0 +1,104 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.HojaRuta; +using Net.Business.DTO.WMS.Picking; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class PickingController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public PickingController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task POST([FromBody] Dto_PickingRequest value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Picking", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Picking", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.Picking.Create(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Picking", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Picking", value.NumOrden, value.DocEntry.ToString(), ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + + [HttpPost] + [Route("[action]")] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Ruta([FromBody] Dto_HojaRuta value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Hoja Ruta", value.DocEntry.ToString(), value.DocEntry.ToString(), "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Hoja Ruta", value.DocEntry.ToString(), value.DocEntry.ToString(), "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.Picking.CreateHojaRuta(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", value.DocEntry.ToString(), value.DocEntry.ToString(), "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", value.DocEntry.ToString(), value.DocEntry.ToString(), ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + + [HttpPost] + [Route("HojaRuta/{docEntry}/Cerrar")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task CerrarHojaRuta(int docEntry) + { + var ObjectNew = await _repository.Picking.CerrarHojaRuta(docEntry); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { docEntry })), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", docEntry.ToString(), docEntry.ToString(), "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { docEntry })), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Hoja Ruta", docEntry.ToString(), docEntry.ToString(), ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + } +} diff --git a/Net.Business.Services/Controllers/ReciboController.cs b/Net.Business.Services/Controllers/ReciboController.cs new file mode 100644 index 0000000..87ab4f5 --- /dev/null +++ b/Net.Business.Services/Controllers/ReciboController.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.Recibo; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class ReciboController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public ReciboController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task POST([FromBody] Dto_ReciboRequest value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Recibo", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Recibo", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.Recibo.Create(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Recibo", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Recibo", value.NumOrden, value.DocEntry.ToString(), ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + } +} diff --git a/Net.Business.Services/Controllers/SolicitudTransferenciaController.cs b/Net.Business.Services/Controllers/SolicitudTransferenciaController.cs new file mode 100644 index 0000000..d300f44 --- /dev/null +++ b/Net.Business.Services/Controllers/SolicitudTransferenciaController.cs @@ -0,0 +1,100 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.SolicitudTransferencia; +using Net.Business.Entities; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + // Modulo 100% nuevo (sin equivalente en el .NET original) - ver + // docs/SOLICITUD_TRANSFERENCIA.md para el contrato completo. + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class SolicitudTransferenciaController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public SolicitudTransferenciaController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + // Responde 200 con el BE_ResultadoTransaccion completo en vez de 204 - + // decision deliberada: un 204 no puede llevar body (RFC 7231 §6.3.5) y + // muchos clientes HTTP, incluido HttpClient de .NET, no lo leen si el + // status es 204 - ver docs/SOLICITUD_TRANSFERENCIA.md. + [HttpPatch] + [Route("{docEntry}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Patch(int docEntry, [FromBody] Dto_SolicitudTransferenciaPatchRequest value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "SolicitudTraslado", "0", docEntry.ToString(), "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "SolicitudTraslado", value.NumOrden, docEntry.ToString(), "0", "0"); + return BadRequest("Invalid model object"); + } + + var error = await _repository.SolicitudTransferencia.Update(docEntry, value.RetornaModelo()); + + var result = error ?? new BE_ResultadoTransaccion + { + DocEntry = docEntry, + StatusCode = 200, + Message = "Registrado Correctamente", + AppName = "SolicitudTransferenciaRepository", + MethodName = "Update", + Data = value, + }; + + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(result)), "SolicitudTraslado", value.NumOrden, docEntry.ToString(), result.DocNum, result.DocEntry?.ToString()); + + if (error != null) + { + return BadRequest(result); + } + return Ok(result); + } + + [HttpPost] + [Route("{docEntry}/cerrar")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task Cerrar(int docEntry) + { + var error = await _repository.SolicitudTransferencia.Cerrar(docEntry); + + var result = error ?? new BE_ResultadoTransaccion + { + DocEntry = docEntry, + StatusCode = 200, + Message = "Cerrado Correctamente", + AppName = "SolicitudTransferenciaRepository", + MethodName = "Cerrar", + }; + + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { docEntry })), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(result)), "SolicitudTraslado", "0", docEntry.ToString(), result.DocNum, result.DocEntry?.ToString()); + + if (error != null) + { + return BadRequest(result); + } + return Ok(result); + } + } +} diff --git a/Net.Business.Services/Controllers/TransferenciaController.cs b/Net.Business.Services/Controllers/TransferenciaController.cs new file mode 100644 index 0000000..f0bbe69 --- /dev/null +++ b/Net.Business.Services/Controllers/TransferenciaController.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Net.Business.DTO.WMS.Transferencia; +using Net.Business.Services.Log; +using Net.Data; +using Newtonsoft.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Business.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ApiExplorerSettings(GroupName = "ApiSAPWMS")] + [Authorize(AuthenticationSchemes = "Bearer")] + public class TransferenciaController : ControllerBase + { + private readonly IRepositoryWrapper _repository; + public TransferenciaController(IRepositoryWrapper repository) + { + this._repository = repository; + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task POST([FromBody] Dto_TransferenciaRequest value) + { + if (value == null) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Master object is null"), "Transferencia", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Master object is null"); + } + + if (!ModelState.IsValid) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes("Invalid model object"), "Transferencia", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest("Invalid model object"); + } + + var ObjectNew = await _repository.Transferencia.Create(value.RetornaModelo()); + + if (ObjectNew.StatusCode != 200) + { + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Transferencia", value.NumOrden, value.DocEntry.ToString(), "0", "0"); + return BadRequest(ObjectNew); + } + B_Log.Add("Cubico", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ObjectNew)), "Transferencia", value.NumOrden, value.DocEntry.ToString(), ObjectNew?.DocNum.ToString(), ObjectNew?.DocEntry.ToString()); + return Ok(ObjectNew); + } + } +} diff --git a/Net.Business.Services/Extensions/ExceptionMiddlewareExtensions.cs b/Net.Business.Services/Extensions/ExceptionMiddlewareExtensions.cs new file mode 100644 index 0000000..8539ae1 --- /dev/null +++ b/Net.Business.Services/Extensions/ExceptionMiddlewareExtensions.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using System.Net; + +namespace Net.Business.Services +{ + public static class ExceptionMiddlewareExtensions + { + public static void ConfigureExceptionHandler(this IApplicationBuilder app) + { + app.UseExceptionHandler(appError => + { + appError.Run(async context => + { + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + context.Response.ContentType = "application/json"; + + var contextFeature = context.Features.Get(); + if (contextFeature != null) + { + + await context.Response.WriteAsync(new DtoErrorDetails() + { + StatusCode = context.Response.StatusCode, + ErrorMessage = contextFeature.Error.Message.ToString() + }.ToString()); + } + }); + }); + } + } +} + +public class DtoErrorDetails +{ + public int StatusCode { get; set; } + public string ErrorMessage { get; set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + +} \ No newline at end of file diff --git a/Net.Business.Services/Extensions/ServiceExtensions.cs b/Net.Business.Services/Extensions/ServiceExtensions.cs new file mode 100644 index 0000000..842afc6 --- /dev/null +++ b/Net.Business.Services/Extensions/ServiceExtensions.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Net.Connection; +using Net.Data; +using System.Net.Http; + +namespace Net.Business.Services +{ + public static class ServiceExtensions + { + + public static void ConfigureCors(this IServiceCollection services) + { + services.AddCors(opt => + { + opt.AddPolicy("CorsPolicy", + builder => builder.WithOrigins("http://192.168.1.4", "http://localhost:4200") + .AllowAnyHeader() + .WithMethods("GET", "POST", "PUT", "PATH") + .AllowCredentials()); + }); + } + + public static void ConfigureIISIntegration(this IServiceCollection services) + { + services.Configure(options => + { + }); + } + + public static void ConfigureSQLConnection(this IServiceCollection services) + { + services.AddScoped(); + } + + public static void ConfigureRepositoryWrapper(this IServiceCollection services) + { + services.AddScoped(); + } + + public static void ConfigureHttpClientServiceLayer(this IServiceCollection services) + { + services.AddHttpClient("bypass-ssl-validation") + .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler + { + ServerCertificateCustomValidationCallback = ( + httpRequestMessage, cert, certChain, policyErrors) => + { + return true; + } + }); + } + } +} diff --git a/Net.Business.Services/ITCA_API_SAP_WMS.xml b/Net.Business.Services/ITCA_API_SAP_WMS.xml new file mode 100644 index 0000000..7984517 --- /dev/null +++ b/Net.Business.Services/ITCA_API_SAP_WMS.xml @@ -0,0 +1,20 @@ + + + + ITCA_API_SAP_WMS + + + + + Obtiene Token de Acceso + + Parametros de filtros + Devuelve Token de Acceso + + + + Registra Proceso de Inventario + + + + diff --git a/Net.Business.Services/Log/B_Log.cs b/Net.Business.Services/Log/B_Log.cs new file mode 100644 index 0000000..a92c164 --- /dev/null +++ b/Net.Business.Services/Log/B_Log.cs @@ -0,0 +1,35 @@ +using Sap.Data.Hana; +using System; + +namespace Net.Business.Services.Log +{ + public class B_Log + { + public static string Add(string Origen, byte[] Trama_Origen, byte[] Trama_Respuesta, string Proceso, string Nro_Orden, string DocEntry, string DocNumSAP, string DocEntrySAP) + { + string DB = "ITCA_LOG_INTEGRACION"; + string Code = System.Guid.NewGuid().ToString(); + string Fecha = DateTime.Now.ToString("yyyy-MM-dd"); + HanaConnection hana = new HanaConnection(Net.Data.LocalData.ConnectionString); + hana.Open(); + HanaCommand hanaCommand = hana.CreateCommand(); + hanaCommand.CommandText = $"INSERT INTO \"ITC_WMS_SAP\".\"{DB}\" (\"CODIGO\", \"ORIGEN\", \"TRAMA_ORIGEN\" , \"TRAMA_RESPUESTA\", \"PROCESO\", \"FECHA\", \"NRO_ORDEN\", \"DOCENTRY\", \"DOCNUMSAP\", \"DOCENTRYSAP\", \"HORA\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + hanaCommand.Parameters.Add("CODIGO", HanaDbType.VarChar).Value = Code; + hanaCommand.Parameters.Add("ORIGEN", HanaDbType.VarChar).Value = Origen; + hanaCommand.Parameters.Add("TRAMA_ORIGEN", HanaDbType.Blob).Value = Trama_Origen; + hanaCommand.Parameters.Add("TRAMA_RESPUESTA", HanaDbType.Blob).Value = Trama_Respuesta; + hanaCommand.Parameters.Add("PROCESO", HanaDbType.VarChar).Value = Proceso; + hanaCommand.Parameters.Add("FECHA", HanaDbType.Date).Value = Fecha; + hanaCommand.Parameters.Add("NRO_ORDEN", HanaDbType.VarChar).Value = Nro_Orden; + hanaCommand.Parameters.Add("DOCENTRY", HanaDbType.VarChar).Value = DocEntry; + hanaCommand.Parameters.Add("DOCNUMSAP", HanaDbType.VarChar).Value = DocNumSAP; + hanaCommand.Parameters.Add("DOCENTRYSAP", HanaDbType.VarChar).Value = DocEntrySAP; + hanaCommand.Parameters.Add("HORA", HanaDbType.VarChar).Value = DateTime.Now.ToString("HH:mm:ss"); + hanaCommand.CommandType = System.Data.CommandType.Text; + hanaCommand.ExecuteNonQuery(); + hana.Close(); + + return Code; + } + } +} diff --git a/Net.Business.Services/Net.Business.Services.csproj b/Net.Business.Services/Net.Business.Services.csproj new file mode 100644 index 0000000..4e05c3e --- /dev/null +++ b/Net.Business.Services/Net.Business.Services.csproj @@ -0,0 +1,40 @@ + + + + netcoreapp3.1 + ITCA_API_SAP_WMS + 24763424-3300-4c85-87e3-503f8fdebd14 + + 1701;1702;1591 + ITCA_API_SAP_WMS.xml + + + + + + + + + + + + + + + + + + + + + + ..\..\..\..\..\..\..\..\Program Files\sap\hdbclient\dotnetcore\v2.1\Sap.Data.Hana.Core.v2.1.dll + + + + + + + diff --git a/Net.Business.Services/Program.cs b/Net.Business.Services/Program.cs new file mode 100644 index 0000000..0d214b4 --- /dev/null +++ b/Net.Business.Services/Program.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace Net.Business.Services +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + + //public static IHostBuilder CreateHostBuilder(string[] args) => + // Host.CreateDefaultBuilder(args) + // .ConfigureWebHostDefaults(webBuilder => + // { + // webBuilder. + // UseStartup() + // .UseContentRoot(Directory.GetCurrentDirectory()) + // .UseKestrel(options => + // { + // options.Limits.MaxRequestBodySize = long.MaxValue; + // }) + // .UseIISIntegration(); + // //.UseKestrel(options => + // //{ + // // options.Limits.MaxRequestBodySize = long.MaxValue; + // //}) + + // }); + + } +} diff --git a/Net.Business.Services/Properties/PublishProfiles/FolderProfile.pubxml b/Net.Business.Services/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..32a8e9e --- /dev/null +++ b/Net.Business.Services/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,21 @@ + + + + + false + false + true + Debug + Any CPU + FileSystem + bin\Debug\netcoreapp3.1\publish\ + FileSystem + <_TargetId>Folder + + netcoreapp3.1 + b4be6148-6e1f-4bb9-b399-424c4e6bf4c0 + false + + \ No newline at end of file diff --git a/Net.Business.Services/Properties/PublishProfiles/FolderProfile1.pubxml b/Net.Business.Services/Properties/PublishProfiles/FolderProfile1.pubxml new file mode 100644 index 0000000..c22099b --- /dev/null +++ b/Net.Business.Services/Properties/PublishProfiles/FolderProfile1.pubxml @@ -0,0 +1,21 @@ + + + + + true + false + true + Debug + Any CPU + FileSystem + bin\Debug\netcoreapp3.1\publish\ + FileSystem + <_TargetId>Folder + + netcoreapp3.1 + b4be6148-6e1f-4bb9-b399-424c4e6bf4c0 + false + + \ No newline at end of file diff --git a/Net.Business.Services/Properties/PublishProfiles/FolderProfile2.pubxml b/Net.Business.Services/Properties/PublishProfiles/FolderProfile2.pubxml new file mode 100644 index 0000000..c22099b --- /dev/null +++ b/Net.Business.Services/Properties/PublishProfiles/FolderProfile2.pubxml @@ -0,0 +1,21 @@ + + + + + true + false + true + Debug + Any CPU + FileSystem + bin\Debug\netcoreapp3.1\publish\ + FileSystem + <_TargetId>Folder + + netcoreapp3.1 + b4be6148-6e1f-4bb9-b399-424c4e6bf4c0 + false + + \ No newline at end of file diff --git a/Net.Business.Services/Properties/launchSettings.json b/Net.Business.Services/Properties/launchSettings.json new file mode 100644 index 0000000..350270e --- /dev/null +++ b/Net.Business.Services/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Net.Business.Services": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + }, + "IIS Desarrollo": { + "commandName": "IIS", + "workingDirectory": "C:\\inetpub\\wwwroot\\integracion", + "launchUrl": "http://localhost/integracion" + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iis": { + "applicationUrl": "http://localhost/integracion", + "sslPort": 0 + }, + "iisExpress": { + "applicationUrl": "http://localhost:54791", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/Net.Business.Services/Startup.cs b/Net.Business.Services/Startup.cs new file mode 100644 index 0000000..cfdf76f --- /dev/null +++ b/Net.Business.Services/Startup.cs @@ -0,0 +1,141 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; + +namespace Net.Business.Services +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + Net.Data.LocalData.Configure(configuration); + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.ConfigureCors(); + services.ConfigureIISIntegration(); + services.ConfigureSQLConnection(); + services.ConfigureHttpClientServiceLayer(); + + /*Linea con el cual obtenemos datos de la cabecera*/ + services.AddSingleton(); + + //Autenticacion + string semilla = Configuration.GetSection("ParametrosTokenConfig").GetValue("Semilla"); + string emisor = Configuration.GetSection("ParametrosTokenConfig").GetValue("Emisor"); + string destinatario = Configuration.GetSection("ParametrosTokenConfig").GetValue("Destinatario"); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(semilla)); + + services.AddAuthentication + (JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(opt => { + opt.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidIssuer = emisor, + ValidAudience = destinatario, + IssuerSigningKey = key + }; + + }); + services.ConfigureRepositoryWrapper(); + + /*De aqui en adelante configuracion de documentacion de nuestra API*/ + services.AddSwaggerGen(options => { + options.SwaggerDoc("ApiSAPWMS", new Microsoft.OpenApi.Models.OpenApiInfo() + { + Title = "API SAP - WMS", + Version = "1", + Description = "API Integración SAP / WMS", + Contact = new Microsoft.OpenApi.Models.OpenApiContact() + { + Name = "IT Consultores Asociados", + }, + License = new Microsoft.OpenApi.Models.OpenApiLicense() + { + Name = "MIT License", + } + }); + + + var archivoXmlComentarios = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var rutaApiComentarios = Path.Combine(AppContext.BaseDirectory, archivoXmlComentarios); + + options.IncludeXmlComments(rutaApiComentarios); + + /*Primero definir el esquema de seguridad*/ + options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme + { + Description = "Autenticacion JWT (Bearer)", + Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http, + Scheme = "bearer" + }); + + options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement { + { + new Microsoft.OpenApi.Models.OpenApiSecurityScheme + { + Reference = new Microsoft.OpenApi.Models.OpenApiReference + { + Id = "Bearer", + Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme + } + }, new List() + } + }); + }); + + services.AddControllers(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.ConfigureExceptionHandler(); + + //Linea para documentacion api + app.UseSwagger(); + + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("swagger/ApiSAPWMS/swagger.json", "API SAP - WMS"); + options.RoutePrefix = ""; + }); + + app.UseRouting(); + + app.UseCors("CorsPolicy"); + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/Net.Business.Services/appsettings.example.json b/Net.Business.Services/appsettings.example.json new file mode 100644 index 0000000..30f3890 --- /dev/null +++ b/Net.Business.Services/appsettings.example.json @@ -0,0 +1,55 @@ +{ + "Logging": { + "LogLevel": { + "Default": "", + "Microsoft": "", + "Microsoft.Hosting.Lifetime": "" + } + }, + "AllowedHosts": "", + "ConnectionStrings": { + "cnnSql": "" + }, + "EntornoConection": { + "Entorno": "", + "EntornoSAP": "" + }, + "ParametersConectionDev": { + "Source": "", + "Catalog": "", + "User": "", + "Password": "" + }, + "ParametersConectionProd": { + "Source": "", + "Catalog": "", + "User": "", + "Password": "" + }, + "ParametrosTokenConfig": { + "Semilla": "", + "Emisor": "", + "Destinatario": "" + }, + "SapServiceLayer": { + "url": "", + "company": "", + "user": "", + "password": "" + }, + "Hana": { + "server": "", + "user": "", + "password": "" + }, + "EmailSenderOptions": { + "Port": "", + "Password": "", + "EnableSsl": "", + "Email": "", + "Host": "" + }, + "RutaAnexo": { + "UbicacionAdjunto": "" + } +} \ No newline at end of file diff --git a/Net.Business.Services/resources/img/logo-prosemedic.png b/Net.Business.Services/resources/img/logo-prosemedic.png new file mode 100644 index 0000000000000000000000000000000000000000..59b1f8bbc91419e2946cc9fd1919c9ffeb03e111 GIT binary patch literal 7139 zcmY*eRa6{JxLjD=Ey03o(8V1V*B=iF?(V^TaR?rQdw}4O;1XPeyA#~q9q#1eo_p>* z%=BnacYj?~Uv;FavMeSV2^t6l!jzYjQU`(HP=T@z3KFm{L(Go^4hSw1@|q~X=8Iw$ z0h}9pYkqQ7H};@(`s`?7ZD&sD>g8lkDXyx@0Ro|xjA zruc05iuj88QeZF`9gG6uhCp}`zRE!B1vD8aK!~ZS8HI3pP1@CI?<2+#K`PB}tVmhs zqd_22c6ljrP0!5ZtpBu@h9~=9XLu>XF$`AU=+(dvZ{d#6j-ruUB62W;WZrEB8pB+O z#I;~G@B?U0^a;H^qiEk-f)0f|eIfJur@3@AOJ7+?C1F>NUyX(iuELfr}6k{We2}j@B5$x!f0U-%nB^kw5nTX?X)DYu=u)C2O-K1Iyz-p7IeB8$YrGb z3)Z7WLjd>n5Wa>j7KR&Um-7(4?W;kLjIm*Em~CgqzhuBcdzeaLMZgFXOS8ns1HO#* zHm7)%8SEK|P8QsW)0>EnTDC!eD3#P99X~;Y5jNMCh>CjH@h7UhkZqvN&bPzLVV!4|oFC-uG<5}FF=SmvcamvLw6hPbrP>xm7y)dN z5?w%F?kN3xERm5`N+#7DD2C(vxSQrL4q|Sqkzj;1{bW++c)GQBuY11qtiktqmZ?k9 zJzk9s(RETW+qAYxiTyvdSmnC;=oIN^D7Z=W&$D3skk1eJ65-@1@N`j zmQ#Ij{`m)>_E@(yyXK-v($|rCKaDm2({xC>rHocO+05?1sxb0-5j0X14n$CeatNY)Z15;unY z*8A?kcXuBfcvu)Q?^SsLbpIFiVy$q_*z zmt#cmG5_YH?xMrWJ8{0JKX+k&uFqoS!nnwaZsr_kY8fz7hzTs40x8cU8DI2dk%|Wu zYQWM$qn3wEH!{(Vl;14hFBy48J)N+QIn#%P7TP6cvu4gEu4@is>h&88toXF_@R`OeyKbKby~HcO>~FumTNUBEKG$;u(Ybu zV&Uc8U+^92T9=$iAQtpkyRS!T(Lmd|s+&QSc-l$19NU?Xs9h9Q%Qv$&i|Kf$>a5#5 zSCU0EgtS`CetY)hbTp_Cm1_p|imuUO$)W!1=Kx4CTqwIWlER*JF+FQ%-=kc6W9tD6 z+p&(-L=s8yCO6mw2&ambm6H)Xga~m=lSLIS$i_p$8w&7u%uWqS4p4UmC&<|?0{vTHT3b>f?Qc9u}JNQyY;_Q{XHS;7xHl- z=;xy6KGcp|j=hF`%&$Pq=OZ1Y29AQBI!m;L)@?WH?TGgvR;vQPL<`8?iN)~=Is7-9 zwK&`CFYp7Oe`45sClvM$H-$_4fsT2kM$>$lh%UNAn%>QRL0Mp5uxvwV_(Brl`0Lsb zH#;p{Q||A&M+4^LH9AV!Aa*yIMl%2b%pxqlxJiTvqqb$vj=?1#f8)wMtgRQM{k z_kELP!8;`_kkb>NxKR@TnHq&0JH`_oM>$aj%p=$~PI7i`FTe3caR|dA@eNJL;=TM$ z`QUsm#sw6b`%3wHF(#s72Y!S$r;kG|s3cu+85m_kdK$;>x{M7{O=nqbXV2+|emC-H ztKbm;@90RSOCkw2EX)i%RIc2<{c8IG#%B0X09`ZDBQx(^(d}^{LM^37RqABdgTCYU zf@{|6X+=;gP&KgXS}VcvQ+e{nRV3T-ouB+Z7jOE9i78dPK`u4JxXI=StzW_wud3%tg~_ zJ1{OprGgH3M{HFxY#g--MIPc%RPO2wjbYdgzzZjtcE_^MT9}?L%Jb&6l(hihI zNammxSWl6+M_OEU4p*fsSAv_}QndO)?Enxj?N5?k`~JcC%O<`gQZ4D~ zTi{=lMzjaDxtDJKgDWs$h*{_Ku@lyQQ^W|xcQ52`S?a3(!qAx;M&h(}bmxTGFB;F! zvh;rFi%+Y*HK$x1wZ-jxMQxpbReEi&d`EV9V?xbOA0`otXcDm+)Ee2Y;f-vCu@ZZ~ zcUN93CH58ls1X1e6Mi(b@Wh3Ohq-HN3@3EO!j=!7kB66j>p-J*7PH1K7zcHoKFQ|d zzr}$WaAGkwJILd>l=txxo%I)6z5o-D3n(?NqQ0fMt;Ndpos6oC@Gu!l%m42Za(pMX z%(*0zfN6406YC#(5YT^tI7TKYSPzf z^`1MGuB@mt6!%U6nse?}h_vxlmP=o{Rr4g$&hBHnbrg0oNdh}N*Gytxx(`#Ueak|u z|Gn%7Cn_l_2Rn{#7u$0gms=^`f|aXm--S*_I@{#)Av;6Q@}l<^nsTa7N|3^zvU%Ot zm*q0G7q#dnGdJaoh0a7YlnmG_>RZYCpqPZehuw-gzj3K@;PffWHo>6jF!fcq3FS>W zIy{6%m?t}SmhVyAsY7Rw;KY)xaE6X>+ka$XGXWb2#GjrSZY*#n*BP8BQrI0WiZbf6iFiXUBr3pn`8g^c}+Fie5huvYgoL(;bBG=>7h371Avz=*> z#$YJKj%R-s^Aa28C&=LaXKz0vGN50X78TxcE8Qzc9t|&)4pcau&u|K}{3S1COvdj8 z&_}>fUL|5l;Nll7s~8Yy>d9730>BgCXeDTBMRi{KV>gwrHz4lveSsgDT>oi%|G68 z&Yc=iwyg&7&BY}>WN)e9%P=cfi(YidXi;$7a7knZ z&mMk*R+6zH&{cNh1BvO$JWpF`1K6k^0N4&^ne*e^I064q+3%<`zhe%TP z;ji0?I zA&22eE5u;fIKUo|cmF68+-z`o>)(r7;v|wfSrSrOMeoNGmLyKKUpNPbVq%8@lZ2{y zzCNRZ+q|9D*YP9!$z$DP3ju>{-EOJqSLK;H|I-vV$bsb~pqP4Af?;}@d~6`dbd6b? z>32Cxaj4j4LH-%goIrVfBUY{sC|$*i=K&mjDa>UcZ@}?MhN-6B4%|70 zGS1E`^q5<>5N>j90{Se`{gTsWNQB9tdu(%LH01Dk!10bn0TLcMu93*^+##l8#K+#h z3OD3FxVh^EA4tqYPLGlDPk@|PmQ`UV~b$!dF^RR@c(<{ggY@DWaaAQ^``2 zro8G!hAb7X7A+I*P2tLPvPWTCa8Em`9;iejla^(tIGV#N0zif&Chd4l;)1EaacVRDQK*r`a9s2utHXS^@BBx~(9(U*FApb=mifd$ zuY-6s+bI;KYLF37Kd`4ZW8t17Ggs)j5TQ5JMf9vXGmJVrl{H}c#b!uymw&&u@O5MB zn&OW+#Ob9)y}Tj&=>Ic zSj{-lfkGV?d7O7esIy9blyFqV@Xt7D_0dp;&V?YHb68ghql0&{_z&wu?d7lglRK5J z8}rYq-~im7ltRlu%YPo5R45ly@US-DrDKRgQ*ID-Kk5x30pZZlE^F)~k|iEFg4W*i zV2QsHUY~OZ8xgb(UFuDwZs-kkcU{RISGfakCYmb8{0Iyjg?TaDJcY$+)VNRfEk`p2 zi$6Mp;ZrxfQn`unmy_@t*b=Fe=~%)6EP7n}<062`;q)?Qb`*)b^M{l0%J~S<`I+1D zwW(-w%9MSivqt_$O!%kJ>FTV{I7@NFAJq=3j28WDXfT;YwKj~Ap^OPM8wbC66DgV8 z_`BTSU5v8^o_T!x6-E3}*`9fFHV^!#;I{D!*-QWWerPyvitBs2ApAAPL?cD)M);{X z=FCSS=l0v~M?+<)C56;Nm~lt$&^b&TL{=23NFs$5p1Y#?d>pr{Ex9`MrG=06LX-c& zRg;n&iKlsCdmxqY@@7?z40{C+!F}qTm(dUJ^z-;eo1~p7{a0w5gTM9#!DRKFE7#ek?JpdbM#!-c=sDmC+~}_ z-EYuM-j+rG@|FuZ;>E;z%-&a;K|NM#*DmUxSee3{jA%0c{3lP|KQL8r;#p|bLueoI z(~_flj64--v*C}~s+2v*UchRqE(>5Fy_fqQKYoCcMo5hi{DU6KOY|2{V^f}=VfJ3} zFTA(ISG_vSum-u(T&}S<&$or$9rubHO2imr(o9tA*#mv1H?OM*(e8XLCdme2VzFsm z9ZEy<&p(WRS=XX;=L{%uupxu9ms*Z_xQzaCz;~S$aVGvF(;}Q4#C_H-rE6=4NhBa$ z-mzLh7y5LGHeNZmzibRtIH*T;9SmcQsvM4zV954cvgamJKP$eQS(h|&M0>qEV-bA; z+yFxD#Tn5HQ3bzKwyM$Wy2qIB-6d+q>547pLgwNd8cwPQO$WE>32$!GJ9;S?bX{7f zI&q_mx#Z&%Mlav;pjniTF;ViCR%9ykhKT&6NQ)3~9Bqx34COAuM?3_(PhB(-Wrxe| z!n@g4vth4bAsGI?!OzFY6ymY9=>JvsqMrtP$1EDFxat6!B>!^xc(y0cY$`V*frliN zQ&DFB*oQ7_=KmjLTy6N#<xah(1@K~?}eaePBj=pc*W z4ZqF}{0K!sVRApz4Q8cQL&i!FmoOwC2G6K^;{^AgyJJ+FcCYJ{CG4u$Jx>Q{%)(hqN(w=~{D6jp4>ow+#Mf4<#UTTf4gokc_a zAXJT+cSq-f~*)PQHu>VQH6}pH1Z4fh{yYYan;s`-!SIQ924>LO@_F3E#d;PA2 z>`g{@T!k8)gnU0}!Vm8%Fg8Z;zMMMykf-CA@?qXHCv3=T07OU@@S1lxg!bk-#V^#z4k?B{v*2!7!Rb z!uWWaGwpayi{qD*VQk(hBvs_Rfr3f^VSKjOh+XM`B;@-m`3ziEn;JSb8|NB_(`bmVp6lV-eaNxtrr!bb z{d*3LEb-$4^EC)zW~VA|CXL#04;WOS5?{??k=K@>_L0mzpTv2sT=FGR8FGS^HVi955d34}2WJxE z@j9b()VwRt&1VX$OkgUGne7vP8w`E4g{;M$lw6gAi?aVrvcF!I8TDn?7b-(XL^ABGe^1Aqnm80k>yvVjeohc%(~KXzY(YA&8P_+2NanE51P($uRkPkEnQrSm!`K_So2d z=_Oka0v!F|9--`6XzfbWulYPg5DvV#*WNp6dO>QEKL+lA+CvnkWiwIN887}r=miU; za26KW-k7eZ-(Y`zx``QXe!-(DepOYC3;mI?7hpJ*J`Nx8d3`K=^)ZKQ6D=gDHly9F zcO_~Fxf>%cVyJqG*48QG6M2Q6L_6VK= zW`*B}(*|^Oi&E@|-zU@MSw-{7t}2DQfO#QiqnlBF$IrB{2*W!#-|pWk18&H&h(ZpD zS=e;v;ua0f8> zeC1Y$bVf`0Uv{wqiyF)N;<7#z`8E)4VP6vB~=_DHlTM z_khEY%FGu!)T!`r78$%bG`i0?*xUCqt#N_Q@hF7}g)woC#Vr?Awz$UF9c{|*MtU1_ zD}F)z5S{;Ek7vY1kyId%5a%-epj-WKVwN`O=02?37H1H2leUg|S=14SdN21Ce(S-n z5!=X6Ygq(7Cp5(YZaw-+94&n2#lADHkXYxXkuE~kOa$2^e#~m*#=^QoS@2dU0E68mNUK1ycbcYksXlAIUVjjVQUDW$sx7YsOs_ENqihb^Zre zrTm6)tn)uuCo;!olghb;Iv;r1!iNAaxpnr`4fJh0?@=Fh23KLLFK5nE*RiI|zWEe$ z2@L@?@yzA71E9W*Vd8KIDvSx>&?!mP;0|-Z)CTlKb7OnigT%A0`lHGDqarXaqn2LW z!)5zp4?wUXM#bWlUj8KIjVy2UK~q4FbrMA1!9w}e(!%VZsT-4vjb}XSxWtEOF)Arc zi_%%5FNsrCrLyQabEBdc%>bQE~7?y=x& zhJ3H#iY#Zu^}G@^q&s1&%5HBteI|1t3>K2B@#%F%T%9MHYx^f-humFrP}+uJpw9Vv zN8U7KnmN24*|6qOSS9e6_{UTm)j2LE1rEc(>hw-lmppMD_bQmvzXntjBE|rx*s}R} zdJjd;(8H&Ix@j5+n@w9C9EmF zBC5RG#K^R*P_2u2ikvc(cnJHHh03<)BV%VXwn|Ogbr(F){VBcmXTp2CWw4Y_WAU@=wQI8q3Dl{>Ua|K{K}iJi;p{Q;~SaJ3$kWhv2f5hSl{&s+jg`A?%E z)#lmfFX~VvFN71a6fNT~00Qkgw;b^I)Pkl2evLL9XY`H7zbQ?uB6keSkyPc))j-P~ zBd6X23@)IWb`wbRHxkDw&m1%Usq<&*-!m`AkmTamg`X9h$HuBOOr3F;+T=ir_)+cn z@>L&ukAkl&~UD^G9C5xD=~s@1&%= literal 0 HcmV?d00001 diff --git a/Net.Business.Services/web.config b/Net.Business.Services/web.config new file mode 100644 index 0000000..655523d --- /dev/null +++ b/Net.Business.Services/web.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Net.Connection.Attributes/ActionType.cs b/Net.Connection.Attributes/ActionType.cs new file mode 100644 index 0000000..1edb9d6 --- /dev/null +++ b/Net.Connection.Attributes/ActionType.cs @@ -0,0 +1,11 @@ +namespace Net.Connection.Attributes +{ + public enum ActionType + { + Everything, + View, + Insert, + Update, + Delete + } +} diff --git a/Net.Connection.Attributes/DBParameter.cs b/Net.Connection.Attributes/DBParameter.cs new file mode 100644 index 0000000..af09508 --- /dev/null +++ b/Net.Connection.Attributes/DBParameter.cs @@ -0,0 +1,64 @@ +using System; +using System.Data; + +namespace Net.Connection.Attributes +{ + public class DBParameter : Attribute + { + public string name { get; set; } + public int size { get; set; } + public SqlDbType dbType { get; set; } + public ParameterDirection direction { get; set; } + public ActionType actionType; + + public Boolean Key { get; set; } + + /// + /// Asignacion del Tipo de Dato + /// + /// Tipo de dato + /// Accion a realizar Everything, View, Insert, Update, Delete + /// Primary Key + public DBParameter(SqlDbType dbType, ActionType actionType, Boolean Key) + { + DBParameterMethod(dbType, 0, ParameterDirection.Input, "", actionType, Key); + } + //public DBParameter(SqlDbType dbType, ActionType actionType) + //{ + // DBParameterMethod(dbType, 0, ParameterDirection.Input, "", actionType, false); + //} + //public DBParameter(SqlDbType dbType, ActionType actionType, ParameterDirection direction) + //{ + // DBParameterMethod(dbType, 0, direction, "", actionType, false); + //} + + /// + /// Asignacion del Tipo de Dato + /// + /// Tipo de Dato + /// Tamano + /// Accion a realizar Everything, View, Insert, Update, Delete + public DBParameter(SqlDbType dbType, int size, ActionType actionType) + { + DBParameterMethod(dbType, size, ParameterDirection.Input, "", actionType, false); + } + //public DBParameter(SqlDbType dbType, int size, ParameterDirection direction, ActionType actionType) + //{ + // DBParameterMethod(dbType, size, direction, "", actionType, false); + //} + //public DBParameter(SqlDbType dbType, int size, ParameterDirection direction, string name, ActionType actionType) + //{ + // DBParameterMethod(dbType, size, direction, name, actionType, false); + //} + + private void DBParameterMethod(SqlDbType dbType, int size, ParameterDirection direction, string name, ActionType actionType, Boolean Key) + { + this.dbType = dbType; + this.direction = direction; + this.size = size; + this.name = name; + this.actionType = actionType; + this.Key = Key; + } + } +} diff --git a/Net.Connection.Attributes/Net.Connection.Attributes.csproj b/Net.Connection.Attributes/Net.Connection.Attributes.csproj new file mode 100644 index 0000000..01ca256 --- /dev/null +++ b/Net.Connection.Attributes/Net.Connection.Attributes.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp3.1 + + + diff --git a/Net.Connection.ServiceLayer/ConnectionServiceLayer.cs b/Net.Connection.ServiceLayer/ConnectionServiceLayer.cs new file mode 100644 index 0000000..bd73740 --- /dev/null +++ b/Net.Connection.ServiceLayer/ConnectionServiceLayer.cs @@ -0,0 +1,1216 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities.ServicesLayer; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Connection.ServiceLayer +{ + public class ConnectionServiceLayer + { + public static bool ServicioActivo = false; + public static string SLSession; + + private readonly string _url; + private readonly string _company; + private readonly string _user; + private readonly string _password; + private readonly string _language; + private readonly IHttpClientFactory _httpClient; + private ResponseLoginServiceLayer _responseLoginServiceLayer; + + public ConnectionServiceLayer(IConfiguration configuration, IHttpClientFactory clientFactory) + { + _url = configuration["SapServiceLayer:url"]; + _company = configuration["SapServiceLayer:company"]; + _user = configuration["SapServiceLayer:user"]; + _password = configuration["SapServiceLayer:password"]; + _language = configuration["SapServiceLayer:language"]; + _httpClient = clientFactory; + _responseLoginServiceLayer = new ResponseLoginServiceLayer(); + } + + private bool ValidarCertificado(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors ssl) + { + return true; + } + + public async Task Login() + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/Login"); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL Content CON EL OBJETO A ENVIAR SERIALIZADO. + request_.Content = new StringContent("{\"CompanyDB\":\"" + _company + "\",\"Password\":\"" + _password + "\",\"UserName\":\"" + _user + "\"}"); + + // DEFINIMOS EL ContentType, EN ESTE CASO ES "application/json" + request_.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + request_.Headers.Add("cache-control", "no-cache"); + + // DEFINIMOS EL MÉTODO HTTP + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK) // 200 + { + // DESERIALIZAMOS Content DEL RESPONSE + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = true; + _responseLoginServiceLayer.MensajeLogin = "Autenticación Correcta"; + return _responseLoginServiceLayer; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + return _responseLoginServiceLayer; + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + return _responseLoginServiceLayer; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return _responseLoginServiceLayer; + } + + } + catch (Exception ex) + { + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = ex.Message.ToString(); + return _responseLoginServiceLayer; + } + } + public async Task LoginPost() + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/Login"); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL Content CON EL OBJETO A ENVIAR SERIALIZADO. + request_.Content = new StringContent("{\"CompanyDB\":\"" + _company + "\",\"Password\":\"" + _password + "\",\"UserName\":\"" + _user + "\"}"); + //request_.Content = new StringContent("{\"CompanyDB\":\"" + _company + "\",\"Password\":\"" + _password + "\",\"UserName\":\"" + _user + "\",\"Language\":\"" + _language + "\"}"); + + // DEFINIMOS EL ContentType, EN ESTE CASO ES "application/json" + request_.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + request_.Headers.Add("cache-control", "no-cache"); + + // DEFINIMOS EL MÉTODO HTTP + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK) // 200 + { + // DESERIALIZAMOS Content DEL RESPONSE + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = true; + _responseLoginServiceLayer.MensajeLogin = "Autenticación Correcta"; + return _responseLoginServiceLayer; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + return _responseLoginServiceLayer; + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + return _responseLoginServiceLayer; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return _responseLoginServiceLayer; + } + + } + catch (Exception ex) + { + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = ex.Message.ToString(); + return _responseLoginServiceLayer; + } + } + public async Task Logout() + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/Logout"); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL Content CON EL OBJETO A ENVIAR SERIALIZADO. + //request_.Content = new StringContent("{\"CompanyDB\":\"" + _company + "\",\"Password\":\"" + _password + "\",\"UserName\":\"" + _user + "\"}"); + + //// DEFINIMOS EL ContentType, EN ESTE CASO ES "application/json" + //request_.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + request_.Headers.Add("cache-control", "no-cache"); + + // DEFINIMOS EL MÉTODO HTTP + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.NoContent) // 204 + { + // DESERIALIZAMOS Content DEL RESPONSE + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = true; + _responseLoginServiceLayer.MensajeLogin = "Cierre de Sesión Correcta"; + return _responseLoginServiceLayer; + } + //else + //// SI NO SE ESTÁ AUTORIZADO ... + //if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + //{ + // _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + // _responseLoginServiceLayer.ServicioActivo = false; + // _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + // return _responseLoginServiceLayer; + //} + //else + //// CUALQUIER OTRA RESPUESTA ... + //if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + // response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + //{ + // _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + // _responseLoginServiceLayer.ServicioActivo = false; + // _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas."; + // return _responseLoginServiceLayer; + //} + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return _responseLoginServiceLayer; + } + + } + catch (Exception ex) + { + _responseLoginServiceLayer.ServicioActivo = false; + _responseLoginServiceLayer.MensajeLogin = ex.Message.ToString(); + return _responseLoginServiceLayer; + } + } + public async Task> GetAsync(string Query, int maxpagesize,bool dinamico = false) + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + //AUTENTICAMOS PARA REALIZAR LAS CONSULTAS + await Login(); + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP + request_.Method = new HttpMethod("GET"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + request_.Headers.Add("cache-control", "no-cache"); + request_.Headers.Add("Prefer", "odata.maxpagesize=" + maxpagesize.ToString()); + + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + //request_.Headers = new AuthenticationHeaderValue("B1SESSION", _responseLoginServiceLayer.SessionId); + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK) // 200 + { + // DESERIALIZAMOS Content DEL RESPONSE + if (!dinamico) + { + var responseBody_ = JsonConvert.DeserializeObject>(responseText_); + return responseBody_.value; + } + + if (dinamico) + { + List lista = new List(); + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + //responseBody.Exito = true; + //var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + //responseBody.Mensaje = "Datos Correctos del SAP"; + lista.Add(responseBody); + return lista; + } + + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(List); + } + } + finally + { + // NO UTILIZAMOS CATCH, + // PASAMOS LA EXCEPCIÓN A LA APP. + } + } + public async Task PostAsync(string Query, object obj) + { + + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + var a = JsonConvert.SerializeObject(obj); + request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = true; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + } + + goto band; + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await Login(); + } + + goto band; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + finally + { + // NO UTILIZAMOS CATCH, + // PASAMOS LA EXCEPCIÓN A LA APP. + } + } + public async Task PostReOpen(string Query) + { + + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + //var a = JsonConvert.SerializeObject(obj); + //request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created || response_.StatusCode == HttpStatusCode.NoContent) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = true; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + } + + goto band; + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await Login(); + } + + goto band; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + finally + { + // NO UTILIZAMOS CATCH, + // PASAMOS LA EXCEPCIÓN A LA APP. + } + } + public async Task PostClose(string Query) + { + + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + //var a = JsonConvert.SerializeObject(obj); + //request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created || response_.StatusCode == HttpStatusCode.NoContent) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = new BE_BaseResponseSap(); //JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = true; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + } + + goto band; + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + responseBody.Exito = false; + var estado = (int)response_.StatusCode; + responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await Login(); + } + + goto band; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + finally + { + // NO UTILIZAMOS CATCH, + // PASAMOS LA EXCEPCIÓN A LA APP. + } + } + public async Task CancelAsyncSBA(string Query) + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("POST"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + //request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + goto band; + } + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + //NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + catch (Exception ex) + { + return default(T); + throw new Exception(ex.Message.ToString()); + } + } + public async Task DeleteAsyncSBA(string Query) + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("DELETE"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + //request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + goto band; + } + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200 + response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + //NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + catch (Exception ex) + { + return default(T); + throw new Exception(ex.Message.ToString()); + } + } + public async Task PatchAsyncSBA(string Query, object obj) + { + try + { + // CONSTRUIMOS LA URL DE LA ACCIÓN + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "") + .Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + // RECUPERAMOS EL HttpClient + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + int NumError = 0; + + band: + + using (var request_ = new HttpRequestMessage()) + { + /////////////////////////////////////// + // CONSTRUIMOS LA PETICIÓN (REQUEST) // + /////////////////////////////////////// + // DEFINIMOS EL MÉTODO HTTP GET + request_.Method = new HttpMethod("PATCH"); + + // DEFINIMOS LA URI + request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute); + + // DEFINIMOS EL Accept, EN ESTE CASO ES "application/json" + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata")); + //request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8")); + request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json"); + + // ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT. + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + ///////////////////////////////////////// + // CONSTRUIMOS LA RESPUESTA (RESPONSE) // + ///////////////////////////////////////// + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + + // OBTENEMOS EL Content DEL RESPONSE como un String + // Utilizamos ConfigureAwait(false) para evitar el DeadLock. + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + // SI ES LA RESPUESTA ESPERADA !! ... + if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created + { + // DESERIALIZAMOS Content DEL RESPONSE + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO "; + return responseBody; + } + else + // SI NO SE ESTÁ AUTORIZADO ... + if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401 + { + + NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + if (NumError == 2) + { + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + + if (_responseLoginServiceLayer.error.code.ToString() == "301") + { + await LoginPost(); + goto band; + } + } + else + // CUALQUIER OTRA RESPUESTA ... + if (response_.StatusCode != System.Net.HttpStatusCode.OK && response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204 + { + + //NumError += 1; + + _responseLoginServiceLayer = JsonConvert.DeserializeObject(responseText_); + _responseLoginServiceLayer.ServicioActivo = false; + + dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + var estado = (int)response_.StatusCode; + //responseBody.CodigoHttp = estado.ToString(); + responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString(); + return responseBody; + } + + if (response_.StatusCode == System.Net.HttpStatusCode.NoContent) + { + //dynamic responseBody = JsonConvert.DeserializeObject(responseText_); + ////responseBody.Mensaje = "OK"; + //return responseBody; + } + + // RETORNAMOS EL OBJETO POR DEFECTO ESPERADO + return default(T); + } + } + catch (Exception ex) + { + return default(T); + throw new Exception(ex.Message.ToString()); + } + } + + // === NUEVO (SolicitudTransferencia / Picking HojaRuta Cerrar) === + // + // PatchAsyncSBA/PostAsync estan pensados para respuestas con body + // (200/201) que se deserializan a T y se les "inyecta" Exito/Mensaje/CodigoHttp + // via dynamic - no sirven para una respuesta sin body como el 204 real que + // devuelve SAP en un PATCH exitoso o en una accion /Close, y PatchAsyncSBA + // tiene ademas un bug conocido ahi (ver docs/PORTE_FUNCIONALIDAD_NUEVA.md, + // hallazgo #2): con un 204 real cae a "return default(T)" sin marcar exito. + // Por eso estos dos metodos nuevos son deliberadamente simples: no devuelven + // un T deserializado, solo exito (sin excepcion) o fallo (excepcion con el + // mensaje real de SAP). + + public async Task PatchNoContentAsync(string Query, object obj, Dictionary extraHeaders = null) + { + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "").Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + await Login(); + + using (var request_ = new HttpRequestMessage()) + { + request_.Method = new HttpMethod("PATCH"); + request_.RequestUri = new Uri(url_, UriKind.RelativeOrAbsolute); + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + request_.Content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json"); + + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + if (extraHeaders != null) + { + foreach (var kv in extraHeaders) + request_.Headers.Add(kv.Key, kv.Value); + } + + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + if (response_.StatusCode == HttpStatusCode.OK || response_.StatusCode == HttpStatusCode.NoContent) + { + return; // exito real - sin body que parsear + } + + throw new Exception(ExtraerMensajeErrorSap(responseText_)); + } + } + + public async Task PostActionAsync(string Query) + { + var urlBuilder_ = new StringBuilder(); + urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "").Append("/" + Query); + var url_ = urlBuilder_.ToString(); + + var client_ = _httpClient.CreateClient("bypass-ssl-validation"); + + await Login(); + + using (var request_ = new HttpRequestMessage()) + { + request_.Method = new HttpMethod("POST"); + request_.RequestUri = new Uri(url_, UriKind.RelativeOrAbsolute); + request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); + request_.Content = new StringContent("{}", Encoding.UTF8, "application/json"); + + if (_responseLoginServiceLayer.ServicioActivo) + request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId); + + var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + + if (response_.StatusCode == HttpStatusCode.OK || response_.StatusCode == HttpStatusCode.Created || response_.StatusCode == HttpStatusCode.NoContent) + { + return; // exito real - sin body que parsear + } + + throw new Exception(ExtraerMensajeErrorSap(responseText_)); + } + } + + private static string ExtraerMensajeErrorSap(string responseText) + { + try + { + var parsed = JsonConvert.DeserializeObject(responseText); + var mensaje = parsed?.error?.message; + if (mensaje == null) return responseText; + // "message" esta tipado como object en ErrorServiceLayer (ver + // ResponseLoginServiceLayer.cs) - Json.NET lo deja como JObject. + if (mensaje is JObject jMensaje) return jMensaje.Value("value") ?? responseText; + return mensaje.ToString(); + } + catch + { + return responseText; + } + } + } +} diff --git a/Net.Connection.ServiceLayer/Net.Connection.ServiceLayer.csproj b/Net.Connection.ServiceLayer/Net.Connection.ServiceLayer.csproj new file mode 100644 index 0000000..f271a67 --- /dev/null +++ b/Net.Connection.ServiceLayer/Net.Connection.ServiceLayer.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/Net.Connection.ServiceLayer/ResponseGetServiceLayer.cs b/Net.Connection.ServiceLayer/ResponseGetServiceLayer.cs new file mode 100644 index 0000000..e3044ad --- /dev/null +++ b/Net.Connection.ServiceLayer/ResponseGetServiceLayer.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Net.Connection.ServiceLayer +{ + public class ResponseGetServiceLayer + { + public List value { get; set; } + } +} diff --git a/Net.Connection.ServiceLayer/ResponseLoginServiceLayer.cs b/Net.Connection.ServiceLayer/ResponseLoginServiceLayer.cs new file mode 100644 index 0000000..84c4512 --- /dev/null +++ b/Net.Connection.ServiceLayer/ResponseLoginServiceLayer.cs @@ -0,0 +1,27 @@ +using System; + +namespace Net.Connection.ServiceLayer +{ + public class ResponseLoginServiceLayer + { + public string SessionId { get; set; } + public string Version { get; set; } + public int? SessionTimeout { get; set; } + public Boolean ServicioActivo { get; set; } + public string MensajeLogin { get; set; } + public ErrorServiceLayer error { get; set; } + } + + public class ErrorServiceLayer + { + public string code { get; set; } + public object message { get; set; } + //public string? message { get; set; } + } + + public class ErrorMensajeServiceLayer + { + public string lang { get; set; } + public string value { get; set; } + } +} diff --git a/Net.Connection/Connection/ConnectionSQL.cs b/Net.Connection/Connection/ConnectionSQL.cs new file mode 100644 index 0000000..c401483 --- /dev/null +++ b/Net.Connection/Connection/ConnectionSQL.cs @@ -0,0 +1,372 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Net.Connection.Attributes; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; + +namespace Net.Connection +{ + public class ConnectionSQL : IConnectionSQL + { + public string _cnx { get; set; } + + public ConnectionSQL(IConfiguration configuration, IServiceProvider serviceProvider) + { + } + + public ConnectionSQL() + { + } + public string DevuelveConnectionSQL() + { + return _cnx; + } + + public IEnumerable ExecuteSqlViewFindByCondition(string procedureName, object parameters) + { + return ExecuteSqlQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.View).ToArray()); + } + + public T ExecuteSqlViewId(string procedureName, object parameters) + { + return ExecuteSqlQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.Everything).ToArray()).FirstOrDefault(); + } + + public IEnumerable ExecuteSqlViewAll(string procedureName, T parameters) + { + return ExecuteSqlQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.Everything).ToArray()); + } + + public object ExecuteSqlInsert(string procedureName, object parameters) + { + return ExecuteSqlNonQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.Insert).ToArray())[0].valor; + } + public object ExecuteSqlUpdate(string procedureName, object parameters) + { + return ExecuteSqlNonQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.Update).ToArray()); + } + + public object ExecuteSqlDelete(string procedureName, T parameters) + { + return ExecuteSqlNonQuery(procedureName, GetParametersSqlQueryAnotation(parameters, ActionType.Delete).ToArray()); + } + + public DbParametro[] ExecuteSqlNonQuery(string procedureName, DbParametro[] parameters) + { + SqlConnection cnx = new SqlConnection(_cnx); + SqlCommand cmd = cnx.CreateCommand(); + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandText = procedureName; + cmd.CommandTimeout = 0; + try + { + foreach (DbParametro parametro in parameters) + { + SqlParameter prm = new SqlParameter(); + prm.ParameterName = parametro.nombre; + if (!parametro.dbType.Equals (System.Data.SqlDbType.VarBinary)) + { + prm.SqlDbType = parametro.dbType; + prm.Size = (parametro.size == 0) ? prm.Size : parametro.size; + } + + prm.Direction = parametro.direccion; + prm.Value = parametro.valor; + cmd.Parameters.Add(prm); + } + + if (cmd.Connection.State.HasFlag(ConnectionState.Closed)) + cmd.Connection.Open(); + + cmd.Transaction = cmd.Connection.BeginTransaction(); + cmd.ExecuteNonQuery(); + if (parameters != null) + { + SqlParameterCollection sqlParameters = cmd.Parameters; + + for (int i = 0; i < parameters.Length; i++) + { + parameters[i].valor = sqlParameters[parameters[i].nombre.ToUpper().Trim()].Value; + } + } + cmd.Transaction.Commit(); + } + catch (SqlException ex) + { + if (cmd.Transaction != null) + { + cmd.Transaction.Rollback(); + } + throw ex; + } + catch (Exception ex) + { + if (cmd.Transaction != null) + { + cmd.Transaction.Rollback(); + } + throw ex; + } + finally + { + if (cmd.Connection != null && cmd.Connection.State == ConnectionState.Open) + { + cmd.Connection.Close(); + cmd.Connection.Dispose(); + cmd.Dispose(); + } + } + return parameters; + } + + public IEnumerable ExecuteSqlQuery(string comandSql) + { + return ExecuteSqlQuery(comandSql, null); + } + + public IEnumerable ExecuteSqlQuery(string procedureName, DbParametro[] parameters) + { + IEnumerable queryResult; + SqlCommand cmd = new SqlCommand(procedureName); + cmd.CommandText = procedureName; + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandTimeout = 0; + try + { + // Asignamos los parámetros + if (parameters != null) + { + foreach (DbParametro parametro in parameters) + { + SqlParameter prm = new SqlParameter(); + prm.ParameterName = parametro.nombre; + prm.SqlDbType = parametro.dbType; + prm.Size = parametro.size; + prm.Direction = parametro.direccion; + prm.Value = parametro.valor; + cmd.Parameters.Add(prm); + } + } + // Creamos la Conexion + cmd.Connection = new SqlConnection(_cnx); + if (cmd.Connection.State.HasFlag(ConnectionState.Closed)) + cmd.Connection.Open(); + + DataTable dataTable = new DataTable(); + cmd.Transaction = cmd.Connection.BeginTransaction(); + using (IDataReader reader = cmd.ExecuteReader()) + { + dataTable.Load(reader); + queryResult = ConvertTo(dataTable); + } + cmd.Transaction.Commit(); + + } + catch (SqlException ex) + { + if (cmd.Transaction != null) + { + cmd.Transaction.Rollback(); + } + throw ex; + } + finally + { + if (cmd.Connection != null && cmd.Connection.State == ConnectionState.Open) + { + cmd.Connection.Close(); + cmd.Connection.Dispose(); + cmd.Dispose(); + } + } + return queryResult; + } + + //private static SqlParameterCollection CreateParametros(string procedureName, string conexion) + //{ + // SqlCommand cmd = new SqlCommand(procedureName.Trim()); + // try + // { + // cmd.CommandType = CommandType.StoredProcedure; + // cmd.Connection = new SqlConnection(conexion); + // if (cmd.Connection.State == ConnectionState.Closed) + // { + // cmd.Connection.Open(); + // } + // SqlCommandBuilder.DeriveParameters(cmd); + // for (int i = 0; i < cmd.Parameters.Count; i++) + // { + // string Nombre = cmd.Parameters[i].ParameterName; + // if (Nombre.Substring(0, 1) == "@") + // { + // Nombre = Nombre.Substring(1); + // } + // cmd.Parameters[i].ParameterName = Nombre.ToUpper(); + // } + // return cmd.Parameters; + // } + // catch (Exception ex) + // { + // throw ex; + // } + // finally + // { + // cmd.Connection.Dispose(); + // cmd.Dispose(); + // } + //} + + //private static IList GetParametersSqlQuery(Object parameters) + //{ + // IList listaParametro = new List(); + + // foreach (PropertyInfo prop in parameters.GetType().GetProperties()) + // { + // dynamic valor = prop.GetValue(parameters, null); + // Type type = Nullable.GetUnderlyingType(prop.PropertyType); + + // if (valor != null) + // { + // type = (type == null) ? prop.PropertyType : type; + + // if (type != typeof(System.Collections.Generic.ICollection<>)) + // { + // listaParametro.Add(new DbParametro() { nombre = prop.Name, valor = valor }); + // } + // } + // } + + // return listaParametro; + //} + + private static IList GetParametersSqlQueryAnotation(T parameters, ActionType actionType) + { + IList listaParametro = new List(); + + foreach (PropertyInfo prop in parameters.GetType().GetProperties()) + { + dynamic valor = prop.GetValue(parameters, null); + Type type = Nullable.GetUnderlyingType(prop.PropertyType); + + if (valor != null) + { + type = (type == null) ? prop.PropertyType : type; + var attributes = prop.GetCustomAttributes(false); + var columnMapping = attributes.FirstOrDefault(a => a.GetType() == typeof(DBParameter)); + if (columnMapping != null) + { + DbParametro parametro = new DbParametro() { valor = valor }; + var mapsto = columnMapping as DBParameter; + + switch (actionType) + { + case ActionType.Insert: + if (mapsto.actionType == ActionType.Everything) + { + mapsto.actionType = ActionType.Insert; + } + break; + case ActionType.Update: + if (mapsto.actionType == ActionType.Everything) + { + mapsto.actionType = ActionType.Update; + } + break; + case ActionType.Delete: + if (mapsto.actionType == ActionType.Everything) + { + mapsto.actionType = ActionType.Delete; + } + break; + case ActionType.View: + if (mapsto.actionType == ActionType.View || + mapsto.actionType == ActionType.Everything) + { + mapsto.actionType = ActionType.View; + } + break; + default: + break; + } + + if (mapsto.actionType == actionType) + { + parametro.nombre = (mapsto.name == "") ? prop.Name : mapsto.name; + parametro.direccion = (mapsto.Key == true && mapsto.actionType == ActionType.Insert) ? ParameterDirection.Output : mapsto.direction; + parametro.dbType = mapsto.dbType; + parametro.size = mapsto.size; + listaParametro.Add(parametro); + } + } + } + } + + return listaParametro; + } + + public static IList ConvertTo(DataTable table) + { + if (table == null) + return null; + + List rows = new List(); + foreach (DataRow row in table.Rows) + rows.Add(row); + + return ConvertTo(rows); + } + + public static IList ConvertTo(IList rows) + { + IList list = null; + if (rows != null) + { + list = new List(); + foreach (DataRow row in rows) + { + T item = CreateItem(row); + list.Add(item); + } + } + return list; + } + + public static T CreateItem(DataRow row) + { + string columnName; + T obj = default(T); + if (row != null) + { + obj = Activator.CreateInstance(); + foreach (DataColumn column in row.Table.Columns) + { + columnName = column.ColumnName; + //Get property with same columnName + PropertyInfo prop = obj.GetType().GetProperty(columnName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); + try + { + if (prop != null) + { + //Get value for the column + object value = (row[columnName].GetType() == typeof(DBNull)) ? null : row[columnName]; + //Set property value + prop.SetValue(obj, value, null); + } + } + catch + { + throw; + //Catch whatever here + } + } + } + return obj; + } + } +} diff --git a/Net.Connection/Connection/DbParametro.cs b/Net.Connection/Connection/DbParametro.cs new file mode 100644 index 0000000..122b524 --- /dev/null +++ b/Net.Connection/Connection/DbParametro.cs @@ -0,0 +1,35 @@ +using System.Data; + +namespace Net.Connection +{ + public class DbParametro + { + public string nombre { get; set; } + public object valor { get; set; } + + public int size { get; set; } + public ParameterDirection direccion { get; set; } + public SqlDbType dbType { get; set; } + + public DbParametro() + { + nombre = ""; + valor = null; + direccion = ParameterDirection.Input; + } + + public DbParametro(string Nombre, object Valor, ParameterDirection Direccion) + { + nombre = Nombre; + valor = Valor; + direccion = Direccion; + } + + public DbParametro(string Nombre, object Valor) + { + nombre = Nombre; + valor = Valor; + direccion = ParameterDirection.Input; + } + } +} diff --git a/Net.Connection/Connection/IConnectionSQL.cs b/Net.Connection/Connection/IConnectionSQL.cs new file mode 100644 index 0000000..72d23d0 --- /dev/null +++ b/Net.Connection/Connection/IConnectionSQL.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Net.Connection +{ + public interface IConnectionSQL + { + public string _cnx { get; set; } + public string DevuelveConnectionSQL(); + public object ExecuteSqlInsert(string procedureName, object parameters); + public object ExecuteSqlUpdate(string procedureName, object parameters); + public object ExecuteSqlDelete(string procedureName, T parameters); + public T ExecuteSqlViewId(string procedureName, object parameters); + public IEnumerable ExecuteSqlViewFindByCondition(string procedureName, object parameters); + public IEnumerable ExecuteSqlViewAll(string procedureName, T parameters); + } +} + diff --git a/Net.Connection/Net.Connection.csproj b/Net.Connection/Net.Connection.csproj new file mode 100644 index 0000000..8bb4b58 --- /dev/null +++ b/Net.Connection/Net.Connection.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + + diff --git a/Net.Connection/RepositoryBase/IRepositoryBase.cs b/Net.Connection/RepositoryBase/IRepositoryBase.cs new file mode 100644 index 0000000..e1bbd70 --- /dev/null +++ b/Net.Connection/RepositoryBase/IRepositoryBase.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Net.Connection +{ + public interface IRepositoryBase + { + IEnumerable FindAll(T entity, string storeProcedure); + IEnumerable FindByCondition(object entity, string storeProcedure); + T FindById(object entity, string storeProcedure); + int Create(object entity, string storeProcedure); + void Update(object entity, string storeProcedure); + void Delete(T entity, string storeProcedure); + } +} diff --git a/Net.Connection/RepositoryBase/RepositoryBase.cs b/Net.Connection/RepositoryBase/RepositoryBase.cs new file mode 100644 index 0000000..d8a0dbe --- /dev/null +++ b/Net.Connection/RepositoryBase/RepositoryBase.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; + +namespace Net.Connection +{ + public abstract class RepositoryBase : IRepositoryBase where T : class + { + protected IConnectionSQL context { get; set; } + + public RepositoryBase(IConnectionSQL context) + { + this.context = context; + } + public IEnumerable FindAll(T entity, string storeProcedure) + { + return context.ExecuteSqlViewAll(storeProcedure, entity); + } + + public IEnumerable FindByCondition(object entity, string storeProcedure) + { + return context.ExecuteSqlViewFindByCondition(storeProcedure, entity); + } + + public T FindById(object entity, string storeProcedure) + { + return context.ExecuteSqlViewId(storeProcedure, entity); + } + + public int Create(object entity, string storeProcedure) + { + return (int)context.ExecuteSqlInsert(storeProcedure, entity); + } + + public void Delete(T entity, string storeProcedure) + { + context.ExecuteSqlDelete(storeProcedure, entity); + } + + public void Update(object entity, string storeProcedure) + { + this.context.ExecuteSqlUpdate(storeProcedure, entity); + } + } +} diff --git a/Net.Constantes/Net.Constantes.csproj b/Net.Constantes/Net.Constantes.csproj new file mode 100644 index 0000000..01ca256 --- /dev/null +++ b/Net.Constantes/Net.Constantes.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp3.1 + + + diff --git a/Net.Constantes/StoreProcedure.cs b/Net.Constantes/StoreProcedure.cs new file mode 100644 index 0000000..18f5092 --- /dev/null +++ b/Net.Constantes/StoreProcedure.cs @@ -0,0 +1,146 @@ +namespace Net.Constantes +{ + public static class StoreProcedure + { + public const string DB_ESQUEMA = "dbo."; + public const string DB_ESQUEMA_GERENCIAL = "FLGERENCIAL.dbo."; + public const string DB_ESQUEMA_VENTAS = "VEN."; + public const string DB_ESQUEMA_EXC = "EXC."; + + + #region TABLA + public const string SP_GET_TABLA_POR_FILTRO = DB_ESQUEMA + "CAJ_GetTablaPorFiltro"; + public const string SP_GET_TABLA_POR_ID = DB_ESQUEMA + "CAJ_GetTablaPorId"; + public const string SP_SET_TABLA = DB_ESQUEMA + "CAJ_SetTablaInsert"; + public const string SP_SET_TABLA_UPDATE = DB_ESQUEMA + "CAJ_SetTablaUpdate"; + public const string SP_SET_TABLA_DELETE = DB_ESQUEMA + "CAJ_SetTablaDelete"; + + #endregion + + #region SEGURIDAD + public const string SP_GET_LIST_PARAMETROS_SISTEMAS_POR_ID = DB_ESQUEMA + "SEG_GetParametroSistemaPorId"; + #endregion + + #region CC/ER + public const string SP_GET_LIST_CAJA_CHICA_POR_FILTRO = DB_ESQUEMA + "CAJ_GetCajaChicaPorFiltro"; + + public const string SP_GET_LIST_CAJA_CHICA_SAP_POR_ID = DB_ESQUEMA + "CAJ_GetCajaChicaSATPorId"; + + public const string SP_GET_LIST_CAJA_CHICA_DETALLE_POR_FILTRO = DB_ESQUEMA + "CAJ_GetCajaChicaDetallePorFiltro"; + public const string SP_GET_LIST_CAJA_CHICA_DETALLE_POR_ID = DB_ESQUEMA + "CAJ_GetCajaChicaDetallePorId"; + public const string SP_GET_LIST_CAJA_CHICA_POR_ID = DB_ESQUEMA + "CAJ_GetCajaChicaPorId"; + public const string SP_GET_LIST_CAJA_CHICA_DETALLE_ADJUNTO_POR_ID_DETALLE = DB_ESQUEMA + "CAJ_GetCajaChicaAdjuntoPorIdDetalle"; + public const string SP_GET_LIST_CAJA_CHICA_DETALLE_ADJUNTO_POR_ID_ADJUNTO = DB_ESQUEMA + "CAJ_GetCajaChicaAdjuntoPorIdAdjunto"; + public const string SP_GET_LIST_CAJA_CHICA_REPORTE_POR_FILTRO = DB_ESQUEMA + "CAJ_GetCajaChicaReportePorFiltro"; + public const string SP_GET_LIST_CAJA_CHICA_CONSOLIDADO_POR_FILTRO = DB_ESQUEMA + "CAJ_GetCajaChicaConsolidadoPorFiltro"; + public const string SP_GET_NOTIFICACION_CAJA_CHICA = DB_ESQUEMA + "CAJ_GetNotificacionCajaChica"; + + + + public const string SP_SET_INSERT_CAJA_CHICA = DB_ESQUEMA + "CAJ_SetCajaChicaInsert"; + public const string SP_SET_INSERT_CAJA_CHICA_DETALLE_ADJUNTO = DB_ESQUEMA + "CAJ_SetCajaChicaAdjuntoMerge"; + public const string SP_SET_DELETE_CAJA_CHICA_DETALLE_ADJUNTO = DB_ESQUEMA + "CAJ_SetCajaChicaAdjuntoDelete"; + + + public const string SP_SET_UPDATE_CAJA_CHICA = DB_ESQUEMA + "CAJ_SetCajaChicaUpdate"; + public const string SP_SET_UPDATE_CAJA_CHICA_DETALLE_SAP = DB_ESQUEMA + "CAJ_SetCajaChicaDetalleSAPUpdate"; + public const string SP_SET_DELETE_CAJA_CHICA = DB_ESQUEMA + "CAJ_SetCajaChicaDelete"; + + public const string SP_SET_UPDATE_ESTADO_CAJA_CHICA = DB_ESQUEMA + "CAJ_SetCajaChicaEstadoUpdate"; + public const string SP_GET_UPDATE_ESTADO_CAJA_CHICA_NOTIFICACION = DB_ESQUEMA + "CAJ_GetCajaChicaDetalleEstadoUpdateNotificacion"; + public const string SP_SET_UPDATE_FECHA_REEMBOLSO_CAJA_CHICA = DB_ESQUEMA + "CAJ_SetCajaChicaFechaReembolsoUpdate"; + public const string SP_SET_UPDATE_ESTADO_CAJA_CHICA_DETALLE = DB_ESQUEMA + "CAJ_SetCajaChicaDetalleEstadoUpdate"; + #endregion + + + #region REPORTES + public const string SP_GET_LIST_REPORTE_VENTAS = DB_ESQUEMA + "REP_GetReporteVentas"; + public const string SP_GET_LIST_REPORTE_VENTAS_ACUMULADO = DB_ESQUEMA + "REP_GetReporteVentasAcumulado"; + public const string SP_GET_LIST_REPORTE_INVENTARIO = DB_ESQUEMA + "REP_GetReporteInventario"; + public const string SP_GET_LIST_PERIODOS = DB_ESQUEMA + "REP_GetPeriodosSap"; + public const string SP_GET_LIST_PROVEEDORES = DB_ESQUEMA_GERENCIAL + "proveedores"; + + public const string SP_GET_LIST_REPORTE_INVENTARIO_VALORIZADO = DB_ESQUEMA + "REP_GetReporteInventarioValorizado"; + public const string SP_GET_LIST_REPORTE_INVENTARIO_VALORIZADO_ALMACENES = DB_ESQUEMA + "REP_GetAlmacenesInventarioValorizado"; + + public const string SP_GET_LIST_REPORTE_MESES_STOCK = DB_ESQUEMA + "REP_GetReporteMesesStock"; + + public const string SP_GET_LIST_REPORTE_FECHA_VENCIMIENTO_FL_TIPOS = DB_ESQUEMA + "REP_GetTipoFechaVencimiento"; + public const string SP_GET_LIST_REPORTE_FECHA_VENCIMIENTO_FL_PRODUCTOS = DB_ESQUEMA + "REP_GetProductosFechaVencimiento"; + public const string SP_GET_LIST_REPORTE_FECHA_VENCIMIENTO_FL = DB_ESQUEMA_GERENCIAL + "SP_FECHA_VEMCIMIENTO"; + + public const string SP_GET_LIST_REPORTE_EGYP = DB_ESQUEMA + "REP_GetReporteEgyp"; + public const string SP_GET_LIST_REPORTE_EGYP_CLIENTES = DB_ESQUEMA_GERENCIAL + "SP_CLIENTES_EGYP"; + + public const string SP_GET_LIST_REPORTE_COMPRAS_FL = DB_ESQUEMA + "REP_GetReporteComprasFl"; + + public const string SP_GET_LIST_REPORTE_CARGA_DESCARGA = DB_ESQUEMA + "REP_GetCargaDescarga"; + + + + + #endregion + + #region INDICADORES + public const string SP_GET_LIST_INDICADOR_GENERAL = DB_ESQUEMA + "IND_GetIndicadorGeneral"; + + #endregion + + #region SERVICES LAYERS + public const string SP_SERVICES_LAYER_WAREHOUSES = "Warehouses"; + public const string SP_SERVICES_LAYER_ITEMGROUPS = "ItemGroups"; + public const string SP_SERVICES_LAYER_SALESPERSONS = "SalesPersons"; + public const string SP_SERVICES_LAYER_BUSINESSPARTNERS = "BusinessPartners"; + public const string SP_SERVICES_LAYER_PRICELISTS = "PriceLists"; + public const string SP_SERVICES_LAYER_CURRENCIES = "Currencies"; + public const string SP_SERVICES_LAYER_PROFITCENTERS = "ProfitCenters"; + public const string SP_SERVICES_LAYER_CHARTOFACCOUNTS = "ChartOfAccounts"; + public const string SP_SERVICES_LAYER_PAYMENTTERMSTYPES = "PaymentTermsTypes"; + public const string SP_SERVICES_LAYER_DISTRIBUTIONRULES = "DistributionRules"; + public const string SP_SERVICES_LAYER_ITEMS = "Items"; + #endregion + + + #region VENTAS + + public const string SP_GET_LIST_PRODUCTOS_PACKS = DB_ESQUEMA_VENTAS + "VEN_GetProductosPacks"; + public const string SP_GET_LIST_VENTAS = DB_ESQUEMA_VENTAS + "VEN_GetVentas"; + public const string SP_GET_LIST_TIPOS_DESCUENTOS = DB_ESQUEMA_VENTAS + "VEN_GetTiposDescuentos"; + public const string SP_GET_LIST_CODIGOS_PROMOCIONALES = DB_ESQUEMA_VENTAS + "VEN_GetCodigosPromocionales"; + public const string SP_GET_LIST_PROMOCIONES_PRODUCTOS_DESCUENTOS = DB_ESQUEMA_VENTAS + "VEN_GetPromocionesProductosDescuento"; + public const string SP_GET_LIST_PROMOCIONES_DESCUENTOS = DB_ESQUEMA_VENTAS + "VEN_GetPromocionesDescuento"; + public const string SP_GET_LIST_DATOS_PARAMETROS_SAP = DB_ESQUEMA_VENTAS + "VEN_GetDatosParametrosVentasSAP"; + + + + + + + public const string SP_SET_INSERT_PROMOCIONESDESCUENTOS_DET = DB_ESQUEMA_VENTAS + "VEN_SetPromocionesDescuentosDetInsert"; + public const string SP_SET_UPDATE_PROMOCIONESDESCUENTOS_DET = DB_ESQUEMA_VENTAS + "VEN_SetPromocionesDescuentosDetUpdate"; + public const string SP_SET_INSERT_VENTAS = DB_ESQUEMA_VENTAS + "VEN_SetVentasInsert"; + public const string SP_SET_UPDATE_VENTAS = DB_ESQUEMA_VENTAS + "VEN_SetVentasUpdate"; + //public const string SP_GET_LIST_PROMOCIONESDESCUENTOS = DB_ESQUEMA_VENTAS + "VEN_GetDatosMaestros"; + + + + + #endregion + + + #region IMPORTACION DE EXCELES + + public const string SP_SET_INSERT_EXCELES = DB_ESQUEMA_EXC + "EXC_SetExcelesCargaWebInsert"; + public const string SP_SET_INSERT_EXCELES_PROCESAR = DB_ESQUEMA_EXC + "EXC_SetExcelesCargaWebProcesar"; + public const string SP_SET_EXCEL_PROCESO = DB_ESQUEMA_EXC + "EXC_SetExcelProceso"; + + + #endregion + + #region TABLA + public const string SP_GET_TABLA_POR_FILTRO_EXC = DB_ESQUEMA_EXC + "EXC_GetTablaPorFiltro"; + + #endregion + + } +} diff --git a/Net.CrossCotting/EncriptaHelper.cs b/Net.CrossCotting/EncriptaHelper.cs new file mode 100644 index 0000000..1e00f48 --- /dev/null +++ b/Net.CrossCotting/EncriptaHelper.cs @@ -0,0 +1,223 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Net.CrossCotting +{ + //Advanced Encryption Standard(AES), + //también conocido como Rijndael(pronunciado “Rain Doll” en inglés), + //es un esquema de cifrado por bloques adoptado como un estándar de + //cifrado por el gobierno de los Estados Unidos. + //El AES fue anunciado por el Instituto + //Nacional de Estándares y Tecnología (NIST) como FIPS PUB 197 de los + //Estados Unidos (FIPS 197) el 26 de noviembre de 2001 después de un + //proceso de estandarización que duró 5 años.Se transformó en un estándar + //efectivo el 26 de mayo de 2002. Desde 2006, el AES es uno de los algoritmos + //más populares usados en criptografía simétrica. + public static class EncriptaHelper + { + + private static string tokenFromUI = "123456$#@$^@1$B@"; + + private static Rfc2898DeriveBytes GetSecretKey() + { + const string encryptionKey = "r3turn-d3-$up3rm4n-!!"; + byte[] salt = Encoding.UTF8.GetBytes(encryptionKey); + + var secretKey = new Rfc2898DeriveBytes(encryptionKey, salt); + return secretKey; + } + + + /// + /// Encripta cualquier texto usando el algoridmo Rijndael. + /// + /// texto a encryptar + /// Array de bytes con el texto encriptado + public static byte[] EncryptToByte(string rawText) + { + + var rijndaelCipher = new RijndaelManaged(); + byte[] rawTextData = Encoding.UTF8.GetBytes(rawText); + + Rfc2898DeriveBytes secretKey = GetSecretKey(); + + + using (var encryptor = rijndaelCipher.CreateEncryptor(secretKey.GetBytes(32), secretKey.GetBytes(16))) + { + using (var memoryStream = new MemoryStream()) + { + using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) + { + cryptoStream.Write(rawTextData, 0, rawTextData.Length); + cryptoStream.FlushFinalBlock(); + return memoryStream.ToArray(); + } + } + } + } + + /// + /// Desencripta un texto previamente encriptado con el algoritmo Rijndael. + /// + /// Array de bytes del texto encriptado a desencriptar. + /// Texto desencriptado. + public static string Decrypt(byte[] encryptByte) + { + try + { + var rijndaelCipher = new RijndaelManaged(); + + Rfc2898DeriveBytes secretKey = GetSecretKey(); + + using (ICryptoTransform decryptor = rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16))) + { + using (var memoryStream = new MemoryStream(encryptByte)) + { + using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) + { + var plainText = new byte[encryptByte.Length]; + int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length); + return Encoding.UTF8.GetString(plainText, 0, decryptedCount); + } + } + } + } + catch + { + return null; + } + } + + public static string DecryptStringAES(string cipherText) + { + var keybytes = Encoding.UTF8.GetBytes(tokenFromUI); + var iv = Encoding.UTF8.GetBytes(tokenFromUI); + + var encrypted = Convert.FromBase64String(cipherText); + var decriptedFromJavascript = DecryptStringFromBytes(encrypted, keybytes, iv); + return decriptedFromJavascript; + } + + private static string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv) + { + // Check arguments. + if (cipherText == null || cipherText.Length <= 0) + { + throw new ArgumentNullException("cipherText"); + } + if (key == null || key.Length <= 0) + { + throw new ArgumentNullException("key"); + } + if (iv == null || iv.Length <= 0) + { + throw new ArgumentNullException("key"); + } + + // Declare the string used to hold + // the decrypted text. + string plaintext = null; + + // Create an RijndaelManaged object + // with the specified key and IV. + using (var rijAlg = new RijndaelManaged()) + { + //Settings + rijAlg.Mode = CipherMode.CBC; + rijAlg.Padding = PaddingMode.PKCS7; + rijAlg.FeedbackSize = 128; + + rijAlg.Key = key; + rijAlg.IV = iv; + + // Create a decrytor to perform the stream transform. + var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); + + try + { + // Create the streams used for decryption. + using (var msDecrypt = new MemoryStream(cipherText)) + { + using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) + { + + using (var srDecrypt = new StreamReader(csDecrypt)) + { + // Read the decrypted bytes from the decrypting stream + // and place them in a string. + plaintext = srDecrypt.ReadToEnd(); + + } + + } + } + } + catch + { + plaintext = "keyError"; + } + } + + return plaintext; + } + + public static string EncryptStringAES(string plainText) + { + var keybytes = Encoding.UTF8.GetBytes(tokenFromUI); + var iv = Encoding.UTF8.GetBytes(tokenFromUI); + + var encryoFromJavascript = EncryptStringToBytes(plainText, keybytes, iv); + return Convert.ToBase64String(encryoFromJavascript); + } + + private static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv) + { + // Check arguments. + if (plainText == null || plainText.Length <= 0) + { + throw new ArgumentNullException("plainText"); + } + if (key == null || key.Length <= 0) + { + throw new ArgumentNullException("key"); + } + if (iv == null || iv.Length <= 0) + { + throw new ArgumentNullException("key"); + } + byte[] encrypted; + // Create a RijndaelManaged object + // with the specified key and IV. + using (var rijAlg = new RijndaelManaged()) + { + rijAlg.Mode = CipherMode.CBC; + rijAlg.Padding = PaddingMode.PKCS7; + rijAlg.FeedbackSize = 128; + + rijAlg.Key = key; + rijAlg.IV = iv; + + // Create a decrytor to perform the stream transform. + var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); + + // Create the streams used for encryption. + using (var msEncrypt = new MemoryStream()) + { + using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) + { + using (var swEncrypt = new StreamWriter(csEncrypt)) + { + //Write all data to the stream. + swEncrypt.Write(plainText); + } + encrypted = msEncrypt.ToArray(); + } + } + } + // Return the encrypted bytes from the memory stream. + return encrypted; + } + } +} diff --git a/Net.CrossCotting/Net.CrossCotting.csproj b/Net.CrossCotting/Net.CrossCotting.csproj new file mode 100644 index 0000000..4f28506 --- /dev/null +++ b/Net.CrossCotting/Net.CrossCotting.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/Net.CrossCotting/PageEventHelper.cs b/Net.CrossCotting/PageEventHelper.cs new file mode 100644 index 0000000..d4a9bd3 --- /dev/null +++ b/Net.CrossCotting/PageEventHelper.cs @@ -0,0 +1,84 @@ +using iTextSharp.text; +using iTextSharp.text.pdf; +using System; + +namespace Net.CrossCotting +{ + public class PageEventHelper : PdfPageEventHelper + { + // This is the contentbyte object of the writer + PdfContentByte cb; + // we will put the final number of pages in a template + PdfTemplate template; + + PdfTemplate templateHeader; + // this is the BaseFont we are going to use for the header / footer + BaseFont bf = null; + // This keeps track of the creation time + DateTime PrintTime = DateTime.Now; + + #region Properties + private string _Title; + public string Title + { + get { return _Title; } + set { _Title = value; } + } + #endregion + // we override the onOpenDocument method + public override void OnOpenDocument(PdfWriter writer, Document document) + { + try + { + PrintTime = DateTime.Now; + bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); + cb = writer.DirectContent; + template = cb.CreateTemplate(document.PageSize.Width, 80); + templateHeader = cb.CreateTemplate(document.PageSize.Width, 80); + } + catch (DocumentException) + { + } + catch (System.IO.IOException) + { + } + } + + public override void OnStartPage(PdfWriter writer, Document document) + { + base.OnStartPage(writer, document); + Rectangle pageSize = document.PageSize; + if (Title != string.Empty) + { + cb.BeginText(); + cb.SetFontAndSize(bf, 15); + cb.SetRgbColorFill(50, 50, 200); + cb.SetColorFill(new BaseColor(103, 93, 152)); + cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetTop(40)); + cb.ShowText(Title); + cb.EndText(); + } + } + + public override void OnEndPage(PdfWriter writer, Document document) + { + base.OnEndPage(writer, document); + int pageN = writer.PageNumber; + Rectangle pageSize = document.PageSize; + cb.SetRgbColorFill(100, 100, 100); + cb.BeginText(); + cb.SetFontAndSize(bf, 8); + cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30)); + cb.EndText(); + } + + public override void OnCloseDocument(PdfWriter writer, Document document) + { + base.OnCloseDocument(writer, document); + template.BeginText(); + template.SetFontAndSize(bf, 8); + template.SetTextMatrix(0, 0); + template.EndText(); + } + } +} diff --git a/Net.CrossCotting/ResultadoTransaccion.cs b/Net.CrossCotting/ResultadoTransaccion.cs new file mode 100644 index 0000000..6e5b4b4 --- /dev/null +++ b/Net.CrossCotting/ResultadoTransaccion.cs @@ -0,0 +1,58 @@ +using Net.Business.Entities; +using System.Collections.Generic; +using System.Net; + +namespace Net.CrossCotting +{ + public class ResultadoTransaccion + { + BE_ResultadoTransaccion _resultadoTransaccion = new BE_ResultadoTransaccion(); + + public ResultadoTransaccion(string NombreMetodo, string NombreAplicacion) + { + _resultadoTransaccion.MethodName = NombreMetodo; + _resultadoTransaccion.AppName = NombreAplicacion; + } + + public BE_ResultadoTransaccion GetInformacionResultado(int IdRegistro, int ResultadoCodigo, string ResultadoDescripcion, IEnumerable ListData) + { + _resultadoTransaccion.DocEntry = IdRegistro; + _resultadoTransaccion.StatusCode = ResultadoCodigo; + _resultadoTransaccion.Message = ResultadoDescripcion; + _resultadoTransaccion.ListData = ListData; + + return _resultadoTransaccion; + } + public BE_ResultadoTransaccion GetInformacionResultado(int DocEntry, string DocNum, string ResultadoDescripcion, T Data) + { + _resultadoTransaccion.DocEntry = DocEntry; + _resultadoTransaccion.DocNum = DocNum; + _resultadoTransaccion.StatusCode = (int)(HttpStatusCode.OK); + _resultadoTransaccion.Message = ResultadoDescripcion; + _resultadoTransaccion.Data = Data; + + return _resultadoTransaccion; + } + + public BE_ResultadoTransaccion GetInformacionResultado(string ResultadoDescripcion, T Data) + { + _resultadoTransaccion.DocEntry = null; + _resultadoTransaccion.StatusCode = (int)HttpStatusCode.InternalServerError; + _resultadoTransaccion.Message = ""; + _resultadoTransaccion.Error = ResultadoDescripcion; + _resultadoTransaccion.Data = Data; + + return _resultadoTransaccion; + } + + + public BE_ResultadoTransaccion GetInformacionResultado(int IdRegistro, int ResultadoCodigo, string ResultadoDescripcion) + { + _resultadoTransaccion.DocEntry = IdRegistro; + _resultadoTransaccion.StatusCode = ResultadoCodigo; + _resultadoTransaccion.Message = ResultadoDescripcion; + + return _resultadoTransaccion; + } + } +} diff --git a/Net.CrossCotting/Serializador.cs b/Net.CrossCotting/Serializador.cs new file mode 100644 index 0000000..efba803 --- /dev/null +++ b/Net.CrossCotting/Serializador.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Xml.Serialization; + +namespace Net.CrossCotting +{ + public class Serializador + { + #region xml + public bool SerializarXml(T entidad, Stream stm) + { + bool result = false; + try + { + XmlSerializer ser = new XmlSerializer(typeof(T)); + ser.Serialize(stm, entidad); + result = true; + } + catch (Exception) + { + + throw; + } + + return result; + } + + public T DeserializarXml(Stream entidad) where T : class + { + T result = null; + entidad.Position = 0; + XmlSerializer ser = new XmlSerializer(typeof(T)); + result = ser.Deserialize(entidad) as T; + return result; + } + + #endregion + #region binario + public bool SerializarBinario(T entidad, Stream stm) + { + bool result = false; + try + { + BinaryFormatter serilializador = new BinaryFormatter(); + serilializador.Serialize(stm, entidad); + result = true; + } + catch (Exception) + { + + throw; + } + return result; + } + public T DeserializarBinario(Stream entidad) where T : class + { + T Result = null; + try + { + entidad.Position = 0; + BinaryFormatter serializador = new BinaryFormatter(); + Result = serializador.Deserialize(entidad) as T; + + } + catch (Exception) + { + + throw; + } + return Result; + } + + + #endregion + #region json + + public bool SerializarJson(T entidad, Stream stm) + { + bool result = false; + try + { + // ReSharper disable once SuggestUseVarKeywordEvident + DataContractJsonSerializer jentidad = new DataContractJsonSerializer(typeof(T)); + jentidad.WriteObject(stm, entidad); + result = true; + } + catch (Exception) + { + + throw; + } + return result; + } + public T DeserializarJson(Stream entidad) where T : class + { + T result = null; + try + { + entidad.Position = 0; + DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); + + result = (T)ser.ReadObject(entidad); + } + catch (Exception) + { + + throw; + } + return result; + } + + #endregion + } +} diff --git a/Net.CrossCotting/Utils.cs b/Net.CrossCotting/Utils.cs new file mode 100644 index 0000000..f019b49 --- /dev/null +++ b/Net.CrossCotting/Utils.cs @@ -0,0 +1,65 @@ +using System; + +namespace Net.CrossCotting +{ + public class Utils + { + public static DateTime DateTimeEmpty() + { + return new DateTime(1, 1, 1, 0, 0, 0); + } + + public static DateTime GetFechaHoraInicioActual(DateTime? fecha) + { + DateTime? data; + + data = fecha; + + if (fecha == null || fecha.Equals(DateTimeEmpty())) + { + data = new DateTime(DateTime.Now.Year, 1, DateTime.Now.Day, 0, 0, 0); + } + else + { + data = new DateTime(((DateTime)fecha).Year, ((DateTime)fecha).Month, ((DateTime)fecha).Day, 0, 0, 0); + } + + return (DateTime)data; + } + + public static DateTime GetFechaHoraFinActual(DateTime? fecha) + { + DateTime? data; + + data = fecha; + + if (fecha == null || fecha.Equals(DateTimeEmpty())) + { + data = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59); + } + else + { + data = new DateTime(((DateTime)fecha).Year, ((DateTime)fecha).Month, ((DateTime)fecha).Day, 23, 59, 59); + } + + return (DateTime)data; + } + + public static string GenerarCodigoAleatorio() + { + Random obj = new Random(); + string sCadena = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + int longitud = sCadena.Length; + char cletra; + int nlongitud = 30; + string sNuevacadena = string.Empty; + + for (int i = 0; i < nlongitud; i++) + { + cletra = sCadena[obj.Next(nlongitud)]; + sNuevacadena += cletra.ToString(); + } + return sNuevacadena; + } + } +} diff --git a/Net.Data/Authenticate/AuthenticateRepository.cs b/Net.Data/Authenticate/AuthenticateRepository.cs new file mode 100644 index 0000000..fde184e --- /dev/null +++ b/Net.Data/Authenticate/AuthenticateRepository.cs @@ -0,0 +1,94 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.IdentityModel.Tokens; +using Net.Business.Entities; +using Net.Business.Entities.Authenticate; +using Net.Connection; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Net.Http; +using System.Security.Claims; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.Authenticate +{ + public class AuthenticateRepository : RepositoryBase, IAuthenticateRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + #endregion + + + public AuthenticateRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _aplicacionName = this.GetType().Name; + } + + public async Task> GetToken(BE_AuthenticateRequest value) + { + + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + return await Task.Run(() => + { + BE_AuthenticateResponse response = new BE_AuthenticateResponse(); + response.Type = "Bearer"; + + //=== OBTENEMOS LISTADO DE CLIENTES + var ls_entity_client = get_client(); + + //=== BUSCAMOS EXISTENCIA DEL CLIENTE + var result_client = ls_entity_client.FirstOrDefault(x => x.client_id == value.client_id); + if (result_client != null) + { + string semilla = "c071$@p*$b@.m0dul3"; + + var claims = new[] + { + new Claim("Usuario", result_client.client_secret) + }; + + //firma - header + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(semilla)); + var signCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + //generador de JWT + var token = new JwtSecurityToken( + issuer: "ARDICORD", + audience: "CUBICO", + claims: claims, + expires: DateTime.Now.AddHours(10), + signingCredentials: signCredentials + ); + + string tokenGenerado = new JwtSecurityTokenHandler().WriteToken(token); + response.Token = tokenGenerado; + return resultadoTransaccion.GetInformacionResultado(0, "", "", response); + } + else + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, "El usuario no tiene permiso"); + } + }); + + } + + public List get_client() + { + return new List() + { + new ModelCredential(){ client_secret = "YzBkZjU0ODY0NjY0NDAxN2FkOTdlMzhjMTIwNGRjMjk", client_id ="0HXoLsLmCIz05OjUwbqISz" }, + new ModelCredential(){ client_secret = "YzBkZjU0ODY0NjY0NDAxN2FkOTdlMzhjMTIwNGRjMjk", client_id ="0HXoLsLmCIz05OjUwbqISx" }, + new ModelCredential(){ client_secret = "XmTjrMQPeAOFwA3SoUUTKolohA9HfDVSijY66pOtSsJ", client_id ="rpDDCZBSsJRbQnejvULvn5" }, + }; + } + } +} diff --git a/Net.Data/Authenticate/IAuthenticateRepository.cs b/Net.Data/Authenticate/IAuthenticateRepository.cs new file mode 100644 index 0000000..a80ee5b --- /dev/null +++ b/Net.Data/Authenticate/IAuthenticateRepository.cs @@ -0,0 +1,15 @@ +using Net.Business.Entities; +using Net.Business.Entities.Authenticate; +using Net.Connection; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Net.Data.Authenticate +{ + public interface IAuthenticateRepository + { + Task> GetToken(BE_AuthenticateRequest value); + } +} diff --git a/Net.Data/DependencyInjection/IRepositoryWrapper.cs b/Net.Data/DependencyInjection/IRepositoryWrapper.cs new file mode 100644 index 0000000..80e966c --- /dev/null +++ b/Net.Data/DependencyInjection/IRepositoryWrapper.cs @@ -0,0 +1,49 @@ +using Net.Data.ServicesLayer; +using Net.Data.ServicesLayer.CreditNotes; +using Net.Data.Authenticate; +using Net.Data.ServicesLayer.ReturnRequest; +using Net.Data.ServicesLayer.StockTransfer; +using Net.Data.ServicesLayer.InventoryGenEntries; +using Net.Data.WMS.Items; +using Net.Data.WMS.Recibo; +using Net.Data.WMS.Picking; +using Net.Data.WMS.SolicitudTransferencia; +using Net.Data.WMS.Transferencia; +using Net.Data.WMS.Inventario; +using Net.Data.ServicesLayer.InventoryGenExits; +using Net.Data.ServicesLayer.HR; +using Net.Data.ServicesLayer.GlobalData; + +namespace Net.Data +{ + public interface IRepositoryWrapper + { + #region WMS + IReciboRepository Recibo { get; } + IInventarioRepository Inventario { get; } + ITransferenciaRepository Transferencia { get; } + IPickingRepository Picking { get; } + ISolicitudTransferenciaRepository SolicitudTransferencia { get; } + + #endregion + + #region SAP (SERVICES LAYER) + IBusinessPartnersRepository BusinessPartners { get; } + ICreditNotesRepository CreditNotes { get; } + IPurchaseInvoicesRepository PurchaseInvoices { get; } + IInvoiceRepository InvoiceRepository { get; } + IPurchaseDeliveryNotesRepository PurchaseDeliveryNotes { get; } + IPurchaseOrdersRepository PurchaseOrders { get; } + IAuthenticateRepository Authenticate { get; } + IItemsRepository Items { get; } + IReturnRequestRepository ReturnRequest { get; } + IStockTransferRepository StockTransfer { get; } + IInventoryGenEntriesRepository InventoryGenEntries { get; } + IInventoryGenExitsRepository InventoryGenExits { get; } + IHRRepository HR { get; } + IGlobalDataRepository GlobalData { get; } + + #endregion + + } +} diff --git a/Net.Data/DependencyInjection/RepositoryWrapper.cs b/Net.Data/DependencyInjection/RepositoryWrapper.cs new file mode 100644 index 0000000..7c8b14d --- /dev/null +++ b/Net.Data/DependencyInjection/RepositoryWrapper.cs @@ -0,0 +1,326 @@ +using Microsoft.Extensions.Configuration; +using Net.Connection; +using Net.CrossCotting; +using Net.Data.Authenticate; +using Net.Data.ServicesLayer; +using Net.Data.ServicesLayer.CreditNotes; +using Net.Data.ServicesLayer.GlobalData; +using Net.Data.ServicesLayer.HR; +using Net.Data.ServicesLayer.InventoryGenEntries; +using Net.Data.ServicesLayer.InventoryGenExits; +using Net.Data.ServicesLayer.ReturnRequest; +using Net.Data.ServicesLayer.StockTransfer; +using Net.Data.WMS.Inventario; +using Net.Data.WMS.Items; +using Net.Data.WMS.Picking; +using Net.Data.WMS.Recibo; +using Net.Data.WMS.SolicitudTransferencia; +using Net.Data.WMS.Transferencia; +using System; +using System.Net.Http; + +namespace Net.Data +{ + public class RepositoryWrapper : IRepositoryWrapper + { + #region Variables de conexion + private string _conSQL; + //private string _conSAPSQL; + + private readonly string _entorno; + private readonly string _Source; + private readonly string _Catalog; + private readonly string _User; + private readonly string _Password; + #endregion + + private IConnectionSQL _repoContext; + private readonly IConfiguration _configuration; + private readonly IHttpClientFactory _clientFactory; + + #region WMS + + private IReciboRepository _Recibo; + private ITransferenciaRepository _Transferencia; + private IStockTransferRepository _StockTransfer; + private IPickingRepository _Picking; + private IInventarioRepository _Inventario; + private ISolicitudTransferenciaRepository _SolicitudTransferencia; + + #endregion + + #region SAP (SERVICES LAYER) + + private IBusinessPartnersRepository _BusinessPartners; + private IPurchaseInvoicesRepository _PurchaseInvoices; + private IInvoiceRepository _Invoice; + private ICreditNotesRepository _CreditNotes; + private IAuthenticateRepository _AuthenticateRepository; + private IPurchaseDeliveryNotesRepository _PurchaseDeliveryNotes; + private IPurchaseOrdersRepository _PurchaseOrders; + private IItemsRepository _Items; + private IReturnRequestRepository _ReturnRequest; + private IInventoryGenEntriesRepository _InventoryGenEntries; + private IInventoryGenExitsRepository _InventoryGenExits; + private IHRRepository _HR; + private IGlobalDataRepository _GlobalData; + + #endregion + + + public RepositoryWrapper(IConnectionSQL repoContext, IConfiguration configuration, IHttpClientFactory clientFactory, IServiceProvider serviceProvider) + { + _repoContext = repoContext; + _configuration = configuration; + _clientFactory = clientFactory; + + #region Conexion CORS + _conSQL = configuration.GetConnectionString("cnnSql"); + + /*Obtenemos que ambiente realizaremos la conexión*/ + _entorno = configuration["EntornoConection:Entorno"]; + _Source = EncriptaHelper.DecryptStringAES(configuration[string.Format("{0}:Source", _entorno)]); + _Catalog = EncriptaHelper.DecryptStringAES(configuration[string.Format("{0}:Catalog", _entorno)]); + _User = EncriptaHelper.DecryptStringAES(configuration[string.Format("{0}:User", _entorno)]); + _Password = EncriptaHelper.DecryptStringAES(configuration[string.Format("{0}:Password", _entorno)]); + _conSQL = _conSQL.Replace("{Source}", _Source).Replace("{Catalog}", _Catalog).Replace("{User}", _User).Replace("{Password}", _Password); + #endregion + } + + #region WMS + public IReciboRepository Recibo + { + get + { + if (_Recibo == null) + { + _repoContext._cnx = _conSQL; + _Recibo = new ReciboRepository(_repoContext, _clientFactory, _configuration); + } + return _Recibo; + } + } + public ITransferenciaRepository Transferencia + { + get + { + if (_Transferencia == null) + { + _repoContext._cnx = _conSQL; + _Transferencia = new TransferenciaRepository(_repoContext, _clientFactory, _configuration); + } + return _Transferencia; + } + } + public IItemsRepository Items + { + get + { + if (_Items == null) + { + _repoContext._cnx = _conSQL; + _Items = new ItemsRepository(_repoContext, _clientFactory, _configuration); + } + return _Items; + } + } + public IPickingRepository Picking + { + get + { + if (_Picking == null) + { + _repoContext._cnx = _conSQL; + _Picking = new PickingRepository(_repoContext, _clientFactory, _configuration); + } + return _Picking; + } + } + public IInventarioRepository Inventario + { + get + { + if (_Inventario == null) + { + _repoContext._cnx = _conSQL; + _Inventario = new InventarioRepository(_repoContext, _clientFactory, _configuration); + } + return _Inventario; + } + } + public ISolicitudTransferenciaRepository SolicitudTransferencia + { + get + { + if (_SolicitudTransferencia == null) + { + _SolicitudTransferencia = new SolicitudTransferenciaRepository(_clientFactory, _configuration); + } + return _SolicitudTransferencia; + } + } + #endregion + + #region SAP (SERVICES LAYER) + public IBusinessPartnersRepository BusinessPartners + { + get + { + if (_BusinessPartners == null) + { + _repoContext._cnx = _conSQL; + _BusinessPartners = new BusinessPartnersRepository(_clientFactory, _configuration, _repoContext); + } + return _BusinessPartners; + } + } + public ICreditNotesRepository CreditNotes + { + get + { + if (_CreditNotes == null) + { + _repoContext._cnx = _conSQL; + _CreditNotes = new CreditNotesRepository(_clientFactory, _configuration, _repoContext); + + } + return _CreditNotes; + } + } + public IInvoiceRepository InvoiceRepository + { + get + { + if (_Invoice == null) + { + _repoContext._cnx = _conSQL; + _Invoice = new InvoiceRepository(_clientFactory, _configuration, _repoContext); + } + return _Invoice; + } + } + public IPurchaseInvoicesRepository PurchaseInvoices + { + get + { + if (_PurchaseInvoices == null) + { + _repoContext._cnx = _conSQL; + _PurchaseInvoices = new PurchaseInvoicesRepository(_clientFactory, _configuration); + } + return _PurchaseInvoices; + } + } + public IPurchaseDeliveryNotesRepository PurchaseDeliveryNotes + { + get + { + if (_PurchaseDeliveryNotes == null) + { + _repoContext._cnx = _conSQL; + _PurchaseDeliveryNotes = new PurchaseDeliveryNotesRepository(_clientFactory, _configuration); + } + return _PurchaseDeliveryNotes; + } + } + public IPurchaseOrdersRepository PurchaseOrders + { + get + { + if (_PurchaseOrders == null) + { + _repoContext._cnx = _conSQL; + _PurchaseOrders = new PurchaseOrdersRepository(_clientFactory, _configuration); + } + return _PurchaseOrders; + } + } + public IAuthenticateRepository Authenticate + { + get + { + if(_AuthenticateRepository == null) + { + _repoContext._cnx = _conSQL; + _AuthenticateRepository = new AuthenticateRepository(_repoContext, _clientFactory, _configuration); + } + return _AuthenticateRepository; + } + } + public IReturnRequestRepository ReturnRequest + { + get + { + if(_ReturnRequest == null) + { + _repoContext._cnx = _conSQL; + _ReturnRequest = new ReturnRequestRepository(_clientFactory, _configuration); + } + return _ReturnRequest; + } + } + public IStockTransferRepository StockTransfer + { + get + { + if (_StockTransfer == null) + { + _repoContext._cnx = _conSQL; + _StockTransfer = new StockTransferRepository(_clientFactory, _configuration); + } + return _StockTransfer; + } + } + public IInventoryGenEntriesRepository InventoryGenEntries + { + get + { + if (_InventoryGenEntries == null) + { + _repoContext._cnx = _conSQL; + _InventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, _repoContext); + } + return _InventoryGenEntries; + } + } + public IInventoryGenExitsRepository InventoryGenExits + { + get + { + if (_InventoryGenExits == null) + { + _repoContext._cnx = _conSQL; + _InventoryGenExits = new InventoryGenExitsRepository(_clientFactory, _configuration, _repoContext); + } + return _InventoryGenExits; + } + } + + public IHRRepository HR + { + get + { + if (_HR == null) + { + _repoContext._cnx = _conSQL; + _HR = new HRRepository(_clientFactory, _configuration, _repoContext); + } + return _HR; + } + } + + public IGlobalDataRepository GlobalData + { + get + { + if (_GlobalData == null) + { + _repoContext._cnx = _conSQL; + _GlobalData = new GlobalDataRepository(_clientFactory, _configuration, _repoContext); + } + return _GlobalData; + } + } + #endregion + } +} diff --git a/Net.Data/HelperData/Correlativo/HelperCorrelativo.cs b/Net.Data/HelperData/Correlativo/HelperCorrelativo.cs new file mode 100644 index 0000000..578bddc --- /dev/null +++ b/Net.Data/HelperData/Correlativo/HelperCorrelativo.cs @@ -0,0 +1,35 @@ +using Sap.Data.Hana; +using System; +using System.Data; + +namespace Net.Data.HelperData.Correlativo +{ + public class HelperCorrelativo + { + public static string Get(string Serie) + { + DataTable dt = new DataTable(); + string Cuenta = ""; + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"SELECT \"U_SYP_NDCD\" FROM \"{LocalData.Schema}\".\"@SYP_NUMDOC\" WHERE \"Code\" = '07' AND \"U_SYP_NDSD\" = ?", con); + cmd.Parameters.Add("Serie", HanaDbType.VarChar).Value = Serie ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + Cuenta = (dt.Rows[x]["U_SYP_NDCD"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_SYP_NDCD"]) : string.Empty; + } + + return Cuenta; + } + } +} + diff --git a/Net.Data/HelperData/HelperDB.cs b/Net.Data/HelperData/HelperDB.cs new file mode 100644 index 0000000..a863b54 --- /dev/null +++ b/Net.Data/HelperData/HelperDB.cs @@ -0,0 +1,27 @@ +using Sap.Data.Hana; +using System.Data; + +namespace Net.Data.HelperData +{ + public class HelperDB + { + public static void SET(string query) + { + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand + { + CommandText = query, + Connection = con, + CommandType = CommandType.Text + }; + cmd.ExecuteNonQuery(); + + con.Close(); + } + } + + + } +} diff --git a/Net.Data/HelperData/HojaRuta/HelperHojaRuta.cs b/Net.Data/HelperData/HojaRuta/HelperHojaRuta.cs new file mode 100644 index 0000000..67a7c09 --- /dev/null +++ b/Net.Data/HelperData/HojaRuta/HelperHojaRuta.cs @@ -0,0 +1,97 @@ +using Net.Business.Entities.ServicesLayer.HR; +using Net.Business.Entities.ServicesLayer.Items; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Data; + +namespace Net.Data.HelperData.HojaRuta +{ + public class HelperHojaRuta + { + public static List Get(int DocEntry) + { + List ListaStock = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITC_GetDataDetalleHR\"(?)", con); + cmd.Parameters.Add("DocEntry", HanaDbType.VarChar).Value = DocEntry.ToString(); + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + ListaStock.Add(new HojaRutaDetailsEntities() + { + U_ARD_PHR_DIRDESP = (dt.Rows[x]["U_ARD_PHR_DIRDESP"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_DIRDESP"]) : string.Empty, + U_ARD_PHR_FEENPED = (dt.Rows[x]["U_ARD_PHR_FEENPED"] != DBNull.Value) ? Convert.ToDateTime(dt.Rows[x]["U_ARD_PHR_FEENPED"]) : DateTime.Now, + U_ARD_PHR_FORPAG = (dt.Rows[x]["U_ARD_PHR_FORPAG"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_FORPAG"]) : string.Empty, + U_ARD_PHR_MONED = (dt.Rows[x]["U_ARD_PHR_MONED"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_MONED"]) : string.Empty, + U_ARD_PHR_NOMCLI = (dt.Rows[x]["U_ARD_PHR_NOMCLI"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_NOMCLI"]) : string.Empty, + U_ARD_PHR_NROFACT = (dt.Rows[x]["U_ARD_PHR_NROFACT"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_NROFACT"]) : string.Empty, + U_ARD_PHR_NROGRE = (dt.Rows[x]["U_ARD_PHR_NROGRE"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_NROGRE"]) : string.Empty, + U_ARD_PHR_NROPED = (dt.Rows[x]["U_ARD_PHR_NROPED"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_NROPED"]) : string.Empty, + U_ARD_PHR_RUCCLI = (dt.Rows[x]["U_ARD_PHR_RUCCLI"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_RUCCLI"]) : string.Empty, + U_ARD_PHR_TERRIT = (dt.Rows[x]["U_ARD_PHR_TERRIT"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_TERRIT"]) : string.Empty, + U_ARD_PHR_TOTALPD = (dt.Rows[x]["U_ARD_PHR_TOTALPD"] != DBNull.Value) ? Convert.ToDecimal(dt.Rows[x]["U_ARD_PHR_TOTALPD"]) : 0, + U_ARD_PHR_ZONA = (dt.Rows[x]["U_ARD_PHR_ZONA"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ARD_PHR_ZONA"]) : string.Empty, + U_ARD_TOTALFC = (dt.Rows[x]["U_ARD_TOTALFC"] != DBNull.Value) ? Convert.ToDecimal(dt.Rows[x]["U_ARD_TOTALFC"]) : 0, + U_ITC_PHR_NOMVEN = (dt.Rows[x]["U_ITC_PHR_NOMVEN"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITC_PHR_NOMVEN"]) : string.Empty, + U_MSV_PKH_CGUI = (dt.Rows[x]["U_MSV_PKH_CGUI"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_MSV_PKH_CGUI"]) : string.Empty, + U_MSV_PKH_DCPE = (dt.Rows[x]["U_MSV_PKH_DCPE"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_MSV_PKH_DCPE"]) : string.Empty, + U_MSV_PKH_DGRE = (dt.Rows[x]["U_MSV_PKH_DGRE"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_MSV_PKH_DGRE"]) : string.Empty, + U_MSV_PKH_DORV = (dt.Rows[x]["U_MSV_PKH_DORV"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_MSV_PKH_DORV"]) : string.Empty, + U_MSV_PKH_PEOV = (dt.Rows[x]["U_MSV_PKH_PEOV"] != DBNull.Value) ? Convert.ToInt32(dt.Rows[x]["U_MSV_PKH_PEOV"]) : 0, + U_MSV_PKH_APLG = (dt.Rows[x]["U_MSV_PKH_APLG"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_MSV_PKH_APLG"]) : string.Empty, + }); + } + + return ListaStock; + } + + + public static List GetConsolidado(string ItemCode, string FromWarehouseCode) + { + List ListaStock = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_WMS_SAP_GetStockConsolidado\"(?, ?)", con); + cmd.Parameters.Add("ItemCode", HanaDbType.VarChar).Value = ItemCode ?? ""; + cmd.Parameters.Add("FromWarehouseCode", HanaDbType.VarChar).Value = FromWarehouseCode ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + ListaStock.Add(new BE_ItemStock() + { + BinCode = (dt.Rows[x]["BinCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["BinCode"]) : string.Empty, + DistNumber = (dt.Rows[x]["DistNumber"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["DistNumber"]) : string.Empty, + ExpDate = (dt.Rows[x]["ExpDate"] != DBNull.Value) ? Convert.ToDateTime(dt.Rows[x]["ExpDate"]) : DateTime.Now, + ItemCode = (dt.Rows[x]["ItemCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemCode"]) : string.Empty, + ItemName = (dt.Rows[x]["ItemName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemName"]) : string.Empty, + OnHandQty = (dt.Rows[x]["OnHandQty"] != DBNull.Value) ? Convert.ToDouble(dt.Rows[x]["OnHandQty"]) : 0, + WhsCode = (dt.Rows[x]["WhsCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsCode"]) : string.Empty, + WhsName = (dt.Rows[x]["WhsName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsName"]) : string.Empty, + AvgPrice = (dt.Rows[x]["AvgPrice"] != DBNull.Value) ? Convert.ToDouble(dt.Rows[x]["AvgPrice"]) : 0, + }); + } + + return ListaStock; + } + } +} diff --git a/Net.Data/HelperData/Inventario/HelperInventario.cs b/Net.Data/HelperData/Inventario/HelperInventario.cs new file mode 100644 index 0000000..c64b8e1 --- /dev/null +++ b/Net.Data/HelperData/Inventario/HelperInventario.cs @@ -0,0 +1,34 @@ +using Sap.Data.Hana; +using System; +using System.Data; + +namespace Net.Data.HelperData.Inventario +{ + public class HelperInventario + { + public static string Get(string TipoMovimiento) + { + DataTable dt = new DataTable(); + string Cuenta = ""; + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_GetAccountCode_TipoEntradaSalida\"(?)", con); + cmd.Parameters.Add("TipoMovimiento", HanaDbType.VarChar).Value = TipoMovimiento ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + Cuenta = (dt.Rows[x]["U_Cuenta"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_Cuenta"]) : string.Empty; + } + + return Cuenta; + } + } +} diff --git a/Net.Data/HelperData/Invoices/HelperInvoice.cs b/Net.Data/HelperData/Invoices/HelperInvoice.cs new file mode 100644 index 0000000..1251f3c --- /dev/null +++ b/Net.Data/HelperData/Invoices/HelperInvoice.cs @@ -0,0 +1,34 @@ +using Sap.Data.Hana; +using System; +using System.Data; + +namespace Net.Data.HelperData.Invoices +{ + public class HelperInvoice + { + public static int Get(string DocNum) + { + DataTable dt = new DataTable(); + int DocEntry = 0; + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_WMS_SAP_GetEntradaPorImportacion\"(?)", con); + cmd.Parameters.Add("DocNum", HanaDbType.VarChar).Value = DocNum ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + DocEntry = (dt.Rows[x]["DocEntry"] != DBNull.Value) ? Convert.ToInt32(dt.Rows[x]["DocEntry"]) : 0; + } + + return DocEntry; + } + } +} diff --git a/Net.Data/HelperData/ProcesoPermitidos/HelperProcesoPermitido.cs b/Net.Data/HelperData/ProcesoPermitidos/HelperProcesoPermitido.cs new file mode 100644 index 0000000..c94fad7 --- /dev/null +++ b/Net.Data/HelperData/ProcesoPermitidos/HelperProcesoPermitido.cs @@ -0,0 +1,106 @@ +using Net.Business.Entities.WMS.ProcesoPicking; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Data; + +namespace Net.Data.HelperData.HelperProcesoPermitido +{ + public class HelperProcesoPermitido + { + public static int Get(string Proceso, int IdEstado, string Endpoint, out List ListaProceso) + { + List list = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"SELECT * FROM \"{LocalData.Schema}\".\"@ITCA_PROWMS\" WHERE \"U_ITCA_PROCESO\" = ? AND \"U_ITCA_ESTADO\" = ? AND \"U_ITCA_ENDPOINT\" = ?", con); + cmd.Parameters.Add("Proceso", HanaDbType.VarChar).Value = (Proceso ?? "").ToUpper(); + cmd.Parameters.Add("IdEstado", HanaDbType.VarChar).Value = IdEstado.ToString(); + cmd.Parameters.Add("Endpoint", HanaDbType.VarChar).Value = Endpoint ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + list.Add(new BE_ProcesoPicking() + { + Code = (dt.Rows[x]["Code"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["Code"]) : string.Empty, + U_ITCA_ESTADO = (dt.Rows[x]["U_ITCA_ESTADO"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITCA_ESTADO"]) : string.Empty, + U_ITCA_GNRPROC = (dt.Rows[x]["U_ITCA_GNRPROC"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITCA_GNRPROC"]) : string.Empty, + U_ITCA_PROCESO = (dt.Rows[x]["U_ITCA_PROCESO"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITCA_PROCESO"]) : string.Empty, + }); + } + con.Close(); + } + ListaProceso = list; + return dt.Rows.Count; + } + + public static string GetMotivoAlmacen(string CodEstado, out bool Reproceso, out string MotivoNotaCredito, out string DescripcionMotivo) + { + string Almacen = ""; + Reproceso = false; + MotivoNotaCredito = ""; + DescripcionMotivo = ""; + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"SELECT * FROM \"{LocalData.Schema}\".\"@SYP_MOTIVOS\" WHERE \"Code\" = ?", con); + cmd.Parameters.Add("Code", HanaDbType.VarChar).Value = (CodEstado ?? "").ToUpper(); + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + Reproceso = (dt.Rows[x]["U_ITC_WMS_RPG"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITC_WMS_RPG"]) == "Y" : false; + Almacen = (dt.Rows[x]["U_ITC_WMS_WHS"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_ITC_WMS_WHS"]) : string.Empty; + MotivoNotaCredito = (dt.Rows[x]["U_SYP_CODMO"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["U_SYP_CODMO"]) : string.Empty; + DescripcionMotivo = (dt.Rows[x]["Name"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["Name"]) : string.Empty; + } + con.Close(); + } + return Almacen; + } + + public static int? ConvertTimeToSeconds(string timeString) + { + string[] parts = timeString.Split(':'); + if (parts.Length != 3) + { + return null; + } + + int hours = int.Parse(parts[0]); + int minutes = int.Parse(parts[1]); + int seconds = int.Parse(parts[2]); + + return (hours * 3600) + (minutes * 60) + seconds; + } + + public static int? ConvertTimeToInteger(string timeString) + { + // Split the time string into hours and minutes + string[] parts = timeString.Split(':'); + if (parts.Length == 1) + { + return null; + } + int hours = int.Parse(parts[0]); + int minutes = int.Parse(parts[1]); + + // Combine hours and minutes into a single integer (e.g., 10:30 becomes 1030) + int result = (hours * 100) + minutes; + return result; + } + + } +} diff --git a/Net.Data/HelperData/ProcesoPiciking/HelperProcesoPiciking.cs b/Net.Data/HelperData/ProcesoPiciking/HelperProcesoPiciking.cs new file mode 100644 index 0000000..8711109 --- /dev/null +++ b/Net.Data/HelperData/ProcesoPiciking/HelperProcesoPiciking.cs @@ -0,0 +1,54 @@ +using Sap.Data.Hana; +using System.Data; + +namespace Net.Data.HelperData.HelperProcesoPermitido +{ + public class HelperProcesoPiciking + { + public static void Set(string Proceso, int IdEstado, int DocEntry, string CodMotivo, string Code) + { + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand(); + // Parametrizado (antes interpolaba el string directo - SQL injection + // real, ver docs/PORTE_FUNCIONALIDAD_NUEVA.md hallazgo #6): Proceso y + // CodMotivo vienen del body del request HTTP sin validar. + cmd.CommandText = $"CALL \"{LocalData.Schema}\".\"ITCA_WMS_SAP_SetProcesoPicking\"(?, ?, ?, ?, ?, ?, ?)"; + cmd.Parameters.Add("Proceso", HanaDbType.VarChar).Value = Proceso; + cmd.Parameters.Add("IdEstado", HanaDbType.Integer).Value = IdEstado; + cmd.Parameters.Add("DocEntry", HanaDbType.Integer).Value = DocEntry; + cmd.Parameters.Add("HoraInicio", HanaDbType.VarChar).Value = ""; + cmd.Parameters.Add("HoraFin", HanaDbType.VarChar).Value = ""; + cmd.Parameters.Add("CodMotivo", HanaDbType.VarChar).Value = CodMotivo; + cmd.Parameters.Add("Code", HanaDbType.VarChar).Value = Code; + cmd.CommandType = System.Data.CommandType.Text; + cmd.Connection = con; + cmd.ExecuteNonQuery(); + con.Close(); + } + } + + public static void Set(string Proceso, int IdEstado, int DocEntry, int? HoraInicio, int? HoraFin, string CodMotivo, string Code) + { + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand(); + // Ver nota de parametrizacion en la sobrecarga de arriba. + cmd.CommandText = $"CALL \"{LocalData.Schema}\".\"ITCA_WMS_SAP_SetProcesoPicking\"(?, ?, ?, ?, ?, ?, ?)"; + cmd.Parameters.Add("Proceso", HanaDbType.VarChar).Value = Proceso; + cmd.Parameters.Add("IdEstado", HanaDbType.Integer).Value = IdEstado; + cmd.Parameters.Add("DocEntry", HanaDbType.Integer).Value = DocEntry; + cmd.Parameters.Add("HoraInicio", HanaDbType.VarChar).Value = HoraInicio?.ToString() ?? ""; + cmd.Parameters.Add("HoraFin", HanaDbType.VarChar).Value = HoraFin?.ToString() ?? ""; + cmd.Parameters.Add("CodMotivo", HanaDbType.VarChar).Value = CodMotivo; + cmd.Parameters.Add("Code", HanaDbType.VarChar).Value = Code; + cmd.CommandType = System.Data.CommandType.Text; + cmd.Connection = con; + cmd.ExecuteNonQuery(); + con.Close(); + } + } + } +} diff --git a/Net.Data/HelperData/Stock/HelperStock.cs b/Net.Data/HelperData/Stock/HelperStock.cs new file mode 100644 index 0000000..a3be4fe --- /dev/null +++ b/Net.Data/HelperData/Stock/HelperStock.cs @@ -0,0 +1,85 @@ +using Net.Business.Entities.ServicesLayer.Items; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Data; + +namespace Net.Data.HelperData.Stock +{ + public class HelperStock + { + public static List Get(string ItemCode, string FromWarehouseCode) + { + List ListaStock = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_WMS_SAP_GetStock\"(?, ?)", con); + cmd.Parameters.Add("ItemCode", HanaDbType.VarChar).Value = ItemCode ?? ""; + cmd.Parameters.Add("FromWarehouseCode", HanaDbType.VarChar).Value = FromWarehouseCode ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + ListaStock.Add(new BE_ItemStock() + { + BinCode = (dt.Rows[x]["BinCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["BinCode"]) : string.Empty, + DistNumber = (dt.Rows[x]["DistNumber"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["DistNumber"]) : string.Empty, + ExpDate = (dt.Rows[x]["ExpDate"] != DBNull.Value) ? Convert.ToDateTime(dt.Rows[x]["ExpDate"]) : DateTime.Now, + ItemCode = (dt.Rows[x]["ItemCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemCode"]) : string.Empty, + ItemName = (dt.Rows[x]["ItemName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemName"]) : string.Empty, + OnHandQty = (dt.Rows[x]["OnHandQty"] != DBNull.Value) ? Convert.ToDouble(dt.Rows[x]["OnHandQty"]) : 0, + WhsCode = (dt.Rows[x]["WhsCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsCode"]) : string.Empty, + WhsName = (dt.Rows[x]["WhsName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsName"]) : string.Empty, + }); + } + + return ListaStock; + } + + + public static List GetConsolidado(string ItemCode, string FromWarehouseCode) + { + List ListaStock = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_WMS_SAP_GetStockConsolidado\"(?, ?)", con); + cmd.Parameters.Add("ItemCode", HanaDbType.VarChar).Value = ItemCode ?? ""; + cmd.Parameters.Add("FromWarehouseCode", HanaDbType.VarChar).Value = FromWarehouseCode ?? ""; + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + con.Close(); + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + ListaStock.Add(new BE_ItemStock() + { + BinCode = (dt.Rows[x]["BinCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["BinCode"]) : string.Empty, + DistNumber = (dt.Rows[x]["DistNumber"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["DistNumber"]) : string.Empty, + ExpDate = (dt.Rows[x]["ExpDate"] != DBNull.Value) ? Convert.ToDateTime(dt.Rows[x]["ExpDate"]) : DateTime.Now, + ItemCode = (dt.Rows[x]["ItemCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemCode"]) : string.Empty, + ItemName = (dt.Rows[x]["ItemName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["ItemName"]) : string.Empty, + OnHandQty = (dt.Rows[x]["OnHandQty"] != DBNull.Value) ? Convert.ToDouble(dt.Rows[x]["OnHandQty"]) : 0, + WhsCode = (dt.Rows[x]["WhsCode"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsCode"]) : string.Empty, + WhsName = (dt.Rows[x]["WhsName"] != DBNull.Value) ? Convert.ToString(dt.Rows[x]["WhsName"]) : string.Empty, + AvgPrice = (dt.Rows[x]["AvgPrice"] != DBNull.Value) ? Convert.ToDouble(dt.Rows[x]["AvgPrice"]) : 0, + }); + } + + return ListaStock; + } + } +} diff --git a/Net.Data/LocalData.cs b/Net.Data/LocalData.cs new file mode 100644 index 0000000..bca0337 --- /dev/null +++ b/Net.Data/LocalData.cs @@ -0,0 +1,37 @@ +using Microsoft.Extensions.Configuration; +using System; + +namespace Net.Data +{ + public class LocalData + { + public static string ConnectionString { get; private set; } + + // Esquema HANA: por defecto la compañia del Service Layer (SapServiceLayer:company) + public static string Schema { get; private set; } + + // Unico punto de lectura de las credenciales HANA (seccion "Hana" de appsettings.json) + public static void Configure(IConfiguration configuration) + { + var server = configuration["Hana:server"]; + var user = configuration["Hana:user"]; + var password = configuration["Hana:password"]; + + if (string.IsNullOrWhiteSpace(server) || string.IsNullOrWhiteSpace(user) || string.IsNullOrEmpty(password)) + { + throw new InvalidOperationException("Falta la seccion \"Hana\" (server, user, password) en appsettings.json"); + } + + ConnectionString = $"Server={server};UserName={user};Password={password}"; + + var schema = configuration["Hana:schema"]; + if (string.IsNullOrWhiteSpace(schema)) schema = configuration["SapServiceLayer:company"]; + if (string.IsNullOrWhiteSpace(schema)) + { + throw new InvalidOperationException("Falta el esquema HANA: configure Hana:schema o SapServiceLayer:company en appsettings.json"); + } + + Schema = schema; + } + } +} diff --git a/Net.Data/Net.Data.csproj b/Net.Data/Net.Data.csproj new file mode 100644 index 0000000..cb5541c --- /dev/null +++ b/Net.Data/Net.Data.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + ..\..\..\..\..\..\..\..\Program Files\sap\hdbclient\dotnetcore\v2.1\Sap.Data.Hana.Core.v2.1.dll + + + + diff --git a/Net.Data/ServicesLayer/BusinessPartners/BusinessPartnersRepository.cs b/Net.Data/ServicesLayer/BusinessPartners/BusinessPartnersRepository.cs new file mode 100644 index 0000000..f0049c7 --- /dev/null +++ b/Net.Data/ServicesLayer/BusinessPartners/BusinessPartnersRepository.cs @@ -0,0 +1,78 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.Constantes; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public class BusinessPartnersRepository : IBusinessPartnersRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + #endregion + + public BusinessPartnersRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + } + + + public async Task> GetBusinessPartnersByFilter(FE_BusinessPartners entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + string select = "select= CardCode, CardName,CardType, FederalTaxID,Address,EmailAddress,Phone1"; + + entidad.CardCode = string.IsNullOrEmpty(entidad.CardCode) ? string.Empty : entidad.CardCode; + entidad.CardName = string.IsNullOrEmpty(entidad.CardName) ? string.Empty : entidad.CardName; + entidad.FederalTaxID = string.IsNullOrEmpty(entidad.FederalTaxID) ? string.Empty : entidad.FederalTaxID; + + string cadena = string.Empty; + + if (!string.IsNullOrEmpty(entidad.CardCode)) + { + cadena = string.Format("{0}?$filter = Valid eq 'tYES' and CardCode eq '{1}' &${2}", StoreProcedure.SP_SERVICES_LAYER_BUSINESSPARTNERS, entidad.CardCode, select); + } + + if (!string.IsNullOrEmpty(entidad.CardName)) + { + cadena = string.Format("{0}?$filter = Valid eq 'tYES' and CardName eq '{1}' &${2}", StoreProcedure.SP_SERVICES_LAYER_BUSINESSPARTNERS, entidad.CardName, select); + } + + if (!string.IsNullOrEmpty(entidad.FederalTaxID)) + { + cadena = string.Format("{0}?$filter = Valid eq 'tYES' and FederalTaxID eq '{1}' &${2}", StoreProcedure.SP_SERVICES_LAYER_BUSINESSPARTNERS, entidad.FederalTaxID, select); + } + + int maxpagesize = 0; + List objectList = await _connectServiceLayer.GetAsync(cadena, maxpagesize); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", objectList); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} \ No newline at end of file diff --git a/Net.Data/ServicesLayer/BusinessPartners/IBusinessPartnersRepository.cs b/Net.Data/ServicesLayer/BusinessPartners/IBusinessPartnersRepository.cs new file mode 100644 index 0000000..ba8440d --- /dev/null +++ b/Net.Data/ServicesLayer/BusinessPartners/IBusinessPartnersRepository.cs @@ -0,0 +1,11 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public interface IBusinessPartnersRepository + { + Task> GetBusinessPartnersByFilter(FE_BusinessPartners entidad); + } +} \ No newline at end of file diff --git a/Net.Data/ServicesLayer/CreditNotes/CreditNotesRepository.cs b/Net.Data/ServicesLayer/CreditNotes/CreditNotesRepository.cs new file mode 100644 index 0000000..118c63b --- /dev/null +++ b/Net.Data/ServicesLayer/CreditNotes/CreditNotesRepository.cs @@ -0,0 +1,92 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.CreditNotes +{ + public class CreditNotesRepository : ICreditNotesRepository + { + + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + #endregion + + public CreditNotesRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + } + + public async Task> SetCreateCreditNotes(BE_CreditNotesNotes entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + //var cadena = "Drafts"; + var cadena = "CreditNotes"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + public async Task> UpdateCreateCreditNotes(dynamic entidad, int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + //var cadena = "Drafts"; + var cadena = $"CreditNotes({DocEntry})"; + var data = await _connectServiceLayer.PatchAsyncSBA(cadena, entidad); + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + + } +} diff --git a/Net.Data/ServicesLayer/CreditNotes/ICreditNotesRepository.cs b/Net.Data/ServicesLayer/CreditNotes/ICreditNotesRepository.cs new file mode 100644 index 0000000..35ddc78 --- /dev/null +++ b/Net.Data/ServicesLayer/CreditNotes/ICreditNotesRepository.cs @@ -0,0 +1,13 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.CreditNotes +{ + public interface ICreditNotesRepository + { + Task> SetCreateCreditNotes(BE_CreditNotesNotes entidad); + + } +} diff --git a/Net.Data/ServicesLayer/GlobalData/GlobalDataRepository.cs b/Net.Data/ServicesLayer/GlobalData/GlobalDataRepository.cs new file mode 100644 index 0000000..e77510b --- /dev/null +++ b/Net.Data/ServicesLayer/GlobalData/GlobalDataRepository.cs @@ -0,0 +1,83 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.HR; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using Net.Data.HelperData.HojaRuta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.GlobalData +{ + public class GlobalDataRepository : IGlobalDataRepository + { + + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + #endregion + + public GlobalDataRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + } + + public async Task> GetSolicitudSalida(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + try + { + + string cadena = $"ITC_SOLSALMER({DocEntry})"; + int maxpagesize = 0; + List objectList = await _connectServiceLayer.GetAsync(cadena, maxpagesize, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", objectList); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + public async Task> GetSolicitudIngreso(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + try + { + + string cadena = $"ITC_SOLINGMER({DocEntry})"; + int maxpagesize = 0; + List objectList = await _connectServiceLayer.GetAsync(cadena, maxpagesize, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", objectList); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/GlobalData/IGlobalDataRepository.cs b/Net.Data/ServicesLayer/GlobalData/IGlobalDataRepository.cs new file mode 100644 index 0000000..c51f4de --- /dev/null +++ b/Net.Data/ServicesLayer/GlobalData/IGlobalDataRepository.cs @@ -0,0 +1,15 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.HR; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.GlobalData +{ + public interface IGlobalDataRepository + { + Task> GetSolicitudSalida(int DocEntry); + Task> GetSolicitudIngreso(int DocEntry); + + } +} diff --git a/Net.Data/ServicesLayer/HR/HRRepository.cs b/Net.Data/ServicesLayer/HR/HRRepository.cs new file mode 100644 index 0000000..4b2d599 --- /dev/null +++ b/Net.Data/ServicesLayer/HR/HRRepository.cs @@ -0,0 +1,146 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.HR; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using Net.Data.HelperData.HojaRuta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.HR +{ + public class HRRepository : IHRRepository + { + + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + #endregion + + public HRRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + } + + public async Task> SetCreateHojaRuta(BE_HojaRutaCreate entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + int Indice = 1; + List detalle = new List(); + entidad.Detalle.ForEach(item => + { + var data = HelperHojaRuta.Get(Convert.ToInt32(item.CodigoInterno)); + var linea = data.FirstOrDefault(); + linea.LineId = Indice; + detalle.Add(linea); + + Indice++; + }); + + HojaRutaSAP HojaRuta = new HojaRutaSAP() + { + ARD_PCK_HJRT_DETCollection = new List(), + U_ARD_PHR_PLACA = entidad.PlacaVehiculo, + U_ARD_PHR_TERRI = entidad.Territorio, + U_ARD_PHR_ZONDIS = entidad.Zona, + U_ARD_PHR_FECCRE = entidad.FechaDespacho, + U_ARD_PHR_MODTRANSP = entidad.ModalidadTransporte, + U_ARD_PHR_NOMDESP = entidad.Despachador, + U_ARD_PHR_ESTDESP = "Embarcado", + U_ARD_PHR_RUCAGENTRANS = entidad.AgenciaTransporte, + U_ARD_PHR_LICCON = entidad.LicenciaConductor, + U_MSV_PKH_ORIG = "Y", + U_ARD_PHR_CNTDOC = entidad.Detalle.Count() + }; + + //if(entidad.ModalidadTransporte == "Privado") + //{ + // HojaRuta = new HojaRutaSAP() + // { + // ARD_PCK_HJRT_DETCollection = new List(), + // U_ARD_PHR_PLACA = entidad.PlacaVehiculo, + // U_ARD_PHR_TERRI = entidad.Territorio, + // U_ARD_PHR_ZONDIS = entidad.Zona, + // U_ARD_PHR_FECCRE = entidad.FechaDespacho, + // U_ARD_PHR_MODTRANSP = entidad.ModalidadTransporte, + // U_ARD_PHR_NOMDESP = entidad.Despachador, + // U_ARD_PHR_NOMAGENTRANS = "ARDICORP S.A.C.", + // U_ARD_PHR_CODAGENTRANS = "P20136836545", + // U_ARD_PHR_RUCAGENTRANS = "20136836545", + // U_ARD_PHR_ESTDESP = "Embarcado" + // }; + //} + //else + //{ + + //} + + HojaRuta.ARD_PCK_HJRT_DETCollection = detalle; + + var cadena = "ARD_PHR"; + var data = await _connectServiceLayer.PostAsync(cadena, HojaRuta); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(data.Mensaje.ToString(), entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)data.DocEntry, data.DocNum.ToString(), "Se Listo correctamento...!!!", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message, entidad); + } + } + + + public async Task> UpdateCreateCreditNotes(dynamic entidad, int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + //var cadena = "Drafts"; + var cadena = $"CreditNotes({DocEntry})"; + var data = await _connectServiceLayer.PatchAsyncSBA(cadena, entidad); + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + + } +} diff --git a/Net.Data/ServicesLayer/HR/IHRRepository.cs b/Net.Data/ServicesLayer/HR/IHRRepository.cs new file mode 100644 index 0000000..8a445ca --- /dev/null +++ b/Net.Data/ServicesLayer/HR/IHRRepository.cs @@ -0,0 +1,14 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.HR; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.HR +{ + public interface IHRRepository + { + Task> SetCreateHojaRuta(BE_HojaRutaCreate entidad); + + } +} diff --git a/Net.Data/ServicesLayer/InventoryGenEntries/IInventoryGenEntriesRepository.cs b/Net.Data/ServicesLayer/InventoryGenEntries/IInventoryGenEntriesRepository.cs new file mode 100644 index 0000000..1958281 --- /dev/null +++ b/Net.Data/ServicesLayer/InventoryGenEntries/IInventoryGenEntriesRepository.cs @@ -0,0 +1,13 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using System.Threading.Tasks; + + +namespace Net.Data.ServicesLayer.InventoryGenEntries +{ + public interface IInventoryGenEntriesRepository + { + Task> SetCreateInventoryGenEntries(BE_InventoryGenEntries entidad, bool Drafts = true); + } +} diff --git a/Net.Data/ServicesLayer/InventoryGenEntries/InventoryGenEntriesRepository.cs b/Net.Data/ServicesLayer/InventoryGenEntries/InventoryGenEntriesRepository.cs new file mode 100644 index 0000000..fc0d8c0 --- /dev/null +++ b/Net.Data/ServicesLayer/InventoryGenEntries/InventoryGenEntriesRepository.cs @@ -0,0 +1,67 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.InventoryGenEntries +{ + public class InventoryGenEntriesRepository : IInventoryGenEntriesRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + + public InventoryGenEntriesRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + //Inicializamos los servicios de services layer + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + _clientFactory = clientFactory; + _configuration = configuration; + + } + + // VENTAS PARA SAP + + public async Task> SetCreateInventoryGenEntries(BE_InventoryGenEntries entidad, bool Draft = true) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = Draft ? "Drafts" : "InventoryGenEntries"; + var dataResponseInvoice = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!dataResponseInvoice.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, dataResponseInvoice.Mensaje); + } + return resultadoTransaccion.GetInformacionResultado(0, "", "Se registró correctamento...!!!", dataResponseInvoice); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/InventoryGenExits/IInventoryGenExitsRepository.cs b/Net.Data/ServicesLayer/InventoryGenExits/IInventoryGenExitsRepository.cs new file mode 100644 index 0000000..d84dc67 --- /dev/null +++ b/Net.Data/ServicesLayer/InventoryGenExits/IInventoryGenExitsRepository.cs @@ -0,0 +1,14 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Business.Entities.ServicesLayer.InventoryGenExits; +using System.Threading.Tasks; + + +namespace Net.Data.ServicesLayer.InventoryGenExits +{ + public interface IInventoryGenExitsRepository + { + Task> SetCreateInventoryGenExits(BE_InventoryGenExits entidad, bool Drafts = true); + } +} diff --git a/Net.Data/ServicesLayer/InventoryGenExits/InventoryGenExitsRepository.cs b/Net.Data/ServicesLayer/InventoryGenExits/InventoryGenExitsRepository.cs new file mode 100644 index 0000000..d255595 --- /dev/null +++ b/Net.Data/ServicesLayer/InventoryGenExits/InventoryGenExitsRepository.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Business.Entities.ServicesLayer.InventoryGenExits; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.InventoryGenExits +{ + public class InventoryGenExitsRepository : IInventoryGenExitsRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + + public InventoryGenExitsRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + //Inicializamos los servicios de services layer + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + _clientFactory = clientFactory; + _configuration = configuration; + + } + + // VENTAS PARA SAP + + public async Task> SetCreateInventoryGenExits(BE_InventoryGenExits entidad, bool Drafts = true) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = Drafts ? "Drafts": "InventoryGenExits"; + var dataResponseInvoice = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!dataResponseInvoice.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, dataResponseInvoice.Mensaje); + } + return resultadoTransaccion.GetInformacionResultado(0, "", "Se registró correctamento...!!!", dataResponseInvoice); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/Invoice/IInvoiceRepository.cs b/Net.Data/ServicesLayer/Invoice/IInvoiceRepository.cs new file mode 100644 index 0000000..4244e4e --- /dev/null +++ b/Net.Data/ServicesLayer/Invoice/IInvoiceRepository.cs @@ -0,0 +1,17 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Connection; +using System.Threading.Tasks; + + +namespace Net.Data.ServicesLayer +{ + public interface IInvoiceRepository + { + + Task> SetCreateInvoices(BE_Invoices entidad); + Task> GetInvoice(int docEntry); + Task> ReOpen(int docEntry); + } +} diff --git a/Net.Data/ServicesLayer/Invoice/InvoiceRepository.cs b/Net.Data/ServicesLayer/Invoice/InvoiceRepository.cs new file mode 100644 index 0000000..e74ccd7 --- /dev/null +++ b/Net.Data/ServicesLayer/Invoice/InvoiceRepository.cs @@ -0,0 +1,118 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.Constantes; +using Net.CrossCotting; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public class InvoiceRepository : IInvoiceRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + private readonly IConnectionSQL _context; + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + + public InvoiceRepository(IHttpClientFactory clientFactory, IConfiguration configuration, IConnectionSQL context) + { + _aplicacionName = this.GetType().Name; + + //Inicializamos los servicios de services layer + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + _context = context; + _clientFactory = clientFactory; + _configuration = configuration; + + } + + // VENTAS PARA SAP + + public async Task> SetCreateInvoices(BE_Invoices entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "Invoices"; + var dataResponseInvoice = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!dataResponseInvoice.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, dataResponseInvoice.Mensaje); + } + return resultadoTransaccion.GetInformacionResultado(0, "", "Se registró correctamento...!!!", dataResponseInvoice); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + // GET INVOICES + public async Task> GetInvoice(int docEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + try + { + + string cadena = $"Invoices({docEntry})"; + int maxpagesize = 0; + List objectList = await _connectServiceLayer.GetAsync(cadena, maxpagesize,true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", objectList); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + public async Task> ReOpen(int docEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + try + { + + string cadena = $"Invoices({docEntry})/Reopen"; + var dataResponseInvoice = await _connectServiceLayer.PostReOpen(cadena); + + if (!dataResponseInvoice.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, dataResponseInvoice.Mensaje); + } + return resultadoTransaccion.GetInformacionResultado(0, "", "Se registró correctamento...!!!", dataResponseInvoice); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/PurchaseDeliveryNotes/IPurchaseDeliveryNotesRepository.cs b/Net.Data/ServicesLayer/PurchaseDeliveryNotes/IPurchaseDeliveryNotesRepository.cs new file mode 100644 index 0000000..177dac0 --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseDeliveryNotes/IPurchaseDeliveryNotesRepository.cs @@ -0,0 +1,13 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes; +using Net.Connection; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public interface IPurchaseDeliveryNotesRepository + { + Task> SetCreatePurchaseDeliveryNotes(BE_PurchaseDeliveryNotes entidad); + } +} diff --git a/Net.Data/ServicesLayer/PurchaseDeliveryNotes/PurchaseDeliveryNotesRepository.cs b/Net.Data/ServicesLayer/PurchaseDeliveryNotes/PurchaseDeliveryNotesRepository.cs new file mode 100644 index 0000000..dd872f7 --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseDeliveryNotes/PurchaseDeliveryNotesRepository.cs @@ -0,0 +1,78 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public class PurchaseDeliveryNotesRepository : IPurchaseDeliveryNotesRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + #endregion + + public PurchaseDeliveryNotesRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = this.GetType().Name; + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + } + + public async Task> SetCreatePurchaseDeliveryNotes(BE_PurchaseDeliveryNotes entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "PurchaseDeliveryNotes"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + // GET INVOICES + public async Task> GetPurchaseDeliveryNotes(int docEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + try + { + + string cadena = $"PurchaseDeliveryNotes({docEntry})"; + int maxpagesize = 0; + List objectList = await _connectServiceLayer.GetAsync(cadena, maxpagesize, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", objectList); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/PurchaseInvoices/IPurchaseInvoicesRepository.cs b/Net.Data/ServicesLayer/PurchaseInvoices/IPurchaseInvoicesRepository.cs new file mode 100644 index 0000000..7aa1a31 --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseInvoices/IPurchaseInvoicesRepository.cs @@ -0,0 +1,13 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public interface IPurchaseInvoicesRepository + { + Task> SetCreatePurchaseInvoices(BE_PurchaseInvoices entidad); + Task> GetPurchaseInvoices(int DocEntry); + } +} diff --git a/Net.Data/ServicesLayer/PurchaseInvoices/PurchaseInvoicesRepository.cs b/Net.Data/ServicesLayer/PurchaseInvoices/PurchaseInvoicesRepository.cs new file mode 100644 index 0000000..92b45e1 --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseInvoices/PurchaseInvoicesRepository.cs @@ -0,0 +1,76 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public class PurchaseInvoicesRepository: IPurchaseInvoicesRepository + { + #region Variables Globales + + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + + #endregion + + public PurchaseInvoicesRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = this.GetType().Name; + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + } + + public async Task> SetCreatePurchaseInvoices(BE_PurchaseInvoices entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "PurchaseInvoices"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + public async Task> GetPurchaseInvoices(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = $"PurchaseInvoices({DocEntry})"; + var data = await _connectServiceLayer.GetAsync(cadena, 0, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/PurchaseOrders/IPurchaseOrdersRepository.cs b/Net.Data/ServicesLayer/PurchaseOrders/IPurchaseOrdersRepository.cs new file mode 100644 index 0000000..d7dcf0d --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseOrders/IPurchaseOrdersRepository.cs @@ -0,0 +1,15 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using Net.Business.Entities.ServicesLayer.PurchaseOrders; +using Net.Connection; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public interface IPurchaseOrdersRepository + { + Task> SetCreatePurchaseInvoices(BE_PurchaseInvoices entidad); + Task> GetPurchaseInvoices(int DocEntry); + } +} diff --git a/Net.Data/ServicesLayer/PurchaseOrders/PurchaseOrdersRepository.cs b/Net.Data/ServicesLayer/PurchaseOrders/PurchaseOrdersRepository.cs new file mode 100644 index 0000000..fa9b86f --- /dev/null +++ b/Net.Data/ServicesLayer/PurchaseOrders/PurchaseOrdersRepository.cs @@ -0,0 +1,79 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using Net.Business.Entities.ServicesLayer.PurchaseOrders; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer +{ + public class PurchaseOrdersRepository : IPurchaseOrdersRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + #endregion + + public PurchaseOrdersRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = this.GetType().Name; + + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + } + + public async Task> SetCreatePurchaseInvoices(BE_PurchaseInvoices entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "PurchaseInvoices"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + public async Task> GetPurchaseInvoices(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = $"PurchaseOrders({DocEntry})"; + var data = await _connectServiceLayer.GetAsync(cadena, 0, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/ReturnRequest/IReturnRequestRepository.cs b/Net.Data/ServicesLayer/ReturnRequest/IReturnRequestRepository.cs new file mode 100644 index 0000000..b5f558a --- /dev/null +++ b/Net.Data/ServicesLayer/ReturnRequest/IReturnRequestRepository.cs @@ -0,0 +1,13 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.ReturnRequest; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.ReturnRequest +{ + public interface IReturnRequestRepository + { + Task> SetCreateReturnRequest(BE_ReturnRequest entidad); + Task> GetRequestReturn(int DocEntry); + } +} diff --git a/Net.Data/ServicesLayer/ReturnRequest/ReturnRequestRepository.cs b/Net.Data/ServicesLayer/ReturnRequest/ReturnRequestRepository.cs new file mode 100644 index 0000000..1fbb81a --- /dev/null +++ b/Net.Data/ServicesLayer/ReturnRequest/ReturnRequestRepository.cs @@ -0,0 +1,77 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.ReturnRequest; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.ReturnRequest +{ + public class ReturnRequestRepository: IReturnRequestRepository + { + #region Variables Globales + + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + + #endregion + + public ReturnRequestRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = this.GetType().Name; + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + } + + public async Task> SetCreateReturnRequest(BE_ReturnRequest entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "ReturnRequest"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + public async Task> GetRequestReturn(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = $"ReturnRequest({DocEntry})"; + var data = await _connectServiceLayer.GetAsync(cadena, 0, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/ServicesLayer/StockTransfer/IStockTransferRepository.cs b/Net.Data/ServicesLayer/StockTransfer/IStockTransferRepository.cs new file mode 100644 index 0000000..254859d --- /dev/null +++ b/Net.Data/ServicesLayer/StockTransfer/IStockTransferRepository.cs @@ -0,0 +1,11 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.StockTransfer +{ + public interface IStockTransferRepository + { + Task> StockTransfer(dynamic entidad); + } +} diff --git a/Net.Data/ServicesLayer/StockTransfer/StockTransferRepository.cs b/Net.Data/ServicesLayer/StockTransfer/StockTransferRepository.cs new file mode 100644 index 0000000..8a16273 --- /dev/null +++ b/Net.Data/ServicesLayer/StockTransfer/StockTransferRepository.cs @@ -0,0 +1,100 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.ServicesLayer.StockTransfer +{ + public class StockTransferRepository: IStockTransferRepository + { + #region Variables Globales + + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + //Services Layer + private readonly ConnectionServiceLayer _connectServiceLayer; + + #endregion + + public StockTransferRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = this.GetType().Name; + _connectServiceLayer = new ConnectionServiceLayer(configuration, clientFactory); + } + + public async Task> StockTransfer(dynamic entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = "StockTransfers"; + var data = await _connectServiceLayer.PostAsync(cadena, entidad); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + + public async Task> CloseInventoryTransferRequest(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = $"InventoryTransferRequests({DocEntry})/Close"; + var data = await _connectServiceLayer.PostClose(cadena); + + if (!data.Exito) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, data.Mensaje); + } + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + + public async Task> GetInventoryTransferRequest(int DocEntry) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var cadena = $"InventoryTransferRequests({DocEntry})"; + var data = await _connectServiceLayer.GetAsync(cadena, 0, true); + + return resultadoTransaccion.GetInformacionResultado(0, 0, "Se Listo correctamento...!!!", data); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(-1, -1, ex.Message.ToString()); + } + } + } +} diff --git a/Net.Data/TextFile1.txt b/Net.Data/TextFile1.txt new file mode 100644 index 0000000..d0fbf97 --- /dev/null +++ b/Net.Data/TextFile1.txt @@ -0,0 +1,5 @@ + try + { + HelperDB.SET($"UPDATE \"{LocalData.DB_NAME}\".\"ODRF\" SET \"U_ITC_WMS_NUMINV\" = '{entidad.NroInventario}' WHERE \"DocEntry\" = {inventoryGenEntries_result.Data.DocEntry} "); + } + catch (Exception) { } \ No newline at end of file diff --git a/Net.Data/WMS/Enums/EnumRecibo.cs b/Net.Data/WMS/Enums/EnumRecibo.cs new file mode 100644 index 0000000..1378a3b --- /dev/null +++ b/Net.Data/WMS/Enums/EnumRecibo.cs @@ -0,0 +1,12 @@ +namespace Net.Data.WMS.Enums +{ + public class EnumRecibo + { + public const int IMPORTACION = 1; + public const int IMPORTACION_ORDEN = 1; + public const int IMPORTACION_ORDEN_COMPRA = 2; + public const int IMPORTACION_SOL_ENTRADA = 10; + public const int NACIONAL = 2; + public const int DEVOLUCION = 3; + } +} diff --git a/Net.Data/WMS/Inventario/IInventarioRepository.cs b/Net.Data/WMS/Inventario/IInventarioRepository.cs new file mode 100644 index 0000000..6d0d34f --- /dev/null +++ b/Net.Data/WMS/Inventario/IInventarioRepository.cs @@ -0,0 +1,11 @@ +using Net.Business.Entities; +using Net.Business.Entities.WMS.Inventario; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Inventario +{ + public interface IInventarioRepository + { + Task> Create(BE_Inventario entidad); + } +} diff --git a/Net.Data/WMS/Inventario/InventarioRepository.cs b/Net.Data/WMS/Inventario/InventarioRepository.cs new file mode 100644 index 0000000..6379e14 --- /dev/null +++ b/Net.Data/WMS/Inventario/InventarioRepository.cs @@ -0,0 +1,601 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Business.Entities.ServicesLayer.InventoryGenExits; +using Net.Business.Entities.ServicesLayer.Items; +using Net.Business.Entities.ServicesLayer.StockTransfer; +using Net.Business.Entities.WMS.Inventario; +using Net.Connection; +using Net.CrossCotting; +using Net.Data.HelperData; +using Net.Data.HelperData.Inventario; +using Net.Data.HelperData.Stock; +using Net.Data.ServicesLayer.InventoryGenEntries; +using Net.Data.ServicesLayer.InventoryGenExits; +using Net.Data.ServicesLayer.StockTransfer; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Inventario +{ + public class InventarioRepository : RepositoryBase, IInventarioRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + public InventarioRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _clientFactory = clientFactory; + _configuration = configuration; + _aplicacionName = GetType().Name; + } + + public async Task> Create(BE_Inventario entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + if (string.IsNullOrEmpty(entidad.TipoMovimiento)) + { + return resultadoTransaccion.GetInformacionResultado("El campo Tipo Movimiento no puede ser vacio", entidad); + } + + if (string.IsNullOrEmpty(entidad.TipoMovimientoSAP)) + { + return resultadoTransaccion.GetInformacionResultado("El campo Tipo Movimiento SAP no puede ser vacio", entidad); + } + + if (string.IsNullOrEmpty(entidad.TipoInventario)) + { + return resultadoTransaccion.GetInformacionResultado("El campo Tipo Inventario no puede ser vacio", entidad); + } + + //=== ASIGNA PRECIO PROMEDIO (solo aplica a entradas de mercancia) + if (entidad.TipoMovimiento == "01") + { + foreach (var x in entidad.Detalle) + { + var Stock = HelperStock.GetConsolidado(x.CodigoArticulo, entidad.SubAlmacen); + + // Un ingreso puede crear el primer stock del articulo: sin datos se conserva el precio del request + if (Stock.Count > 0) + { + x.PrecioPromedio = Stock.FirstOrDefault().AvgPrice; + } + }; + } + + var ListaxLista = new List(); + var lista = entidad.Detalle; + for (int i = 0; i < lista.Count; i += 100) + { + var bloque = lista.Skip(i).Take(100).ToList(); + // Copia por bloque: antes se reutilizaba "entidad" y todos los bloques + // terminaban apuntando al ultimo detalle (documentos repetidos y lineas perdidas) + var Inventario = new BE_Inventario() + { + Fecha = entidad.Fecha, + FechaVencimiento = entidad.FechaVencimiento, + TipoMovimientoSAP = entidad.TipoMovimientoSAP, + TipoMovimiento = entidad.TipoMovimiento, + TipoInventario = entidad.TipoInventario, + Almacen = entidad.Almacen, + SubAlmacen = entidad.SubAlmacen, + NroInventario = entidad.NroInventario, + Detalle = bloque + }; + ListaxLista.Add(Inventario); + } + + return await Task.Run(() => + { + try + { + string CuentaContable = HelperInventario.Get(entidad.TipoMovimientoSAP); + + if (string.IsNullOrEmpty(CuentaContable)) + { + return resultadoTransaccion.GetInformacionResultado("No existe cuenta contable configurado para el tipo movimiento SAP", entidad); + } + + //=== OBTIENE PRECIO PROMEDIO (solo aplica a entradas de mercancia) + if (entidad.TipoMovimiento == "01") + { + entidad.Detalle.ForEach(detalle => + { + var ListaStockConsolidado = HelperStock.GetConsolidado(detalle.CodigoArticulo, entidad.Almacen); + + // Un ingreso puede crear el primer stock del articulo: sin datos se conserva el precio del request + if (ListaStockConsolidado.Count > 0) + { + detalle.PrecioPromedio = ListaStockConsolidado.FirstOrDefault().AvgPrice; + } + }); + } + + //=== TIPO DE INVENTARIO GENERAL + if (entidad.TipoInventario == "01") + { + //=== INGRESO DE MERCANCIA + if (entidad.TipoMovimiento == "01") + { + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_InventoryGenEntries _InventoryGenEntries = new BE_InventoryGenEntries() + { + DocObjectCode = "oInventoryGenEntry", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOENTME = entidad_inventario.TipoMovimientoSAP, + U_ITC_WMS_NUMINV = entidad_inventario.NroInventario + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(detalle => + { + _InventoryGenEntries.DocumentLines.Add(new BE_InventoryGenEntriesLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = detalle.DescripcionArticulo, + Quantity = (double)detalle.Cantidad, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.Cantidad, + WarehouseCode = entidad.SubAlmacen, + AccountCode = CuentaContable, + CostingCode = detalle.CentroCosto ?? "", + BatchNumbers = new List() + { + new BE_InventoryGenEntriesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (double)detalle.Cantidad + } + } + }); + + LineNum++; + }); + + InventoryGenEntriesRepository inventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, context); + var inventoryGenEntries_result = inventoryGenEntries.SetCreateInventoryGenEntries(_InventoryGenEntries, false).Result; + if (inventoryGenEntries_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenEntries_result.Message.ToString(), entidad); + } + + DocEntry = (int)inventoryGenEntries_result.Data.DocEntry; + DocNum = (int)inventoryGenEntries_result.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + } + + //=== SALIDA DE MERCANCIA + if (entidad.TipoMovimiento == "02") + { + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_InventoryGenExits _InventoryGenExits = new BE_InventoryGenExits() + { + DocObjectCode = "oInventoryGenExit", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOSALME = entidad_inventario.TipoMovimientoSAP, + U_ITC_WMS_NUMINV = entidad_inventario.NroInventario + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(detalle => + { + _InventoryGenExits.DocumentLines.Add(new BE_InventoryGenExitsLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = detalle.DescripcionArticulo, + Quantity = (double)detalle.Cantidad, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.Cantidad, + WarehouseCode = entidad.SubAlmacen, + AccountCode = CuentaContable, + BatchNumbers = new List(), + CostingCode = detalle.CentroCosto ?? "", + }); + + LineNum++; + }); + + _InventoryGenExits.DocumentLines.ForEach(line => + { + #region CONSULTA A HANA + + List ListaStock = HelperStock.Get(line.ItemCode, entidad.SubAlmacen); + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + var cantidadStock = ListaStock.Sum(x => x.OnHandQty); + if (cantidadStock < line.Quantity) + { + throw new Exception($"El producto {line.ItemCode} no cuenta con stock suficiente"); + } + else + { + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty }); + CantidadPendiente -= Lote.OnHandQty; + } + } + }); + } + + #endregion + }); + + InventoryGenExitsRepository inventoryGenExits = new InventoryGenExitsRepository(_clientFactory, _configuration, context); + var inventoryGenExits_result = inventoryGenExits.SetCreateInventoryGenExits(_InventoryGenExits, false).Result; + if (inventoryGenExits_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenExits_result.Message.ToString(), entidad); + } + DocEntry = (int)inventoryGenExits_result.Data.DocEntry; + DocNum = (int)inventoryGenExits_result.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + } + } + + //=== TIPO DE INVENTARIO CICLICO + if (entidad.TipoInventario == "02") + { + //=== INGRESO DE MERCANCIA + if (entidad.TipoMovimiento == "01") + { + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_InventoryGenEntries _InventoryGenEntries = new BE_InventoryGenEntries() + { + DocObjectCode = "oInventoryGenEntry", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOENTME = entidad_inventario.TipoMovimientoSAP, + U_ITC_WMS_NUMINV = entidad_inventario.NroInventario + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(detalle => + { + _InventoryGenEntries.DocumentLines.Add(new BE_InventoryGenEntriesLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = detalle.DescripcionArticulo, + Quantity = (double)detalle.Cantidad, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.Cantidad, + WarehouseCode = entidad.SubAlmacen, + AccountCode = CuentaContable, + CostingCode = detalle.CentroCosto ?? "", + BatchNumbers = new List() + { + new BE_InventoryGenEntriesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (double)detalle.Cantidad + } + } + }); + + LineNum++; + }); + + InventoryGenEntriesRepository inventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, context); + var inventoryGenEntries_result = inventoryGenEntries.SetCreateInventoryGenEntries(_InventoryGenEntries).Result; + if (inventoryGenEntries_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenEntries_result.Message.ToString(), entidad); + } + DocEntry = (int)inventoryGenEntries_result.Data.DocEntry; + DocNum = (int)inventoryGenEntries_result.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + } + + //=== SALIDA DE MERCANCIA [GENERA TRANSFERENCIA] + if (entidad.TipoMovimiento == "02") + { + string AlmacenDestino = "ALM12"; + //=== CREA INSTANCIA PARA CONECTAR A SAP + StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_StockTransfer StockTransfer = new BE_StockTransfer + { + DocDate = DateTime.Now, + DueDate = DateTime.Now, + TaxDate = DateTime.Now, + FromWarehouse = entidad.SubAlmacen, + ToWarehouse = AlmacenDestino, + Comments = "Transferencia Generado desde Cubico - SAP", + StockTransferLines = new List(), + U_ITC_WMS_NUMINV = entidad.NroInventario, + U_SYP_TPOENTME = entidad.TipoMovimientoSAP + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(x => + { + var Detalle = new BE_StockTransferLine + { + FromWarehouseCode = entidad.SubAlmacen, + WarehouseCode = AlmacenDestino, + ItemCode = x.CodigoArticulo, + Quantity = (double)x.Cantidad, + BaseLine = null, + BaseEntry = null, + BaseType = null, + LineNum = LineNum, + BatchNumbers = new List() + }; + StockTransfer.StockTransferLines.Add(Detalle); + LineNum++; + }); + + // == REALIZA DISTRIBUCION DE STOCK POR LOTE / ALMACEN + StockTransfer.StockTransferLines.ForEach(line => + { + #region CONSULTA A HANA + + List ListaStock = HelperStock.Get(line.ItemCode, entidad.SubAlmacen); + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + var cantidadStock = ListaStock.Sum(x => x.OnHandQty); + if (cantidadStock < line.Quantity) + { + throw new Exception($"El producto {line.ItemCode} no cuenta con stock suficiente"); + } + else + { + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_StockTransferLineBatchNumber() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_StockTransferLineBatchNumber() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty }); + CantidadPendiente -= Lote.OnHandQty; + } + } + }); + } + + #endregion + }); + var jsonForma = Newtonsoft.Json.JsonConvert.SerializeObject(StockTransfer); + var ResultTransaction = stockTransferRepository.StockTransfer(StockTransfer).Result; + if (ResultTransaction.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(ResultTransaction.Message.ToString(), entidad); + } + DocEntry = (int)ResultTransaction.Data.DocEntry; + DocNum = (int)ResultTransaction.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + } + } + + //=== TIPO DE INVENTARIO POR CONSUMO + if (entidad.TipoInventario == "03") + { + //=== INGRESO DE MERCANCIA + if (entidad.TipoMovimiento == "01") + { + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_InventoryGenEntries _InventoryGenEntries = new BE_InventoryGenEntries() + { + DocObjectCode = "oInventoryGenEntry", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOENTME = entidad.TipoMovimientoSAP, + U_ITC_WMS_NUMINV = entidad.NroInventario + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(detalle => + { + _InventoryGenEntries.DocumentLines.Add(new BE_InventoryGenEntriesLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = detalle.DescripcionArticulo, + Quantity = (double)detalle.Cantidad, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.Cantidad, + WarehouseCode = entidad.SubAlmacen, + AccountCode = CuentaContable, + CostingCode = detalle.CentroCosto ?? "", + BatchNumbers = new List() + { + new BE_InventoryGenEntriesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (double)detalle.Cantidad + } + } + }); + + LineNum++; + }); + + InventoryGenEntriesRepository inventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, context); + var inventoryGenEntries_result = inventoryGenEntries.SetCreateInventoryGenEntries(_InventoryGenEntries, false).Result; + if (inventoryGenEntries_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenEntries_result.Message.ToString(), entidad); + } + DocEntry = (int)inventoryGenEntries_result.Data.DocEntry; + DocNum = (int)inventoryGenEntries_result.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + // return resultadoTransaccion.GetInformacionResultado((int)inventoryGenEntries_result.Data.DocEntry, inventoryGenEntries_result.Data.DocNum.ToString(), "Registrado Correctamente", entidad); + } + + //=== SALIDA DE MERCANCIA + if (entidad.TipoMovimiento == "02") + { + int DocEntry = 0; + int DocNum = 0; + foreach (var entidad_inventario in ListaxLista) + { + BE_InventoryGenExits _InventoryGenExits = new BE_InventoryGenExits() + { + DocObjectCode = "oInventoryGenExit", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOSALME = entidad.TipoMovimientoSAP, + U_ITC_WMS_NUMINV = entidad.NroInventario + }; + + int LineNum = 0; + entidad_inventario.Detalle.ForEach(detalle => + { + _InventoryGenExits.DocumentLines.Add(new BE_InventoryGenExitsLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = detalle.DescripcionArticulo, + Quantity = (double)detalle.Cantidad, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.Cantidad, + WarehouseCode = entidad.SubAlmacen, + AccountCode = CuentaContable, + BatchNumbers = new List(), + CostingCode = detalle.CentroCosto ?? "", + }); + + LineNum++; + }); + + _InventoryGenExits.DocumentLines.ForEach(line => + { + #region CONSULTA A HANA + + List ListaStock = HelperStock.Get(line.ItemCode, entidad.SubAlmacen); + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + var cantidadStock = ListaStock.Sum(x => x.OnHandQty); + if (cantidadStock < line.Quantity) + { + throw new Exception($"El producto {line.ItemCode} no cuenta con stock suficiente"); + } + else + { + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty }); + CantidadPendiente -= Lote.OnHandQty; + } + } + }); + } + + #endregion + }); + InventoryGenExitsRepository inventoryGenExits = new InventoryGenExitsRepository(_clientFactory, _configuration, context); + var inventoryGenExits_result = inventoryGenExits.SetCreateInventoryGenExits(_InventoryGenExits, false).Result; + if (inventoryGenExits_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenExits_result.Message.ToString(), entidad); + } + DocEntry = (int)inventoryGenExits_result.Data.DocEntry; + DocNum = (int)inventoryGenExits_result.Data.DocNum; + }; + + return resultadoTransaccion.GetInformacionResultado(DocEntry, DocNum.ToString(), "Registrado Correctamente", entidad); + //return resultadoTransaccion.GetInformacionResultado((int)inventoryGenExits_result.Data.DocEntry, inventoryGenExits_result.Data.DocNum.ToString(), "Registrado Correctamente", entidad); + } + } + return resultadoTransaccion.GetInformacionResultado(0, "", "Registrado Correctamente", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } + }); + } + } +} diff --git a/Net.Data/WMS/Items/IItemsRepository.cs b/Net.Data/WMS/Items/IItemsRepository.cs new file mode 100644 index 0000000..c020a73 --- /dev/null +++ b/Net.Data/WMS/Items/IItemsRepository.cs @@ -0,0 +1,11 @@ +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer.Items; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Items +{ + public interface IItemsRepository + { + Task> GetStockItem(); + } +} diff --git a/Net.Data/WMS/Items/ItemsRepository.cs b/Net.Data/WMS/Items/ItemsRepository.cs new file mode 100644 index 0000000..f4133f2 --- /dev/null +++ b/Net.Data/WMS/Items/ItemsRepository.cs @@ -0,0 +1,80 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer.Items; +using Net.Connection; +using Net.CrossCotting; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Data; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Items +{ + public class ItemsRepository : RepositoryBase, IItemsRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + #endregion + + public ItemsRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _aplicacionName = GetType().Name; + } + + public async Task> GetStockItem() + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + + return await Task.Run(() => + { + try + { + List ListaStock = new List(); + DataTable dt = new DataTable(); + using (HanaConnection con = new HanaConnection(LocalData.ConnectionString)) + { + con.Open(); + HanaCommand cmd = new HanaCommand($"CALL\"{LocalData.Schema}\".\"ITCA_WMS_SAP_GetStockConsolidado\"", con); + HanaDataAdapter da = new HanaDataAdapter(cmd); + if (da != null) + { + da.Fill(dt); + } + } + + for (int x = 0; x < dt.Rows.Count; x++) + { + ListaStock.Add(new BE_ItemStock() + { + BinCode = dt.Rows[x]["BinCode"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["BinCode"]) : string.Empty, + DistNumber = dt.Rows[x]["DistNumber"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["DistNumber"]) : string.Empty, + ExpDate = dt.Rows[x]["ExpDate"] != DBNull.Value ? Convert.ToDateTime(dt.Rows[x]["ExpDate"]) : DateTime.Now, + ItemCode = dt.Rows[x]["ItemCode"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["ItemCode"]) : string.Empty, + ItemName = dt.Rows[x]["ItemName"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["ItemName"]) : string.Empty, + OnHandQty = dt.Rows[x]["OnHandQty"] != DBNull.Value ? Convert.ToDouble(dt.Rows[x]["OnHandQty"]) : 0, + WhsCode = dt.Rows[x]["WhsCode"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["WhsCode"]) : string.Empty, + WhsName = dt.Rows[x]["WhsName"] != DBNull.Value ? Convert.ToString(dt.Rows[x]["WhsName"]) : string.Empty, + AvgPrice = dt.Rows[x]["AvgPrice"] != DBNull.Value ? Convert.ToDouble(dt.Rows[x]["AvgPrice"]) : 0, + }); + } + return resultadoTransaccion.GetInformacionResultado(0, 0, "Datos obtenidos Correctamente", ListaStock); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), null); + } + }); + } + + + } +} diff --git a/Net.Data/WMS/Picking/IPickingRepository.cs b/Net.Data/WMS/Picking/IPickingRepository.cs new file mode 100644 index 0000000..6d3be0a --- /dev/null +++ b/Net.Data/WMS/Picking/IPickingRepository.cs @@ -0,0 +1,14 @@ +using Net.Business.Entities; +using Net.Business.Entities.WMS.HojaRuta; +using Net.Business.Entities.WMS.Picking; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Picking +{ + public interface IPickingRepository + { + Task> Create(BE_PickingRequest entidad); + Task> CreateHojaRuta(BE_HojaRutaEntities entidad); + Task> CerrarHojaRuta(int docEntry); + } +} diff --git a/Net.Data/WMS/Picking/PickingRepository.cs b/Net.Data/WMS/Picking/PickingRepository.cs new file mode 100644 index 0000000..93982c3 --- /dev/null +++ b/Net.Data/WMS/Picking/PickingRepository.cs @@ -0,0 +1,794 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Business.Entities.ServicesLayer.InventoryGenExits; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Business.Entities.ServicesLayer.Items; +using Net.Business.Entities.ServicesLayer.ReturnRequest; +using Net.Business.Entities.ServicesLayer.StockTransfer; +using Net.Business.Entities.WMS.HojaRuta; +using Net.Business.Entities.WMS.Picking; +using Net.Business.Entities.WMS.ProcesoPicking; +using Net.Connection; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using Net.Data.HelperData.Correlativo; +using Net.Data.HelperData.HelperProcesoPermitido; +using Net.Data.HelperData.Stock; +using Net.Data.ServicesLayer; +using Net.Data.ServicesLayer.CreditNotes; +using Net.Data.ServicesLayer.GlobalData; +using Net.Data.ServicesLayer.InventoryGenExits; +using Net.Data.ServicesLayer.ReturnRequest; +using Net.Data.ServicesLayer.StockTransfer; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Picking +{ + public class PickingRepository : RepositoryBase, IPickingRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + public PickingRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _clientFactory = clientFactory; + _configuration = configuration; + _aplicacionName = GetType().Name; + } + + public async Task> Create(BE_PickingRequest entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + if (entidad.DocEntry == 0) + { + return resultadoTransaccion.GetInformacionResultado("El campo docEntry no puede ser cero o vacio", entidad); + } + + return await Task.Run(() => + { + try + { + var Almacen = HelperProcesoPermitido.GetMotivoAlmacen(entidad.CodMotivo, out bool Reproceso, out string MotivoNotaCredito, out string DescripcionMotivo); + + if (string.IsNullOrEmpty(entidad.Proceso)) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita definir el proceso para continuar con el proceso.", entidad); + } + + if (entidad.IdEstadoCubico == 0) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita indicar el IdEstado Cubico para continuar con el proceso.", entidad); + } + + int Existe = HelperProcesoPermitido.Get(entidad.Proceso, entidad.IdEstadoCubico, "PICKING", out List ListaProceso); + var Proceso = ListaProceso.FirstOrDefault(); + if (Existe == 0) + { + return resultadoTransaccion.GetInformacionResultado("El Proceso y estado no se encuentra configurado para este EndPoint", entidad); + } + + var TotalDetalle = 0; + var TotalDetalle_Anulado = 0; + var TotalDetalle_Parcial = 0; + var TotalDetalle_Completo = 0; + if (Existe > 1) + { + TotalDetalle = entidad.Detalle.Count(); + TotalDetalle_Anulado = entidad.Detalle.Where(x=> x.Estado == "A").Count(); + TotalDetalle_Parcial = entidad.Detalle.Where(x => x.Estado == "P").Count(); + TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count(); + if(TotalDetalle == TotalDetalle_Anulado) + { + Proceso = ListaProceso.FirstOrDefault(x => x.Code == "013"); + if (Reproceso) + { + Proceso = ListaProceso.FirstOrDefault(x => x.Code == "017"); + } + } + else + { + Proceso = ListaProceso.FirstOrDefault(x => x.Code == "012"); + } + } + else + { + TotalDetalle = entidad.Detalle.Count(); + TotalDetalle_Anulado = entidad.Detalle.Where(x => x.Estado == "A").Count(); + TotalDetalle_Parcial = entidad.Detalle.Where(x => x.Estado == "P").Count(); + TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count(); + } + + //=== REALIZA PROCESO COMPLETO DE ACTUALIZACION + HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code); + + // === NUEVO (Picking diurno/nocturno): "notificacion" distinta de "cierre" + // (o ausente) es la notificacion preliminar en tiempo real - solo actualiza + // estado en HANA (ya hecho arriba), NUNCA debe crear documentos en SAP. + // Default seguro: cualquier valor que no sea "cierre" exacto cae aca. + if (!string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase)) + { + return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad); + } + if(TotalDetalle == TotalDetalle_Completo && entidad.IdTipoDoc != 9) + { + return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Se registro correctamente...!!!", entidad); + } + + #region PROCESO DE NOTA DE CREDITO + + if (entidad.Proceso.ToUpper() == "DESPACHO" && (entidad.IdEstadoCubico == 6 || entidad.IdEstadoCubico == 5)) + { + if (entidad.IdTipoDoc != 9) + { + CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context); + BE_CreditNotesNotes creditNotesNotes = new BE_CreditNotesNotes + { + DocObjectCode = "oCreditNotes", + DocumentLines = new List() + }; + + InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context); + BE_ResultadoTransaccion response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result; + + if (response_invoicesRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad); + } + + + BE_InvoicesConsulta _invoices = response_invoicesRepository.ListData.FirstOrDefault(); + + if (_invoices.DocumentStatus != "bost_Open") + { + var Response_Reopen = invoicestRepository.ReOpen(_invoices.DocEntry).Result; + if (Response_Reopen.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se puede reabrir", entidad); + } + } + + string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10"; + string Correlativo = HelperCorrelativo.Get(Serie); + creditNotesNotes.DocCurrency = _invoices.DocCurrency; + creditNotesNotes.CardCode = _invoices.CardCode; + creditNotesNotes.CardName = _invoices.CardName; + creditNotesNotes.PaymentGroupCode = _invoices.PaymentGroupCode; + creditNotesNotes.DocDate = DateTime.Now; + creditNotesNotes.DocDueDate = DateTime.Now; + creditNotesNotes.U_SYP_MDTO = _invoices.U_SYP_MDTD; + creditNotesNotes.U_SYP_MDCO = _invoices.U_SYP_MDCD; + creditNotesNotes.U_SYP_MDSO = _invoices.U_SYP_MDSD; + creditNotesNotes.U_SYP_MOTNC = DescripcionMotivo; + creditNotesNotes.U_SYP_TPONC = MotivoNotaCredito; + creditNotesNotes.U_SYP_MDCD = Correlativo; + creditNotesNotes.U_SYP_MDSD = Serie; + creditNotesNotes.U_SYP_MDTD = "07"; + creditNotesNotes.U_SYP_FECHAREF = _invoices.DocDate.ToString("yyyy-MM-dd"); + creditNotesNotes.NumAtCard = ("07-" + Serie + "-" + Correlativo); + + entidad.Detalle.ForEach(x => + { + var Item = _invoices.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + if (Item.Quantity - x.CantidadPedida > 0) + { + creditNotesNotes.DocumentLines.Add(new BE_CreditNotesLine() + { + Currency = _invoices.DocCurrency, + BatchNumbers = new List(), + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = Item.Quantity - x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 13, + LineNum = x.Item, + U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Item.WarehouseCode : Almacen), + }); + } + } + }); + + // == REALIZA DISTRIBUCION DE STOCK POR LOTE / ALMACEN + creditNotesNotes.DocumentLines.ForEach(line => + { + #region CONSULTA A HANA + + //List ListaStock = HelperStock.Get(line.ItemCode, entidad.CodigoAlmacen); + var ReferenciaFactura = _invoices.DocumentLines.FirstOrDefault(t => t.LineNum == line.LineNum); + var ListaStock = _invoices.DocumentLines.FirstOrDefault(InvoiceLine => InvoiceLine.LineNum == ReferenciaFactura.BaseLine).BatchNumbers; + + double CantidadPendiente = (double)line.Quantity; + var ListOrdenadaFecha = ListaStock; + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.Quantity >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.Quantity < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = Lote.Quantity }); + CantidadPendiente -= Lote.Quantity; + } + } + }); + + #endregion + }); + + if (creditNotesNotes.DocumentLines.Count > 0) + { + var result_creditNotesRepository = _creditNotesRepository.SetCreateCreditNotes(creditNotesNotes).Result; + + if (result_creditNotesRepository.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_creditNotesRepository.Message.ToString(), entidad); + } + else + { + List ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList(); + List ListDocEntry = new List(); + ListaUnicaAlmacen.ForEach(Almacen => + { + List ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList(); + ListaUnicaAlmDestino.ForEach(Destino => + { + if (Almacen != Destino) + { + BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico(); + Transfer.FromWarehouse = Almacen; + Transfer.ToWarehouse = Destino; + Transfer.DocDate = creditNotesNotes.DocDate; + Transfer.TaxDate = creditNotesNotes.DocDate; + Transfer.U_SYP_MDTS = "TSI"; + Transfer.U_SYP_MDMT = "24"; + Transfer.DueDate = creditNotesNotes.DocDueDate; + Transfer.PriceList = -2; + var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList(); + var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList(); + Transfer.StockTransferLines = new List(); + Transfer.DocumentReferences = new List(); + ListaUnicaArticulo.ForEach(x => + { + var ListLote = new List(); + ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().BatchNumbers.ForEach(r => + { + ListLote.Add(new BE_StockTransferLineBatchNumber() + { + BatchNumber = r.BatchNumber, + Quantity = r.Quantity + }); + }); + Transfer.StockTransferLines.Add(new BE_StockTransferLine() + { + + ItemCode = x, + ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription, + Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)), + WarehouseCode = Destino, + FromWarehouseCode = Almacen, + BatchNumbers = ListLote + }); + + + //=== AGREGA DOCUMENTO REFERENCIA + Transfer.DocumentReferences = new List + { + new BE_StockTransferDocumentReferences() + { + RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry, + RefObjType = "rot_SalesCreditNote", + IssueDate = DateTime.Now, + Remark = "Nota de Credito", + } + }; + + + + }); + + //=== CREA INSTANCIA PARA CONECTAR A SAP + StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); + var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; + if (ResultTransfer.StatusCode == -1) + { + + } + else + { + ListDocEntry.Add((int)ResultTransfer.Data.DocEntry); + } + } + }); + }); + + + if (ListDocEntry.Count > 0) + { + var listaReferencia = new List(); + ListDocEntry.ForEach(x => + { + listaReferencia.Add(new BE_CreditNotesDocumentReferences() + { + RefDocEntr = x, + IssueDate = DateTime.Now, + RefObjType = "rot_InventoryTransfer", + Remark = "Transferencias Automatica" + }); + }); + + var credit = new + { + DocumentReferences = listaReferencia + }; + + var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result; + } + return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + } + else + { + return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad); + } + } + else + { + //=== ASIGNA PRECIO PROMEDIO + foreach (var x in entidad.Detalle) + { + var Stock = HelperStock.GetConsolidado(x.CodigoArticulo, entidad.CodigoAlmacen); + if (Stock.Count == 0) + { + return resultadoTransaccion.GetInformacionResultado("No existe stock disponible para el articulo " + x.CodigoArticulo, entidad); + } + x.PrecioPromedio = Stock.FirstOrDefault().AvgPrice; + }; + + GlobalDataRepository globalDataRepository = new GlobalDataRepository(_clientFactory, _configuration, context); + + var Data_SolicitudSalida = globalDataRepository.GetSolicitudSalida(entidad.DocEntry).Result.ListData.FirstOrDefault(); + + InventoryGenExitsRepository inventoryGenExitsRepository = new InventoryGenExitsRepository(_clientFactory, _configuration, context); + BE_InventoryGenExits _InventoryGenExits = new BE_InventoryGenExits() + { + DocObjectCode = "oInventoryGenExit", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOSALME = Data_SolicitudSalida.U_ITC_MDTS, + U_ITC_WMS_NUMINV = "", + U_ARD_PERSOLIC = Data_SolicitudSalida.U_ITC_USRSOL, + Comments = Data_SolicitudSalida.U_ITC_MDCM + }; + + int LineNum = 0; + entidad.Detalle.ForEach(detalle => + { + _InventoryGenExits.DocumentLines.Add(new BE_InventoryGenExitsLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_ItemName, + Quantity = (double)detalle.CantidadPedida, + LineNum = LineNum, + PriceAfterVAT = detalle.PrecioPromedio, + LineTotal = detalle.PrecioPromedio * (double)detalle.CantidadPedida, + WarehouseCode = entidad.CodigoAlmacen, + AccountCode = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_AccCode, + BatchNumbers = new List(), + CostingCode = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_CCOST, + }); + + LineNum++; + }); + + + _InventoryGenExits.DocumentLines.ForEach(line => + { + #region CONSULTA A HANA + + List ListaStock = HelperStock.Get(line.ItemCode, entidad.CodigoAlmacen); + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + var cantidadStock = ListaStock.Sum(x => x.OnHandQty); + if (cantidadStock < line.Quantity) + { + throw new Exception($"El producto {line.ItemCode} no cuenta con stock suficiente"); + } + else + { + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty }); + CantidadPendiente -= Lote.OnHandQty; + } + } + }); + } + + #endregion + }); + + var Result = inventoryGenExitsRepository.SetCreateInventoryGenExits(_InventoryGenExits, false).Result; + if (Result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(Result.Message.ToString(), entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad); + } + } + + if (entidad.Proceso.ToUpper() == "PICKING" && entidad.IdEstadoCubico == 13) + { + CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context); + BE_CreditNotesNotes creditNotesNotes = new BE_CreditNotesNotes + { + DocObjectCode = "oCreditNotes", + DocumentLines = new List() + }; + + InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context); + BE_ResultadoTransaccion response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result; + + if (response_invoicesRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad); + } + BE_InvoicesConsulta _invoices = response_invoicesRepository.ListData.FirstOrDefault(); + + if (_invoices.DocumentStatus != "bost_Open") + { + var Response_Reopen = invoicestRepository.ReOpen(_invoices.DocEntry).Result; + if (Response_Reopen.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se puede reabrir", entidad); + } + } + + string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10"; + string Correlativo = HelperCorrelativo.Get(Serie); + + creditNotesNotes.DocCurrency = _invoices.DocCurrency; + creditNotesNotes.CardCode = _invoices.CardCode; + creditNotesNotes.CardName = _invoices.CardName; + creditNotesNotes.PaymentGroupCode = _invoices.PaymentGroupCode; + creditNotesNotes.DocDate = DateTime.Now; + creditNotesNotes.DocDueDate = DateTime.Now; + creditNotesNotes.U_SYP_MDTO = _invoices.U_SYP_MDTD; + creditNotesNotes.U_SYP_MDCO = _invoices.U_SYP_MDCD; + creditNotesNotes.U_SYP_MDSO = _invoices.U_SYP_MDSD; + creditNotesNotes.U_SYP_MOTNC = DescripcionMotivo; + creditNotesNotes.U_SYP_TPONC = MotivoNotaCredito; + creditNotesNotes.U_SYP_MDCD = Correlativo; + creditNotesNotes.U_SYP_MDSD = Serie; + creditNotesNotes.U_SYP_MDTD = "07"; + creditNotesNotes.U_SYP_FECHAREF = _invoices.DocDate.ToString("yyyy-MM-dd"); + creditNotesNotes.NumAtCard = ("07-" + Serie+ "-" + Correlativo); + + entidad.Detalle.ForEach(x => + { + var Item = _invoices.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + creditNotesNotes.DocumentLines.Add(new BE_CreditNotesLine() + { + Currency = _invoices.DocCurrency, + BatchNumbers = new List(), + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = Item.Quantity - x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 13, + LineNum = x.Item, + U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Item.WarehouseCode : Almacen), + }); + } + }); + + var _Invoice = response_invoicesRepository.ListData.FirstOrDefault(); + creditNotesNotes.DocumentLines.ForEach(line => + { + + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), Quantity = (double)line.Quantity }); + }); + + if (creditNotesNotes.DocumentLines.Count > 0) + { + var result_creditNotesRepository = _creditNotesRepository.SetCreateCreditNotes(creditNotesNotes).Result; + if (result_creditNotesRepository.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_creditNotesRepository.Message.ToString(), entidad); + } + else + { + + List ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList(); + List ListDocEntry = new List(); + ListaUnicaAlmacen.ForEach(Almacen => + { + List ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList(); + ListaUnicaAlmDestino.ForEach(Destino => + { + if (Almacen != Destino) + { + BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico(); + Transfer.FromWarehouse = Almacen; + Transfer.ToWarehouse = Destino; + Transfer.DocDate = creditNotesNotes.DocDate; + Transfer.TaxDate = creditNotesNotes.DocDate; + Transfer.DueDate = creditNotesNotes.DocDueDate; + Transfer.U_SYP_MDTS = "TSI"; + Transfer.U_SYP_MDMT = "24"; + Transfer.PriceList = -2; + var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList(); + var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList(); + + Transfer.StockTransferLines = new List(); + Transfer.DocumentReferences = new List(); + + ListaUnicaArticulo.ForEach(x => + { + var ListLote = new List(); + ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().BatchNumbers.ForEach(r => + { + ListLote.Add(new BE_StockTransferLineBatchNumber() + { + BatchNumber = r.BatchNumber, + Quantity = r.Quantity + }); + }); + Transfer.StockTransferLines.Add(new BE_StockTransferLine() + { + ItemCode = x, + ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription, + Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)), + WarehouseCode = Destino, + FromWarehouseCode = Almacen, + BatchNumbers = ListLote + }); + + //=== AGREGA DOCUMENTO REFERENCIA + Transfer.DocumentReferences = new List + { + new BE_StockTransferDocumentReferences() + { + RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry, + RefObjType = "rot_SalesCreditNote", + IssueDate = DateTime.Now, + Remark = "Nota de Credito", + } + }; + }); + + //=== CREA INSTANCIA PARA CONECTAR A SAP + StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); + var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; + if (ResultTransfer.StatusCode == -1) + { + + } + else + { + ListDocEntry.Add((int)ResultTransfer.Data.DocEntry); + } + } + }); + }); + + if (ListDocEntry.Count > 0) + { + var listaReferencia = new List(); + ListDocEntry.ForEach(x => + { + listaReferencia.Add(new BE_CreditNotesDocumentReferences() + { + RefDocEntr = x, + IssueDate = DateTime.Now, + RefObjType = "rot_InventoryTransfer", + Remark = "Transferencias Automatica" + }); + }); + + var credit = new + { + DocumentReferences = listaReferencia + }; + var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result; + } + return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + } + else + { + return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad); + } + } + if(entidad.Proceso.ToUpper() == "ULTIMA MILLA" && entidad.IdEstadoCubico == 23) + { + if(Proceso.U_ITCA_GNRPROC == "SOLICITUD DEV" && !Reproceso) + { + + if (string.IsNullOrEmpty(Almacen)) + { + return resultadoTransaccion.GetInformacionResultado("El motivo no tiene asignado un almacen de destino", entidad); + } + + ReturnRequestRepository returnRequestRepository = new ReturnRequestRepository(_clientFactory, _configuration); + + InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context); + BE_ResultadoTransaccion response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result; + + if (response_invoicesRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad); + } + BE_InvoicesConsulta invoices = response_invoicesRepository.ListData.FirstOrDefault(); + BE_ReturnRequest _ReturnRequest = new BE_ReturnRequest() + { + CardCode = invoices.CardCode, + CardName = invoices.CardName, + DocCurrency = invoices.DocCurrency, + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + DocObjectCode = "oReturnRequest", + PaymentGroupCode = invoices.PaymentGroupCode, + U_SYP_MOTNC = DescripcionMotivo, + U_SYP_TPONC = MotivoNotaCredito, + U_SYP_MDTO = invoices.U_SYP_MDTD, + U_SYP_MDCO = invoices.U_SYP_MDCD, + U_SYP_MDSO = invoices.U_SYP_MDSD, + U_SYP_FECHAREF = invoices.DocDate, + DocumentLines = new List() + }; + + var ListaDetalle = entidad.Detalle.Where(x => x.Estado != "C").ToList(); + ListaDetalle.ForEach(detalle => + { + var Detalle_Factura = invoices.DocumentLines.FirstOrDefault(x => x.LineNum == detalle.Item); + _ReturnRequest.DocumentLines.Add(new BE_ReturnRequestLine() + { + LineNum = detalle.Item, + BaseEntry = entidad.DocEntry, + BaseLine = Detalle_Factura.LineNum, + BatchNumbers = new List(), + Currency = invoices.DocCurrency, + ItemCode = Detalle_Factura.ItemCode, + ItemDescription = Detalle_Factura.ItemDescription, + PriceAfterVAT = Detalle_Factura.PriceAfterVAT, + Quantity = (Detalle_Factura.Quantity - detalle.CantidadPedida), + WarehouseCode = Detalle_Factura.WarehouseCode, + BaseType = 13, + U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Detalle_Factura.WarehouseCode: Almacen), + }); + }); + + var _returnRequestRepository_Result = returnRequestRepository.SetCreateReturnRequest(_ReturnRequest).Result; + if (_returnRequestRepository_Result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(_returnRequestRepository_Result.Message.ToString(), entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)_returnRequestRepository_Result.Data.DocEntry, _returnRequestRepository_Result.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + } + + #endregion + return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Registrado Correctamente", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } + }); + } + + public async Task> CreateHojaRuta(BE_HojaRutaEntities entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + if (entidad.DocEntry == 0) + { + return resultadoTransaccion.GetInformacionResultado("El campo docEntry no puede ser cero o vacio", entidad); + } + + return await Task.Run(() => + { + try + { + if (string.IsNullOrEmpty(entidad.Proceso)) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita definir el proceso para continuar con el proceso.", entidad); + } + + if (entidad.IdEstadoCubico == 0) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita indicar el IdEstado Cubico para continuar con el proceso.", entidad); + } + + int Existe = HelperProcesoPermitido.Get(entidad.Proceso, entidad.IdEstadoCubico, "HOJARUTA", out List ListaProceso); + if (Existe == 0) + { + return resultadoTransaccion.GetInformacionResultado("El Proceso y estado no se encuentra configurado para este EndPoint", entidad); + } + + HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, HelperProcesoPermitido.ConvertTimeToInteger(entidad.HoraInicio), HelperProcesoPermitido.ConvertTimeToInteger(entidad.FinRuta), entidad.CodMotivo, ListaProceso.FirstOrDefault().Code); + if (entidad.Proceso == "Picking") + { + //=== IDENTIFICA DESCRIPCION DE ESTADO + } + + return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.DocEntry.ToString(), "Registrado Correctamente", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } + }); + } + + public async Task> CerrarHojaRuta(int docEntry) + { + _metodoName = "CerrarHojaRuta"; + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + // Hoja de Ruta es un UDO en SAP (ARD_PHR) - mismo patron que + // SolicitudTransferencia/{docEntry}/cerrar (POST {recurso}({docEntry})/Close). + var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); + await connectServiceLayer.PostActionAsync($"ARD_PHR({docEntry})/Close"); + return resultadoTransaccion.GetInformacionResultado(docEntry, docEntry.ToString(), "Cerrado Correctamente", (object)null); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)null); + } + } + + } +} diff --git a/Net.Data/WMS/Recibo/IReciboRepository.cs b/Net.Data/WMS/Recibo/IReciboRepository.cs new file mode 100644 index 0000000..e249d5e --- /dev/null +++ b/Net.Data/WMS/Recibo/IReciboRepository.cs @@ -0,0 +1,12 @@ +using Net.Business.Entities; +using Net.Business.Entities.WMS.Recibo; +using Net.Connection; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Recibo +{ + public interface IReciboRepository : IRepositoryBase + { + Task> Create(BE_ReciboRequest entidad); + } +} diff --git a/Net.Data/WMS/Recibo/ReciboRepository.cs b/Net.Data/WMS/Recibo/ReciboRepository.cs new file mode 100644 index 0000000..8b45435 --- /dev/null +++ b/Net.Data/WMS/Recibo/ReciboRepository.cs @@ -0,0 +1,642 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.CreditNotes; +using Net.Business.Entities.ServicesLayer.InventoryGenEntries; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Business.Entities.ServicesLayer.PurchaseDeliveryNotes; +using Net.Business.Entities.ServicesLayer.PurchaseInvoices; +using Net.Business.Entities.ServicesLayer.PurchaseOrders; +using Net.Business.Entities.ServicesLayer.ReturnRequest; +using Net.Business.Entities.ServicesLayer.StockTransfer; +using Net.Business.Entities.WMS.Recibo; +using Net.Connection; +using Net.CrossCotting; +using Net.Data.HelperData.Correlativo; +using Net.Data.HelperData.Stock; +using Net.Data.ServicesLayer; +using Net.Data.ServicesLayer.CreditNotes; +using Net.Data.ServicesLayer.GlobalData; +using Net.Data.ServicesLayer.InventoryGenEntries; +using Net.Data.ServicesLayer.ReturnRequest; +using Net.Data.ServicesLayer.StockTransfer; +using Net.Data.WMS.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Recibo +{ + public class ReciboRepository : RepositoryBase, IReciboRepository + { + #region Variables Globales + + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + + #endregion + + public ReciboRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _clientFactory = clientFactory; + _configuration = configuration; + _aplicacionName = GetType().Name; + } + + public async Task> Create(BE_ReciboRequest entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + return await Task.Run(async () => + { + try + { + //=== INICIALIZA OBJETO DE SAP + PurchaseDeliveryNotesRepository _purchaseDeliveryNotes = new PurchaseDeliveryNotesRepository(_clientFactory, _configuration); + CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context); + + BusinessPartnersRepository businessPartnersRepository = new BusinessPartnersRepository(_clientFactory, _configuration, context); + var response_businessPartnersRepository = await businessPartnersRepository.GetBusinessPartnersByFilter(new FE_BusinessPartners() + { + CardCode = entidad.CodigoERPProveedor + }); + + if (response_businessPartnersRepository.ListData.Count() == 0) + { + return resultadoTransaccion.GetInformacionResultado("SAP: El Proveedor no se encuentra registrado en SAP", entidad); + } + + #region PROCESO POR COMPRA DE IMPORTACION + + if (entidad.IdTipo == EnumRecibo.IMPORTACION) + { + //=== INICIALIZA OBJETO DE SAP + BE_PurchaseDeliveryNotes purchaseDeliveryNotes = new BE_PurchaseDeliveryNotes + { + DocObjectCode = "oPurchaseDeliveryNotes", + DocumentLines = new List() + }; + + if (entidad.IdTipoDoc == EnumRecibo.IMPORTACION_ORDEN) + { + PurchaseInvoicesRepository purchaseInvoicesRepository = new PurchaseInvoicesRepository(_clientFactory, _configuration); + BE_ResultadoTransaccion response_purchaseInvoicesRepository = purchaseInvoicesRepository.GetPurchaseInvoices(entidad.DocEntry).Result; + if (response_purchaseInvoicesRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Factura de reserva por importaciones no se encuentra", entidad); + } + + BE_PurchaseInvoices purchaseOrders = response_purchaseInvoicesRepository.ListData.FirstOrDefault(); + purchaseDeliveryNotes.DocCurrency = purchaseOrders.DocCurrency; + purchaseDeliveryNotes.CardCode = purchaseOrders.CardCode; + purchaseDeliveryNotes.CardName = purchaseOrders.CardName; + purchaseDeliveryNotes.PaymentGroupCode = purchaseOrders.PaymentGroupCode; + purchaseDeliveryNotes.DocDate = DateTime.Now; + purchaseDeliveryNotes.DocDueDate = DateTime.Now; + purchaseDeliveryNotes.NumAtCard = entidad.DocImportacion; + purchaseDeliveryNotes.U_SYP_MDCD = entidad.U_SYP_MDCD; + purchaseDeliveryNotes.U_SYP_MDSD = entidad.U_SYP_MDSD; + purchaseDeliveryNotes.U_SYP_MDTD = entidad.U_SYP_MDTD; + entidad.Detalle.ForEach(x => + { + if (x.CantidadPedida > 0) + { + var Item = purchaseOrders.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + purchaseDeliveryNotes.DocumentLines.Add(new BE_PurchaseDeliveryNotesLine() + { + Currency = purchaseOrders.DocCurrency, + BatchNumbers = new List + { + new BE_PurchaseDeliveryNotesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (int)x.CantidadPedida + }, + }, + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = (double)x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 18, + LineNum = x.Item, + }); + } + } + }); + + var result_purchaseDeliveryNotes = _purchaseDeliveryNotes.SetCreatePurchaseDeliveryNotes(purchaseDeliveryNotes).Result; + if (result_purchaseDeliveryNotes.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_purchaseDeliveryNotes.Message, entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)result_purchaseDeliveryNotes.Data.DocEntry, result_purchaseDeliveryNotes.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + + if (entidad.IdTipoDoc == EnumRecibo.IMPORTACION_ORDEN_COMPRA) + { + PurchaseOrdersRepository purchaseOrdersRepository = new PurchaseOrdersRepository(_clientFactory, _configuration); + BE_ResultadoTransaccion response_purchaseOrdersRepository = purchaseOrdersRepository.GetPurchaseInvoices(entidad.DocEntry).Result; + + if (response_purchaseOrdersRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Orden de Compra no se encuentra", entidad); + } + + BE_PurchaseOrders purchaseOrders = response_purchaseOrdersRepository.ListData.FirstOrDefault(); + purchaseDeliveryNotes.DocCurrency = purchaseOrders.DocCurrency; + purchaseDeliveryNotes.CardCode = purchaseOrders.CardCode; + purchaseDeliveryNotes.CardName = purchaseOrders.CardName; + purchaseDeliveryNotes.PaymentGroupCode = purchaseOrders.PaymentGroupCode; + purchaseDeliveryNotes.DocDate = DateTime.Now; + purchaseDeliveryNotes.DocDueDate = DateTime.Now; + purchaseDeliveryNotes.NumAtCard = entidad.DocImportacion; + purchaseDeliveryNotes.U_SYP_MDCD = entidad.U_SYP_MDCD; + purchaseDeliveryNotes.U_SYP_MDSD = entidad.U_SYP_MDSD; + purchaseDeliveryNotes.U_SYP_MDTD = entidad.U_SYP_MDTD; + + entidad.Detalle.ForEach(x => + { + var Item = purchaseOrders.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + purchaseDeliveryNotes.DocumentLines.Add(new BE_PurchaseDeliveryNotesLine() + { + Currency = purchaseOrders.DocCurrency, + BatchNumbers = new List + { + new BE_PurchaseDeliveryNotesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (int)x.CantidadPedida + }, + }, + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = (double)x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 22, + LineNum = x.Item + }); + } + }); + + var result_purchaseDeliveryNotes = _purchaseDeliveryNotes.SetCreatePurchaseDeliveryNotes(purchaseDeliveryNotes).Result; + if (result_purchaseDeliveryNotes.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_purchaseDeliveryNotes.Message, entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)result_purchaseDeliveryNotes.Data.DocEntry, result_purchaseDeliveryNotes.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + + if (entidad.IdTipoDoc == EnumRecibo.IMPORTACION_SOL_ENTRADA) + { + GlobalDataRepository globalDataRepository = new GlobalDataRepository(_clientFactory, _configuration, context); + var Result_globalDataRepository = globalDataRepository.GetSolicitudIngreso(entidad.DocEntry).Result.ListData.FirstOrDefault(); + + BE_InventoryGenEntries _InventoryGenEntries = new BE_InventoryGenEntries() + { + DocObjectCode = "oInventoryGenEntry", + DocDate = DateTime.Now, + DocDueDate = DateTime.Now, + PaymentGroupCode = "-2", + DocCurrency = "S/", + DocRate = 1, + DocumentLines = new List(), + U_SYP_TPOENTME = Result_globalDataRepository.U_ITC_MDTI, + U_ITC_WMS_NUMINV = "", + U_ARD_PERSOLIC = Result_globalDataRepository.U_ITC_USRSOL, + Comments = Result_globalDataRepository.U_ITC_MDCM + }; + + int LineNum = 0; + entidad.Detalle.ForEach(detalle => + { + var LineaDetalle = Result_globalDataRepository.ITC_SOLINGMERDETCollection.FirstOrDefault(x => x.LineId == detalle.Item); + + var Precio = HelperStock.GetConsolidado(detalle.CodigoArticulo, Result_globalDataRepository.U_ITC_MDWC).FirstOrDefault().AvgPrice; + + _InventoryGenEntries.DocumentLines.Add(new BE_InventoryGenEntriesLine() + { + Currency = "S/", + ItemCode = detalle.CodigoArticulo, + ItemDescription = LineaDetalle.U_ITC_ITEMNAME, + Quantity = (double)detalle.CantidadPedida, + LineNum = LineNum, + PriceAfterVAT = Precio, + LineTotal = Precio * (double)detalle.CantidadPedida, + WarehouseCode = Result_globalDataRepository.U_ITC_MDWC, + AccountCode = LineaDetalle.U_ITC_ACCCODE, + CostingCode = LineaDetalle.U_ITC_CCOSTO ?? "", + BatchNumbers = new List() + { + new BE_InventoryGenEntriesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (double)detalle.CantidadPedida + } + } + }); + + LineNum++; + }); + + InventoryGenEntriesRepository inventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, context); + var inventoryGenEntries_result = inventoryGenEntries.SetCreateInventoryGenEntries(_InventoryGenEntries, false).Result; + if (inventoryGenEntries_result.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(inventoryGenEntries_result.Message.ToString(), entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)inventoryGenEntries_result.Data.DocEntry, inventoryGenEntries_result.Data.DocNum.ToString(), "Registrado Correctamente", entidad); + + } + } + + #endregion + + #region PROCESO POR COMPRA NACIONAL + + if (entidad.IdTipo == EnumRecibo.NACIONAL) + { + //=== INICIALIZA OBJETO DE SAP + BE_PurchaseDeliveryNotes purchaseDeliveryNotes = new BE_PurchaseDeliveryNotes + { + DocObjectCode = "oPurchaseDeliveryNotes", + DocumentLines = new List() + }; + + PurchaseOrdersRepository purchaseOrdersRepository = new PurchaseOrdersRepository(_clientFactory, _configuration); + BE_ResultadoTransaccion response_purchaseOrdersRepository = purchaseOrdersRepository.GetPurchaseInvoices(entidad.DocEntry).Result; + + if (response_purchaseOrdersRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Orden de Compra no se encuentra", entidad); + } + + BE_PurchaseOrders purchaseOrders = response_purchaseOrdersRepository.ListData.FirstOrDefault(); + purchaseDeliveryNotes.DocCurrency = purchaseOrders.DocCurrency; + purchaseDeliveryNotes.CardCode = purchaseOrders.CardCode; + purchaseDeliveryNotes.CardName = purchaseOrders.CardName; + purchaseDeliveryNotes.PaymentGroupCode = purchaseOrders.PaymentGroupCode; + purchaseDeliveryNotes.DocDate = DateTime.Now; + purchaseDeliveryNotes.DocDueDate = DateTime.Now; + purchaseDeliveryNotes.NumAtCard = entidad.DocImportacion; + purchaseDeliveryNotes.U_SYP_MDCD = entidad.U_SYP_MDCD; + purchaseDeliveryNotes.U_SYP_MDSD = entidad.U_SYP_MDSD; + purchaseDeliveryNotes.U_SYP_MDTD = entidad.U_SYP_MDTD; + + entidad.Detalle.ForEach(x => + { + var Item = purchaseOrders.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + purchaseDeliveryNotes.DocumentLines.Add(new BE_PurchaseDeliveryNotesLine() + { + Currency = purchaseOrders.DocCurrency, + BatchNumbers = new List + { + new BE_PurchaseDeliveryNotesBatchNumbers() + { + BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), + Quantity = (int)x.CantidadPedida + }, + }, + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = (double)x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 22, + LineNum = x.Item + }); + } + }); + + var result_purchaseDeliveryNotes = _purchaseDeliveryNotes.SetCreatePurchaseDeliveryNotes(purchaseDeliveryNotes).Result; + if (result_purchaseDeliveryNotes.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_purchaseDeliveryNotes.Message, entidad); + } + + return resultadoTransaccion.GetInformacionResultado((int)result_purchaseDeliveryNotes.Data.DocEntry, result_purchaseDeliveryNotes.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + + #endregion + + #region PROCESO DE NOTA DE CREDITO + + if (entidad.IdTipo == EnumRecibo.DEVOLUCION) + { + BE_CreditNotesNotes creditNotesNotes = new BE_CreditNotesNotes + { + DocObjectCode = "oCreditNotes", + DocumentLines = new List() + }; + + ReturnRequestRepository returnRequestRepository = new ReturnRequestRepository(_clientFactory, _configuration); + BE_ResultadoTransaccion response_purchaseOrdersRepository = returnRequestRepository.GetRequestReturn(entidad.DocEntry).Result; + + if (response_purchaseOrdersRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: Solicitud de Devolucion no se encuentra", entidad); + } + + BE_ReturnRequest returnRequest = response_purchaseOrdersRepository.ListData.FirstOrDefault(); + + #region OBTIENE FACTURAS RELACIONADA A LA SOLICITUD DE DEVOLUCION + + List ListaDocEntryFactura = returnRequest.DocumentLines.Select(x => !x.BaseEntry.HasValue? 0: x.BaseEntry.Value).Distinct().Where(x => x > 0).ToList(); + BE_InvoicesConsulta _Invoice = null; + ListaDocEntryFactura.ForEach(DocEntry => + { + var _InvoiceRepository = new InvoiceRepository(_clientFactory, _configuration, context); + + var _Invoice_Result = _InvoiceRepository.GetInvoice(DocEntry).Result; + if (_Invoice_Result.ListData.Count() > 0) + { + _Invoice = _Invoice_Result.ListData.FirstOrDefault(); + } + }); + string SerieOrigen = ""; + string U_SYP_MDTO = ""; + string U_SYP_MDCO = ""; + string U_SYP_MDSO = ""; + DateTime DocDate; + + if (_Invoice == null) + { + SerieOrigen = returnRequest.U_SYP_MDSO; + U_SYP_MDTO = returnRequest.U_SYP_MDTO; + U_SYP_MDCO = returnRequest.U_SYP_MDCO; + U_SYP_MDSO = returnRequest.U_SYP_MDSO; + DocDate = returnRequest.U_SYP_FECHAREF; + } + else + { + SerieOrigen = _Invoice.U_SYP_MDSD; + U_SYP_MDTO = _Invoice.U_SYP_MDTD; + U_SYP_MDCO = _Invoice.U_SYP_MDCD; + U_SYP_MDSO = _Invoice.U_SYP_MDSD; + DocDate = _Invoice.DocDate; + } + + #endregion + string Serie = SerieOrigen == "03" ? "BC10" : "FC10"; + string Correlativo = HelperCorrelativo.Get(Serie); + creditNotesNotes.DocCurrency = returnRequest.DocCurrency; + creditNotesNotes.CardCode = returnRequest.CardCode; + creditNotesNotes.CardName = returnRequest.CardName; + creditNotesNotes.PaymentGroupCode = returnRequest.PaymentGroupCode; + creditNotesNotes.DocDate = DateTime.Now; + creditNotesNotes.DocDueDate = DateTime.Now; + //creditNotesNotes.NumAtCard = entidad.DocImportacion; + creditNotesNotes.NumAtCard = ("07-" + Serie +"-" + Correlativo); + creditNotesNotes.U_SYP_MDTO = U_SYP_MDTO; + creditNotesNotes.U_SYP_MDCO = U_SYP_MDCO; + creditNotesNotes.U_SYP_MDSO = U_SYP_MDSO; + creditNotesNotes.U_SYP_MOTNC = returnRequest.U_SYP_MOTNC; + creditNotesNotes.U_SYP_TPONC = returnRequest.U_SYP_TPONC; + creditNotesNotes.U_SYP_MDCD = Correlativo; + creditNotesNotes.U_SYP_MDSD = Serie; + creditNotesNotes.U_SYP_MDTD = "07"; + creditNotesNotes.U_SYP_FECHAREF = DocDate.ToString("yyyy-MM-dd"); + entidad.Detalle.ForEach(x => + { + var Item = returnRequest.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item); + if (Item != null) + { + creditNotesNotes.DocumentLines.Add(new BE_CreditNotesLine() + { + Currency = returnRequest.DocCurrency, + BatchNumbers = new List + { + new BE_CreditNotesBatchNumbers() + { + BatchNumber = x.LoteProducto, + Quantity = (int)x.CantidadPedida + }, + }, + ItemCode = Item.ItemCode, + ItemDescription = Item.ItemDescription, + PriceAfterVAT = Item.PriceAfterVAT, + Quantity = x.CantidadPedida, + WarehouseCode = Item.WarehouseCode, + BaseEntry = entidad.DocEntry, + BaseLine = x.Item, + BaseType = 234000031, + LineNum = x.Item + }); + } + }); + + if (_Invoice == null) + { + //=== REALIZA DISTRIBUCION DE STOCK POR LOTE + creditNotesNotes.DocumentLines.ForEach(line => + { + #region CONSULTA A HANA + + var ListaStock = HelperStock.Get(line.ItemCode, line.WarehouseCode); + if (ListaStock.Count > 0) + { + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= (double)CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = (double)CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < (double)CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = (double)Lote.OnHandQty }); + CantidadPendiente -= (decimal)Lote.OnHandQty; + } + } + }); + } + else + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), Quantity = (double)line.Quantity }); + } + + #endregion + }); + } + else + { + creditNotesNotes.DocumentLines.ForEach(line => + { + var ReferenciaFactura = returnRequest.DocumentLines.FirstOrDefault(t => t.LineNum == line.LineNum); + var ListaStock = _Invoice.DocumentLines.FirstOrDefault(InvoiceLine => InvoiceLine.LineNum == ReferenciaFactura.BaseLine).BatchNumbers; + if (ListaStock.Count > 0) + { + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock; + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.Quantity >= (double)CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = (double)CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.Quantity < (double)CantidadPendiente) + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = (double)Lote.Quantity }); + CantidadPendiente -= (decimal)Lote.Quantity; + } + } + }); + } + else + { + line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), Quantity = (double)line.Quantity }); + } + }); + } + + var result_creditNotesRepository = _creditNotesRepository.SetCreateCreditNotes(creditNotesNotes).Result; + if (result_creditNotesRepository.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado(result_creditNotesRepository.Message, entidad); + } + else + { + List ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList(); + List ListDocEntry = new List(); + ListaUnicaAlmacen.ForEach(Almacen => + { + List ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList(); + ListaUnicaAlmDestino.ForEach(Destino => + { + if (Almacen != Destino) + { + BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico(); + Transfer.FromWarehouse = Almacen; + Transfer.ToWarehouse = Destino; + Transfer.DocDate = creditNotesNotes.DocDate; + Transfer.TaxDate = creditNotesNotes.DocDate; + Transfer.DueDate = creditNotesNotes.DocDueDate; + Transfer.U_SYP_MDTS = "TSI"; + Transfer.U_SYP_MDMT = "24"; + Transfer.PriceList = -2; + var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList(); + var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList(); + + Transfer.StockTransferLines = new List(); + Transfer.DocumentReferences = new List(); + + ListaUnicaArticulo.ForEach(x => + { + var ListLote = new List(); + ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().BatchNumbers.ForEach(r => + { + ListLote.Add(new BE_StockTransferLineBatchNumber() + { + BatchNumber = r.BatchNumber, + Quantity = r.Quantity + }); + }); + Transfer.StockTransferLines.Add(new BE_StockTransferLine() + { + ItemCode = x, + ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription, + Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)), + WarehouseCode = Destino, + FromWarehouseCode = Almacen, + BatchNumbers = ListLote + }); + + //=== AGREGA DOCUMENTO REFERENCIA + Transfer.DocumentReferences = new List + { + new BE_StockTransferDocumentReferences() + { + RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry, + RefObjType = "rot_SalesCreditNote", + IssueDate = DateTime.Now, + Remark = "Nota de Credito", + } + }; + }); + + //=== CREA INSTANCIA PARA CONECTAR A SAP + StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); + var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; + if (ResultTransfer.StatusCode == -1) + { + + } + else + { + ListDocEntry.Add((int)ResultTransfer.Data.DocEntry); + } + } + }); + }); + + if (ListDocEntry.Count > 0) + { + var listaReferencia = new List(); + ListDocEntry.ForEach(x => + { + listaReferencia.Add(new BE_CreditNotesDocumentReferences() + { + RefDocEntr = x, + IssueDate = DateTime.Now, + RefObjType = "rot_InventoryTransfer", + Remark = "Transferencias Automatica" + }); + }); + + var credit = new + { + DocumentReferences = listaReferencia + }; + var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result; + } + return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + + //return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad); + } + + #endregion + + return resultadoTransaccion.GetInformacionResultado(0, "", "Se registro correctamente...!!!", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } + }); + } + } +} diff --git a/Net.Data/WMS/SolicitudTransferencia/ISolicitudTransferenciaRepository.cs b/Net.Data/WMS/SolicitudTransferencia/ISolicitudTransferenciaRepository.cs new file mode 100644 index 0000000..7de51c2 --- /dev/null +++ b/Net.Data/WMS/SolicitudTransferencia/ISolicitudTransferenciaRepository.cs @@ -0,0 +1,12 @@ +using Net.Business.Entities; +using Net.Business.Entities.WMS.SolicitudTransferencia; +using System.Threading.Tasks; + +namespace Net.Data.WMS.SolicitudTransferencia +{ + public interface ISolicitudTransferenciaRepository + { + Task> Update(int docEntry, BE_SolicitudTransferenciaPatchRequest entidad); + Task> Cerrar(int docEntry); + } +} diff --git a/Net.Data/WMS/SolicitudTransferencia/SolicitudTransferenciaRepository.cs b/Net.Data/WMS/SolicitudTransferencia/SolicitudTransferenciaRepository.cs new file mode 100644 index 0000000..50f9ad6 --- /dev/null +++ b/Net.Data/WMS/SolicitudTransferencia/SolicitudTransferenciaRepository.cs @@ -0,0 +1,109 @@ +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer.InventoryTransferRequest; +using Net.Business.Entities.WMS.SolicitudTransferencia; +using Net.Connection.ServiceLayer; +using Net.CrossCotting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Net.Data.WMS.SolicitudTransferencia +{ + // Modulo 100% nuevo (sin equivalente en el .NET original) - porte 1:1 de + // itca_api_sap_wms_python/app/services/solicitud_transferencia_service.py. + // Actualiza y cierra documentos InventoryTransferRequests (Solicitud de + // Traslado) en SAP Business One via Service Layer. Ver + // docs/SOLICITUD_TRANSFERENCIA.md para el detalle completo del contrato. + public class SolicitudTransferenciaRepository : ISolicitudTransferenciaRepository + { + private readonly string _aplicacionName; + private readonly IConfiguration _configuration; + private readonly IHttpClientFactory _clientFactory; + + public SolicitudTransferenciaRepository(IHttpClientFactory clientFactory, IConfiguration configuration) + { + _aplicacionName = GetType().Name; + _configuration = configuration; + _clientFactory = clientFactory; + } + + // Devuelve null en exito (el caller arma un BE_ResultadoTransaccion 200 con + // body - ver el controller; no responde 204 porque muchos clientes HTTP, + // incluido HttpClient de .NET, no leen el body de un 204 - ver + // docs/SOLICITUD_TRANSFERENCIA.md). + // + // El PATCH SOLO actualiza cantidades de linea existentes en SAP - no toca + // fechas, almacenes ni ningun otro campo del documento - y ELIMINA una + // linea cuando Cantidad = 0. Confirmado contra el Service Layer real de QA: + // alcanza con mandar LineNum + Quantity por linea junto con el header + // B1S-ReplaceCollectionsOnPatch: true, que le indica a Service Layer que + // trate StockTransferLines como reemplazo COMPLETO del array, no un merge + // parcial. SAP ademas RECHAZA una linea mandada explicita con Quantity: 0, + // por eso se omite del array en vez de mandarla en cero. + // + // Al ser un reemplazo completo, SAP TAMBIEN exige el Rate real de cada + // linea (hallazgo de QA, no cubierto en la primera tanda de pruebas) - por + // eso se hace un GET previo para leerlo y reenviarlo, en vez de mandar + // Rate: 0 fijo (pisaria la valorizacion real de la linea). + public async Task> Update(int docEntry, BE_SolicitudTransferenciaPatchRequest entidad) + { + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion("Update", _aplicacionName); + + try + { + var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); + + var doc = (await connectServiceLayer.GetAsync($"InventoryTransferRequests({docEntry})", 0, true)).FirstOrDefault(); + var ratesByLine = (doc?.StockTransferLines ?? new List()) + .ToDictionary(l => l.LineNum, l => l.Rate); + + var lines = new List(); + foreach (var detalle in entidad.Detalle ?? new List()) + { + if (detalle.Cantidad == 0) continue; + + if (!ratesByLine.TryGetValue(detalle.Linea, out var rate)) + { + return resultadoTransaccion.GetInformacionResultado($"La linea {detalle.Linea} no existe en la Solicitud de Traslado {docEntry}", (object)entidad); + } + + lines.Add(new { LineNum = detalle.Linea, Quantity = detalle.Cantidad, Rate = rate }); + } + + await connectServiceLayer.PatchNoContentAsync( + $"InventoryTransferRequests({docEntry})", + new { StockTransferLines = lines }, + new Dictionary { ["B1S-ReplaceCollectionsOnPatch"] = "true" }); + + return null; + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)entidad); + } + } + + // Cierra el documento completo. Funcionalidad nueva (no existe en el .NET + // original) - SAP Service Layer cierra documentos via POST a la sub-ruta + // /Close, mismo patron que Picking/HojaRuta/Cerrar. Devuelve null en exito + // (el caller arma el BE_ResultadoTransaccion 200 con body). + public async Task> Cerrar(int docEntry) + { + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion("Cerrar", _aplicacionName); + + try + { + var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); + await connectServiceLayer.PostActionAsync($"InventoryTransferRequests({docEntry})/Close"); + return null; + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)null); + } + } + } +} diff --git a/Net.Data/WMS/Transferencia/ITransferenciaRepository.cs b/Net.Data/WMS/Transferencia/ITransferenciaRepository.cs new file mode 100644 index 0000000..05e6d8e --- /dev/null +++ b/Net.Data/WMS/Transferencia/ITransferenciaRepository.cs @@ -0,0 +1,11 @@ +using Net.Business.Entities; +using Net.Business.Entities.WMS.Transferencia; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Transferencia +{ + public interface ITransferenciaRepository + { + Task> Create(BE_TransferenciaRequest entidad); + } +} diff --git a/Net.Data/WMS/Transferencia/TransferenciaRepository.cs b/Net.Data/WMS/Transferencia/TransferenciaRepository.cs new file mode 100644 index 0000000..a78e107 --- /dev/null +++ b/Net.Data/WMS/Transferencia/TransferenciaRepository.cs @@ -0,0 +1,184 @@ +using iTextSharp.text; +using Microsoft.Extensions.Configuration; +using Net.Business.Entities; +using Net.Business.Entities.ServicesLayer; +using Net.Business.Entities.ServicesLayer.Invoices; +using Net.Business.Entities.ServicesLayer.Items; +using Net.Business.Entities.ServicesLayer.StockTransfer; +using Net.Business.Entities.WMS.Transferencia; +using Net.Connection; +using Net.CrossCotting; +using Net.Data.HelperData.Invoices; +using Net.Data.HelperData.Stock; +using Net.Data.ServicesLayer; +using Net.Data.ServicesLayer.StockTransfer; +using Sap.Data.Hana; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Net.Data.WMS.Transferencia +{ + public class TransferenciaRepository : RepositoryBase, ITransferenciaRepository + { + #region Variables Globales + private string _aplicacionName; + private string _metodoName; + private readonly Regex regex = new Regex(@"<(\w+)>.*"); + + private readonly IHttpClientFactory _clientFactory; + private readonly IConfiguration _configuration; + #endregion + + public TransferenciaRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context) + { + _clientFactory = clientFactory; + _configuration = configuration; + _aplicacionName = GetType().Name; + } + + public async Task> Create(BE_TransferenciaRequest entidad) + { + _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); + + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + return await Task.Run(() => + { + try + { + //=== CREA INSTANCIA PARA CONECTAR A SAP + StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); + + BE_StockTransfer StockTransfer = new BE_StockTransfer + { + DocDate = entidad.FechaOrden, + DueDate = entidad.FechaOrden, + TaxDate = entidad.FechaOrden, + FromWarehouse = entidad.CodigoSubAlmacenOrigen, + ToWarehouse = entidad.CodigoSubAlmacenDestino, + Comments = "Transferencia Generado desde Cubico - SAP", + StockTransferLines = new List() + }; + + entidad.TransferenciaDetalles.ForEach(x => + { + var Detalle = new BE_StockTransferLine + { + FromWarehouseCode = entidad.CodigoSubAlmacenOrigen, + WarehouseCode = entidad.CodigoSubAlmacenDestino, + ItemCode = x.CodigoArticulo, + Quantity = (double)x.CantidadPedida, + BaseLine = entidad.DocEntry == 0 ? null : (int?)x.Item, + BaseEntry = entidad.DocEntry == 0 ? null : (int?)entidad.DocEntry, + BaseType = entidad.DocEntry == 0 ? null : "InventoryTransferRequest", + LineNum = x.Item, + BatchNumbers = new List() + }; + StockTransfer.StockTransferLines.Add(Detalle); + }); + + // == REALIZA DISTRIBUCION DE STOCK POR LOTE / ALMACEN + StockTransfer.StockTransferLines.ForEach(line => + { + #region CONSULTA A HANA + + List ListaStock = HelperStock.Get(line.ItemCode, line.FromWarehouseCode); + var CantidadPendiente = line.Quantity; + var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList(); + ListOrdenadaFecha.ForEach(Lote => + { + if (CantidadPendiente > 0) + { + if (Lote.OnHandQty >= CantidadPendiente) + { + line.BatchNumbers.Add(new BE_StockTransferLineBatchNumber() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente }); + CantidadPendiente = 0; + } + else if (Lote.OnHandQty < CantidadPendiente) + { + line.BatchNumbers.Add(new BE_StockTransferLineBatchNumber() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty }); + CantidadPendiente -= Lote.OnHandQty; + } + } + }); + + #endregion + }); + + //=== SI EL ALMACEN ES ALM99, FUERZA EL AMARRE CON LA ENTRADA DE MERCANCIA + if (entidad.CodigoSubAlmacenOrigen == "ALM99") + { + StockTransfer.U_SYP_MDMT = "21"; + int DocEntry_Entada = entidad.DocEntryEM; //HelperInvoice.Get(entidad.NumOrden); + if(DocEntry_Entada > 0) + { + PurchaseDeliveryNotesRepository _purchaseDeliveryNotesRepository = new PurchaseDeliveryNotesRepository(_clientFactory, _configuration); + var _purchaseDeliveryNotesRepository_Response = _purchaseDeliveryNotesRepository.GetPurchaseDeliveryNotes(DocEntry_Entada).Result.ListData.FirstOrDefault(); + + //=== RESETEA STOCK POR LOTES + StockTransfer.StockTransferLines.ForEach(line => + { + var Lines = _purchaseDeliveryNotesRepository_Response.DocumentLines.FirstOrDefault(line_purchaseDeliveryNotesRepository_Response => line_purchaseDeliveryNotesRepository_Response.BaseLine == line.LineNum); + line.BatchNumbers = new List(); + + //=== AGREGA LOTES + Lines.BatchNumbers.ForEach(lotes => + { + line.BatchNumbers.Add(new BE_StockTransferLineBatchNumber() + { + BatchNumber = lotes.BatchNumber, + Quantity = lotes.Quantity, + }); + }); + + line.BaseLine = Lines.LineNum; + line.BaseType = "PurchaseDeliveryNotes"; + line.BaseEntry = DocEntry_Entada; + }); + } + } + + var ResultTransaction = stockTransferRepository.StockTransfer(StockTransfer).Result; + if (ResultTransaction.StatusCode == -1) + { + return resultadoTransaccion.GetInformacionResultado(ResultTransaction.Message.ToString(), entidad); + } + + // === SOLO SE EJECUTA CUANDO TIENE UN DOCUMENTO BASE [SOLICITUD DE TRASLADO] + if (entidad.DocEntry != 0) + { + var Result_SolicitudTraslado = stockTransferRepository.GetInventoryTransferRequest(entidad.DocEntry).Result; + if (Result_SolicitudTraslado.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La solicitud no se encuentra", entidad); + } + var _SolicitudTraslado = Result_SolicitudTraslado.ListData.FirstOrDefault(); + + // === SOLO CIERRA CUANDO EL DOCUMENTO ESTA ABIERTO + if (_SolicitudTraslado.DocumentStatus == "bost_Open") + { + var Response_Close = stockTransferRepository.CloseInventoryTransferRequest(entidad.DocEntry).Result; + if (Response_Close.DocEntry == -1) + { + return resultadoTransaccion.GetInformacionResultado("SAP: La Solicitud no se puede cerrar en automatico", entidad); + } + } + } + + return resultadoTransaccion.GetInformacionResultado((int)ResultTransaction.Data.DocEntry, ResultTransaction.Data.DocNum.ToString(), "Registrado Correctamente", entidad); + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } + }); + } + + + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..aafadd6 --- /dev/null +++ b/README.md @@ -0,0 +1,149 @@ +# ITCA_API_SAP_WMS (.NET) — build, publish y despliegue en IIS + +API de integración WMS ↔ SAP Business One (Service Layer + HANA directo), +**ASP.NET Core 3.1**. Para contexto de por qué este proyecto sigue activo +(hay una reescritura en Python en paralelo) ver [`CLAUDE.md`](./CLAUDE.md). + +## Requisitos para compilar + +- .NET Core 3.1 SDK. +- Cliente HANA .NET instalado en + `C:\Program Files\sap\hdbclient\dotnetcore\v2.1\Sap.Data.Hana.Core.v2.1.dll` + (ruta hardcodeada vía `HintPath` en los `.csproj` de `Net.Data` y + `Net.Business.Services` — sin esto no compila ningún proyecto que dependa + de HANA). +- **Compilar desde macOS/Linux**: el `HintPath` es relativo (6 niveles hacia + arriba + `Program Files\sap\...`). Se puede compilar copiando el repo a + `/a/b/c/d/repo/` y poniendo la DLL en + `/Program Files/sap/hdbclient/dotnetcore/v2.1/` — así el `HintPath` + resuelve sin tocar los `.csproj`. (Pasar `AssemblySearchPaths` por línea + de comandos NO sirve: rompe la resolución del framework.) + +## Configuración de HANA (`appsettings.json`, sección `Hana`) + +Las credenciales y el esquema de HANA ya **no** están fijos en el código; hay +un único lugar, `LocalData.Configure(...)` (`Net.Data/LocalData.cs`), que se +llama desde `Startup`: + +```json +"Hana": { + "server": "192.168.0.13:30015", + "user": "", + "password": "", + "schema": "" +} +``` + +- `schema` es opcional: si no está, se usa `SapServiceLayer:company` (si no hay ninguno de los dos la app no arranca, no hay valor por defecto), de modo + que lecturas por HANA (`CALL ""."ITCA_..."`) y escrituras por + Service Layer apunten siempre a la misma compañía. +- **Si falta la sección `Hana` la app no arranca** (`InvalidOperationException` + clara en `LocalData.Configure`). Al desplegar sobre un sitio existente hay + que agregarla a su `appsettings.json` **antes** de iniciar el pool. + +## Correr localmente + +``` +dotnet run --project Net.Business.Services +``` + +Swagger queda en la raíz (`RoutePrefix = ""` en `Startup.cs`): `http://localhost:/`. + +## Generar el publish para IIS + +``` +dotnet publish Net.Business.Services/Net.Business.Services.csproj -c Release -r win-x64 --self-contained false -o +``` + +- `-r win-x64 --self-contained false`: genera un `.exe` nativo (apphost) de + 64 bits que no incluye el runtime — depende de que el servidor ya tenga el + **ASP.NET Core 3.1 Hosting Bundle** instalado (confirmarlo con + `dotnet --list-runtimes` en el servidor: debe listar + `Microsoft.AspNetCore.App 3.1.x` y `Microsoft.NETCore.App 3.1.x`). +- El `.xml` de comentarios (`ITCA_API_SAP_WMS.xml`, que Swagger necesita vía + `IncludeXmlComments` en `Startup.cs`) ya se genera solo en Release desde + que se sacó la condición `Debug|AnyCPU` del `.csproj` — si en algún + momento vuelve a faltar en el output del publish, revisar que esa + propiedad (`DocumentationFile`) siga sin estar condicionada a Debug. +- `dotnet publish` transforma automáticamente el `processPath` del + `web.config` para que apunte al `.exe` publicado — **no** copiar el + `web.config` del código fuente (ese apunta a `bin\Debug\...`, es el de + desarrollo) a una carpeta de publish. + +## Desplegar/actualizar un sitio en IIS + +### Si el sitio YA corre desde una carpeta de publish (actualización de versión) + +1. Detener el Application Pool del sitio (libera los locks de los `.dll`/`.exe`). +2. Copiar el contenido del nuevo publish **sin tocar** `appsettings.json` ni + `web.config` existentes — esos quedan tal cual están configurados en ese + servidor/ambiente (pueden tener valores distintos a los del repo, ej. + `SapServiceLayer:company` apuntando a una base SAP distinta de QA/prod). +3. Iniciar el Application Pool. + +### Si el sitio corre directo desde el código fuente (`bin\Debug\...`) + +Así corre al menos un ambiente real (`CLONE-SRV-WEB`, ruta física +`...\BackEnd\Desarrollo\BackEnd\Net.Business.Services`, `web.config` con +`processPath="bin\Debug\netcoreapp3.1\ITCA_API_SAP_WMS.exe"`) — ahí **no** +se usa `dotnet publish`, se compila in situ: + +1. Detener el Application Pool primero (si no, falla la compilación por + archivos en uso). +2. Copiar los `.cs`/`.csproj` que cambiaron a las mismas rutas relativas + dentro de la solución en el servidor (no hace falta tocar ningún + `.csproj` para agregar archivos nuevos — son proyectos SDK-style con + glob automático de `**/*.cs`). +3. Compilar la solución ahí (Visual Studio → Build Solution en Debug, o + `dotnet build` desde la carpeta de la solución). +4. Iniciar el Application Pool. + +### Checklist de configuración del Application Pool (IIS Manager, una sola vez por pool nuevo) + +- **.NET CLR Version**: Sin código administrado (No Managed Code). +- **Configuración avanzada → Habilitar aplicaciones de 32 bits**: **False** + (el `.exe`/DLLs son de 64 bits — con esto en True da + `500.32 Failed to load .NET Core host`, bitness mismatch). +- **Configuración avanzada → Cargar perfil de usuario (Load User Profile)**: + **True** — sin esto, arranque falla con `ErrorCode '0x8007023e'` + (excepción no manejada al iniciar el proceso in-process). +- **Permisos de carpeta**: `IIS AppPool\` con **Lectura y + ejecución** sobre toda la carpeta del sitio, y **Modificar** sobre la + subcarpeta `logs\` (para que `stdoutLogEnabled` pueda escribir si hace + falta diagnosticar). + +### Diagnóstico de errores de arranque + +1. Visor de eventos de Windows → Registros de Windows → Aplicación → buscar + el evento de `IIS AspNetCoreModule V2` más reciente — casi siempre trae + el error real. +2. Si no alcanza, poner `stdoutLogEnabled="true"` en el `web.config` de esa + carpeta y revisar `.\logs\stdout_*.log` después de reciclar el pool. + +### Editar `appsettings.json` de un sitio ya desplegado + +No hace falta detener el Application Pool para editarlo (no queda +bloqueado como los binarios) — pero conviene **reciclar el pool** después +de guardar, para garantizar que el valor nuevo se relea (el host usa +`Host.CreateDefaultBuilder`, que ya trae `reloadOnChange: true` para +`appsettings.json`, pero no vale la pena depender de eso para un cambio +puntual). + +El nombre de la base SAP (`CompanyDB`) se configura en +`SapServiceLayer:company` dentro de `appsettings.json` — lo lee +`ConnectionServiceLayer.cs` (`_company = configuration["SapServiceLayer:company"]`) +para armar el body del `Login` contra el Service Layer. + +## Riesgos de seguridad heredados (documentados, no corregidos sin coordinar antes) + +- `appsettings.json` tiene credenciales reales en texto plano (SAP Service + Layer, **HANA `B1ADMIN`**, semilla JWT) — no hay `git` en esta carpeta; si alguna vez se versiona o se sube + a un remoto compartido, hay que decidir qué hacer con ese archivo primero. +- `B1ADMIN` es un usuario administrador de SAP B1; la API solo necesita + ejecutar los `ITCA_*` y leer algunas tablas. Conviene un usuario HANA de + permisos mínimos y rotar la contraseña (estuvo en texto plano en el código + y en el historial git del repo antiguo archivado). +- `ValidarCertificado` en `ConnectionServiceLayer.cs` acepta cualquier + certificado TLS (`return true;` siempre) — bypass de validación de + certificado hacia el Service Layer, igual criterio que + `SERVICE_LAYER_VERIFY_SSL=false` en la reescritura Python. diff --git a/docs/PICKING.md b/docs/PICKING.md new file mode 100644 index 0000000..9680129 --- /dev/null +++ b/docs/PICKING.md @@ -0,0 +1,272 @@ +# Cambio de negocio a portar — Picking diurno/nocturno + +Requerimiento de negocio **sin equivalente en este `.NET`**: las +notificaciones de Picking durante el día ya no deben crear documentos +transaccionales en SAP inmediatamente — eso causaba que el WMS reportara +éxito sin que SAP reflejara nada. Especificación traducida 1:1 de la +implementación ya validada en Python +(`itca_api_sap_wms_python/app/services/picking_service.py`, +`app/schemas/picking.py`, `app/api/routes/picking.py`). + +Ver también [`PORTE_FUNCIONALIDAD_NUEVA.md`](./PORTE_FUNCIONALIDAD_NUEVA.md) +para el detalle de un bug de SQL injection real (`HelperProcesoPiciking.Set`) +que hay que corregir como parte de este mismo trabajo, porque es +exactamente el código que este cambio va a aislar y reusar. + +## Flujo de negocio + +La hoja de ruta contiene varias facturas. El repartidor va notificando el +estado de cada factura a medida que llega a cada punto de entrega +(**preliminar**, sin crear nada en SAP). Al volver a la oficina, el tercero +recorre esas mismas facturas con un `FOR` de su lado llamando otra vez al +mismo endpoint pero en modo **cierre** (ahí sí se crean los documentos SAP), +y al final cierra la hoja de ruta completa **una sola vez**. + +## Resumen del contrato + +| Método | Ruta | Cambia hoy | Qué hace | +|---|---|---|---| +| `POST` | `/api/picking` | **Sí** — agrega campo `Notificacion` | `"cierre"` → lógica actual completa (crea documento SAP); cualquier otro valor/ausente → solo actualiza estado en HANA, nunca toca SAP. | +| `POST` | `/api/picking/ruta` | No | Sin cambios — `CreateHojaRuta` ya existe y sigue igual. | +| `POST` | `/api/picking/hojaruta/{docEntry}/cerrar` | **Nuevo** | Cierra el UDO `ARD_PHR` completo en SAP. Sin body. | + +## 1. Campo `Notificacion` en `POST /api/Picking` + +### DTO/Entidad — agregar una propiedad + +**Archivo**: `Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs` — agregar: +```csharp +public string Notificacion { get; set; } // "preliminar" | "cierre"; cualquier otro valor o ausente = "preliminar" +``` + +**Archivo**: `Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs` — agregar la +misma propiedad **y** copiarla en `RetornaModelo()`: +```csharp +public string Notificacion { get; set; } + +public BE_PickingRequest RetornaModelo() +{ + return new BE_PickingRequest() + { + // ... resto de los campos existentes, sin tocar ... + Notificacion = Notificacion, + }; +} +``` + +### Dónde cortar la lógica — `PickingRepository.Create` + +**Archivo**: `Net.Data/WMS/Picking/PickingRepository.cs`, método `Create`. + +La buena noticia: el corte es **un único early-return**, justo después de la +línea que ya actualiza el estado en HANA — no hace falta duplicar ninguna de +las validaciones de arriba (a diferencia de la versión Python, que sí +duplicó el bloque de validación en una función separada porque Python +separa `actualizar_estado()`/`create()` en dos funciones independientes; acá +alcanza con un `if` adentro del mismo método). + +```csharp +// ... validaciones existentes sin cambios (lineas 51-93: DocEntry, Proceso, +// IdEstadoCubico, HelperProcesoPermitido.Get, desambiguacion Existe > 1) ... + +//=== REALIZA PROCESO COMPLETO DE ACTUALIZACION +HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code); +// <-- linea 96 actual, sin tocar + +// === NUEVO: notificacion preliminar (diurna) - nunca toca SAP +if (!string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase)) +{ + return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad); +} + +#region PROCESO DE NOTA DE CREDITO +// ... todo el resto del metodo (lineas 98-333 actuales) sin ninguna modificacion ... +#endregion +``` + +Es decir: **todo lo que hoy hace `Create()` (líneas 45-341 completas)** sigue +siendo exactamente la lógica de `notificacion == "cierre"` — no se toca nada +de ahí. Solo se agrega el `if` de corte después de la línea 96. + +> **Nota de contrato**: `detalle` ya es obligatorio hoy en este endpoint (la +> validación de arriba lo necesita para desambiguar `Existe > 1`), así que no +> hace falta agregar ninguna validación nueva ahí — la versión Python +> solo lo documentó explícito porque separó la función, acá ya viene gratis +> al reusar el mismo método. + +### Bodies de ejemplo + +**Notificación preliminar** (reparto en curso — `Notificacion` ausente o +distinto de `"cierre"`): +```json +{ + "numOrden": "OT-2026-001", + "docEntry": 500, + "proceso": "DESPACHO", + "codMotivo": "M01", + "idEstadoCubico": 6, + "codigoAlmacen": "ALM01", + "detalle": [ + { "item": 0, "codigoArticulo": "ART-001", "cantidadPedida": 3, "estado": "C" } + ] +} +``` + +**Cierre** (mismo shape, agrega `notificacion: "cierre"` — crea el documento +SAP real, misma respuesta que hoy): +```json +{ + "numOrden": "OT-2026-001", + "docEntry": 500, + "proceso": "DESPACHO", + "codMotivo": "M01", + "idEstadoCubico": 6, + "codigoAlmacen": "ALM01", + "notificacion": "cierre", + "detalle": [ + { "item": 0, "codigoArticulo": "ART-001", "cantidadPedida": 3, "estado": "C" } + ] +} +``` + +### Respuesta — notificación preliminar (éxito) + +```json +{ + "docEntry": 500, + "docNum": "OT-2026-001", + "statusCode": 200, + "message": "Estado actualizado correctamente", + "error": null, + "appName": "PickingRepository", + "methodName": "Create", + "listData": null, + "data": { "...": "eco del PickingRequest enviado" }, + "nombreEstacion": "SERVER-WMS" +} +``` + +(La respuesta de cierre no cambia respecto a la que ya devuelve `Create()` +hoy — ver el controller existente.) + +## 2. `POST /api/Picking/HojaRuta/{docEntry}/Cerrar` (nuevo) + +Cierra la Hoja de Ruta completa en SAP — se llama **una sola vez**, después +de que el tercero terminó el `FOR` de cierre por cada factura. + +- **Hoja de Ruta es un UDO en SAP**: `ARD_PHR`. +- **SAP Service Layer**: `POST ARD_PHR({docEntry})/Close` — mismo patrón que + `SolicitudTransferencia/{docEntry}/cerrar` (ver + [`SOLICITUD_TRANSFERENCIA.md`](./SOLICITUD_TRANSFERENCIA.md) para el gap de + infraestructura compartido: hace falta un método para `POST .../Close` con + body vacío, no existe ninguno hoy en `ConnectionServiceLayer`). +- **Body del request**: ninguno (solo `docEntry` en la ruta). +- **Body enviado a SAP**: `{}`. +- **Interfaz**: agregar a `IPickingRepository.cs`: + ```csharp + Task> CerrarHojaRuta(int docEntry); + ``` + +```csharp +public async Task> CerrarHojaRuta(int docEntry) +{ + _metodoName = "CerrarHojaRuta"; + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); + await connectServiceLayer.PostAsync($"ARD_PHR({docEntry})/Close", new { }); + return null; + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), null); + } +} +``` + +Controller (`PickingController.cs`, agregar junto a `Ruta`): + +```csharp +[HttpPost] +[Route("HojaRuta/{docEntry}/Cerrar")] +public async Task CerrarHojaRuta(int docEntry) +{ + var error = await _repository.Picking.CerrarHojaRuta(docEntry); + + var result = error ?? new BE_ResultadoTransaccion + { + DocEntry = docEntry, + StatusCode = 200, + Message = "Cerrado Correctamente", + AppName = "PickingRepository", + MethodName = "CerrarHojaRuta", + }; + + B_Log.Add(/* mismo patron que el resto - proceso "Hoja Ruta" */); + + return error == null ? Ok(result) : BadRequest(result); +} +``` + +> **Por qué `200` con body y no `204`**: mismo motivo que +> `SolicitudTransferencia` — un `204` no puede llevar body (RFC 7231 §6.3.5) +> y muchos clientes HTTP, incluido `HttpClient` de .NET, no lo leen. `201` se +> descarta porque no se crea nada nuevo. + +### Respuesta éxito (`200`) + +```json +{ + "docEntry": 77, + "docNum": null, + "statusCode": 200, + "message": "Cerrado Correctamente", + "error": null, + "appName": "PickingRepository", + "methodName": "CerrarHojaRuta", + "listData": null, + "data": null, + "nombreEstacion": "SERVER-WMS" +} +``` + +### Respuesta error (`400`) + +```json +{ + "docEntry": null, + "docNum": null, + "statusCode": 500, + "message": null, + "error": "La hoja de ruta ya esta cerrada", + "appName": "PickingRepository", + "methodName": "CerrarHojaRuta", + "listData": null, + "data": null, + "nombreEstacion": "SERVER-WMS" +} +``` + +## Checklist de integración para el WMS + +1. **Nunca mandar un array a `POST /api/Picking`.** Un documento (una + factura) por llamada — el `FOR` por factura es responsabilidad del WMS. +2. **`notificacion` ausente o distinto de `"cierre"` = preliminar** (default + seguro, nunca crea nada en SAP). +3. **El orden importa**: primero el `FOR` de cierre por cada factura + (`notificacion: "cierre"`), y **recién al final** —una sola vez— el + `POST /api/Picking/HojaRuta/{docEntry}/Cerrar`. +4. **`docEntry` en `POST /api/Picking` es el de la Factura**, no el de la + Hoja de Ruta. + +## Pendiente de validar en QA + +- Confirmar en QA si el nuevo `Close` del UDO `ARD_PHR` efectivamente bloquea + modificaciones futuras sobre el `DocEntry` una vez cerrado (no confirmado + todavía ni en la versión Python). +- Correr los mismos casos contra el endpoint `.NET` levantado antes de dar + por válido este port — en Python tampoco se probó esto todavía end-to-end + contra Service Layer real (ver `CLAUDE.md` del proyecto Python, sección + "Pruebas contra HANA/SAP reales"). diff --git a/docs/PORTE_FUNCIONALIDAD_NUEVA.md b/docs/PORTE_FUNCIONALIDAD_NUEVA.md new file mode 100644 index 0000000..0bfd88c --- /dev/null +++ b/docs/PORTE_FUNCIONALIDAD_NUEVA.md @@ -0,0 +1,231 @@ +# Porte de funcionalidad nueva desde la reescritura Python + +Este documento (y los dos que lo acompañan, [`SOLICITUD_TRANSFERENCIA.md`](./SOLICITUD_TRANSFERENCIA.md) +y [`PICKING.md`](./PICKING.md)) son la guía para agregar a **este proyecto +`.NET Core 3.1`** la funcionalidad de negocio nueva que se diseñó e +implementó primero en la reescritura Python +(`/Users/george/Documents/Desarrollo/ITCG/itca_api_sap_wms_python`), porque +este `.NET` va a seguir corriendo en producción (IIS, Windows) más tiempo +del previsto originalmente. + +**La lógica de negocio ya está validada en Python — acá es 100% traducción +de lenguaje, no rediseño.** El contrato HTTP (rutas, shapes de request/response, +status codes) debe quedar idéntico al de la API Python, porque ambas corren +sobre el mismo SAP Business One y el mismo WMS las va a consumir. + +> Alcance confirmado: **solo la funcionalidad nueva** (sin equivalente en +> este `.NET` hoy). No se portan acá las correcciones de bugs de contrato que +> sí se hicieron en la reescritura Python (ej. `201` real en los `POST` de +> creación, `400` explícito en Inventario/Recibo en vez de éxito falso) — +> quedan fuera de este trabajo salvo que se decida lo contrario más adelante. + +## Qué hay que agregar + +1. **Módulo SolicitudTransferencia completo** (no existe ningún controller + ni repositorio hoy) — ver [`SOLICITUD_TRANSFERENCIA.md`](./SOLICITUD_TRANSFERENCIA.md). +2. **Picking diurno/nocturno** — campo `Notificacion` en el `POST /api/Picking` + existente + nuevo `POST /api/Picking/HojaRuta/{docEntry}/Cerrar` — ver + [`PICKING.md`](./PICKING.md). + +## Dónde vive cada pieza hoy (mapa de archivos .NET) + +| Concepto | Archivo | +|---|---| +| Controllers existentes | `Net.Business.Services/Controllers/*.cs` | +| Repositorios de negocio (WMS) | `Net.Data/WMS/*/` | +| Repositorios de Service Layer (SAP) | `Net.Data/ServicesLayer/*/` | +| Cliente HTTP de Service Layer | `Net.Connection.ServiceLayer/ConnectionServiceLayer.cs` | +| DTOs (shape del request HTTP) | `Net.Business.DTO/**/Dto_*.cs` | +| Entidades de negocio | `Net.Business.Entities/**/BE_*.cs` | +| Wrapper de inyección de dependencias | `Net.Data/DependencyInjection/{IRepositoryWrapper,RepositoryWrapper}.cs` | +| Wrapper de resultado (`BE_ResultadoTransaccion`) | `Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs` + `Net.CrossCotting/ResultadoTransaccion.cs` | +| Logging de auditoría | `Net.Business.Services/Log/B_Log.cs` (se llama desde cada controller, después del repositorio) | +| Handler global de excepciones | `Net.Business.Services/Extensions/ExceptionMiddlewareExtensions.cs` | + +Patrón a seguir para cada pieza nueva (igual que `TransferenciaController`/ +`TransferenciaRepository`/`StockTransferRepository`): DTO → `RetornaModelo()` +→ Entidad → Repositorio de negocio (usa `ConnectionServiceLayer` + helpers de +HANA) → Controller (valida, llama al repo, llama a `B_Log.Add`, decide el +status code). + +## Gaps de infraestructura compartida a tener en cuenta + +Estos dos módulos nuevos necesitan cosas que `ConnectionServiceLayer.cs` hoy +**no soporta**, y hay que agregarlas: + +1. **Headers extra en PATCH.** `SolicitudTransferencia` necesita mandar + `B1S-ReplaceCollectionsOnPatch: true` en el PATCH a SAP. Ningún método de + `ConnectionServiceLayer` (`PostAsync`, `PatchAsyncSBA`, etc.) acepta headers + adicionales hoy — todos hardcodean `Accept`/`Content-Type`/`Cookie` + únicamente. Hay que agregar un parámetro opcional (ej. + `Dictionary extraHeaders = null`) a `PatchAsyncSBA`. +2. **GET de un solo recurso (no colección).** `SolicitudTransferencia` + necesita `GET InventoryTransferRequests({docEntry})` (un objeto, no una + lista `.value`). `ConnectionServiceLayer.GetAsync` ya tiene un + parámetro `dinamico` que deserializa `T` directo sin esperar el wrapper + `{ "value": [...] }` (`ConnectionServiceLayer.cs:363-373`) — **reusar esa + ruta** (`dinamico: true`) en vez de escribir un método nuevo. +3. **Acción `/Close` sin body.** Ni `SolicitudTransferencia` ni + `Picking/HojaRuta` tienen hoy un método para `POST {Recurso}({docEntry})/Close` + con body vacío — el único análogo es `StockTransferRepository.StockTransfer` + (`Net.Data/ServicesLayer/StockTransfer/StockTransferRepository.cs`), que sí + manda body. Hay que agregar un método nuevo (ej. `CloseAsyncSBA`) o un + overload de `PostAsync` que acepte `obj: null`/`{}`. + +## Bugs e inconsistencias encontrados en el código `.NET` existente + +Auditado puntualmente el código que estos dos módulos nuevos van a tocar o +reusar (`ConnectionServiceLayer.cs`, `HelperProcesoPiciking.cs`, +`BE_ResultadoTransaccion.cs`). No es una auditoría completa del proyecto — +solo lo relevante para este trabajo. + +### 1. `BE_ResultadoTransaccion.NombreEstacion` — setter con recursión infinita (bug serio, no relacionado al porte pero lo tocan ambos módulos nuevos) + +**Archivo**: `Net.Business.Entities/ResultadoTransaccion/BE_ResultadoTransaccion.cs`, +línea 36 (propiedad `NombreEstacion`). + +```csharp +public string NombreEstacion { get => System.Environment.MachineName; set => NombreEstacion = System.Environment.MachineName; } +``` + +El `set` asigna `NombreEstacion = ...`, lo que vuelve a invocar al propio +setter — recursión infinita. Si alguna vez se invoca ese setter (por ejemplo, +si algo deserializa un `BE_ResultadoTransaccion` con `JsonConvert.DeserializeObject` +y el JSON trae la propiedad `NombreEstacion`/`nombreEstacion`, o si cualquier +código hace `objeto.NombreEstacion = "algo"` directamente), el proceso +revienta con `StackOverflowException` — una excepción que **.NET no puede +atrapar con try/catch**, tumba el proceso entero (el worker de IIS). + +Hoy no se dispara porque nada construye `BE_ResultadoTransaccion` por +deserialización ni asigna esa propiedad directamente (todo pasa por +`ResultadoTransaccion.GetInformacionResultado(...)`, que no la toca). Pero +al escribir el código nuevo para SolicitudTransferencia/HojaRuta, **nunca +hacer `.NombreEstacion = ...` a mano ni deserializar un `BE_ResultadoTransaccion` +desde JSON** — usar siempre `GetInformacionResultado(...)`. + +**Solución propuesta**: la propiedad solo necesita ser de lectura. + +```csharp +public string NombreEstacion => System.Environment.MachineName; +``` + +(o, si hace falta que el setter exista por compatibilidad con algo que no +vimos en esta auditoría puntual, que el setter no haga nada: `set { }`). + +### 2. `ConnectionServiceLayer.PatchAsyncSBA` nunca marca éxito en un `204` + +**Archivo**: `Net.Connection.ServiceLayer/ConnectionServiceLayer.cs`, +método `PatchAsyncSBA`, líneas 739-856 (el caso puntual, líneas 840-848). + +Con un `204 No Content` real de SAP, el código no entra en la rama de éxito +(la que solo cubre `200`/`201`, líneas 788-796) ni en ninguna rama de error +— el bloque `if (response_.StatusCode == NoContent) { ... }` (línea 840) está +con el cuerpo comentado, así que cae directo a `return default(T);` (línea +848), o sea `null`. Cualquier caller que acceda a una propiedad del +resultado (`.Exito`, `.DocEntry`, etc.) revienta con `NullReferenceException`. +Ya es un bug conocido y documentado en el proyecto Python (`CLAUDE.md`, +regla 4) — ahí se corrigió tratando un `204` real como éxito explícito. + +**Importante**: confirmado que **nadie llama a este método hoy** +(`grep` de `PatchAsyncSBA` en todo el proyecto no da otro resultado que su +propia definición) — es seguro modificarlo directamente, no hace falta +duplicarlo para no romper nada en producción. + +**Solución propuesta**: al construir el repositorio de SolicitudTransferencia, +modificar `PatchAsyncSBA` para que un `204` (o `200`) se trate como éxito +real, sin intentar deserializar un body que puede venir vacío — por ejemplo, +devolviendo un `bool`/un objeto liviano de éxito en vez de `T` deserializado +a la fuerza, o agregando un chequeo explícito antes del `return default(T)` +final. + +### 3. `ConnectionServiceLayer.PatchAsyncSBA` — un `401` con `error.code` distinto de `"301"` también devuelve `null` silenciosamente + +**Archivo**: `Net.Connection.ServiceLayer/ConnectionServiceLayer.cs`, +método `PatchAsyncSBA`, líneas 797-822. + +Dentro de la rama `401`, si `NumError < 2` y el código de error de SAP no es +`"301"` (el que dispara relogin + reintento), no hay ningún `goto band` ni +`return` — el flujo simplemente sale del `if/else if` (porque ya entró a la +rama `401`, la siguiente condición es `else if` y no se evalúa) y cae en el +`return default(T);` del final del método. Mismo síntoma que el bug anterior +(`null` silencioso, no un error explícito) pero por una causa distinta. + +**Solución propuesta**: agregar un `else` final dentro de la rama `401` que +construya y devuelva un resultado de error explícito, en vez de dejar que el +flujo caiga al `return default(T)` genérico. + +### 4. `ConnectionServiceLayer` — `throw` muerto después de `return` en 3 métodos + +**Archivo**: `Net.Connection.ServiceLayer/ConnectionServiceLayer.cs`, +métodos `CancelAsyncSBA` (líneas 621-625), `DeleteAsyncSBA` (líneas +733-737) y `PatchAsyncSBA` (líneas 851-855): + +```csharp +catch (Exception ex) +{ + return default(T); + throw new Exception(ex.Message.ToString()); +} +``` + +El `throw` es código inalcanzable (el compilador de C# debería marcarlo con +el warning `CS0162`) — la excepción original queda silenciada sin loguear ni +propagar, y el caller recibe `null` sin ninguna pista de qué pasó. + +**Solución propuesta**: sacar el `throw` muerto y decidir explícitamente el +comportamiento — si se quiere tragar el error y devolver `null`/un resultado +de error (dejar solo el `return`), o repropagar la excepción real (`throw;`, +sin el `return` antes). Para los métodos nuevos de SolicitudTransferencia, no +repetir este patrón: loguear o envolver el error en el `BE_ResultadoTransaccion` +de salida, igual que hace el resto del proyecto (ver `TransferenciaRepository.Create`, +que atrapa la excepción y la mete en `GetInformacionResultado(ex.Message, entidad)`). + +### 5. `ConnectionServiceLayer.Login()` y `.LoginPost()` — código duplicado + +**Archivo**: `Net.Connection.ServiceLayer/ConnectionServiceLayer.cs`, +`Login()` (líneas 44-130) y `LoginPost()` (líneas 131-218). + +Son copias casi idénticas línea por línea — la única diferencia real es un +parámetro `Language` que está comentado en `LoginPost`. No es un bug +funcional, es una inconsistencia de mantenimiento (dos lugares que hay que +tocar a mano si cambia el login). No bloquea el porte de la funcionalidad +nueva — se deja solo documentado por si se decide refactorizar en el futuro. + +**Solución propuesta**: unificar en un solo método (`LoginPost` ya tiene el +parámetro `Language` listo para habilitarse si hiciera falta). + +### 6. `HelperProcesoPiciking.Set` — SQL injection real por interpolación de string + +**Archivo**: `Net.Data/HelperData/ProcesoPiciking/HelperProcesoPiciking.cs`, +ambas sobrecargas de `Set` (líneas 14 y 28): + +```csharp +cmd.CommandText = $"CALL\"B1_ARDI_PROD\".\"ITCA_WMS_SAP_SetProcesoPicking\"('{Proceso}', {IdEstado}, {DocEntry}, '', '', '{CodMotivo}', '{Code}')"; +``` + +`Proceso` y `CodMotivo` vienen directo del body del request HTTP +(`entidad.Proceso`, `entidad.CodMotivo` en `PickingRepository.cs:96` y +`:374`) e, interpolados así, son un vector de SQL injection real — mismo +patrón de vulnerabilidad ya documentado y confirmado en el módulo Chatbot del +`.NET` (`CLAUDE.md` del proyecto Python, sección "Pendiente"). Este método es +justo el que hay que tocar para aislar la actualización de estado (ver +[`PICKING.md`](./PICKING.md)), así que es un buen momento para corregirlo de +una vez en vez de solo copiarlo. + +**Solución propuesta**: parametrizar con `HanaParameter`/placeholders en vez +de interpolar el string, por ejemplo: + +```csharp +cmd.CommandText = "CALL \"B1_ARDI_PROD\".\"ITCA_WMS_SAP_SetProcesoPicking\"(?, ?, ?, ?, ?, ?, ?)"; +cmd.Parameters.Add(new HanaParameter("1", Proceso)); +cmd.Parameters.Add(new HanaParameter("2", IdEstado)); +cmd.Parameters.Add(new HanaParameter("3", DocEntry)); +cmd.Parameters.Add(new HanaParameter("4", HoraInicio?.ToString() ?? "")); +cmd.Parameters.Add(new HanaParameter("5", HoraFin?.ToString() ?? "")); +cmd.Parameters.Add(new HanaParameter("6", CodMotivo)); +cmd.Parameters.Add(new HanaParameter("7", Code)); +``` + +(Ajustar la sintaxis exacta de binding de parámetros al driver `Sap.Data.Hana` +realmente instalado — confirmar la forma correcta de parámetros posicionales +de ese driver ADO.NET antes de aplicar, no asumida en esta auditoría.) diff --git a/docs/SOLICITUD_TRANSFERENCIA.md b/docs/SOLICITUD_TRANSFERENCIA.md new file mode 100644 index 0000000..062c47f --- /dev/null +++ b/docs/SOLICITUD_TRANSFERENCIA.md @@ -0,0 +1,301 @@ +# Endpoint nuevo — Solicitud de Transferencia (a construir en .NET) + +Módulo **100% nuevo** — no existe ningún `SolicitudTransferenciaController` +ni repositorio para `InventoryTransferRequests` en este proyecto hoy +(confirmado: no hay ninguna referencia a `InventoryTransferRequests` en +`Net.Data/`). Esta es la especificación para construirlo, traducida 1:1 de +la implementación ya validada en Python +(`itca_api_sap_wms_python/app/services/solicitud_transferencia_service.py`, +`app/schemas/solicitud_transferencia.py`, `app/api/routes/solicitud_transferencia.py`). + +Ver también [`PORTE_FUNCIONALIDAD_NUEVA.md`](./PORTE_FUNCIONALIDAD_NUEVA.md) +para los gaps de infraestructura compartida (headers extra en PATCH, GET de +un solo recurso, acción `/Close`) y los bugs encontrados en el código que +este módulo va a reusar. + +## Resumen del contrato + +| Método | Ruta | Respuesta éxito | Qué hace | +|---|---|---|---| +| `PATCH` | `/api/solicitudtransferencia/{docEntry}` | `200` + `BE_ResultadoTransaccion` | Actualiza cantidades de línea; `cantidad: 0` elimina la línea. Hay que reenviar todas las líneas a conservar. | +| `POST` | `/api/solicitudtransferencia/{docEntry}/cerrar` | `200` + `BE_ResultadoTransaccion` | Cierra el documento completo. Sin body de request. | + +- **Ruta base**: `api/SolicitudTransferencia` (bajo el virtual path `/integracion` + de IIS, igual que el resto de los controllers — no hace falta nada especial + en el código para eso). +- **Autenticación**: `[Authorize(AuthenticationSchemes = "Bearer")]`, igual + que el resto de los controllers (ver `TransferenciaController`/`PickingController` + como referencia). +- **Objeto SAP asociado**: `InventoryTransferRequests` (Service Layer). + +## Cómo funciona el `PATCH` (reglas de negocio, confirmadas contra SAP real en QA) + +El `PATCH` de una Solicitud de Traslado **solo actualiza cantidades de línea +existentes**, y **elimina la línea** cuando la cantidad llega en `0`. No toca +fechas, almacenes, comentarios ni ningún otro campo del documento — por eso +el DTO de este endpoint es mucho más chico que el de `Transferencia` (solo +`NumOrden` + `Detalle[{Linea, Cantidad}]`). + +Reglas confirmadas directo contra el Service Layer real de QA: + +1. Alcanza con mandar `LineNum` + `Quantity` por línea — nada de `ItemCode`, + `WarehouseCode`, fechas, etc. +2. SAP **rechaza** una línea si se manda explícita con `Quantity: 0` — + por eso una línea con `Cantidad: 0` en el request **se omite del array** + en vez de mandarse en cero. +3. Para que SAP realmente **elimine** la línea omitida (en vez de dejarla + intacta), hace falta el header `B1S-ReplaceCollectionsOnPatch: true` — le + indica a Service Layer que trate `StockTransferLines` como reemplazo + **completo** del array, no un merge parcial. +4. **Hallazgo posterior, crítico** (no estaba cubierto en la primera tanda de + pruebas, que usó un documento con `Rate=0` en todas las líneas): al ser un + reemplazo completo, SAP **también exige el `Rate` de cada línea** — si el + documento tiene líneas valorizadas (`Rate != 0`) y no se reenvía, el PATCH + falla. Por eso hay que hacer un `GET InventoryTransferRequests({docEntry})` + **antes** del PATCH, leer el `Rate` real de cada línea, y reenviarlo tal + cual junto con la `Quantity` nueva — **nunca mandar `Rate: 0` fijo**, eso + pisaría la valorización real del documento (en C# esto no tiene el + problema de serialización que tuvo la versión Python con `decimal.Decimal` + de `hdbcli` — `Newtonsoft.Json` serializa `decimal`/`double` sin problema + — pero la regla de negocio de todas formas aplica igual: hay que leer el + `Rate` real, no inventarlo). + +> ⚠️ **Consecuencia del header para el WMS**: como el array es reemplazo +> completo, cualquier línea que el request **no incluya** en `Detalle` +> también se elimina de SAP — igual que si viniera con `Cantidad: 0`. No es +> un PATCH parcial tradicional. El cliente (WMS) tiene que mandar **siempre** +> todas las líneas que el documento debe conservar. + +## DTO/Entidad a crear + +```csharp +// Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchDetalle.cs +public class BE_SolicitudTransferenciaPatchDetalle +{ + public int Linea { get; set; } + public double Cantidad { get; set; } +} + +// Net.Business.Entities/WMS/SolicitudTransferencia/BE_SolicitudTransferenciaPatchRequest.cs +public class BE_SolicitudTransferenciaPatchRequest +{ + public string NumOrden { get; set; } // opcional, solo para el log de auditoria - no se usa en el PATCH a SAP + public List Detalle { get; set; } +} +``` + +El `Dto_SolicitudTransferenciaPatchRequest` (en `Net.Business.DTO/WMS/SolicitudTransferencia/`) +es el mismo shape, con su `RetornaModelo()`, siguiendo el patrón de +`Dto_TransferenciaRequest`/`Dto_PickingRequest`. El binding de ASP.NET Core ya +es case-insensitive por defecto (igual que en Python), así que no hace falta +nada especial para aceptar `numOrden`/`NumOrden`/`detalle`/`Detalle`. + +### Body de ejemplo (`PATCH /api/SolicitudTransferencia/{docEntry}`) + +```json +{ + "numOrden": "SOL-000123", + "detalle": [ + { "linea": 0, "cantidad": 8 }, + { "linea": 1, "cantidad": 0 } + ] +} +``` + +## Lógica del repositorio (`SolicitudTransferenciaRepository.Update`) + +Traducción directa de `solicitud_transferencia_service.py::update`: + +```csharp +public async Task> Update(int docEntry, BE_SolicitudTransferenciaPatchRequest entidad) +{ + _metodoName = "Update"; + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + // 1. GET del documento actual para leer el Rate real de cada linea. + // Reusar ConnectionServiceLayer.GetAsync(..., dinamico: true) - + // ver nota de "gap de infraestructura" en PORTE_FUNCIONALIDAD_NUEVA.md. + var doc = (await _connectServiceLayer.GetAsync( + $"InventoryTransferRequests({docEntry})", 1, dinamico: true)).FirstOrDefault(); + + var ratesByLine = doc.StockTransferLines.ToDictionary(l => l.LineNum, l => l.Rate); + + // 2. Armar las lineas: omitir cantidad=0, preservar Rate real. + var lines = new List(); + foreach (var detalle in entidad.Detalle) + { + if (detalle.Cantidad == 0) continue; + + if (!ratesByLine.TryGetValue(detalle.Linea, out var rate)) + { + return resultadoTransaccion.GetInformacionResultado( + $"La linea {detalle.Linea} no existe en la Solicitud de Traslado {docEntry}", entidad); + } + + lines.Add(new { LineNum = detalle.Linea, Quantity = detalle.Cantidad, Rate = rate }); + } + + // 3. PATCH con el header B1S-ReplaceCollectionsOnPatch. + // Requiere el overload de PatchAsyncSBA con headers extra - ver gap #1. + await _connectServiceLayer.PatchAsyncSBA( + $"InventoryTransferRequests({docEntry})", + new { StockTransferLines = lines }, + extraHeaders: new Dictionary { ["B1S-ReplaceCollectionsOnPatch"] = "true" }); + + return null; // exito real de SAP = 204/200 real (ver controller abajo) + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad); + } +} +``` + +(Pseudocódigo de referencia — ajustar nombres exactos de clases/métodos una +vez que exista el overload de `PatchAsyncSBA` con headers y la entidad +`BE_InventoryTransferRequest`/`BE_InventoryTransferRequestLine` para +deserializar el `GET`.) + +## `POST /api/SolicitudTransferencia/{docEntry}/cerrar` + +Cierra el documento completo vía `POST InventoryTransferRequests({docEntry})/Close` +— acción fija de Service Layer (no se traduce). Sin body de request, body +vacío (`{}`) hacia SAP. Confirmado contra SAP real que cierra el documento +completo aunque alguna línea ya se haya convertido en una Transferencia. + +```csharp +public async Task> Cerrar(int docEntry) +{ + _metodoName = "Cerrar"; + ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion(_metodoName, _aplicacionName); + + try + { + await _connectServiceLayer.PostAsync($"InventoryTransferRequests({docEntry})/Close", new { }); + return null; + } + catch (Exception ex) + { + return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), null); + } +} +``` + +## Controller + +Igual patrón que `TransferenciaController`, con una diferencia importante de +status code (ver nota abajo): + +```csharp +[HttpPatch("{docEntry}")] +public async Task Patch(int docEntry, [FromBody] Dto_SolicitudTransferenciaPatchRequest value) +{ + var error = await _repository.SolicitudTransferencia.Update(docEntry, value.RetornaModelo()); + + var result = error ?? new BE_ResultadoTransaccion + { + DocEntry = docEntry, + StatusCode = 200, + Message = "Registrado Correctamente", + AppName = "SolicitudTransferenciaRepository", + MethodName = "Update", + Data = value, + }; + + B_Log.Add(/* ... mismo patron que el resto de los controllers ... */); + + return error == null ? Ok(result) : BadRequest(result); // 200 con body si OK, 400 si error +} + +[HttpPost("{docEntry}/cerrar")] +public async Task Cerrar(int docEntry) +{ + var error = await _repository.SolicitudTransferencia.Cerrar(docEntry); + + var result = error ?? new BE_ResultadoTransaccion + { + DocEntry = docEntry, + StatusCode = 200, + Message = "Cerrado Correctamente", + AppName = "SolicitudTransferenciaRepository", + MethodName = "Cerrar", + }; + + B_Log.Add(/* ... */); + + return error == null ? Ok(result) : BadRequest(result); +} +``` + +> **Por qué `200` con body y no `204`**: decisión deliberada, igual que en +> Python. Un `204 No Content` no puede llevar body por spec HTTP (RFC 7231 +> §6.3.5), y muchos clientes HTTP — **incluido `HttpClient` de .NET**, que es +> justo el que va a consumir esto el WMS si está en .NET también — ni +> siquiera lo leen si el status es `204`. `201` se descartó porque ni el +> `PATCH` ni el `cerrar` crean un recurso nuevo. El resto de los endpoints +> `PATCH` del proyecto (`Transferencia`) sigue en `204` sin body — esta es +> una excepción deliberada, solo para estos dos endpoints nuevos. + +## Respuestas de ejemplo + +### `PATCH` éxito (`200`) + +```json +{ + "docEntry": 4521, + "docNum": null, + "statusCode": 200, + "message": "Registrado Correctamente", + "error": null, + "appName": "SolicitudTransferenciaRepository", + "methodName": "Update", + "listData": null, + "data": { "numOrden": "SOL-000123", "detalle": [ { "linea": 0, "cantidad": 8 } ] }, + "nombreEstacion": "SERVER-WMS" +} +``` + +### `PATCH` error (`400`) + +```json +{ + "docEntry": null, + "docNum": null, + "statusCode": 500, + "message": null, + "error": "DocEntry no existe", + "appName": "SolicitudTransferenciaRepository", + "methodName": "Update", + "listData": null, + "data": { "numOrden": "SOL-000123", "detalle": [ "..." ] }, + "nombreEstacion": "SERVER-WMS" +} +``` + +(El `statusCode: 500` interno + el `400` HTTP real del controller es el mismo +patrón que usa `ResultadoTransaccion.GetInformacionResultado(string, T)` ya +existente — ver `Net.CrossCotting/ResultadoTransaccion.cs`.) + +## Checklist de integración para el WMS (igual que la versión Python) + +1. **Mandar solo la línea que cambia y no las demás** → borra las no + incluidas (header de reemplazo completo). Reconstruir siempre el + `detalle` completo. +2. **Mandar `cantidad: 0` esperando que quede en cero** → no, `0` significa + "eliminar esta línea". +3. **Usar `linea` con un número que no existe en el documento** → SAP + devuelve error, no crea una línea nueva. +4. **Esperar un `204 No Content`** → este endpoint responde `200` con body. + +## Pendiente de validar en QA antes de dar por cerrado el porte + +- Correr los mismos casos de `tools/solicitud-transferencia-patch.http` y + `tools/solicitud-transferencia-post-close.http` (del proyecto Python) + contra el nuevo endpoint `.NET` levantado, no solo contra Service Layer + directo. +- Confirmar el nombre exacto del método de binding de parámetros del driver + `Sap.Data.Hana` instalado (si se toca `HelperProcesoPiciking` como parte de + este trabajo — ver bug #6 en `PORTE_FUNCIONALIDAD_NUEVA.md`, no aplica + directo a este módulo pero comparte el mismo cliente HANA).