2015-03-03 09:25:30 +00:00
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2013-08-05 09:29:54 +00:00
# License: GNU General Public License v3. See license.txt
2013-03-19 06:31:24 +00:00
from __future__ import unicode_literals
2014-02-14 10:17:51 +00:00
import frappe
2017-01-16 11:53:20 +00:00
from frappe . utils import cint , flt , cstr
2014-02-14 10:17:51 +00:00
from frappe import msgprint , _
import frappe . defaults
2016-03-04 09:03:49 +00:00
from erpnext . accounts . utils import get_fiscal_year
2014-10-06 06:23:52 +00:00
from erpnext . accounts . general_ledger import make_gl_entries , delete_gl_entries , process_gl_map
2015-08-24 09:02:38 +00:00
from erpnext . controllers . accounts_controller import AccountsController
2017-01-25 13:17:53 +00:00
from erpnext . stock . stock_ledger import get_valuation_rate
2017-06-15 05:39:27 +00:00
from erpnext . stock import get_warehouse_account_map
2013-03-19 06:31:24 +00:00
class StockController ( AccountsController ) :
2016-11-16 11:51:59 +00:00
def validate ( self ) :
super ( StockController , self ) . validate ( )
self . validate_inspection ( )
2017-01-16 11:53:20 +00:00
2016-12-30 10:51:35 +00:00
def make_gl_entries ( self , gl_entries = None , repost_future_gle = True , from_repost = False ) :
2014-03-28 08:25:00 +00:00
if self . docstatus == 2 :
delete_gl_entries ( voucher_type = self . doctype , voucher_no = self . name )
2014-04-07 13:21:58 +00:00
2014-02-14 10:17:51 +00:00
if cint ( frappe . defaults . get_global_default ( " auto_accounting_for_stock " ) ) :
2017-06-15 05:39:27 +00:00
warehouse_account = get_warehouse_account_map ( )
2014-04-07 13:21:58 +00:00
2014-03-28 08:25:00 +00:00
if self . docstatus == 1 :
2016-12-30 10:51:35 +00:00
if not gl_entries :
gl_entries = self . get_gl_entries ( warehouse_account )
make_gl_entries ( gl_entries , from_repost = from_repost )
2013-10-22 18:21:41 +00:00
2014-03-27 11:48:29 +00:00
if repost_future_gle :
2014-09-26 08:52:18 +00:00
items , warehouses = self . get_items_and_warehouses ( )
2014-10-06 06:23:52 +00:00
update_gl_entries_after ( self . posting_date , self . posting_time , warehouses , items ,
2014-10-15 06:53:35 +00:00
warehouse_account )
2014-04-07 13:21:58 +00:00
2013-11-14 13:10:08 +00:00
def get_gl_entries ( self , warehouse_account = None , default_expense_account = None ,
2013-09-17 09:45:16 +00:00
default_cost_center = None ) :
2014-10-06 06:23:52 +00:00
2013-09-17 09:45:16 +00:00
if not warehouse_account :
2017-06-15 05:39:27 +00:00
warehouse_account = get_warehouse_account_map ( )
2014-04-07 13:21:58 +00:00
2014-04-17 06:07:46 +00:00
sle_map = self . get_stock_ledger_details ( )
voucher_details = self . get_voucher_details ( default_expense_account , default_cost_center , sle_map )
2014-04-07 13:21:58 +00:00
2013-08-28 13:23:11 +00:00
gl_list = [ ]
2013-09-17 04:51:20 +00:00
warehouse_with_no_account = [ ]
2017-01-16 11:53:20 +00:00
2016-12-15 08:16:03 +00:00
for item_row in voucher_details :
sle_list = sle_map . get ( item_row . name )
2013-08-28 13:23:11 +00:00
if sle_list :
for sle in sle_list :
if warehouse_account . get ( sle . warehouse ) :
# from warehouse account
2017-01-16 11:53:20 +00:00
2016-12-15 08:16:03 +00:00
self . check_expense_account ( item_row )
2017-01-16 11:53:20 +00:00
2017-04-14 10:24:04 +00:00
# If the item does not have the allow zero valuation rate flag set
2017-02-06 11:43:39 +00:00
# and ( valuation rate not mentioned in an incoming entry
2017-03-31 07:14:29 +00:00
# or incoming entry not found while delivering the item),
2017-02-06 11:43:39 +00:00
# try to pick valuation rate from previous sle or Item master and update in SLE
# Otherwise, throw an exception
2017-02-06 19:53:26 +00:00
if not sle . stock_value_difference and self . doctype != " Stock Reconciliation " \
2017-04-14 10:24:04 +00:00
and not item_row . get ( " allow_zero_valuation_rate " ) :
2017-02-06 19:53:26 +00:00
2017-02-06 11:43:39 +00:00
sle = self . update_stock_ledger_entries ( sle )
2015-10-15 06:58:20 +00:00
2013-08-28 13:23:11 +00:00
gl_list . append ( self . get_gl_dict ( {
2017-06-15 05:39:27 +00:00
" account " : warehouse_account [ sle . warehouse ] [ " account " ] ,
2016-12-15 08:16:03 +00:00
" against " : item_row . expense_account ,
" cost_center " : item_row . cost_center ,
2014-04-07 06:32:57 +00:00
" remarks " : self . get ( " remarks " ) or " Accounting Entry for Stock " ,
2015-08-19 08:19:10 +00:00
" debit " : flt ( sle . stock_value_difference , 2 ) ,
2015-08-28 13:54:22 +00:00
} , warehouse_account [ sle . warehouse ] [ " account_currency " ] ) )
2013-08-28 13:23:11 +00:00
2015-10-15 06:58:20 +00:00
# to target warehouse / expense account
2013-08-28 13:23:11 +00:00
gl_list . append ( self . get_gl_dict ( {
2016-12-15 08:16:03 +00:00
" account " : item_row . expense_account ,
2017-06-15 05:39:27 +00:00
" against " : warehouse_account [ sle . warehouse ] [ " account " ] ,
2016-12-15 08:16:03 +00:00
" cost_center " : item_row . cost_center ,
2014-04-07 06:32:57 +00:00
" remarks " : self . get ( " remarks " ) or " Accounting Entry for Stock " ,
2015-08-19 08:19:10 +00:00
" credit " : flt ( sle . stock_value_difference , 2 ) ,
2016-12-15 08:16:03 +00:00
" project " : item_row . get ( " project " ) or self . get ( " project " )
2013-08-28 13:23:11 +00:00
} ) )
2013-09-17 04:51:20 +00:00
elif sle . warehouse not in warehouse_with_no_account :
warehouse_with_no_account . append ( sle . warehouse )
2014-04-07 13:21:58 +00:00
if warehouse_with_no_account :
2016-10-24 12:47:57 +00:00
for wh in warehouse_with_no_account :
if frappe . db . get_value ( " Warehouse " , wh , " company " ) :
2017-06-15 05:39:27 +00:00
frappe . throw ( _ ( " Warehouse {0} is not linked to any account, please mention the account in the warehouse record or set default inventory account in company {1} . " ) . format ( wh , self . company ) )
2015-10-15 06:58:20 +00:00
2013-08-28 13:23:11 +00:00
return process_gl_map ( gl_list )
2017-01-16 11:53:20 +00:00
2017-01-25 13:17:53 +00:00
def update_stock_ledger_entries ( self , sle ) :
2017-03-31 07:14:29 +00:00
sle . valuation_rate = get_valuation_rate ( sle . item_code , sle . warehouse ,
self . doctype , self . name , currency = self . company_currency )
2017-02-06 11:43:39 +00:00
2017-01-25 13:50:35 +00:00
sle . stock_value = flt ( sle . qty_after_transaction ) * flt ( sle . valuation_rate )
2017-02-06 11:43:39 +00:00
sle . stock_value_difference = flt ( sle . actual_qty ) * flt ( sle . valuation_rate )
2017-03-31 07:14:29 +00:00
2017-01-28 07:48:49 +00:00
if sle . name :
2017-02-06 11:43:39 +00:00
frappe . db . sql ( """
2017-03-31 07:14:29 +00:00
update
` tabStock Ledger Entry `
set
2017-02-06 11:43:39 +00:00
stock_value = % ( stock_value ) s ,
2017-03-31 07:14:29 +00:00
valuation_rate = % ( valuation_rate ) s ,
stock_value_difference = % ( stock_value_difference ) s
where
2017-02-06 11:43:39 +00:00
name = % ( name ) s """ , (sle))
2017-03-31 07:14:29 +00:00
2017-02-06 11:43:39 +00:00
return sle
2017-03-31 07:14:29 +00:00
2014-04-17 06:07:46 +00:00
def get_voucher_details ( self , default_expense_account , default_cost_center , sle_map ) :
if self . doctype == " Stock Reconciliation " :
return [ frappe . _dict ( { " name " : voucher_detail_no , " expense_account " : default_expense_account ,
" cost_center " : default_cost_center } ) for voucher_detail_no , sle in sle_map . items ( ) ]
else :
2014-12-26 07:45:21 +00:00
details = self . get ( " items " )
2014-04-17 06:07:46 +00:00
if default_expense_account or default_cost_center :
for d in details :
if default_expense_account and not d . get ( " expense_account " ) :
d . expense_account = default_expense_account
if default_cost_center and not d . get ( " cost_center " ) :
d . cost_center = default_cost_center
return details
2014-04-07 13:21:58 +00:00
2014-09-26 08:52:18 +00:00
def get_items_and_warehouses ( self ) :
2014-03-27 11:48:29 +00:00
items , warehouses = [ ] , [ ]
2014-04-07 13:21:58 +00:00
2014-12-26 07:45:21 +00:00
if hasattr ( self , " items " ) :
item_doclist = self . get ( " items " )
2014-03-28 08:25:00 +00:00
elif self . doctype == " Stock Reconciliation " :
2014-03-27 11:48:29 +00:00
import json
item_doclist = [ ]
2014-03-28 08:25:00 +00:00
data = json . loads ( self . reconciliation_json )
2014-03-27 11:48:29 +00:00
for row in data [ data . index ( self . head_row ) + 1 : ] :
d = frappe . _dict ( zip ( [ " item_code " , " warehouse " , " qty " , " valuation_rate " ] , row ) )
item_doclist . append ( d )
2014-04-07 13:21:58 +00:00
2014-03-27 11:48:29 +00:00
if item_doclist :
for d in item_doclist :
if d . item_code and d . item_code not in items :
items . append ( d . item_code )
2014-04-07 13:21:58 +00:00
2014-04-07 06:32:57 +00:00
if d . get ( " warehouse " ) and d . warehouse not in warehouses :
2014-03-27 11:48:29 +00:00
warehouses . append ( d . warehouse )
2014-04-07 13:21:58 +00:00
2014-04-07 06:32:57 +00:00
if self . doctype == " Stock Entry " :
if d . get ( " s_warehouse " ) and d . s_warehouse not in warehouses :
warehouses . append ( d . s_warehouse )
if d . get ( " t_warehouse " ) and d . t_warehouse not in warehouses :
warehouses . append ( d . t_warehouse )
2014-03-27 11:48:29 +00:00
2014-09-26 08:52:18 +00:00
return items , warehouses
2014-04-07 13:21:58 +00:00
2013-08-28 13:23:11 +00:00
def get_stock_ledger_details ( self ) :
stock_ledger = { }
2017-02-06 11:43:39 +00:00
stock_ledger_entries = frappe . db . sql ( """
2017-03-31 07:14:29 +00:00
select
2017-02-06 19:53:26 +00:00
name , warehouse , stock_value_difference , valuation_rate ,
2017-03-31 07:14:29 +00:00
voucher_detail_no , item_code , posting_date , posting_time ,
2017-02-06 19:53:26 +00:00
actual_qty , qty_after_transaction
2017-02-06 11:43:39 +00:00
from
` tabStock Ledger Entry `
where
voucher_type = % s and voucher_no = % s
""" , (self.doctype, self.name), as_dict=True)
2017-02-06 19:53:26 +00:00
2017-02-06 11:43:39 +00:00
for sle in stock_ledger_entries :
2013-08-28 13:23:11 +00:00
stock_ledger . setdefault ( sle . voucher_detail_no , [ ] ) . append ( sle )
return stock_ledger
2014-04-07 13:21:58 +00:00
2017-04-21 07:10:19 +00:00
def make_batches ( self , warehouse_field ) :
2017-04-20 09:51:01 +00:00
''' Create batches if required. Called before submit '''
for d in self . items :
2017-04-21 07:10:19 +00:00
if d . get ( warehouse_field ) and not d . batch_no :
has_batch_no , create_new_batch = frappe . db . get_value ( ' Item ' , d . item_code , [ ' has_batch_no ' , ' create_new_batch ' ] )
if has_batch_no and create_new_batch :
d . batch_no = frappe . get_doc ( dict (
doctype = ' Batch ' ,
item = d . item_code ,
supplier = getattr ( self , ' supplier ' , None ) ,
reference_doctype = self . doctype ,
reference_name = self . name ) ) . insert ( ) . name
2017-04-20 09:51:01 +00:00
2013-08-28 13:23:11 +00:00
def make_adjustment_entry ( self , expected_gle , voucher_obj ) :
2013-12-12 13:42:19 +00:00
from erpnext . accounts . utils import get_stock_and_account_difference
2013-08-26 11:23:30 +00:00
account_list = [ d . account for d in expected_gle ]
acc_diff = get_stock_and_account_difference ( account_list , expected_gle [ 0 ] . posting_date )
2014-04-07 13:21:58 +00:00
2013-08-26 11:23:30 +00:00
cost_center = self . get_company_default ( " cost_center " )
stock_adjustment_account = self . get_company_default ( " stock_adjustment_account " )
2013-08-06 10:27:25 +00:00
gl_entries = [ ]
for account , diff in acc_diff . items ( ) :
if diff :
2013-08-26 11:23:30 +00:00
gl_entries . append ( [
# stock in hand account
2013-08-28 13:23:11 +00:00
voucher_obj . get_gl_dict ( {
2013-08-26 11:23:30 +00:00
" account " : account ,
" against " : stock_adjustment_account ,
" debit " : diff ,
" remarks " : " Adjustment Accounting Entry for Stock " ,
} ) ,
2014-04-07 13:21:58 +00:00
2013-08-26 11:23:30 +00:00
# account against stock in hand
2013-08-28 13:23:11 +00:00
voucher_obj . get_gl_dict ( {
2013-08-26 11:23:30 +00:00
" account " : stock_adjustment_account ,
" against " : account ,
" credit " : diff ,
" cost_center " : cost_center or None ,
" remarks " : " Adjustment Accounting Entry for Stock " ,
} ) ,
] )
2014-04-07 13:21:58 +00:00
2013-08-06 10:27:25 +00:00
if gl_entries :
2013-12-12 13:42:19 +00:00
from erpnext . accounts . general_ledger import make_gl_entries
2013-08-06 10:27:25 +00:00
make_gl_entries ( gl_entries )
2014-04-07 13:21:58 +00:00
2013-08-26 11:23:30 +00:00
def check_expense_account ( self , item ) :
2014-04-16 13:50:11 +00:00
if not item . get ( " expense_account " ) :
2014-05-01 12:12:21 +00:00
frappe . throw ( _ ( " Expense or Difference account is mandatory for Item {0} as it impacts overall stock value " ) . format ( item . item_code ) )
2014-04-07 13:21:58 +00:00
2014-06-19 13:55:19 +00:00
else :
2014-06-25 13:42:24 +00:00
is_expense_account = frappe . db . get_value ( " Account " ,
item . get ( " expense_account " ) , " report_type " ) == " Profit and Loss "
2016-02-08 16:44:55 +00:00
if self . doctype not in ( " Purchase Receipt " , " Purchase Invoice " , " Stock Reconciliation " , " Stock Entry " ) and not is_expense_account :
2014-06-25 13:42:24 +00:00
frappe . throw ( _ ( " Expense / Difference account ( {0} ) must be a ' Profit or Loss ' account " )
. format ( item . get ( " expense_account " ) ) )
2014-06-19 13:55:19 +00:00
if is_expense_account and not item . get ( " cost_center " ) :
frappe . throw ( _ ( " {0} {1} : Cost Center is mandatory for Item {2} " ) . format (
_ ( self . doctype ) , self . name , item . get ( " item_code " ) ) )
2014-04-07 13:21:58 +00:00
def get_sl_entries ( self , d , args ) :
2014-11-03 09:38:21 +00:00
sl_dict = frappe . _dict ( {
2014-05-02 12:06:13 +00:00
" item_code " : d . get ( " item_code " , None ) ,
2014-04-07 06:32:57 +00:00
" warehouse " : d . get ( " warehouse " , None ) ,
2014-03-28 08:25:00 +00:00
" posting_date " : self . posting_date ,
" posting_time " : self . posting_time ,
2016-03-04 09:03:49 +00:00
' fiscal_year ' : get_fiscal_year ( self . posting_date , company = self . company ) [ 0 ] ,
2014-03-28 08:25:00 +00:00
" voucher_type " : self . doctype ,
" voucher_no " : self . name ,
2013-08-02 06:12:11 +00:00
" voucher_detail_no " : d . name ,
2014-04-07 06:32:57 +00:00
" actual_qty " : ( self . docstatus == 1 and 1 or - 1 ) * flt ( d . get ( " stock_qty " ) ) ,
2015-09-21 03:48:43 +00:00
" stock_uom " : frappe . db . get_value ( " Item " , args . get ( " item_code " ) or d . get ( " item_code " ) , " stock_uom " ) ,
2013-08-02 06:12:11 +00:00
" incoming_rate " : 0 ,
2014-03-28 08:25:00 +00:00
" company " : self . company ,
2014-05-02 12:06:13 +00:00
" batch_no " : cstr ( d . get ( " batch_no " ) ) . strip ( ) ,
" serial_no " : d . get ( " serial_no " ) ,
2016-03-09 11:32:59 +00:00
" project " : d . get ( " project " ) ,
2014-03-28 08:25:00 +00:00
" is_cancelled " : self . docstatus == 2 and " Yes " or " No "
2014-11-03 09:38:21 +00:00
} )
2014-04-07 13:21:58 +00:00
2013-08-02 06:12:11 +00:00
sl_dict . update ( args )
return sl_dict
2014-04-07 13:21:58 +00:00
2015-04-06 13:59:16 +00:00
def make_sl_entries ( self , sl_entries , is_amended = None , allow_negative_stock = False ,
2015-03-27 10:08:31 +00:00
via_landed_cost_voucher = False ) :
2013-12-12 13:42:19 +00:00
from erpnext . stock . stock_ledger import make_sl_entries
2015-03-27 10:08:31 +00:00
make_sl_entries ( sl_entries , is_amended , allow_negative_stock , via_landed_cost_voucher )
2014-04-07 13:21:58 +00:00
2016-08-19 11:09:33 +00:00
def make_gl_entries_on_cancel ( self , repost_future_gle = True ) :
2014-04-07 13:21:58 +00:00
if frappe . db . sql ( """ select name from `tabGL Entry` where voucher_type= %s
2014-03-28 08:25:00 +00:00
and voucher_no = % s """ , (self.doctype, self.name)):
2016-12-30 10:51:35 +00:00
self . make_gl_entries ( repost_future_gle = repost_future_gle )
2014-04-07 13:21:58 +00:00
2014-06-25 08:01:02 +00:00
def get_serialized_items ( self ) :
serialized_items = [ ]
2014-12-26 07:45:21 +00:00
item_codes = list ( set ( [ d . item_code for d in self . get ( " items " ) ] ) )
2014-06-25 08:01:02 +00:00
if item_codes :
serialized_items = frappe . db . sql_list ( """ select name from `tabItem`
2015-07-24 09:46:25 +00:00
where has_serial_no = 1 and name in ( { } ) """ .format( " , " .join([ " %s " ]*len(item_codes))),
2014-06-25 08:01:02 +00:00
tuple ( item_codes ) )
return serialized_items
2015-08-03 10:43:33 +00:00
2016-01-19 12:35:28 +00:00
def get_incoming_rate_for_sales_return ( self , item_code , against_document ) :
2015-07-17 09:49:02 +00:00
incoming_rate = 0.0
if against_document and item_code :
2015-11-16 13:35:46 +00:00
incoming_rate = frappe . db . sql ( """ select abs(stock_value_difference / actual_qty)
2015-07-17 09:49:02 +00:00
from ` tabStock Ledger Entry `
2015-10-15 06:58:20 +00:00
where voucher_type = % s and voucher_no = % s
2016-01-19 12:35:28 +00:00
and item_code = % s limit 1 """ ,
( self . doctype , against_document , item_code ) )
2015-07-17 09:49:02 +00:00
incoming_rate = incoming_rate [ 0 ] [ 0 ] if incoming_rate else 0.0
return incoming_rate
2017-01-16 11:53:20 +00:00
2015-11-18 11:33:33 +00:00
def validate_warehouse ( self ) :
from erpnext . stock . utils import validate_warehouse_company
warehouses = list ( set ( [ d . warehouse for d in
self . get ( " items " ) if getattr ( d , " warehouse " , None ) ] ) )
for w in warehouses :
validate_warehouse_company ( w , self . company )
2017-01-16 11:53:20 +00:00
2016-01-06 11:02:06 +00:00
def update_billing_percentage ( self , update_modified = True ) :
2015-12-30 13:38:11 +00:00
self . _update_percent_field ( {
" target_dt " : self . doctype + " Item " ,
" target_parent_dt " : self . doctype ,
" target_parent_field " : " per_billed " ,
" target_ref_field " : " amount " ,
" target_field " : " billed_amt " ,
" name " : self . name ,
2016-01-06 11:02:06 +00:00
} , update_modified )
2014-06-25 08:01:02 +00:00
2016-11-16 11:51:59 +00:00
def validate_inspection ( self ) :
2016-11-10 13:45:11 +00:00
''' Checks if quality inspection is set for Items that require inspection.
On submit , throw an exception '''
2017-01-16 11:53:20 +00:00
2016-11-18 09:22:13 +00:00
inspection_required_fieldname = None
2016-11-16 11:51:59 +00:00
if self . doctype in [ " Purchase Receipt " , " Purchase Invoice " ] :
inspection_required_fieldname = " inspection_required_before_purchase "
elif self . doctype in [ " Delivery Note " , " Sales Invoice " ] :
inspection_required_fieldname = " inspection_required_before_delivery "
2017-01-16 11:53:20 +00:00
2016-11-16 11:51:59 +00:00
if not inspection_required_fieldname or \
( self . doctype in [ " Sales Invoice " , " Purchase Invoice " ] and not self . update_stock ) :
return
2017-01-16 11:53:20 +00:00
2016-11-10 13:45:11 +00:00
for d in self . get ( ' items ' ) :
2017-01-16 11:53:20 +00:00
if ( frappe . db . get_value ( " Item " , d . item_code , inspection_required_fieldname )
2016-11-10 13:45:11 +00:00
and not d . quality_inspection ) :
2017-01-16 11:53:20 +00:00
2016-11-10 13:45:11 +00:00
frappe . msgprint ( _ ( " Quality Inspection required for Item {0} " ) . format ( d . item_code ) )
if self . docstatus == 1 :
raise frappe . ValidationError
2014-10-06 06:23:52 +00:00
def update_gl_entries_after ( posting_date , posting_time , for_warehouses = None , for_items = None ,
2014-10-15 06:53:35 +00:00
warehouse_account = None ) :
2014-03-27 11:48:29 +00:00
def _delete_gl_entries ( voucher_type , voucher_no ) :
2014-04-07 13:21:58 +00:00
frappe . db . sql ( """ delete from `tabGL Entry`
2014-03-27 11:48:29 +00:00
where voucher_type = % s and voucher_no = % s """ , (voucher_type, voucher_no))
2014-04-07 13:21:58 +00:00
2014-03-27 11:48:29 +00:00
if not warehouse_account :
2017-06-15 05:39:27 +00:00
warehouse_account = get_warehouse_account_map ( )
2014-09-26 08:52:18 +00:00
future_stock_vouchers = get_future_stock_vouchers ( posting_date , posting_time , for_warehouses , for_items )
2014-03-27 11:48:29 +00:00
gle = get_voucherwise_gl_entries ( future_stock_vouchers , posting_date )
2017-01-16 11:53:20 +00:00
2014-03-27 11:48:29 +00:00
for voucher_type , voucher_no in future_stock_vouchers :
existing_gle = gle . get ( ( voucher_type , voucher_no ) , [ ] )
2014-03-31 11:57:06 +00:00
voucher_obj = frappe . get_doc ( voucher_type , voucher_no )
2014-03-27 11:48:29 +00:00
expected_gle = voucher_obj . get_gl_entries ( warehouse_account )
if expected_gle :
2016-08-08 08:42:16 +00:00
if not existing_gle or not compare_existing_and_expected_gle ( existing_gle , expected_gle ) :
_delete_gl_entries ( voucher_type , voucher_no )
2016-12-30 10:51:35 +00:00
voucher_obj . make_gl_entries ( gl_entries = expected_gle , repost_future_gle = False , from_repost = True )
2014-03-27 11:48:29 +00:00
else :
_delete_gl_entries ( voucher_type , voucher_no )
2014-04-07 13:21:58 +00:00
2014-03-27 11:48:29 +00:00
def compare_existing_and_expected_gle ( existing_gle , expected_gle ) :
matched = True
for entry in expected_gle :
2016-09-12 03:17:14 +00:00
account_existed = False
2014-03-27 11:48:29 +00:00
for e in existing_gle :
2016-09-12 03:17:14 +00:00
if entry . account == e . account :
account_existed = True
if entry . account == e . account and entry . against_account == e . against_account \
and ( not entry . cost_center or not e . cost_center or entry . cost_center == e . cost_center ) \
and ( entry . debit != e . debit or entry . credit != e . credit ) :
matched = False
break
if not account_existed :
matched = False
break
2014-03-27 11:48:29 +00:00
return matched
2013-03-19 06:31:24 +00:00
2014-09-26 08:52:18 +00:00
def get_future_stock_vouchers ( posting_date , posting_time , for_warehouses = None , for_items = None ) :
2014-03-27 11:48:29 +00:00
future_stock_vouchers = [ ]
2014-04-07 13:21:58 +00:00
2014-08-27 16:39:03 +00:00
values = [ ]
2014-03-27 11:48:29 +00:00
condition = " "
if for_items :
2014-08-27 16:39:03 +00:00
condition + = " and item_code in ( {} ) " . format ( " , " . join ( [ " %s " ] * len ( for_items ) ) )
values + = for_items
2014-04-07 13:21:58 +00:00
2014-09-26 08:52:18 +00:00
if for_warehouses :
condition + = " and warehouse in ( {} ) " . format ( " , " . join ( [ " %s " ] * len ( for_warehouses ) ) )
values + = for_warehouses
2014-04-07 13:21:58 +00:00
for d in frappe . db . sql ( """ select distinct sle.voucher_type, sle.voucher_no
2014-03-27 11:48:29 +00:00
from ` tabStock Ledger Entry ` sle
2014-08-27 16:39:03 +00:00
where timestamp ( sle . posting_date , sle . posting_time ) > = timestamp ( % s , % s ) { condition }
order by timestamp ( sle . posting_date , sle . posting_time ) asc , name asc """ .format(condition=condition),
tuple ( [ posting_date , posting_time ] + values ) , as_dict = True ) :
2014-03-27 11:48:29 +00:00
future_stock_vouchers . append ( [ d . voucher_type , d . voucher_no ] )
2014-04-07 13:21:58 +00:00
2014-03-27 11:48:29 +00:00
return future_stock_vouchers
2014-04-07 13:21:58 +00:00
2014-03-27 11:48:29 +00:00
def get_voucherwise_gl_entries ( future_stock_vouchers , posting_date ) :
gl_entries = { }
if future_stock_vouchers :
2014-04-07 13:21:58 +00:00
for d in frappe . db . sql ( """ select * from `tabGL Entry`
where posting_date > = % s and voucher_no in ( % s ) """ %
( ' %s ' , ' , ' . join ( [ ' %s ' ] * len ( future_stock_vouchers ) ) ) ,
2014-03-27 11:48:29 +00:00
tuple ( [ posting_date ] + [ d [ 1 ] for d in future_stock_vouchers ] ) , as_dict = 1 ) :
gl_entries . setdefault ( ( d . voucher_type , d . voucher_no ) , [ ] ) . append ( d )
2014-04-07 13:21:58 +00:00
2017-06-15 05:39:27 +00:00
return gl_entries