ofbiz进击 。 ofbiz 退货流程(包含获取可退货项流程分析 以及 取消退货项的过程分析)

根据订单获取可退货项流程分析

退货的时候,调用 services_return.xml 中的获取可进行退货的退货项  getReturnableItems  ,该服务调用了Java类 org.ofbiz.order.order.OrderReturnServices 中的getReturnableItems方法。

通过获取到的orderId 获得相对应的订单,通过查询条件,(orderId = ‘DEMO1002‘ AND orderItemStatusId IN (‘ITEM_APPROVED‘, ‘ITEM_COMPLETED‘))

去执行 OrderItemQuantityReportGroupByItem 视图查询,获取 根据item分组得到的数据列表 ,

根据订单的类型判断订单是否为销售订单(SALES_ORDER),

根据上面分组得到的数据列表进行循环调用 getReturnableQuantity service服务,该服务调用的同样是上述java类中的getReturnableQuantity方法,

根据orderItem中的productId 获取对应的Product实体对象,根据该商品的returned属性,去判断该商品是否支持退货操作。

在根据该商品的supportDiscontinuationDate 的支持终止日期与当前时间做比较,如果小于当前时间,则不能进行退货操作。

定义一个orderQty变量,如果可以进行退货操作,获取orderItem的数量并进行赋值,如果orderItem中的cancelQuantity数目存在的话,将cancelQuantity与orderQty相减获取订单的数目,赋值给orderQty变量,

获取orderItem的statusId状态,如果状态存在于ITEM_APPROVED 或者 ITEM_COMPLETED中,进行下面的循环。

根据OrderItem获取对应的退货项列表,如果退货项为空的话,可退货数目则为上面定义的orderQty的值,

如果退货项列表不为空的话,定义一个returnedQty变量,对列表进行循环,如果退货项的状态不为RETURN_CANCELLED,就对returnedQty 进行 增加的操作,最终将订单的orderQty数目与 returnedQty 数目相减,获取该orderitem可归还的数目。

生成退货单流程分析

因为我个人是打算用的ofbiz里面的service服务的,因此,要直接使用这个服务的时候,要求界面上的所要提交的参数值要保证跟ofbiz原生的页面相差不多,因此,直接对使用ofbiz原生的页面进行样式修改。

调用上面的获取可退货项的服务之后,获取了页面之后,然后进行提交,提交的target为createReturnAndItemOrAdjustment这个服务(control里面的调用事件type为service-multi),这个服务是调用simplemethod方法,method定义的文件为component://order/script/org/ofbiz/order/order/OrderReturnServices.xml,调用的方法为createReturnAndItemOrAdjustment,

先判断参数里面是否包含returnId,如果returnId为空,则创建退货单,然后根据返回回来的returnId,去调用createReturnItemOrAdjustment这个服务,这个服务的实现方法是使用java的方式,java类为org.ofbiz.order.order.OrderReturnServices,调用的方法为createReturnItemOrAdjustment,判断orderItemSeqId是否存在,如果存在,则调用createReturnItem,如果不存在,则调用createReturnAdjustment服务。

createReturnItem 服务是使用simplemethod的 方式,method的定义文件为component://order/script/org/ofbiz/order/order/OrderReturnServices.xml,调用方法为createReturnItem,这个服务里面有很多判断,例如是否有权限,是否有returntypeId,是否有归还数目等等,具体的要到对应的文件里面去看具体实现方法。

受理退货单

首先调用updateReturnHeader服务,服务定义在services_return.xml文件中,服务的实现方法为simple-method,定义文件为component://order/script/org/ofbiz/order/order/OrderReturnServices.xml,调用的方法为updateReturnHeader

在该服务中,没有明显的其他操作,但是很明显的在执行updateReturnHeader这个服务的时候,在后台能看到执行了好多其他的方法,说明在secas.xml中定义了该服务执行时会触发别的服务的执行。该文件一般存在于/emt/applications/order/servicedef/secas.xml   即跟服务文件同目录下,然后然后去看对应的服务在某些condition条件的满足下,会触发哪些别的服务。

 1 <eca service="updateReturnHeader" event="return">
 2         <condition field-name="statusId" operator="equals" value="RETURN_ACCEPTED"/>
 3         <!-- The quickReceiveReturn service checks this, and some status update calls may not pass it in, so don‘t
 4              check it here or the option may be ignored.
 5          <condition field-name="needsInventoryReceive" operator="equals" value="Y"/> -->
 6         <action service="quickReceiveReturn" mode="sync"/>
 7     </eca>
 8     <eca service="updateReturnHeader" event="commit">
 9         <condition field-name="statusId" operator="equals" value="RETURN_ACCEPTED"/>
10         <condition field-name="oldStatusId" operator="not-equals" value="RETURN_ACCEPTED"/>
11         <action service="processWaitReplacementReservedReturn" mode="sync"/>
12         <action service="processReplaceImmediatelyReturn" mode="sync"/>
13         <action service="createShipmentAndItemsForReturn" mode="sync"/>
14         <action service="processCrossShipReplacementReturn" mode="sync"/>
15         <action service="createTrackingCodeOrderReturns" mode="sync" run-as-user="system"/>
16         <action service="sendReturnAcceptNotification" mode="async" persist="true"/>
17         <action service="processRefundImmediatelyReturn" mode="sync"/>
18         <action service="createReturnStatus" mode="sync"/>
19     </eca>

首先当触发event事件并且statusId状态为RETURN_ACCEPTED的时候,就会调用quickReceiveReturn服务,下面为该服务的逻辑判断,如果嫌长可以快速掠过。

  1 <simple-method method-name="quickReceiveReturn" short-description="Quick Receive Entire Return">
  2         <entity-one entity-name="ReturnHeader" value-field="returnHeader">
  3             <field-map field-name="returnId" from-field="parameters.returnId"/>
  4         </entity-one>
  5
  6         <if-compare field="returnHeader.needsInventoryReceive" operator="equals" value="Y">
  7             <!-- before receiving inventory, check to see if there is inventory information in this database -->
  8             <entity-count entity-name="InventoryItem" count-field="iiCount">
  9                 <condition-expr field-name="facilityId" operator="equals" from-field="returnHeader.destinationFacilityId"/>
 10             </entity-count>
 11
 12             <if-compare field="iiCount" operator="greater" value="0" type="Integer">
 13                 <!-- create a return shipment for this return -->
 14                 <set field="shipmentCtx.returnId" from-field="parameters.returnId"/>
 15                 <call-service service-name="createShipmentForReturn" in-map-name="shipmentCtx">
 16                     <result-to-field result-name="shipmentId"/>
 17                 </call-service>
 18                 <log level="info" message="Created new shipment ${shipmentId}"/>
 19
 20                 <entity-condition entity-name="ReturnItem" list="returnItems">
 21                     <condition-expr field-name="returnId" operator="equals" from-field="returnHeader.returnId"/>
 22                 </entity-condition>
 23
 24                 <!-- if no inventory item type specified, get default from facility -->
 25                 <if-empty field="parameters.inventoryItemTypeId">
 26                     <get-related-one value-field="returnHeader" relation-name="Facility" to-value-field="facility"/>
 27                     <set field="parameters.inventoryItemTypeId" from-field="facility.defaultInventoryItemTypeId" default-value="NON_SERIAL_INV_ITEM"/>
 28                 </if-empty>
 29
 30                 <now-timestamp field="nowTimestamp"/>
 31
 32                 <entity-count entity-name="ReturnItem" count-field="returnItemCount">
 33                     <condition-expr field-name="returnId" operator="equals" from-field="returnHeader.returnId"/>
 34                 </entity-count>
 35                 <set field="nonProductItems" type="Long" value="0"/>
 36
 37                 <iterate entry="returnItem" list="returnItems">
 38                     <!-- record this return item on the return shipment as well.  not sure if this is actually necessary... -->
 39                     <clear-field field="shipItemCtx"/>
 40                     <set from-field="shipmentId" field="shipItemCtx.shipmentId"/>
 41                     <set from-field="returnItem.productId" field="shipItemCtx.productId"/>
 42                     <set from-field="returnItem.returnQuantity" field="shipItemCtx.quantity"/>
 43                     <log level="info" message="calling create shipment item with ${shipItemCtx}"/>
 44                     <call-service service-name="createShipmentItem" in-map-name="shipItemCtx">
 45                         <result-to-field result-name="shipmentItemSeqId"/>
 46                     </call-service>
 47                 </iterate>
 48                 <iterate entry="returnItem" list="returnItems">
 49                     <clear-field field="receiveCtx"/>
 50
 51                     <if-empty field="returnItem.expectedItemStatus">
 52                         <set value="INV_RETURNED" field="returnItem.expectedItemStatus" type="String"/>
 53                     </if-empty>
 54                     <get-related-one value-field="returnItem" relation-name="OrderItem" to-value-field="orderItem"/>
 55                     <if-not-empty field="orderItem.productId">
 56                         <set field="costCtx.returnItemSeqId" from-field="returnItem.returnItemSeqId"/>
 57                         <set field="costCtx.returnId" from-field="returnItem.returnId"/>
 58                         <call-service service-name="getReturnItemInitialCost" in-map-name="costCtx">
 59                             <result-to-field result-name="initialItemCost" field="receiveCtx.unitCost"/>
 60                         </call-service>
 61                         <!--check if the items already have SERIALIZED inventory. If so, it still puts them back as SERIALIZED with status "Accepted."-->
 62                         <entity-count entity-name="InventoryItem" count-field="serializedItemCount">
 63                             <condition-list combine="and">
 64                                 <condition-expr field-name="productId" operator="equals" from-field="returnItem.productId"/>
 65                                 <condition-expr field-name="facilityId" operator="equals" from-field="returnHeader.destinationFacilityId"/>
 66                                 <condition-expr field-name="inventoryItemTypeId" operator="equals" value="SERIALIZED_INV_ITEM"/>
 67                             </condition-list>
 68                         </entity-count>
 69                         <set field="setNonSerial" value="false"/>
 70                         <if-compare field="parameters.inventoryItemTypeId" value="NON_SERIAL_INV_ITEM" operator="equals">
 71                             <if-compare field="serializedItemCount" value="0" operator="equals">
 72                                 <set field="parameters.inventoryItemTypeId" value="NON_SERIAL_INV_ITEM"/>
 73                                 <set field="setNonSerial" value="true"/>
 74                             </if-compare>
 75                         </if-compare>
 76                         <if-compare field="setNonSerial" value="false" operator="equals">
 77                             <set field="parameters.inventoryItemTypeId" value="SERIALIZED_INV_ITEM"/>
 78                             <set field="returnItem.returnQuantity" value="1" type="BigDecimal"/>
 79                         </if-compare>
 80
 81                         <set from-field="parameters.inventoryItemTypeId" field="receiveCtx.inventoryItemTypeId"/>
 82                         <set from-field="returnItem.expectedItemStatus" field="receiveCtx.statusId"/>
 83                         <set from-field="returnItem.productId" field="receiveCtx.productId"/>
 84                         <set from-field="returnItem.returnItemSeqId" field="receiveCtx.returnItemSeqId"/>
 85                         <set from-field="returnItem.returnId" field="receiveCtx.returnId"/>
 86                         <set from-field="returnItem.returnQuantity" field="receiveCtx.quantityAccepted"/>
 87                         <set from-field="returnHeader.destinationFacilityId" field="receiveCtx.facilityId"/>
 88                         <!-- important: associate ShipmentReceipt with return shipment created -->
 89                         <set field="receiveCtx.shipmentId" from-field="shipmentId"/>
 90
 91                         <set field="receiveCtx.comments" value="Returned Item RA# ${returnItem.returnId}"/>
 92                         <set field="receiveCtx.datetimeReceived" from-field="nowTimestamp"/>
 93                         <set field="receiveCtx.quantityRejected" value="0" type="BigDecimal"/>
 94
 95                         <call-service service-name="receiveInventoryProduct" in-map-name="receiveCtx"/>
 96                     <else>
 97                         <calculate field="nonProductItems" type="Long">
 98                             <calcop operator="add">
 99                                 <number value="1"/>
100                             </calcop>
101                         </calculate>
102                     </else>
103                     </if-not-empty>
104                 </iterate>
105
106                 <!-- now that the receive is done; set the need flag to N -->
107                 <refresh-value value-field="returnHeader"/>
108                 <set field="returnHeader.needsInventoryReceive" value="N"/>
109                 <store-value value-field="returnHeader"/>
110
111                 <!-- always check/update the ReturnHeader status, even though it might have been from the receiving above, just make sure -->
112                 <if-compare field="returnHeader.statusId" operator="not-equals" value="RETURN_RECEIVED">
113                     <set field="retStCtx.returnId" from-field="returnHeader.returnId"/>
114                     <set field="retStCtx.statusId" value="RETURN_RECEIVED"/>
115                     <call-service service-name="updateReturnHeader" in-map-name="retStCtx"/>
116                 </if-compare>
117             <else>
118                 <log level="info" message="Not receiving inventory for returnId ${returnHeader.returnId}, no inventory information available."/>
119             </else>
120             </if-compare>
121         </if-compare>
122     </simple-method>

大概分析下该simple-method方法,判断returnHeader退货头的needsInventoryReceive字段(需要仓库接收 ),如果是的话,判断退货头的DESTINATION_FACILITY_ID是否等于facilityId,如果等于,就获取库存项的数目,如果库存量大于0,则调用createShipmentForReturn(创建针对退货的装运头)的服务,生成shipmentId,然后判断参数parameters.inventoryItemTypeId是否为空,如果为空,就给默认值NON_SERIAL_INV_ITEM,获取退货项的数目,循环退货项的列表,调用createShipmentItem(装运项)服务,接着继续根据退货项列表循环调用receiveInventoryProduct(创建新的库存项目接收库存(S))服务。

然后还会调好多的别的服务,我就实在没有心思一一仔细阅读了,最后还需要调用这个createReturnStatus服务,这个服务就跟流程日志一样,不管是创建还是针对该对象进行的任何修改操作,都会新增一条这样的状态,用于跟踪退货单的流程。

时间: 2024-11-10 14:05:31

ofbiz进击 。 ofbiz 退货流程(包含获取可退货项流程分析 以及 取消退货项的过程分析)的相关文章

iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析

iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析 浏览: 149 发布日期: 2016-10-19  分类: ios 最近在项目中接入了微信支付和支付宝支付,总的来说没有那么坑,很多人都说文档不全什么的,确实没有面面 俱到,但是认真一步一步测试下还是妥妥的,再配合懂得后台,效率也是很高的,看了这篇文章,你也只要几分钟, 就能轻松接入支付宝,在别人投来崇拜的眼光的同时,你就能潇洒的回一句,略懂略懂......   先给大家我写的微信支付,很详细哦,喜欢的点个赞点击打开微信支付链

Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析

本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 前置文章: <Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划> <Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析> <Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程

Net Core 使用外部登陆提供程序登陆的流程,以及身份认证的流程

原文出自Rui Figueiredo的博文<External Login Providers in ASP.NET Core> (本文很长) 摘要:本文主要介绍了使用外部登陆提供程序登陆的流程,以及身份认证的流程. 为了能够使用google.facebook.twitter.微博等外部登陆提供程序,从而避免创建本地账户以及电子邮件验证等繁琐步骤,我们一般会引用到外部登陆服务,将验证用户身份的任务委托给他们.外部验证最为流行的协议就是OAuth2和OpenId Connect. 在Asp.Net

Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程

本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 前置文章: <Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划> <Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析> <Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程

【代码篇】JBPM4.4开发流程节点(动态代理实现流程管理业务)

继之前的博客,[思想篇]工作流技术JBPM4.4开发入门(四),[思想篇]工作流技术JBPM4.4开发入门(五)本篇博客来结合代码简单说说,如何让流程来管理业务: 先来看看我们抽出来的代理类: StartAbstractJBPM:流程启动节点 package com.hjy.ssh.action; import com.hjy.ssh.beans.AbstractApply; import java.lang.reflect.Method; import java.lang.reflect.Pr

activiti 一个流程的运转步骤 以请假流程为例

---为了加深对activiti的理解记忆,对自己做的一个流程进行自述.加强记忆 请假实例 一.设计请假的流程图以及流程文件,完善对应数据项,比如用户信息,请假单信息 --请假单 --流程图 --流程文件leaveBill.bpmn <?xml version="1.0" encoding="UTF-8"?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL&qu

linux内核数据包转发流程(三)网卡帧接收分析

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.邮箱:shallnew*163.com] 每个cpu都有队列来处理接收到的帧,都有其数据结构来处理入口和出口流量,因此,不同cpu之间没有必要使用上锁机制,.此队列数据结构为softnet_data(定义在include/linux/netdevice.h中): /* * Incoming packets are placed on per-cpu queues so that * no locking is neede

BPM实例分享:领导不通过某流程时,如何即可结束流程并告知发起人驳回通知

在很多业务场景中,你是否碰到这样的流程疑问: 领导不通过某审批单时,如何实现即刻结束流程并告知发起人该审批被驳回的通知?   鉴于近期有H3 BPM 10.0的用户向小编咨询这个问题, 且一些业务场景中一般都会涉及此流程, 小编特此整理此文并与大家共同分享! 系统版本:H3 BPM 10.0 用户:结束流程是指直接跳过中间流程直接结束?还是指该流程已作废? 回答:是中间节点全部跳过,直接结束流程.流程作废和流程结束是两个流程状态,不能混淆了. 用户:在哪个地方.如何设置流程结束通知? 我在属性-

java使用websocket,并且获取HttpSession,源码分析

一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Spring boot使用websocket 2.1:依赖包 websocket本身是servlet容器所提供的服务,所以需要在web容器中运行,像我们所使用的tomcat,当然,spring boot中已经内嵌了tomcat. websocket遵循了javaee规范,所以需要引入javaee的包 <