403Webshell
Server IP : 210.245.233.93  /  Your IP : 216.73.216.226
Web Server : Apache/2.2.15 (CentOS)
System : Linux webserver2.onesolution.com.hk 2.6.32-754.35.1.el6.x86_64 #1 SMP Sat Nov 7 12:42:14 UTC 2020 x86_64
User : apache ( 48)
PHP Version : 5.3.3
Disable Function : exec, shell_exec, system, passthru, popen, proc_open, pcntl_exec
MySQL : ON  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/hkosl.com/m.musiccircle/webadmin/models/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/hkosl.com/m.musiccircle/webadmin/models/Inventory.php
<?php

use Illuminate\Database\Capsule\Manager as DB;
use Carbon\Carbon as Carbon;

class Inventory extends BaseModel{
	protected $table = "inventory";

	public function invetoryTxns(){
		return $this->hasMany('InventoryTxn');
	}

	public function proProductSku(){
		return $this->belongsTo('ProProductSku', 'productsku_id');
	}

	public function warehouse(){
		return $this->belongsTo('Warehouse', 'warehouse_id');
	}





	//----------------------------static functions--------------------------------------

	public static function stockin($productsku_id, $qty, $warehouse_id, $settings=array()){
		global $dbh;
		// insert into (optional)

		// insert into inventory
		$inventory = Inventory::create(array(
			'company_id' => 1,
			'productsku_id' => $productsku_id,
			'warehouse_id' => $warehouse_id,
			'org_qty' => $qty,
			'qty' => $qty,
			'docdate' => date('Y-m-d'),
			'unit_cost' => $settings['unit_cost'] ?: 0,
		));
		$inventory_id = $inventory->id;

		// insert into inventory_txn
		$inventory_txn = InventoryTxn::create(array(
			'company_id' => 1,
			'productsku_id' => $productsku_id,
			'inventory_id' => $inventory_id,
			'docdate' => date('Y-m-d'),
			'doc_type' => $settings['doc_type'] ?: 'StockAdjustment',
			'doc_id' => $settings['doc_id'] ?: false,
			'from_warehouse_id' => false,
			'to_warehouse_id' => $warehouse_id,
			'qty' => $qty,
		));

		// update productsku.qty
		self::update_productsku_qty($productsku_id);
		return true;
	}

	public static function stockout_reserved($productsku_id, $qty, $settings=array()){
		return self::stockout($productsku_id, $qty, array('deduct_reserved_qty'=>true)+$settings);
	}

	public static function stockout($productsku_id, $qty, $settings=array()){
		$productsku = ProProductSku::find($productsku_id);
		if($qty>$productsku['qty']){
			throw new Exception("Insufficient stock", 1);
		}

		$qty_remaining = $qty;

		$inventoryTxns = array();
		while($qty_remaining>0){
			$inventory = self::stockout_inventory($productsku_id, $settings);
			if(!$inventory){
				// roll back
				throw new Exception("Insufficient stock", 1);
			}

			$qty_to_deduct = min($inventory['qty'], $qty_remaining);
			$qty_remaining -= $qty_to_deduct;
			// var_dump("Stock out {$qty_to_deduct} from inventory {$inventory['id']}");

			// insert into inventory_txn
			$inventoryTxns[] = InventoryTxn::create(array(
				'company_id' => 1,
				'order_item_id' => $settings['order_item_id'],
				'productsku_id' => $productsku_id,
				'inventory_id' => $inventory['id'],
				'docdate' => date('Y-m-d'),
				'doc_type' => $settings['doc_type'] ?: 'StockAdjustment',
				'doc_id' => $settings['doc_id'],
				'from_warehouse_id' => $inventory['warehouse_id'],
				'to_warehouse_id' => false,
				'qty' => $qty_to_deduct,
			));

			// update inventory.qty
			self::update_inventory_qty($inventory['id'], $inventory['warehouse_id']);
			// decrease pro_product_sku.reserved_qty
			if($qty && $settings['deduct_reserved_qty']!==false){
				// reserve qty in negative qty
				self::reserve($productsku_id, $qty, false);
			}
		}

		// update productsku.qty
		self::update_productsku_qty($productsku_id);
		return $inventoryTxns;
	}

	// $settings = [
	// 	'createby' => 'user1',
	// 	'stockout_doc' => [
	// 		'doc_type' => 'DeliveryNote',
	// 		'doc_id' => '1000001',
	// 	],
	// 	'stockin_doc' => [
	// 		'doc_type' => 'TransferNote',
	// 		'doc_id' => '50000000',
	// 	]
	// ]
	public static function stockTransfer($productsku_id, $qty, $from_warehouse_id, $to_warehouse_id, $settings=array()){
		$inventoryTxns = self::stockout($productsku_id, $qty, $settings['stockout_doc']+$settings);
		foreach($inventoryTxns as $inventoryTxn){
			// var_dump("Stockout for Txn:{$inventoryTxn->id} qty:{$inventoryTxn->qty} cost:{$inventoryTxn->inventory->unit_cost}");
			self::stockin($productsku_id, $inventoryTxn->qty, $to_warehouse_id, array(
				'doc_type' => $settings['stockin_doc']['doc_type'] ?: 'STOCK_TRANSFER',
				'doc_id' => $settings['stockin_doc']['doc_id'] ?: 0,
				'unit_cost' => $inventoryTxn->inventory->unit_cost,
			));
		}

		return count($inventoryTxns)>0;
	}

	// reverse txn with AVERAGE unit cost
	public static function stockReturn($inventory_txn_id, $qty, $settings=array()){
		// txn lookup
		$old_txn = InventoryTxn::find($inventory_txn_id);
		// var_dump($old_txn);

		if($old_txn){
			if(!$old_txn['from_warehouse_id'] && !$settings['to_warehouse_id']){
				// default stock return warehouse
				$settings['to_warehouse_id'] = Warehouse::stockin_warehouse($old_txn->proProductSku->supplier_id)->id;
			}

			if($settings['to_warehouse_id']){
				// stockin to specific warehouse with orginal cost
				self::stockin($productsku_id, $qty, $warehouse_id, array(
					'doc_type' => $settings['doc_type'],
					'doc_id' => $settings['doc_id'],
					'unit_cost' => $settings['unit_cost'] ?: $old_txn->inventory->unit_cost,
				));
			}else{
				// insert to txn
				$inventroyTxn = InventoryTxn::create(array(
					'company_id' => 1,
					'productsku_id' => $old_txn['productsku_id'],
					'inventory_id' => $old_txn['inventory_id'],
					'docdate' => date('Y-m-d'),
					'doc_type' => 'StockAdjustment',
					'doc_id' => 0,
					'from_warehouse_id' => $old_txn['to_warehouse_id'],
					'to_warehouse_id' => $old_txn['from_warehouse_id'],
					'qty' => $qty,
				));

				// update inventory.qty for both in and out
				if($old_txn['from_warehouse_id']){
					self::update_inventory_qty($old_txn['inventory_id'], $old_txn['from_warehouse_id']);
				}
				if($old_txn['to_warehouse_id']){
					self::update_inventory_qty($old_txn['inventory_id'], $old_txn['to_warehouse_id']);
				}

				// update productsku.qty
				self::update_productsku_qty($old_txn->inventory->productsku_id);
			}
		}else{
			// TODO: refactor flow control
			// transaction/source warehouse not found

			// somehow we managed to stockin unknown source product to the inventory with provided warehouse_id and unitcost
			// self::stockin()
		}

	}

	public static function reserve($productsku_id, $qty, $is_reserve=true){
		$proProductSku = ProProductSku::find($productsku_id);
		if(!$is_reserve){
			$proProductSku->reserved_qty = max($proProductSku->reserved_qty - $qty, 0);
		}else{
			$proProductSku->reserved_qty = max($proProductSku->reserved_qty + $qty, 0);
		}
		$proProductSku->save();
	}

	protected static function stockout_inventory($productsku_id, $settings = array()){
		if(isset($settings['from_warehouse_id'])){
			// specified stockout from warehouse
			$inventory = Inventory::whereDeleted(0)
							->where('qty', '>', 0)
							->where('productsku_id', $productsku_id)
							->where('warehouse_id', $settings['from_warehouse_id'])
							->orderBy('id', 'asc')
							->first();
			return $inventory;
		}else{
			// best strategy
			// stockout based on warehouse priority
			$inventory = Inventory::select('inventory.*')
							->join('warehouse', 'warehouse.id', '=', 'inventory.warehouse_id')
							->where('inventory.deleted', 0)
							->where('warehouse.deleted', 0)
							->where('inventory.qty', '>', 0)
							->where('productsku_id', $productsku_id)
							->where('is_eshop_warehouse', 1)
							->orderBy('warehouse.priority', 'asc')
							->orderBy('inventory.id', 'asc')
							->first();
			return $inventory;
		}
	}

	protected static function update_productsku_qty($productsku_id){
		$sum = Inventory::whereDeleted(0)
				->where('productsku_id', $productsku_id)
				->where('qty', '>', 0)
				->sum('qty');

		$proProductSku = ProProductSku::find($productsku_id);
		$proProductSku->qty = $sum;
		$proProductSku->save();
	}

	protected static function update_inventory_qty($inventory_id, $warehouse_id){
		$sum_to_inventory = InventoryTxn::whereDeleted(0)
								->where('inventory_id', $inventory_id)
								->where('qty', '>', 0)
								->where('to_warehouse_id', $warehouse_id)
								->sum('qty');
		$sum_from_inventory = InventoryTxn::whereDeleted(0)
								->where('inventory_id', $inventory_id)
								->where('qty', '>', 0)
								->where('from_warehouse_id', $warehouse_id)
								->sum('qty');

		$inventory = Inventory::find($inventory_id);
		$inventory->qty = $sum_to_inventory - $sum_from_inventory;
		$inventory->save();
	}

	// test cases =======================================================================================
	public static function test_reserve(){
		global $dbh;
		var_dump(__FUNCTION__, '==START==');
		$dbh->beginTransaction();

		Inventory::reserve(4, 2);

		$dbh->commit();
		var_dump('==ENDED==');
	}
	public static function test_stockin(){
		global $dbh;
		var_dump(__FUNCTION__, '==START==');
		$dbh->beginTransaction();

		Inventory::stockin(4, 5, 7);

		$dbh->commit();
		var_dump('==ENDED==');
	}
	public static function test_stockout(){
		global $dbh;
		var_dump(__FUNCTION__, '==START==');
		$dbh->beginTransaction();

		$txns = Inventory::stockout(4, 3);

		$dbh->commit();
		var_dump($txns);
		var_dump('==ENDED==');
	}
	public static function test_stockout_reserved(){
		global $dbh;
		var_dump(__FUNCTION__, '==START==');
		$dbh->beginTransaction();

		Inventory::stockout_reserved(4, 1, array('deduct_reserved_qty'=>1));

		$dbh->commit();
		var_dump('==ENDED==');
	}
	public static function test_selectInventory(){
		var_dump(__FUNCTION__, '==START==');
		var_dump( Inventory::stockout_inventory(1) );
		// var_dump( Inventory::stockout_inventory(1, ['from_warehouse_id'=>2]) );
	}
	public static function test_stockTransfer(){
		Inventory::stockTransfer(4, 3, 7, 15, array(
			'stockout_doc' => array(
				'doc_type' => 'TransferNote',
				'doc_id' => '50000000',
			),
			'stockin_doc' => array(
				'doc_type' => 'TransferNote',
				'doc_id' => '50000000',
			)
		));
	}
}


Youez - 2016 - github.com/yon3zu
LinuXploit