1 CREATE OR REPLACE FUNCTION relocateInventory(INTEGER, INTEGER, INTEGER, NUMERIC, TEXT) RETURNS INTEGER AS $$
2 -- Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple.
3 -- See www.xtuple.com/CPAL for the full text of the software license.
5 RETURN relocateInventory($1, $2, $3, $4, $5, CURRENT_TIMESTAMP);
9 CREATE OR REPLACE FUNCTION relocateInventory(pSourceItemlocid INTEGER,
10 pTargetLocationid INTEGER,
14 pGLDistTS TIMESTAMP WITH TIME ZONE) RETURNS INTEGER AS $$
15 -- Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple.
16 -- See www.xtuple.com/CPAL for the full text of the software license.
18 _GlDistTS TIMESTAMP WITH TIME ZONE;
19 _targetItemlocid INTEGER;
24 _qtyunreserved NUMERIC := 0.0;
25 _qtytomove NUMERIC := 0.0;
26 _result INTEGER := -1;
27 _itemlocSeries INTEGER := NEXTVAL('itemloc_series_seq');
31 IF ((pGlDistTS IS NULL) OR (CAST(pGlDistTS AS date)=CURRENT_DATE)) THEN
32 _GlDistTS := CURRENT_TIMESTAMP;
34 _GLDistTS := pGLDistTS;
37 -- Make sure the passed itemsite points to a real item
38 IF ( ( SELECT (item_type IN ('R', 'F') OR itemsite_costmethod = 'J')
40 WHERE ( (itemsite_item_id=item_id)
41 AND (itemsite_id=pItemsiteid) ) ) ) THEN
45 -- Cache some parameters
47 itemloc_itemsite_id AS itemsiteid,
52 WHERE (itemloc_id=pSourceItemlocid);
54 -- Check to make sure the qty being transfered exists
55 IF (_p.itemloc_qty < pQty) THEN
59 -- Create the RL transaction
60 SELECT NEXTVAL('invhist_invhist_id_seq') INTO _invhistid;
62 ( invhist_id, invhist_itemsite_id,
63 invhist_transtype, invhist_invqty,
64 invhist_qoh_before, invhist_qoh_after,
65 invhist_comments, invhist_transdate,
66 invhist_invuom, invhist_unitcost, invhist_costmethod,
67 invhist_value_before, invhist_value_after, invhist_series)
68 SELECT _invhistid, itemsite_id,
70 itemsite_qtyonhand, itemsite_qtyonhand,
73 CASE WHEN (itemsite_costmethod='A') THEN avgcost(itemsite_id)
75 END, itemsite_costmethod,
76 itemsite_value, itemsite_value, _itemlocSeries
77 FROM item, itemsite, uom
78 WHERE ((itemsite_item_id=item_id)
79 AND (item_inv_uom_id=uom_id)
80 AND (itemsite_controlmethod <> 'N')
81 AND (itemsite_id=pItemsiteid));
83 -- Relocate the inventory from the source and record the transactions
85 ( invdetail_invhist_id, invdetail_location_id, invdetail_ls_id,
86 invdetail_qty, invdetail_qty_before, invdetail_qty_after,
87 invdetail_expiration, invdetail_warrpurc )
88 SELECT _invhistid, itemloc_location_id, itemloc_ls_id,
89 (pQty * -1), itemloc_qty, (itemloc_qty - pQty),
90 itemloc_expiration, itemloc_warrpurc
92 WHERE (itemloc_id=pSourceItemlocid);
95 SET itemloc_qty=(itemloc_qty - pQty)
97 WHERE ( (itemloc_itemsite_id=itemsite_id)
98 AND (NOT itemsite_freeze)
99 AND (itemloc_id=pSourceItemlocid) );
101 -- Check to see if any of the current Lot/Serial #/Expiration exists at the target location
102 SELECT itemloc_id INTO _targetItemlocid
104 WHERE ( (COALESCE(itemloc_ls_id, -1)=COALESCE(_p.itemloc_ls_id,-1))
105 AND (COALESCE(itemloc_expiration,endOfTime())=COALESCE(_p.itemloc_expiration,endOfTime()))
106 AND (COALESCE(itemloc_warrpurc,endOfTime())=COALESCE(_p.itemloc_warrpurc,endOfTime()))
107 AND (itemloc_itemsite_id=pItemsiteid)
108 AND (itemloc_location_id=pTargetLocationid) );
111 SELECT NEXTVAL('itemloc_itemloc_id_seq') INTO _targetItemlocid;
113 ( itemloc_id, itemloc_itemsite_id, itemloc_location_id,
114 itemloc_ls_id, itemloc_expiration, itemloc_warrpurc, itemloc_qty )
116 ( _targetItemlocid, pItemsiteid, pTargetLocationid,
117 _p.itemloc_ls_id, _p.itemloc_expiration, _p.itemloc_warrpurc, 0 );
120 -- Relocate the inventory to the resultant target and record the transactions
121 INSERT INTO invdetail
122 ( invdetail_invhist_id, invdetail_location_id, invdetail_ls_id,
123 invdetail_qty, invdetail_qty_before, invdetail_qty_after,
124 invdetail_expiration, invdetail_warrpurc )
125 SELECT _invhistid, pTargetLocationid, _p.itemloc_ls_id,
126 pQty, itemloc_qty, (itemloc_qty + pQty),
127 _p.itemloc_expiration, _p.itemloc_warrpurc
129 WHERE (itemloc_id=_targetItemlocid);
132 SET itemloc_qty=(itemloc_qty + pQty)
134 WHERE ( (itemloc_itemsite_id=itemsite_id)
135 AND (NOT itemsite_freeze)
136 AND (itemloc_id=_targetItemlocid) );
139 SET invhist_hasdetail=TRUE
140 WHERE (invhist_id=_invhistid);
142 -- Check to see if there is anything left at the target Itemloc and delete if not
143 -- Could be zero if relocate increased a negative quantity to zero
145 WHERE ( (itemloc_qty=0)
146 AND (itemloc_id=_targetItemlocid) );
148 -- Handle Reservations
149 IF (fetchMetricBool('EnableSOReservationsByLocation')) THEN
150 SELECT CASE WHEN (qtyReservedLocation(itemloc_id) > itemloc_qty)
151 THEN (qtyReservedLocation(itemloc_id) - itemloc_qty)
153 END INTO _qtyunreserved
155 WHERE (itemloc_id=pSourceItemlocid);
156 -- Move reservations as necessary
157 WHILE (_qtyunreserved > 0.0) LOOP
160 WHERE ((reserve_supply_type='I')
161 AND (reserve_supply_id=pSourceItemlocid))
162 ORDER BY reserve_qty;
164 RAISE EXCEPTION 'Cannot find reservation to unreserve.';
166 IF (_rsrv.reserve_qty > _qtyunreserved) THEN
167 _qtytomove := _qtyunreserved;
169 _qtytomove := _rsrv.reserve_qty;
171 -- Unreserve Source Location
172 SELECT unreserveSOLineQty(_rsrv.reserve_demand_id,
174 pSourceItemlocid) INTO _result;
175 IF (_result < 0) THEN
176 RAISE EXCEPTION 'unreserveSOLineQty failed with result=%, reserve_id=%, qty=%',
177 _result, _rsrv.reserve_id, _qtytomove;
179 -- Reserve to new Location
180 SELECT reserveSOLineQty(_rsrv.reserve_demand_id,
183 _targetItemlocid) INTO _result;
184 IF (_result < 0) THEN
185 RAISE EXCEPTION 'reserveSOLineQty failed with result=%, reserve_id=%, qty=%',
186 _result, _rsrv.reserve_id, _qtytomove;
188 -- Calculate running total
189 _qtyunreserved := _qtyunreserved - _qtytomove;
193 -- Check to see if there is anything left at the source Itemloc and delete if not
195 WHERE ( (itemloc_qty=0)
196 AND (itemloc_id=pSourceItemlocid) );
198 -- Return the invhist_id