Search code examples
c#mysqlfifoinventory-management

How to update stock table quantity on the basis of expiry date?


Hello everyone i have a table of inventory stock with columns as following

Item_ID  | Expiry_Date | Quantity | Rate
 cB0001  | 01-18-2021  |     5    | 150
 cB0001  | 12-08-2020  |     3    | 145
 cB0001  | 02-15-2021  |     25   | 155

Note : Rate is not an issue I just want to update the Stock Table Quantity on the basis on expiry date and available qty.

Now i want to sale inventory to customers of item cB0001 qty : 10 from the stock that expire first. Now the problem is that sale quantity is 10 and I want to minus the quantity 5 of expiry date 01-18-2021 and 3 From expiry date 12-08-2020 and 2 from 02-15-2021. Basically i want to implement FIFO logic using one query. I want to update the stock table quantity using this

update stock set quantity = quantity - '10' where item_id = 'cB0001' and expiry_Date < Now()

But this not giving accurate result. How to fix this problem? you have any idea?

I hope you understand my question


Solution

  • I assume you intend to do this in a trigger. So the 'trick' is to work out when the sale is fulfilled (working out IF it can be fulfilled is another issue). To do this allocate a value of 0 to rows where the cumulative quantity is less than the sale, 1 to the row where the sale can finally be fullfilled and 2 after that. I have assumed there is a unique row identifier to cope with multiple inventory entries for the same date - in my case inventory.id

    drop table if exists inventory,sales;
    create table inventory
    (id int auto_increment primary key,Item_ID varchar(20),  Expiry_Date date,  Quantity int, Rate int);
    
    create table sales (item_id varchar(20), quantity int);
    
    insert into inventory values
    ( null,'cB0001'  , str_to_date('01-18-2021','%m-%d-%Y'),     5    , 150),
    ( null,'cB0001'  , str_to_date('12-08-2020','%m-%d-%Y'),     3    , 145),
    ( null,'cB0001'  , str_to_date('02-15-2021','%m-%d-%Y'),     25   , 155),
    ( null,'cB0001'  , str_to_date('02-15-2021','%m-%d-%Y'),     10   , 155),
    ( null,'cB0001'  , str_to_date('02-15-2021','%m-%d-%Y'),     10   , 155),
    ( null,'cB0001'  , str_to_date('02-15-2021','%m-%d-%Y'),     10   , 155),
    ( null,'cB0002'  , str_to_date('02-15-2021','%m-%d-%Y'),     30   , 155);
    
    drop trigger if exists t;
    delimiter $$
    create trigger t after insert on sales
    for each row 
    begin
    update  inventory  left join
    (select s.*,
             if(fst = 0, @runqty:=@runqty+quantity,@runqty:=@runqty) qty
    from
    (
    select *,
             @t:=@t+quantity cumqty,
             if(@t>=@sale,if(@p>=1,2,@p:=1),@p:=0) fst
    from inventory
    cross join (select @t:=0,@p:=0,@sale:=new.quantity) t
    where quantity > 0 and item_id = new.item_id
    order by item_id,expiry_date
    ) s
    cross join (select @runqty:=0) r
    where fst in (0,1)
    ) a
    on a.id = inventory.id 
    set inventory.quantity = case when fst = 0 then 0 
                                          when fst = 1 then inventory.quantity - (new.quantity - a.qty)
                                     else inventory.quantity
                                     end;
    
    end $$
    
    delimiter ;
    
    
    MariaDB [sandbox]> insert into sales values('cb0001',10);
    Query OK, 1 row affected (0.095 sec)
    
    MariaDB [sandbox]> select * from inventory order by item_id,expiry_date;
    +----+---------+-------------+----------+------+
    | id | Item_ID | Expiry_Date | Quantity | Rate |
    +----+---------+-------------+----------+------+
    |  2 | cB0001  | 2020-12-08  |        0 |  145 |
    |  1 | cB0001  | 2021-01-18  |        0 |  150 |
    |  3 | cB0001  | 2021-02-15  |       23 |  155 |
    |  4 | cB0001  | 2021-02-15  |       10 |  155 |
    |  5 | cB0001  | 2021-02-15  |       10 |  155 |
    |  6 | cB0001  | 2021-02-15  |       10 |  155 |
    |  7 | cB0002  | 2021-02-15  |       30 |  155 |
    +----+---------+-------------+----------+------+
    7 rows in set (0.001 sec)
    
    MariaDB [sandbox]>
    MariaDB [sandbox]> insert into sales values('cb0001',25);
    Query OK, 1 row affected (0.111 sec)
    
    MariaDB [sandbox]>
    MariaDB [sandbox]> select * from inventory order by item_id,expiry_date;
    +----+---------+-------------+----------+------+
    | id | Item_ID | Expiry_Date | Quantity | Rate |
    +----+---------+-------------+----------+------+
    |  2 | cB0001  | 2020-12-08  |        0 |  145 |
    |  1 | cB0001  | 2021-01-18  |        0 |  150 |
    |  3 | cB0001  | 2021-02-15  |        0 |  155 |
    |  4 | cB0001  | 2021-02-15  |        8 |  155 |
    |  5 | cB0001  | 2021-02-15  |       10 |  155 |
    |  6 | cB0001  | 2021-02-15  |       10 |  155 |
    |  7 | cB0002  | 2021-02-15  |       30 |  155 |
    +----+---------+-------------+----------+------+
    7 rows in set (0.001 sec)