Record manual stock changes in InventoryJournal
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 35/100
Línea de trabajo
Start with InventoryManageService and IInventoryManageService, then trace the listed stock-update paths in ProductViewModelService, BaseProductController, and the API command handlers. Review InventoryJournal and InventoryManageServiceTests before estimating how the shared adjustment flow fits. Done means all listed adjustment paths, notification behavior, no-op handling, and the specified tests meet the acceptance criteria.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
Manual stock changes leave no trace. InventoryJournal (src/Core/Grand.Domain/Catalog/InventoryJournal.cs) is written only for shipments: InventoryManageService.InsertInventoryJournal (src/Business/Grand.Business.Catalog/Services/Products/InventoryManageService.cs) is called with ObjectType = nameof(Shipment). When an administrator or an API client edits a quantity, the old value is simply overwritten, so there is no answer to "who changed this, when, from what to what, and why".
Code paths that change StockQuantity / ProductWarehouseInventory / combination stock without a journal entry:
- Product edit -
ProductViewModelService(src/Web/Grand.Web.AdminShared/Services/ProductViewModelService.cs):StockQuantityis mapped from the model on update, andSaveProductWarehouseInventory(~L439) writes per-warehouseStockQuantityand then sums toproduct.StockQuantity. Same flow for create (~L771) and update (~L830). - Bulk edit (grid) - same file, ~L1362-1367:
product.StockQuantity = pModel.StockQuantity. - Attribute combinations - same file, ~L2200-2260:
combination.StockQuantity,PrepareCombinationWarehouseInventory(per-warehouseProductCombinationWarehouseInventory), and the recalculatedproduct.StockQuantity. Also the "generate all combinations" path (BaseProductController, ~L2949 resetsStockQuantity = 0). - Out-of-stock subscription notifications live in this view-model layer (
OutOfStockNotifications, ~L189 and ~L223), so they only fire for panel edits. - Store owner and Vendor panels reuse the same AdminShared services/controllers, so they have the same gap.
- Backend API (
src/Modules/Grand.Module.Api):PUT /ProductandPATCH /Product/{key}->UpdateProductCommandHandlermapsStockQuantityfrom the DTO and callsUpdateProduct; it has its own, partial copy of the back-in-stock logic.POST /Product/{key}/UpdateStock->UpdateProductStockCommandHandlersetsproduct.StockQuantityor theProductWarehouseInventoryrow; it duplicatesOutOfStockNotificationsa third time.ProductAttributeCombinationDto.StockQuantityis part of the DTO, so combination stock can change through product update as well.
Product import (ProductImportDataObject) also sets StockQuantity; it is a bulk path and is probably better handled as a follow-up.
The panels do not display InventoryJournal anywhere (no reference in Grand.Web.*); the collection is currently write-only from shipments and read nowhere.
Proposal
Add a core method to IInventoryManageService, for example:
Task AdjustStock(Product product, ProductAttributeCombination combination, string warehouseId,
int newQuantity, string reason, string reference);
(or a delta-based overload). It should:
- apply the new quantity to the product / warehouse row / combination (and its warehouse row), recompute the aggregates, and call
UpdateStockProductso LowStock / auto-unpublish keep working as today; - insert an
InventoryJournalentry with a newObjectTypefor manual adjustments (e.g."StockAdjustment"),InQty/OutQtyderived from the delta,ProductId,Attributes(combination),WarehouseId,Comments = reason,Reference = who/what(user e-mail,"api"); - do nothing (no journal entry) when the quantity did not change;
- own the out-of-stock subscription notifications: move
OutOfStockNotificationsfromProductViewModelServiceinto core so the panel and every API path share one implementation, and delete the copies in the API handlers.
Route every path listed above through it: product edit and warehouse inventory, bulk edit, combination create/edit, API PUT/PATCH/UpdateStock.
Out of scope / follow-ups
- A journal view per product in the admin panel (read side of
InventoryJournal). - An optional "reason" field in the panel UI (until then
Commentscan be a default text such as "Manual adjustment"). - Journal entries for product import.
Acceptance criteria
-
IInventoryManageServiceexposes a stock adjustment method covering product, warehouse and combination (+ combination warehouse) quantities. - Each adjustment writes one
InventoryJournalentry with a dedicatedObjectType, correctInQty/OutQty,CommentsandReference. - Unchanged quantities produce no entry.
- Admin, Store and Vendor product edit, bulk edit and combination edit go through the new method.
- API
PUT,PATCHandUpdateStockgo through the new method;Referenceidentifies the API caller. - LowStock flag, auto-unpublish / out-of-stock behaviour and back-in-stock notifications behave as before, from a single implementation in core.
- Unit tests in
InventoryManageServiceTestscover product, warehouse and combination adjustments, no-op, and notification triggering.
Notes
- Add an index on
InventoryJournal(ProductId,CreateDateUtc) - needed as soon as a per-product view reads it. - No migration needed for existing data; history starts from the release that ships this.
- Lenguaje dominante
- C#
- Estrellas
- 1.3k
- Forks
- 549
- Merge medio
- 7 h 58 min
- PR fusionados (30 d)
- 52
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de grandnode/grandnode2
-
HTML sitemap lists unpublished pagesPosiblemente ocupada @KrzysztofPajak la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
grandnode/grandnode2#883 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 3/5 1-2 días Aptitud para principiantes 65/100
grandnode/grandnode2#881 ·
Los mantenedores suelen responder en 1 día
-
Please add the offer systemAbierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
grandnode/grandnode2#849 ·
Los mantenedores suelen responder en 1 día
-
grandnode/grandnode2#499 ·
Los mantenedores suelen responder en 1 día
-
grandnode/grandnode2#410 ·
Los mantenedores suelen responder en 1 día
Todos los issues de grandnode/grandnode2
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
stryker-mutator/stryker-net#3892 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
MobiFlight/MobiFlight-Connector#3419 ·
Los mantenedores suelen responder en 1 día
-
`Source` with an `avares://` URI and a `#fragment` throws instead of scrolling to the anchorAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Kryptos-FR/MarkView.Avalonia#105 ·
Los mantenedores suelen responder en 1 día
-
[辞書]Abierto提案 辞書
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
microsoft/fluentui-blazor#5410 ·
Los mantenedores suelen responder en 1 día