[ 
https://issues.apache.org/jira/browse/OFBIZ-6964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15220637#comment-15220637
 ] 

Shrenik Bhura commented on OFBIZ-6964:
--------------------------------------

[~swash78] At the onset, thanks for giving it a deep thought once again.

bq. Here, the suggested usage of "Replenishment" per se seems to be defined in 
a very limited sense i.e.,to just serve the purpose of re-filling the retail 
store's warehouse by moving/transferring the stock from one(centralized) 
warehouse to another. I would have rather referred this a simple case of "Store 
Transfer" as its just one of possible way for replenishing the stock at store 
level. In real world, the replenishment policies vary from organization to 
organization based on the kind of product/brand mix they deal in. 

We got to make a start on the concept of replenishment and that's what this is 
with the idea of KISS. Let's not confuse the "metaphor" with its dictionary 
meaning. We are seeking a metpahor for the sake of implementing a 
functionality. At the same time the need is to differentiate it from the 
concept of requirements - Product Requirement resulting in purchase orders or 
Internal Requirement used mostly for parts/raw material movement for 
manufacturing/assembling. Hence, I strongly feel that the word "replenishment" 
with the current definition in this context seems apt and enough.

bq. The product can be replenished in various ways e.g. via inter-store 
transfers or via local vendors directly or via drop shipments from vendor's own 
distribution centers (VMI) etc. depending on many factors like cost/lead 
times/seasonality/obsolescence/contractual agreements etc.

Let's dissect the 'various ways' and see what else can we address in this story 
-
i. via inter-store transfers - I would rather have inter-facility transfers to 
be specific. We need to understand the difference between inter-store transfer 
and inter-facility transfer. What we are actually aiming for in this story is 
inter-facility transfer. A store or stores is/are just a front-end for one or 
more facilities.
ii. via local vendors directly - Is already handled via product requirements, 
purchase orders and incoming shipments, etc. This is widely referred in OFBiz 
as purchase requirements. Hence this no longer needs to be handled. 
iii. via drop shipments from vendor's own distribution centers (VMI) etc. - Is 
also handled via purchase orders and related process, differing just in the 
absence of an incoming shipment. And I would not call it as replenishment in 
any way, it is direct order fulfilment or any other terminology.

bq. With respect to above problem statement, though the suggested approach 
works good to handle the basic use case reported in ticket but it would be 
equally interesting to have clarifications on few open questions(possible 
limitations) to come up with a holistic design:

bq.   1. Does it provide support to handle the cases when two stores get 
associated to the same facility (as per ProductStore.InventoryFacilityId or 
ProductStoreFacility) and both stores happen to follow different stocking 
policies, for example one store always like to get it's stock refilled from 
backup warehouse and another store from another specified warehouse or directly 
from vendor.

I have categorically mentioned in the suggested approach that replenishment 
policy be defined at a facility level and it has no bearing on the store. A 
store need/should not decide from where its saleable items are coming as long 
as they are going to be fulfilled by the facility or facilities it relies on. 
Viewing the business functions in a compact and modular way will help us solve 
this in a more simple way.

Hence if the replenishment policy is defined on the ProductFacility entity then 
yes we have full support for any of the scenarios you have highlighted.

bq.   2. With the sample data shared, it seems each store's facility would have 
corresponding replenishment method but is it expected that store should be able 
to have any fall back facility also defined to re-stock if stock can't be 
replenished/re-filled via associated method.

"store should be able to have fall back facility" is incorrect interpretation. 
I have stated "Additional now we can provision for defining of backup facility 
for any facility." with some mandatory safeguards. Hence please rethink your 
query with this understanding.

bq. Execution: new MrpEvents get created with Proposed Quantity with dates to 
replenish the product's stock via Purchase Orders, Production Runs etc. The 
output is a then transformed into series of requirements of type 
PRODUCT_REQUIREMENT corresponding to MrpEventType PROP_PUR_O_RECP 
(i.e.,proposed for sourcing product from outside the facility) or 
INTERNAL_REQUIREMENT corresponding to MrpEventType PROP_MANUF_O_RECP 
(i.e.,proposed for manufacturing the product within a facility)

Found this in Opentaps seed data, which may be helpful -

{code:xml}
    <!-- It come from ofbiz 
applications/manufacturing/data/ManufacturingData.xml, but it not exist in 
ofbiz no longer, so move it here -->
    <InventoryEventPlannedType inventoryEventPlanTypeId="INITIAL_QOH" 
description="Initial QOH" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="MRP_REQUIREMENT" 
description="Mrp requirement" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="MANUF_ORDER_RECP" 
description="Manufacturing Order receipt" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="MANUF_ORDER_REQ" 
description="Manufacturing Order requirement" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PROP_MANUF_O_RECP" 
description="Proposed Manufacturing Order receipt" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PUR_ORDER_RECP" 
description="Purchase Order receipt" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PROD_REQ_RECP" 
description="Product Requirement Receipt" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PROP_PUR_O_RECP" 
description="Proposed Purchase Order receipt" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="SALES_ORDER_SHIP" 
description="Sales order shipment" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="ERROR" 
description="Error"/>

    <!-- Additional inventory event plan types for MRP -->
    <InventoryEventPlannedType inventoryEventPlanTypeId="INVENTORY_XFER_IN" 
description="Inbound Inventory Transfer" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="INVENTORY_XFER_OUT" 
description="Outbound Inventory Transfer" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PROP_INV_XFER_IN" 
description="Proposed Inbound Inventory Transfer" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="PROP_INV_XFER_OUT" 
description="Proposed Outbound Inventory Transfer" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="SALES_FORECAST" 
description="Sales Forecast" inOut="-"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="INV_XFER_REQ_IN" 
description="Inbound Inventory Transfer Requirement" inOut="+"/>
    <InventoryEventPlannedType inventoryEventPlanTypeId="INV_XFER_REQ_OUT" 
description="Outbound Inventory Transfer Requirement" inOut="-"/>
        
    <!-- Requirement for transferring inventory -->
    <RequirementType requirementTypeId="TRANSFER_REQUIREMENT" 
description="Inventory Transfer Requirement" hasTable="N"/>
{code}

Additionally this documentation may bring some clarity on what can be achieved -
http://www.opentaps.org/docs/index.php/Step_By_Step:_Using_the_Inventory_Requirements#Processing_Inventory_Transfers_for_Approved_Transfer_Requirements
 (do check the corss-references also)
http://www.opentaps.org/docs/index.php/Material_Resources_Planning#Transferring_Inventory

I hope we shall be on a more common footing after this attempt at provinding 
further clarity.

> Support for replenishment of a secondary warehouse from a main warehouse
> ------------------------------------------------------------------------
>
>                 Key: OFBIZ-6964
>                 URL: https://issues.apache.org/jira/browse/OFBIZ-6964
>             Project: OFBiz
>          Issue Type: New Feature
>          Components: manufacturing, product
>            Reporter: Shrenik Bhura
>              Labels: features
>             Fix For: Upcoming Branch
>
>
> At the onset let me define a few terms clearly as I mean it in the story 
> description below :
> Requirement - A request generated for a particular product for a specific 
> quantity that needs to be purchased from a supplier for satisfying certain 
> inventory needs of a particular facility.
> Replenishment - A request generated for a particular product for a specific 
> quantity that needs to be transferred from a "backup facility" for satisfying 
> certain inventory needs of a particular facility.
> Fulfilment - The process of reserving, picking, packing and shipping the 
> ordered quantity of product(s) as per a sales order.
> Terms 'warehouse' and 'facility' have been used interchangeably.
> *The Use Case:*
> Consider a scenario wherein there is a website and a physical retail store of 
> the same Company.
> Each having its own facility i.e. 1:1 mapping.
> {{Store A (webstore) -> associated with facility 1 (webstore facility)}}
> {{Store B (retailstore) -> associated with facility 2 (retailstore facility)}}
> However, both the stores share the same catalog/products. But both have 
> independent inventory requirement and replenishment rules for the same 
> product. 
> There is a Requirement Method Enum ID (RMEI) of each product which is 
> applicable irrespective of the store and supersedes the RMEI defined, if any, 
> on a store. 
> A product's inventory thresholds (Minimum Stock, Reorder Quantity) are 
> independently managed via the facilities tab for the product. A product has 
> its ATP and QOH levels on a per facility basis. _Do note that all these 
> inventory numbers are at a facility level and has no bearing at a store 
> level._
> Where the difficulty crops up with the current implementation is the way 
> requirements are generated. A product can have only one RMEI. When an order 
> is placed from any store, then based on the combination of a product's RMEI 
> and the store mapped facility's inventory threshold, requirements are 
> generated. This is without consideration of the inventory status (surplus or 
> otherwise) at another facility of the same Company. If a store has multiple 
> facilities associated with it then the one defined in the ProductStore entity 
> -> inventoryFacilityId field would be considered for picking the inventory 
> threshold values and thus for requirement generation. 
> Most typical real-world facility arrangements: 
>       1. Usually an organisation would have a main facility/warehouse where 
> all the purchases are received and sub-facilities which are replenished from 
> the main facility after QA, internal processes, etc. OR 
>       2. For each product there would be a primary facility where the product 
> is received from the supplier (to derive benefits of demographic convenience 
> and consumption patterns) and then replenished to other facilities on a 
> demand based pull basis.
> To drive efficiencies across an organisation they need methods to consider 
> open fulfilment needs, in process purchase orders and inventory levels across 
> multiple facilities and thereafter propose inventory transfers across them to 
> facilitate better stocking and thus order fulfilment.
> Coming back to our use case, the webstore warehouse is the main facility at 
> which incoming shipments from suppliers are received for the entire Company 
> but sales order fulfilment happens only for the webstore. The retail 
> warehouse is primarily 're-stocked' via replenishment requests raised upon 
> the webstore warehouse and thus need not issue direct purchase orders to 
> suppliers. However, if the need be, requirement generated based on the 
> product's RMEI and the retail facility's inventory thresholds can also be 
> approved, converted into Purchase order and issued.
> *Proposed Solution:*
> There doesn't seem to be an out of the box solution for this in OFBiz. This 
> could work if either we think of -
> Approach A: Setting RMEI at a ProductFacility level as well which shall 
> supersede the Product level RMEI setting OR 
> Approach B: Build in support for a solution that I have encountered in 
> Opentaps (a system built atop OFBiz) i.e. implement support for a new setting 
> *Replenishment Method Enum ID (RPMEI)* and the concept of *Backup Facility*.
> The obvious difficulty with Approach A could be the need to modify existing 
> logic everywhere RMEI is being used and _may_ be difficult to implement and 
> validate (must confess that I have not given this approach much more 
> thought). On the contrary the Approach B seems a safer method to add this 
> feature with minimum possibility of breaking existing functionality.
> _Herein is the Approach B in detail-_
>  
> Introduce a ProductFacility specific *Replenishment Method Enum ID (RPMEI)* 
> with values such as -
> **Code snippets are from Opentaps**
> {code:xml}
> <!-- Enumeration for ProductFacility replenishMethodEnumId -->
>     <EnumerationType enumTypeId="PFAC_REPL_METHOD" hasTable="N" 
> description="Product Facility Replenish Methods"/>
>     <Enumeration enumId="PF_RM_NEVER" description="Never transfer" 
> enumTypeId="PFAC_REPL_METHOD"/>
>     <Enumeration enumId="PF_RM_BACKUP" description="Transfer from backup 
> warehouse if available" enumTypeId="PFAC_REPL_METHOD"/>
>     <Enumeration enumId="PF_RM_SPECIF" description="Transfer from specified 
> warehouse if available" enumTypeId="PFAC_REPL_METHOD"/>
>     <Enumeration enumId="PF_RM_BACKUP_ALW" description="Always transfer from 
> backup warehouse" enumTypeId="PFAC_REPL_METHOD"/>
>     <Enumeration enumId="PF_RM_SPECIF_ALW" description="Always transfer from 
> specified warehouse" enumTypeId="PFAC_REPL_METHOD"/>
> {code}
> and extend the entity ProductFacility -
> {code:xml}
> <extend-entity entity-name="ProductFacility">
> <field name="replenishMethodEnumId" type="id"/>
> <field name="replenishFromFacilityId" type="id-ne"/>
> <relation type="one" rel-entity-name="Facility" fk-name="PF_R_FAC" 
> title="ResplenishFromFacility">
> <key-map field-name="facilityId"/>
> </relation>
> <relation title="ResplenishMethod" fk-name="PF_R_METH" 
> rel-entity-name="Enumeration" type="one">
> <key-map field-name="replenishMethodEnumId" rel-field-name="enumId"/>
> </relation>
> </extend-entity>
> {code}
> Create new entities -
> {code:xml}
> <entity entity-name="FacilityAssoc" 
> package-name="org.opentaps.common.facility"
> title="Define associations between facilities">
> <field name="facilityId" type="id-ne"/>
> <field name="facilityIdTo" type="id-ne"/>
> <field name="facilityAssocTypeId" type="id-ne"/>
> <field name="fromDate" type="date-time"/>
> <field name="thruDate" type="date-time"/>
> <field name="sequenceNum" type="numeric"/> 
> <prim-key field="facilityId"/>
> <prim-key field="facilityIdTo"/>
> <prim-key field="facilityAssocTypeId"/>
> <prim-key field="fromDate"/>
> <relation type="one" fk-name="FACASSOC_FAC" title="From" 
> rel-entity-name="Facility">
> <key-map field-name="facilityId"/>
> </relation>
> <relation type="one" fk-name="FACASSOC_FACTO" title="To" 
> rel-entity-name="Facility">
> <key-map field-name="facilityIdTo" rel-field-name="facilityId"/>
> </relation>
> <relation type="one" fk-name="FACASSOC_TYPE" 
> rel-entity-name="FacilityAssocType">
> <key-map field-name="facilityAssocTypeId"/>
> </relation>
> </entity>
> <entity entity-name="FacilityAssocType" 
> package-name="org.opentaps.common.facility"
> title="Define associations between facilities">
> <field name="facilityAssocTypeId" type="id-ne"/>
> <field name="description" type="description"/>
> <prim-key field="facilityAssocTypeId"/> 
> </entity>
> <FacilityAssocType facilityAssocTypeId="BACKUP_INVENTORY" description="Holds 
> backup inventory"/>
> {code}
> Hence now we can define a replenishment method at a product level and that 
> too on a per facility basis.
> Additional now we can provision for defining of backup facility for any 
> facility. (May consider using the parentFacilityId available on the Facility 
> entity but am not sure about its purpose and there is no way to define the 
> relation between the parent and child.)
> We have to safeguard these:
>       1. There should be no direct or indirect cyclic backup facility 
> relation between any 2 facilities due to backup facility relation definition. 
>       2. There should be no direct or indirect cyclic replenishment facility 
> relation created due to defining of replenishFromFacilityId in a 
> ProductFacility entry for a product.
> Now when an order is placed on the retail store and ATP falls below Minimum 
> Stock at the primary facility mapped to the retail store, then depending on 
> the product's or store's RMEI setting combined with the facility's inventory 
> thresholds a purchase requirement may be generated. However, we are not 
> interested in this and may even block the generation of such a purchase 
> requirement for product's which have a RPMEI defined for a particular 
> facility. 
> Instead on a subsequent MRP run for the retailstore facility, based on the 
> open sales orders, we should generate/propose 'Inventory transfer 
> requirement' from the _backup facility_ or the _replenishFromFacilityId_ 
> depending on what's defined in the ProductFacility entity.
> This solution should hold good even in the case of many:many mapping between 
> stores and facilities as existing implementation is to reserve inventory 
> against the facility that is mapped to the store via inventoryFacilityId. 
> Hence there is no chance of the same sales order resulting in redundant 
> requirements on multiple facilities. 
> And since the RPMEI (Replenishment Method Enum Id) is defined at the 
> ProductFacility level there is no possibility of a general setting of RPMEI 
> at a facility or store level to compete with.
> This seems to be a rather important feature without which many businesses 
> operating brick and mortar stores as well as an ecommerce web-front can't 
> favourable use OFBiz.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to