ofbiz-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Swapnil Shah (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (OFBIZ-6964) Support for replenishment of a secondary warehouse from a main warehouse
Date Fri, 15 Apr 2016 05:30:26 GMT

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

Swapnil Shah edited comment on OFBIZ-6964 at 4/15/16 5:29 AM:
--------------------------------------------------------------

Thanks for the detailed feedback and other references. Few thoughts 
{quote}
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.
{quote}
I might not have made myself very clear but intention was never to theoretically or metahorically
belabor around the Replenishment concept. Instead idea is to explore the most commonly used
Replenishment "*Policies*" followed in retail domain across industries that have physical
stores spread across geographically. It could have possibly helped in coming up more holistic
design and solution that could be more widely acceptable (even if we start with piece-meal
apprach or KISS as per your liking). 
 
{quote}
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.
{quote}
Thanks for dissecting it further and Yes, surely we can refer it as inter-facility transfer.
I earlier specified it as inter-store because requirement would be essentially driven based
on Pull from store front for a given item rather than Push from any associted or backup facility.
 
 
{quote}
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.
{quote} 
Yes, while its true that in Ofbiz parlance they are kind of purchase requirement but culminatoin
of these process flows in PO generation is not always necessarily true. On numerous occassions
we have seen scenarios where Store at best can suggest How much & When product need to
be replenished based on sales velocity & forecasted demand to venodrs but they are not
necessarily transformed into purchase orders per se. It is purely vendor's prerogative. In
other words such replenishments works more on *Push* based mechanism from Vendor and not necessarily
driven through PO. So in short YES, for now we can keep it out from the scope of handling
Inter-facility transfer flow but they should be still considerered for any standard requirement
generation flow.

Coming back to the concept of requirement, The Product Requirement resulting into purchase
order and Iternal Requirement into production order is a typical OFbiz workflow historically
and in that sense i agree that auto-refilling of the store via inter-store(facility) "Stock
Transfer" is a new workflow or possibly an extension of the existing MRP flow. 
Based on all these understanding i believe, the core business requirement is still to have
the system to suggest the Requirements in terms of Qty and Timing based on certain pre-defined
set of rules replenishment policies. Subsequently there might be different ways to further
process these requirements like, via Purchase or Production Orders (based on existing Ofbiz
support) or via Inter-Facility Transfer (by introducing new systemic mechanism to support
it)
Also based on the shared Opentaps data, it seems they are using all the exact same existing
set of MrpEventTypeIds for defining InventoryEventPlannedType along with new needed ones.
I am not too sure from architeture and implemention point of view which could be simpler route
to follow. But similar new types could be added to MrpEventType as well to achieve the desired
results by leveraging upon most of the existing MRP algorithm (and UI support), of course
with needed extension for supporting new modes of processing product requirements via Transfers.
Something like as follows:

Let's say a typical Retail store supply chain setup looks like (as presented in flow diagram).

!screenshot-1.png|width=800px!

Introduce new ProductFacilityAssoc,FacilityAssocType, MrpEventType and corresponding RequirementType
to serve the requirement for replenishing the store's via Inter-facility transfers mode. We
could extend the MRP logic to honor these new types and create corresponding event & requirement
for Stock transfer. The data model & UI could be extended as follows:
{code}
<!-- New Entity ProductFacilityAssoc (Product-wise associations between facilities to define
from what all facilities a given product can be replenished)-->
<entity entity-name="ProductFacilityAssoc"
title="Define associations between Product facilities">
<field name="productId" type="id-ne"/>
<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="productId"/>
<prim-key field="facilityId"/>
<prim-key field="facilityIdTo"/>
<prim-key field="facilityAssocTypeId"/>
<prim-key field="fromDate"/>

<relation type="one" fk-name="PRFACASSOC_PRO" rel-entity-name="Product">
<key-map field-name="productId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_FAC" title="From" rel-entity-name="Facility">
<key-map field-name="facilityId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_FACTO" title="To" rel-entity-name="Facility">
<key-map field-name="facilityIdTo" rel-field-name="facilityId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_TYPE" rel-entity-name="FacilityAssocType">
<key-map field-name="facilityAssocTypeId"/>
</relation>
</entity>

<!-- New Entity FacilityAssocType (type of associations between facilities)-->
<entity entity-name="FacilityAssocType"
title="Define associations between facilities">
<field name="FacilityAssocType" type="id-ne"/>
<field name="description" type="description"/>
<prim-key field="facilityAssocTypeId"/> 
</entity>

<!-- New FacilityAssocType (type of association between facilities)-->
<ProductFacilityAssocType productFacilityAssocTypeId="BACKUP_WAREHOUSE" description="Facility
that serves another facility in terms of inventory"/>

<!-- New ProductFacilityAssoc (Association between facilities)-->
<ProductFacilityAssoc productId="GZ-8544" facilityId ="RegionalWarehouse_01" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="RegionalWarehouse_02" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="02" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="03" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="RegionalWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="RegionalWarehouse_02"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>

<!-- New MRPEventType (apart from existing ones in Ofbiz)-->
<MrpEventType description="Initial ATP" mrpEventTypeId="INITIAL_ATP"/>
<MrpEventType description="Proposed stock transfer if ATP is less than minimum quantity"
mrpEventTypeId="PROP_ATP_STOCK_TRANSFER"/>

<!-- New RequirementType (apart from existing ones in Ofbiz)-->
<RequirementType description="Inter-facility Transfer Requirement" requirementTypeId="TRANSFER_REQUIREMENT"/>

<!-- New Enumeration for Product Store Facility's requirementhMethodEnumId to be used to
trigger inter-facility transfer -->
<Enumeration description="When ATP Reaches Minimum Stock for Product-Store-Facility" enumCode="XFER_STOCK_ATP"
enumId="XFERRQM_STOCK_ATP" enumTypeId="PROD_REQ_METHOD"/>

<!-- Existing ProductStore for setting primary facility for each store -->
<ProductStore productStoreId="9100" inventoryFacilityId="StoreWarehouse_01" checkInventory="N"
oneInventoryFacility="N" requireInventory="N" reserveInventory="Y" reserveOrderEnumId="INVRO_FIFO_REC"
/> 

<!-- Extended ProductStoreFacility for setting RMEI)-->
<ProductStoreFacility productStoreId="9100" facilityId=="StoreWarehouse_01" requirementMethodEnumId="XFERRQM_STOCK_ATP"
fromDate="2001-04-13 12:00:00"/>

<!-- Existing ProductFacility (with Minimum Stock and ATP) -->
<ProductFacility facilityId="StoreWarehouse_01" lastInventoryCount="20.000000" minimumStock="100.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="RegionalWarehouse_01" lastInventoryCount="40.000000" minimumStock="200.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="RegionalWarehouse_02" lastInventoryCount="60.000000" minimumStock="200.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="CentralWarehouse" lastInventoryCount="200.000000" minimumStock="300.000000"
productId="GZ-8544"/>
{code}

MRP engine would start creating event beginning with store's primary facility based on set
RMEI under ProductStoreFacility e.g, XFERRQM_STOCK_ATP for StoreWarehouse_01, In other words
if MinStock < ATP , then MRP algorithm would: 
# Look up and consume the respective ATP from all the eligible "facilityIdTo" (based on ProductFacilityAssoc),
from where given product is transferable. Based on their priorities start allocating ATP unless
it meet the (MinStock-ATP) requirement for a given store e.g., 'StoreWarehouse_01' .
# Create new MRP Event with Event type "PROP_ATP_STOCK_TRANSFER" with Proposed Quantity =
MINIMUM STOCK - ATP from the facility (with highest priority i.e.,RegionalWarehouse_01).
## If demand for (MinStock-ATP) is still not fully met by any facility with higher priority
then repeat step#1 for all the associated facilities in desecending order of prioriy unless
ATP from all eligible facilities is exhausted.
# Based on above MRP Event Type and proposed quantity, In turn create the new Requirement
with type TRANSFER_REQUIREMENT.
# Over Requirement screen (UI) we can provide the "Transfer" button against all the requirement
with type TRANSFER_REQUIREMENT
# On hitting the "Transfer" button, The new 'Stock Transfer' requests could be created for
a product between eligible facilities based on step#1 above. 
# The created Stock Transfer request can be completed by shipping and receiving given product
from originating facility and destination facility respectively.



was (Author: swash78):
Thanks for the detailed feedback and other references. Few thoughts 
{quote}
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.
{quote}
I might not have made myself very clear but intention was never to theoretically or metahorically
belabor around the Replenishment concept. Instead idea is to explore the most commonly used
Replenishment "*Policies*" followed in retail domain across industries that have physical
stores spread across geographically. It could have possibly helped in coming up more holistic
design and solution that could be more widely acceptable (even if we start with piece-meal
apprach or KISS as per your liking). 
 
{quote}
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.
{quote}
Thanks for dissecting it further and Yes, surely we can refer it as inter-facility transfer.
I earlier specified it as inter-store because requirement would be essentially driven based
on Pull from store front for a given item rather than Push from any associted or backup facility.
 
 
{quote}
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.
{quote} 
Yes, while its true that in Ofbiz parlance they are kind of purchase requirement but culminatoin
of these process flows in PO generation is not always necessarily true. On numerous occassions
we have seen scenarios where Store at best can suggest How much & When product need to
be replenished based on sales velocity & forecasted demand to venodrs but they are not
necessarily transformed into purchase orders per se. It is purely vendor's prerogative. In
other words such replenishments works more on *Push* based mechanism from Vendor and not necessarily
driven through PO. So in short YES, for now we can keep it out from the scope of handling
Inter-facility transfer flow but they should be still considerered for any standard requirement
generation flow.

Coming back to the concept of requirement, The Product Requirement resulting into purchase
order and Iternal Requirement into production order is a typical OFbiz workflow historically
and in that sense i agree that auto-refilling of the store via inter-store(facility) "Stock
Transfer" is a new workflow or possibly an extension of the existing MRP flow. 
Based on all these understanding i believe, the core business requirement is still to have
the system to suggest the Requirements in terms of Qty and Timing based on certain pre-defined
set of rules replenishment policies. Subsequently there might be different ways to further
process these requirements like, via Purchase or Production Orders (based on existing Ofbiz
support) or via Inter-Facility Transfer (by introducing new systemic mechanism to support
it)
Also based on the shared Opentaps data, it seems they are using all the exact same existing
set of MrpEventTypeIds for defining InventoryEventPlannedType along with new needed ones.
I am not too sure from architeture and implemention point of view which could be simpler route
to follow. But similar new types could be added to MrpEventType as well to achieve the desired
results by leveraging upon most of the existing MRP algorithm (and UI support), of course
with needed extension for supporting new modes of processing product requirements via Transfers.
Something like as follows:

Let's say a typical Retail store supply chain setup looks like (as presented in flow diagram).

!screenshot-1.png!

Introduce new ProductFacilityAssoc,FacilityAssocType, MrpEventType and corresponding RequirementType
to serve the requirement for replenishing the store's via Inter-facility transfers mode. We
could extend the MRP logic to honor these new types and create corresponding event & requirement
for Stock transfer. The data model & UI could be extended as follows:
{code}
<!-- New Entity ProductFacilityAssoc (Product-wise associations between facilities to define
from what all facilities a given product can be replenished)-->
<entity entity-name="ProductFacilityAssoc"
title="Define associations between Product facilities">
<field name="productId" type="id-ne"/>
<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="productId"/>
<prim-key field="facilityId"/>
<prim-key field="facilityIdTo"/>
<prim-key field="facilityAssocTypeId"/>
<prim-key field="fromDate"/>

<relation type="one" fk-name="PRFACASSOC_PRO" rel-entity-name="Product">
<key-map field-name="productId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_FAC" title="From" rel-entity-name="Facility">
<key-map field-name="facilityId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_FACTO" title="To" rel-entity-name="Facility">
<key-map field-name="facilityIdTo" rel-field-name="facilityId"/>
</relation>
<relation type="one" fk-name="PRFACASSOC_TYPE" rel-entity-name="FacilityAssocType">
<key-map field-name="facilityAssocTypeId"/>
</relation>
</entity>

<!-- New Entity FacilityAssocType (type of associations between facilities)-->
<entity entity-name="FacilityAssocType"
title="Define associations between facilities">
<field name="FacilityAssocType" type="id-ne"/>
<field name="description" type="description"/>
<prim-key field="facilityAssocTypeId"/> 
</entity>

<!-- New FacilityAssocType (type of association between facilities)-->
<ProductFacilityAssocType productFacilityAssocTypeId="BACKUP_WAREHOUSE" description="Facility
that serves another facility in terms of inventory"/>

<!-- New ProductFacilityAssoc (Association between facilities)-->
<ProductFacilityAssoc productId="GZ-8544" facilityId ="RegionalWarehouse_01" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="RegionalWarehouse_02" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="02" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="StoreWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="03" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="RegionalWarehouse_01"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>
<ProductFacilityAssoc productId="GZ-8544" facilityId ="CentralWarehouse" facilityIdTo="RegionalWarehouse_02"
facilityAssocTypeId="BACKUP_WAREHOUSE" sequenceNum="01" fromDate="2001-01-01 12:00:00"/>

<!-- New MRPEventType (apart from existing ones in Ofbiz)-->
<MrpEventType description="Initial ATP" mrpEventTypeId="INITIAL_ATP"/>
<MrpEventType description="Proposed stock transfer if ATP is less than minimum quantity"
mrpEventTypeId="PROP_ATP_STOCK_TRANSFER"/>

<!-- New RequirementType (apart from existing ones in Ofbiz)-->
<RequirementType description="Inter-facility Transfer Requirement" requirementTypeId="TRANSFER_REQUIREMENT"/>

<!-- New Enumeration for Product Store Facility's requirementhMethodEnumId to be used to
trigger inter-facility transfer -->
<Enumeration description="When ATP Reaches Minimum Stock for Product-Store-Facility" enumCode="XFER_STOCK_ATP"
enumId="XFERRQM_STOCK_ATP" enumTypeId="PROD_REQ_METHOD"/>

<!-- Existing ProductStore for setting primary facility for each store -->
<ProductStore productStoreId="9100" inventoryFacilityId="StoreWarehouse_01" checkInventory="N"
oneInventoryFacility="N" requireInventory="N" reserveInventory="Y" reserveOrderEnumId="INVRO_FIFO_REC"
/> 

<!-- Extended ProductStoreFacility for setting RMEI)-->
<ProductStoreFacility productStoreId="9100" facilityId=="StoreWarehouse_01" requirementMethodEnumId="XFERRQM_STOCK_ATP"
fromDate="2001-04-13 12:00:00"/>

<!-- Existing ProductFacility (with Minimum Stock and ATP) -->
<ProductFacility facilityId="StoreWarehouse_01" lastInventoryCount="20.000000" minimumStock="100.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="RegionalWarehouse_01" lastInventoryCount="40.000000" minimumStock="200.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="RegionalWarehouse_02" lastInventoryCount="60.000000" minimumStock="200.000000"
productId="GZ-8544"/>
<ProductFacility facilityId="CentralWarehouse" lastInventoryCount="200.000000" minimumStock="300.000000"
productId="GZ-8544"/>
{code}

MRP engine would start creating event beginning with store's primary facility based on set
RMEI under ProductStoreFacility e.g, XFERRQM_STOCK_ATP for StoreWarehouse_01, In other words
if MinStock < ATP , then MRP algorithm would: 
# Look up and consume the respective ATP from all the eligible "facilityIdTo" (based on ProductFacilityAssoc),
from where given product is transferable. Based on their priorities start allocating ATP unless
it meet the (MinStock-ATP) requirement for a given store e.g., 'StoreWarehouse_01' .
# Create new MRP Event with Event type "PROP_ATP_STOCK_TRANSFER" with Proposed Quantity =
MINIMUM STOCK - ATP from the facility (with highest priority i.e.,RegionalWarehouse_01).
## If demand for (MinStock-ATP) is still not fully met by any facility with higher priority
then repeat step#1 for all the associated facilities in desecending order of prioriy unless
ATP from all eligible facilities is exhausted.
# Based on above MRP Event Type and proposed quantity, In turn create the new Requirement
with type TRANSFER_REQUIREMENT.
# Over Requirement screen (UI) we can provide the "Transfer" button against all the requirement
with type TRANSFER_REQUIREMENT
# On hitting the "Transfer" button, The new 'Stock Transfer' requests could be created for
a product between eligible facilities based on step#1 above. 
# The created Stock Transfer request can be completed by shipping and receiving given product
from originating facility and destination facility respectively.


> 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
>
>         Attachments: screenshot-1.png
>
>
> 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)

Mime
View raw message