def on_submit(self): if not getlist(self.doclist, 'maintenance_schedule_detail'): msgprint("Please click on 'Generate Schedule' to get schedule") raise Exception self.check_serial_no_added() self.validate_serial_no_warranty() self.validate_schedule() email_map = {} for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: self.update_amc_date(d.serial_no, d.end_date) if d.incharge_name not in email_map: e = sql( "select email_id, name from `tabSales Person` where name='%s' " % (d.incharge_name), as_dict=1)[0] email_map[d.incharge_name] = (e['email_id']) scheduled_date =sql("select scheduled_date from `tabMaintenance Schedule Detail` \ where incharge_name='%s' and item_code='%s' and parent='%s' " %(d.incharge_name, \ d.item_code, self.doc.name), as_dict=1) for key in scheduled_date: if email_map[d.incharge_name]: self.add_calender_event(key["scheduled_date"], email_map[d.incharge_name], d.item_code) webnotes.conn.set(self.doc, 'status', 'Submitted')
def on_submit(self): if not getlist(self.doclist, 'maintenance_schedule_detail'): msgprint("Please click on 'Generate Schedule' to get schedule") raise Exception self.check_serial_no_added() self.validate_serial_no_warranty() self.validate_schedule() email_map ={} for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: self.update_amc_date(d.serial_no, d.end_date) if d.incharge_name not in email_map: e = sql("select email_id, name from `tabSales Person` where name='%s' " %(d.incharge_name),as_dict=1)[0] email_map[d.incharge_name] = (e['email_id']) scheduled_date =sql("select scheduled_date from `tabMaintenance Schedule Detail` \ where incharge_name='%s' and item_code='%s' and parent='%s' " %(d.incharge_name, \ d.item_code, self.doc.name), as_dict=1) for key in scheduled_date: if email_map[d.incharge_name]: self.add_calender_event(key["scheduled_date"],email_map[d.incharge_name],d.item_code) webnotes.conn.set(self.doc, 'status', 'Submitted')
def get_balance(self): if not getlist(self.doclist,'entries'): msgprint("Please enter atleast 1 entry in 'GL Entries' table") else: flag, self.doc.total_debit, self.doc.total_credit = 0,0,0 diff = flt(self.doc.difference) # If any row without amount, set the diff on that row for d in getlist(self.doclist,'entries'): if (d.credit==0 or d.credit is None) and (d.debit==0 or d.debit is None) and (flt(diff) != 0): if diff>0: d.credit = flt(diff) elif diff<0: d.debit = flt(diff) flag = 1 # Set the diff in a new row if flag == 0 and (flt(diff) != 0): jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', self.doclist) if diff>0: jd.credit = flt(diff) elif diff<0: jd.debit = flt(diff) # Set the total debit, total credit and difference for d in getlist(self.doclist,'entries'): self.doc.total_debit += flt(d.debit) self.doc.total_credit += flt(d.credit) self.doc.difference = flt(self.doc.total_debit) - flt(self.doc.total_credit)
def get_balance(self): if not getlist(self.doclist, 'entries'): msgprint("Please enter atleast 1 entry in 'GL Entries' table") else: flag, self.doc.total_debit, self.doc.total_credit = 0, 0, 0 diff = flt(self.doc.difference) # If any row without amount, set the diff on that row for d in getlist(self.doclist, 'entries'): if (d.credit == 0 or d.credit is None) and ( d.debit == 0 or d.debit is None) and (flt(diff) != 0): if diff > 0: d.credit = flt(diff) elif diff < 0: d.debit = flt(diff) flag = 1 # Set the diff in a new row if flag == 0 and (flt(diff) != 0): jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', self.doclist) if diff > 0: jd.credit = flt(abs(diff)) elif diff < 0: jd.debit = flt(abs(diff)) # Set the total debit, total credit and difference for d in getlist(self.doclist, 'entries'): self.doc.total_debit += flt(d.debit) self.doc.total_credit += flt(d.credit) self.doc.difference = flt(self.doc.total_debit) - flt( self.doc.total_credit)
def cal_charges_and_item_tax_amt(self): """ Re-calculates other charges values and itemwise tax amount for getting valuation rate""" import json for pr in self.selected_pr: obj = get_obj('Purchase Receipt', pr, with_children = 1) total = 0 self.reset_other_charges(obj) for prd in getlist(obj.doclist, 'purchase_receipt_details'): prev_total, item_tax = flt(prd.amount), 0 total += flt(prd.qty) * flt(prd.purchase_rate) try: item_tax_rate = prd.item_tax_rate and json.loads(prd.item_tax_rate) or {} except ValueError: item_tax_rate = prd.item_tax_rate and eval(prd.item_tax_rate) or {} ocd = getlist(obj.doclist, 'purchase_tax_details') # calculate tax for other charges for oc in range(len(ocd)): # Get rate : consider if diff for this item if item_tax_rate.get(ocd[oc].account_head) and ocd[oc].charge_type != 'Actual': rate = item_tax_rate[ocd[oc].account_head] else: rate = flt(ocd[oc].rate) tax_amount = self.cal_tax(ocd, prd, rate, obj.doc.net_total, oc) total, prev_total, item_tax = self.add_deduct_taxes(ocd, oc, tax_amount, total, prev_total, item_tax) prd.item_tax_amount = flt(item_tax) prd.save() obj.doc.save()
def create_sal_slip(self): """ Creates salary slip for selected employees if already not created """ emp_list = self.get_emp_list() ss_list = [] for emp in emp_list: if not sql( """select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s """, (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)): ss = Document('Salary Slip') ss.fiscal_year = self.doc.fiscal_year ss.employee = emp[0] ss.month = self.doc.month ss.email_check = self.doc.send_email ss.company = self.doc.company ss.save(1) ss_obj = get_obj('Salary Slip', ss.name, with_children=1) ss_obj.get_emp_and_leave_details() ss_obj.calculate_net_pay() ss_obj.validate() ss_obj.doc.save() for d in getlist(ss_obj.doclist, 'earning_details'): d.save() for d in getlist(ss_obj.doclist, 'deduction_details'): d.save() ss_list.append(ss.name) return self.create_log(ss_list)
def get_against_account(self): # Debit = Credit debit, credit = 0.0, 0.0 debit_list, credit_list = [], [] for d in getlist(self.doclist, 'entries'): debit += flt(d.debit) credit += flt(d.credit) if flt(d.debit) > 0 and (d.account not in debit_list): debit_list.append(d.account) if flt(d.credit) > 0 and (d.account not in credit_list): credit_list.append(d.account) self.doc.total_debit = debit if self.doc.tds_applicable == 'Yes': self.doc.total_credit = credit + flt(self.doc.ded_amount) else: self.doc.total_credit = credit if abs(self.doc.total_debit - self.doc.total_credit) > 0.001: msgprint("Debit must be equal to Credit. The difference is %s" % (self.doc.total_debit - self.doc.total_credit)) raise Exception # update against account for d in getlist(self.doclist, 'entries'): if flt(d.debit) > 0: d.against_account = ', '.join(credit_list) if flt(d.credit) > 0: d.against_account = ', '.join(debit_list)
def update_prevdoc_detail(self, obj, is_submit): import math self.ref_doctype_dict = {} for d in getlist(obj.doclist, obj.fname): if d.fields.has_key('prevdoc_docname') and d.prevdoc_docname: transaction = cstr(d.prevdoc_doctype) + ' - ' + cstr( obj.doc.doctype) curr_qty = (transaction == 'Purchase Request - Purchase Order' ) and flt(d.qty) * flt(d.conversion_factor) or flt( d.qty) self.update_ref_doctype_dict( flt(curr_qty), d.doctype, d.prevdoc_docname, d.prevdoc_doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, transaction, d.item_code, is_submit, obj.doc.doctype, obj.doc.name) # for payable voucher if d.fields.has_key('purchase_order') and d.purchase_order: curr_qty = sql( "select sum(qty) from `tabPurchase Invoice Item` where po_detail = '%s' and parent = '%s'" % (cstr(d.po_detail), cstr(obj.doc.name))) curr_qty = curr_qty and flt(curr_qty[0][0]) or 0 self.update_ref_doctype_dict( curr_qty, d.doctype, d.purchase_order, 'Purchase Order', 'po_detail', d.po_detail, 'Purchase Order - ' + cstr(obj.doc.doctype), d.item_code, is_submit, obj.doc.doctype, obj.doc.name) if d.fields.has_key('purchase_receipt') and d.purchase_receipt: self.update_ref_doctype_dict( flt(d.qty), d.doctype, d.purchase_receipt, 'Purchase Receipt', 'pr_detail', d.pr_detail, 'Purchase Receipt - ' + cstr(obj.doc.doctype), d.item_code, is_submit, obj.doc.doctype, obj.doc.name) for ref_dn in self.ref_doctype_dict: # Calculate percentage #---------------------- ref_doc_obj = get_obj(self.ref_doctype_dict[ref_dn][0], ref_dn, with_children=1) count = 0 percent = 0 for d in getlist(ref_doc_obj.doclist, ref_doc_obj.fname): ref_qty = d.fields[self.update_qty[ self.ref_doctype_dict[ref_dn][2]]] if flt(d.qty) - flt(ref_qty) <= 0: percent += 100 else: percent += (flt(ref_qty) / flt(d.qty) * 100) count += 1 percent_complete = math.floor(flt(percent) / flt(count)) # update percent complete and modified #------------------------------------- sql("update `tab%s` set %s = '%s', modified = '%s' where name = '%s'" % (self.ref_doctype_dict[ref_dn][0], self.update_percent_field[self.ref_doctype_dict[ref_dn][2]], percent_complete, obj.doc.modified, ref_dn))
def create_sal_slip(self): """ Creates salary slip for selected employees if already not created """ emp_list = self.get_emp_list() ss_list = [] for emp in emp_list: if not sql("""select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s """, (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)): ss = Document('Salary Slip') ss.fiscal_year = self.doc.fiscal_year ss.employee = emp[0] ss.month = self.doc.month ss.email_check = self.doc.send_email ss.company = self.doc.company ss.save(1) ss_obj = get_obj('Salary Slip', ss.name, with_children=1) ss_obj.get_emp_and_leave_details() ss_obj.calculate_net_pay() ss_obj.validate() ss_obj.doc.save() for d in getlist(ss_obj.doclist, 'earning_details'): d.save() for d in getlist(ss_obj.doclist, 'deduction_details'): d.save() ss_list.append(ss.name) return self.create_log(ss_list)
def get_allocated_sum(self,obj): sum = 0 for d in getlist(obj.doclist,'sales_team'): sum += flt(d.allocated_percentage) if (flt(sum) != 100) and getlist(obj.doclist,'sales_team'): msgprint("Total Allocated % of Sales Persons should be 100%") raise Exception
def get_allocated_sum(self, obj): sum = 0 for d in getlist(obj.doclist, 'sales_team'): sum += flt(d.allocated_percentage) if (flt(sum) != 100) and getlist(obj.doclist, 'sales_team'): msgprint("Total Allocated % of Sales Persons should be 100%") raise Exception
def validate_for_items(self): check_list, flag = [], 0 chk_dupl_itm = [] # Sales Order Items Validations for d in getlist(self.doclist, 'sales_order_details'): if self.doc.quotation_no and cstr(self.doc.quotation_no) == cstr( d.prevdoc_docname): flag = 1 if d.prevdoc_docname: if self.doc.quotation_date and getdate( self.doc.quotation_date) > getdate( self.doc.transaction_date): msgprint( "Sales Order Date cannot be before Quotation Date") raise Exception # validates whether quotation no in doctype and in table is same if not cstr(d.prevdoc_docname) == cstr(self.doc.quotation_no): msgprint( "Items in table does not belong to the Quotation No mentioned." ) raise Exception # validates whether item is not entered twice e = [ d.item_code, d.description, d.reserved_warehouse, d.prevdoc_docname or '' ] f = [d.item_code, d.description] #check item is stock item st_itm = sql( "select is_stock_item from `tabItem` where name = '%s'" % d.item_code) if st_itm and st_itm[0][0] == 'Yes': if e in check_list: msgprint("Item %s has been entered twice." % d.item_code) else: check_list.append(e) elif st_itm and st_itm[0][0] == 'No': if f in chk_dupl_itm: msgprint("Item %s has been entered twice." % d.item_code) else: chk_dupl_itm.append(f) # used for production plan d.transaction_date = self.doc.transaction_date tot_avail_qty = sql("select projected_qty from `tabBin` \ where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.reserved_warehouse)) d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0 if getlist( self.doclist, 'sales_order_details') and self.doc.quotation_no and flag == 0: msgprint("There are no items of the quotation selected", raise_exception=1)
def update_current_stock(self): for d in getlist(self.doclist, 'delivery_note_details'): bin = sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 for d in getlist(self.doclist, 'packing_details'): bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
def validate_reference_value(self, obj, to_docname): """ Check consistency of value with reference document""" for t in getlist(self.doclist, 'table_mapper_details'): # Reference key is the fieldname which will relate to the from_table if t.reference_doctype_key: for d in getlist(obj.doclist, t.to_field): if d.fields[t.reference_doctype_key] == self.doc.from_doctype: self.check_consistency(obj.doc, d, to_docname) self.check_ref_docstatus()
def validate_reference_value(self, obj, to_docname): """ Check consistency of value with reference document""" for t in getlist(self.doclist, 'table_mapper_details'): # Reference key is the fieldname which will relate to the from_table if t.reference_doctype_key: for d in getlist(obj.doclist, t.to_field): if d.fields[ t.reference_doctype_key] == self.doc.from_doctype: self.check_consistency(obj.doc, d, to_docname) self.check_ref_docstatus()
def update_current_stock(self): for d in getlist(self.doclist, 'entries'): if d.item_code and d.warehouse: bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 for d in getlist(self.doclist, 'packing_details'): bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
def check_serial_no_added(self): serial_present =[] for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: serial_present.append(d.item_code) for m in getlist(self.doclist, 'maintenance_schedule_detail'): if serial_present: if m.item_code in serial_present and not m.serial_no: msgprint("Please click on 'Generate Schedule' to fetch serial no added for item "+m.item_code) raise Exception
def on_update(self): """ Update C-Form No on invoices""" if len(getlist(self.doclist, 'invoice_details')): inv = "'" + "', '".join([d.invoice_no for d in getlist(self.doclist, 'invoice_details')]) + "'" sql("""update `tabSales Invoice` set c_form_no = '%s', modified ='%s' where name in (%s)"""%(self.doc.name, self.doc.modified, inv)) sql("""update `tabSales Invoice` set c_form_no = '', modified = %s where name not in (%s) and ifnull(c_form_no, '') = %s""", (self.doc.modified, self.doc.name, inv)) else: msgprint("Please enter atleast 1 invoice in the table below", raise_exception=1) self.calculate_total_invoiced_amount()
def check_serial_no_added(self): serial_present = [] for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: serial_present.append(d.item_code) for m in getlist(self.doclist, 'maintenance_schedule_detail'): if serial_present: if m.item_code in serial_present and not m.serial_no: msgprint( "Please click on 'Generate Schedule' to fetch serial no added for item " + m.item_code) raise Exception
def get_item_list(self, obj, is_stopped=0): """get item list""" il = [] for d in getlist(obj.doclist,obj.fname): reserved_wh, reserved_qty = '', 0 # used for delivery note qty = flt(d.qty) if is_stopped: qty = flt(d.qty) > flt(d.delivered_qty) and flt(flt(d.qty) - flt(d.delivered_qty)) or 0 if d.prevdoc_doctype == 'Sales Order': # used in delivery note to reduce reserved_qty # Eg.: if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. # But in this case reserved qty should only be reduced by 10 and not 12. tot_qty, max_qty, tot_amt, max_amt, reserved_wh = self.get_curr_and_ref_doc_details(d.doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, obj.doc.name, obj.doc.doctype) if((flt(tot_qty) + flt(qty) > flt(max_qty))): reserved_qty = -(flt(max_qty)-flt(tot_qty)) else: reserved_qty = - flt(qty) if obj.doc.doctype == 'Sales Order': reserved_wh = d.reserved_warehouse if self.has_sales_bom(d.item_code): for p in getlist(obj.doclist, 'packing_details'): if p.parent_detail_docname == d.name and p.parent_item == d.item_code: # the packing details table's qty is already multiplied with parent's qty il.append({ 'warehouse': p.warehouse, 'reserved_warehouse': reserved_wh, 'item_code': p.item_code, 'qty': flt(p.qty), 'reserved_qty': (flt(p.qty)/qty)*(reserved_qty), 'uom': p.uom, 'batch_no': cstr(p.batch_no).strip(), 'serial_no': cstr(p.serial_no).strip(), 'name': d.name }) else: il.append({ 'warehouse': d.warehouse, 'reserved_warehouse': reserved_wh, 'item_code': d.item_code, 'qty': qty, 'reserved_qty': reserved_qty, 'uom': d.stock_uom, 'batch_no': cstr(d.batch_no).strip(), 'serial_no': cstr(d.serial_no).strip(), 'name': d.name }) return il
def get_item_list(self, obj, is_stopped=0): """get item list""" il = [] for d in getlist(obj.doclist,obj.fname): reserved_wh, reserved_qty = '', 0 # used for delivery note qty = flt(d.qty) if is_stopped: qty = flt(d.qty) > flt(d.delivered_qty) and flt(flt(d.qty) - flt(d.delivered_qty)) or 0 if d.prevdoc_doctype == 'Sales Order': # used in delivery note to reduce reserved_qty # Eg.: if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. # But in this case reserved qty should only be reduced by 10 and not 12. tot_qty, max_qty, tot_amt, max_amt, reserved_wh = self.get_curr_and_ref_doc_details(d.doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, obj.doc.name, obj.doc.doctype) if((flt(tot_qty) + flt(qty) > flt(max_qty))): reserved_qty = -(flt(max_qty)-flt(tot_qty)) else: reserved_qty = - flt(qty) if obj.doc.doctype == 'Sales Order': reserved_wh = d.reserved_warehouse if self.has_sales_bom(d.item_code): for p in getlist(obj.doclist, 'packing_details'): if p.parent_detail_docname == d.name and p.parent_item == d.item_code: # the packing details table's qty is already multiplied with parent's qty il.append({ 'warehouse': p.warehouse, 'reserved_warehouse': reserved_wh, 'item_code': p.item_code, 'qty': flt(p.qty), 'reserved_qty': (flt(p.qty)/qty)*(reserved_qty), 'uom': p.uom, 'batch_no': p.batch_no, 'serial_no': p.serial_no, 'name': d.name }) else: il.append({ 'warehouse': d.warehouse, 'reserved_warehouse': reserved_wh, 'item_code': d.item_code, 'qty': qty, 'reserved_qty': reserved_qty, 'uom': d.stock_uom, 'batch_no': d.batch_no, 'serial_no': d.serial_no, 'name': d.name }) return il
def set_against_income_account(self): """Set against account for debit to account""" against_acc = [] for d in getlist(self.doclist, 'entries'): if d.income_account not in against_acc: against_acc.append(d.income_account) self.doc.against_income_account = ','.join(against_acc)
def update_rw_material_detail(self): for d in getlist(self.doclist,'purchase_receipt_details'): item_det = sql("select is_sub_contracted_item, is_purchase_item from `tabItem` where name = '%s'"%(d.item_code)) if item_det[0][0] == 'Yes': if item_det[0][1] == 'Yes': if not self.doc.is_subcontracted: msgprint("Please enter whether purchase receipt to be made for subcontracting or for purchase in 'Is Subcontracted' field .") raise Exception if self.doc.is_subcontracted == 'Yes': if not self.doc.supplier_warehouse: msgprint("Please Enter Supplier Warehouse for subcontracted Items") raise Exception self.add_bom(d) else: self.doclist = self.doc.clear_table(self.doclist,'pr_raw_material_details',1) self.doc.save() elif item_det[0][1] == 'No': if not self.doc.supplier_warehouse: msgprint("Please Enter Supplier Warehouse for subcontracted Items") raise Exception self.add_bom(d) self.delete_irrelevant_raw_material() #---------------calculate amt in Purchase Receipt Item Supplied------------- self.calculate_amount(d)
def update_against_document_in_jv(self, obj, table_field_name, against_document_no, against_document_doctype, account_head, dr_or_cr,doctype): for d in getlist(obj.doclist, table_field_name): self.validate_jv_entry(d, account_head, dr_or_cr) if flt(d.advance_amount) == flt(d.allocated_amount): # cancel JV jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children=1) get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel =1, adv_adj =1) # update ref in JV Detail webnotes.conn.sql("update `tabJournal Voucher Detail` set %s = '%s' where name = '%s'" % (doctype=='Purchase Invoice' and 'against_voucher' or 'against_invoice', cstr(against_document_no), d.jv_detail_no)) # re-submit JV jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children =1) get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel = 0, adv_adj =1) elif flt(d.advance_amount) > flt(d.allocated_amount): # cancel JV jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children=1) get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel =1, adv_adj = 1) # add extra entries self.add_extra_entry(jv_obj, d.journal_voucher, d.jv_detail_no, flt(d.allocated_amount), account_head, doctype, dr_or_cr, against_document_no) # re-submit JV jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children =1) get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel = 0, adv_adj = 1) else: msgprint("Allocation amount cannot be greater than advance amount") raise Exception
def pr_required(self): res = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'pr_required'") if res and res[0][0] == 'Yes': for d in getlist(self.doclist,'entries'): if not d.purchase_receipt: msgprint("Purchase Receipt No. required against item %s"%d.item_code) raise Exception
def validate_materials(self): """ Validate raw material entries """ check_list = [] for m in getlist(self.doclist, 'bom_materials'): # check if operation no not in op table if self.doc.with_operations and cstr(m.operation_no) not in self.op: msgprint("""Operation no: %s against item: %s at row no: %s \ is not present at Operations table""" % (m.operation_no, m.item_code, m.idx), raise_exception = 1) item = self.get_item_det(m.item_code) if item[0]['is_manufactured_item'] == 'Yes': if not m.bom_no: msgprint("Please enter BOM No aginst item: %s at row no: %s" % (m.item_code, m.idx), raise_exception=1) else: self.validate_bom_no(m.item_code, m.bom_no, m.idx) elif m.bom_no: msgprint("""As Item %s is not a manufactured / sub-contracted item, \ you can not enter BOM against it (Row No: %s).""" % (m.item_code, m.idx), raise_exception = 1) if flt(m.qty) <= 0: msgprint("Please enter qty against raw material: %s at row no: %s" % (m.item_code, m.idx), raise_exception = 1) self.check_if_item_repeated(m.item_code, m.operation_no, check_list)
def generate_schedule(self): import datetime self.doclist = self.doc.clear_table(self.doclist, 'maintenance_schedule_detail') count = 0 sql("delete from `tabMaintenance Schedule Detail` where parent='%s'" % (self.doc.name)) for d in getlist(self.doclist, 'item_maintenance_detail'): self.validate_maintenance_detail() s_list = [] s_list = self.create_schedule_list(d.start_date, d.end_date, d.no_of_visits) for i in range(d.no_of_visits): child = addchild(self.doc, 'maintenance_schedule_detail', 'Maintenance Schedule Detail', 1, self.doclist) child.item_code = d.item_code child.item_name = d.item_name child.scheduled_date = s_list[i].strftime('%Y-%m-%d') if d.serial_no: child.serial_no = d.serial_no child.idx = count count = count + 1 child.incharge_name = d.incharge_name child.save(1) self.on_update()
def clear_advances(self, obj, table_name, table_field_name): for d in getlist(obj.doclist, table_field_name): if not flt(d.allocated_amount): webnotes.conn.sql( "update `tab%s` set parent = '' where name = '%s' and parent = '%s'" % (table_name, d.name, d.parent)) d.parent = ''
def validate(self): """Validate invoice that c-form is applicable and no other c-form is received for that""" for d in getlist(self.doclist, "invoice_details"): inv = webnotes.conn.sql( """select c_form_applicable, c_form_no from `tabSales Invoice` where name = %s""", d.invoice_no, ) if not inv: webnotes.msgprint( "Invoice: %s is not exists in the system, please check." % d.invoice_no, raise_exception=1 ) elif inv[0][0] != "Yes": webnotes.msgprint("C-form is not applicable for Invoice: %s" % d.invoice_no, raise_exception=1) elif inv[0][1] and inv[0][1] != self.doc.name: webnotes.msgprint( """Invoice %s is tagged in another C-form: %s. If you want to change C-form no for this invoice, please remove invoice no from the previous c-form and then try again""" % (d.invoice_no, inv[0][1]), raise_exception=1, )
def get_tds_category_account(self): for d in getlist(self.doclist,'entries'): if flt(d.debit) > 0 and not d.against_voucher and d.is_advance == 'Yes': acc = sql("select tds_applicable from `tabAccount` where name = '%s'" % d.account) acc_tds_applicable = acc and acc[0][0] or 'No' if acc_tds_applicable == 'Yes': # TDS applicable field become mandatory for advance payment towards supplier or related party if not self.doc.tds_applicable: msgprint("Please select TDS Applicable or Not") raise Exception # If TDS applicable, category and supplier account bocome mandatory elif self.doc.tds_applicable == 'Yes': self.validate_category_account(d.account) if self.doc.ded_amount and not self.doc.tax_code: msgprint("Please enter Tax Code in TDS section") raise Exception #If TDS not applicable, all related fields should blank else: self.set_fields_null() # If tds amount but tds applicability not mentioned in account master elif self.doc.ded_amount: msgprint("Please select TDS Applicable = 'Yes' in account head: '%s' if you want to deduct TDS." % self.doc.supplier_account) raise Exception
def get_other_charges(self, obj, default=0): obj.doclist = obj.doc.clear_table(obj.doclist, 'other_charges') if not getlist(obj.doclist, 'other_charges'): if default: add_cond = 'ifnull(t2.is_default,0) = 1' else: add_cond = 't1.parent = "' + cstr(obj.doc.charge) + '"' idx = 0 other_charge = webnotes.conn.sql("""\ select t1.* from `tabSales Taxes and Charges` t1, `tabSales Taxes and Charges Master` t2 where t1.parent = t2.name and t2.company = '%s' and %s order by t1.idx""" % (obj.doc.company, add_cond), as_dict=1) from webnotes.model import default_fields for other in other_charge: # remove default fields like parent, parenttype etc. # from query results for field in default_fields: if field in other: del other[field] d = addchild(obj.doc, 'other_charges', 'Sales Taxes and Charges', 1, obj.doclist) d.fields.update(other) d.rate = flt(d.rate) d.tax_amount = flt(d.tax_rate) d.included_in_print_rate = cint(d.included_in_print_rate) d.idx = idx idx += 1 return obj.doclist
def on_update(self): # Set default warehouse from pos setting if cint(self.doc.is_pos) == 1: if cint(self.doc.update_stock) == 1: w = self.get_warehouse() if w: for d in getlist(self.doclist, 'entries'): if not d.warehouse: d.warehouse = cstr(w) self.make_packing_list() else: self.doclist = self.doc.clear_table(self.doclist, 'packing_details') if flt(self.doc.paid_amount) == 0: if self.doc.cash_bank_account: webnotes.conn.set(self.doc, 'paid_amount', (flt(self.doc.grand_total) - flt(self.doc.write_off_amount))) else: # show message that the amount is not paid webnotes.conn.set(self.doc,'paid_amount',0) webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.") else: self.doclist = self.doc.clear_table(self.doclist, 'packing_details') webnotes.conn.set(self.doc,'paid_amount',0) webnotes.conn.set(self.doc, 'outstanding_amount', flt(self.doc.grand_total) - flt(self.doc.total_advance) - flt(self.doc.paid_amount) - flt(self.doc.write_off_amount))
def validate_for_items(self): check_list, chk_dupl_itm = [], [] for d in getlist(self.doclist, 'delivery_note_details'): ch = sql("select is_stock_item from `tabItem` where name = '%s'" % d.item_code) if d.prevdoc_doctype and d.prevdoc_detail_docname and ch and ch[0][ 0] == 'Yes': self.validate_items_with_prevdoc(d) # validates whether item is not entered twice e = [ d.item_code, d.description, d.warehouse, d.prevdoc_docname or '', d.batch_no or '' ] f = [d.item_code, d.description, d.prevdoc_docname or ''] if ch and ch[0][0] == 'Yes': if e in check_list: msgprint( "Please check whether item %s has been entered twice wrongly." % d.item_code) else: check_list.append(e) elif ch and ch[0][0] == 'No': if f in chk_dupl_itm: msgprint( "Please check whether item %s has been entered twice wrongly." % d.item_code) else: chk_dupl_itm.append(f)
def so_required(self): """check in manage account if sales order required or not""" if webnotes.conn.get_value('Global Defaults', 'Global Defaults', 'so_required') == 'Yes': for d in getlist(self.doclist,'delivery_note_details'): if not d.prevdoc_docname: msgprint("Sales Order No. required against item %s"%d.item_code) raise Exception
def validate_serial_no_warranty(self): for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: dt = sql( "select warranty_expiry_date, amc_expiry_date from `tabSerial No` where name = %s", d.serial_no, as_dict=1) if dt[0]['warranty_expiry_date']: if dt[0]['warranty_expiry_date'] >= getdate(d.start_date): msgprint("Serial no " + d.serial_no + " for item " + d.item_code + " is already under warranty till " + (dt[0]['warranty_expiry_date'] ).strftime('%Y-%m-%d') + ". You can schedule AMC start date after " + (dt[0]['warranty_expiry_date'] ).strftime('%Y-%m-%d')) raise Exception if dt[0]['amc_expiry_date']: if dt[0]['amc_expiry_date'] >= getdate(d.start_date): msgprint( "Serial no " + d.serial_no + " for item " + d.item_code + " is already under AMC till " + (dt[0]['amc_expiry_date']).strftime('%Y-%m-%d') + ". You can schedule new AMC start date after " + (dt[0]['amc_expiry_date']).strftime('%Y-%m-%d')) raise Exception
def validate_reference_value(self, obj): ref_doc = [] for d in getlist(obj.doclist, obj.fname): if d.prevdoc_doctype and d.prevdoc_docname and d.prevdoc_doctype not in ref_doc: mapper_name = d.prevdoc_doctype + '-' + obj.doc.doctype get_obj('DocType Mapper', mapper_name, with_children = 1).validate_reference_value(obj, obj.doc.name) ref_doc.append(d.prevdoc_doctype)
def on_cancel(self): for d in getlist(self.doclist, 'item_maintenance_detail'): if d.serial_no: self.update_amc_date(d.serial_no, '') webnotes.conn.set(self.doc, 'status', 'Cancelled') sql("delete from `tabEvent` where ref_type='Maintenance Schedule' and ref_name='%s' " % (self.doc.name))
def set_pos_item_values(self): """Set default values related to pos for previously created sales invoice.""" if cint(self.doc.is_pos) == 1: dtl = webnotes.conn.sql( "select income_account, warehouse, cost_center from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company), as_dict=1) if not dtl: dtl = webnotes.conn.sql( "select income_account, warehouse, cost_center from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % (self.doc.company), as_dict=1) for d in getlist(self.doclist, 'entries'): # overwrite if mentioned in item item = webnotes.conn.sql( "select default_income_account, default_sales_cost_center, default_warehouse from tabItem where name = '%s'" % (d.item_code), as_dict=1) d.income_account = item and item[0][ 'default_income_account'] or dtl and dtl[0][ 'income_account'] or d.income_account d.cost_center = item and item[0][ 'default_sales_cost_center'] or dtl and dtl[0][ 'cost_center'] or d.cost_center d.warehouse = item and item[0][ 'default_warehouse'] or dtl and dtl[0][ 'warehouse'] or d.warehouse
def get_income_account(self,doctype): for d in getlist(self.doclist, doctype): if d.item_code: item = webnotes.conn.get_value("Item", d.item_code, ["default_income_account", "default_sales_cost_center"], as_dict=True) d.income_account = item['default_income_account'] or "" d.cost_center = item['default_sales_cost_center'] or ""
def add_charges_in_pr(self): """ Add additional charges in selected pr proportionately""" total_amt = self.get_total_amt() for pr in self.selected_pr: pr_obj = get_obj('Purchase Receipt', pr, with_children = 1) cumulative_grand_total = flt(pr_obj.doc.grand_total) for lc in getlist(self.doclist, 'landed_cost_details'): amt = flt(lc.amount) * flt(pr_obj.doc.net_total)/ flt(total_amt) self.prwise_cost[pr] = self.prwise_cost.get(pr, 0) + amt cumulative_grand_total += amt pr_oc_row = sql("select name from `tabPurchase Taxes and Charges` where parent = %s and category = 'Valuation' and add_deduct_tax = 'Add' and charge_type = 'Actual' and account_head = %s",(pr, lc.account_head)) if not pr_oc_row: # add if not exists ch = addchild(pr_obj.doc, 'purchase_tax_details', 'Purchase Taxes and Charges') ch.category = 'Valuation' ch.add_deduct_tax = 'Add' ch.charge_type = 'Actual' ch.description = lc.description ch.account_head = lc.account_head ch.rate = amt ch.tax_amount = amt ch.total = cumulative_grand_total ch.docstatus = 1 ch.idx = 500 # add at the end ch.save(1) else: # overwrite if exists sql("update `tabPurchase Taxes and Charges` set rate = %s, tax_amount = %s where name = %s and parent = %s ", (amt, amt, pr_oc_row[0][0], pr))
def create_remarks(self): r = [] if self.doc.cheque_no : if self.doc.cheque_date: r.append('Via Reference #%s dated %s' % (self.doc.cheque_no, formatdate(self.doc.cheque_date))) else : msgprint("Please enter Reference date") raise Exception for d in getlist(self.doclist, 'entries'): if d.against_invoice and d.credit: currency = sql("select currency from `tabSales Invoice` where name = '%s'" % d.against_invoice) currency = currency and currency[0][0] or '' r.append('%s %s against Invoice: %s' % (cstr(currency), fmt_money(flt(d.credit)), d.against_invoice)) if d.against_voucher and d.debit: bill_no = sql("select bill_no, bill_date, currency from `tabPurchase Invoice` where name=%s", d.against_voucher) if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() not in ['na', 'not applicable', 'none']: bill_no = bill_no and bill_no[0] r.append('%s %s against Bill %s dated %s' % (bill_no[2] and cstr(bill_no[2]) or '', fmt_money(flt(d.debit)), bill_no[0], bill_no[1] and formatdate(bill_no[1].strftime('%Y-%m-%d')) or '')) if self.doc.user_remark: r.append("User Remark : %s"%self.doc.user_remark) if r: self.doc.remark = ("\n").join(r)
def validate_sales_mntc_quotation(self): for d in getlist(self.doclist, 'sales_order_details'): if d.prevdoc_docname: res = sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.doc.order_type)) if not res: msgprint("""Order Type (%s) should be same in Quotation: %s \ and current Sales Order""" % (self.doc.order_type, d.prevdoc_docname))
def make_gl_entries(self, doc, doclist, cancel=0, adv_adj = 0, use_mapper='', merge_entries = 1, update_outstanding='Yes'): self.entries = [] # get entries le_map_list = webnotes.conn.sql("select * from `tabGL Mapper Detail` where parent = %s", use_mapper or doc.doctype, as_dict=1) self.td, self.tc = 0.0, 0.0 for le_map in le_map_list: if le_map['table_field']: for d in getlist(doclist,le_map['table_field']): # purchase_tax_details is the table of other charges in purchase cycle if le_map['table_field'] != 'purchase_tax_details' or (le_map['table_field'] == 'purchase_tax_details' and d.fields.get('category') != 'Valuation'): self.make_single_entry(doc,d,le_map,cancel, merge_entries) else: self.make_single_entry(None,doc,le_map,cancel, merge_entries) # save entries self.save_entries(cancel, adv_adj, update_outstanding) # check total debit / credit # Due to old wrong entries (total debit != total credit) some voucher could be cancelled if abs(self.td - self.tc) > 0.01 and not cancel: msgprint("Debit and Credit not equal for this voucher: Diff (Debit) is %s" % (self.td-self.tc)) raise Exception # set as cancelled if cancel: vt = self.get_val(le_map['voucher_type'], doc, doc) vn = self.get_val(le_map['voucher_no'], doc, doc) webnotes.conn.sql("update `tabGL Entry` set is_cancelled='Yes' where voucher_type=%s and voucher_no=%s", (vt, vn))
def get_other_charges(self,obj, default=0): obj.doclist = obj.doc.clear_table(obj.doclist, 'other_charges') if not getlist(obj.doclist, 'other_charges'): if default: add_cond = 'ifnull(t2.is_default,0) = 1' else: add_cond = 't1.parent = "'+cstr(obj.doc.charge)+'"' idx = 0 other_charge = webnotes.conn.sql("""\ select t1.* from `tabSales Taxes and Charges` t1, `tabSales Taxes and Charges Master` t2 where t1.parent = t2.name and t2.company = '%s' and %s order by t1.idx""" % (obj.doc.company, add_cond), as_dict=1) from webnotes.model import default_fields for other in other_charge: # remove default fields like parent, parenttype etc. # from query results for field in default_fields: if field in other: del other[field] d = addchild(obj.doc, 'other_charges', 'Sales Taxes and Charges', 1, obj.doclist) d.fields.update(other) d.rate = flt(d.rate) d.tax_amount = flt(d.tax_rate) d.included_in_print_rate = cint(d.included_in_print_rate) d.idx = idx idx += 1 return obj.doclist
def reconcile(self): """ Links booking and payment voucher 1. cancel payment voucher 2. split into multiple rows if partially adjusted, assign against voucher 3. submit payment voucher """ if not self.doc.voucher_no or not sql("select name from `tab%s` where name = %s" %(self.dt[self.doc.voucher_type], '%s'), self.doc.voucher_no): msgprint("Please select valid Voucher No to proceed", raise_exception=1) lst = [] for d in getlist(self.doclist, 'ir_payment_details'): if flt(d.amt_to_be_reconciled) > 0: args = { 'voucher_no' : d.voucher_no, 'voucher_detail_no' : d.voucher_detail_no, 'against_voucher_type' : self.dt[self.doc.voucher_type], 'against_voucher' : self.doc.voucher_no, 'account' : self.doc.account, 'is_advance' : 'No', 'dr_or_cr' : self.acc_type=='debit' and 'credit' or 'debit', 'unadjusted_amt' : flt(d.amt_due), 'allocated_amt' : flt(d.amt_to_be_reconciled) } lst.append(args) if lst: get_obj('GL Control').reconcile_against_document(lst) msgprint("Successfully allocated.") else: msgprint("No amount allocated.", raise_exception=1)
def validate_item_code(self): for d in getlist(self.doclist, 'entries'): if not d.item_code: msgprint( "Please enter Item Code at line no : %s to update stock for POS or remove check from Update Stock in Basic Info Tab." % (d.idx)) raise Exception
def update_against_document_in_jv(self): """ Links invoice and advance voucher: 1. cancel advance voucher 2. split into multiple rows if partially adjusted, assign against voucher 3. submit advance voucher """ lst = [] for d in getlist(self.doclist, 'advance_adjustment_details'): if flt(d.allocated_amount) > 0: args = { 'voucher_no' : d.journal_voucher, 'voucher_detail_no' : d.jv_detail_no, 'against_voucher_type' : 'Sales Invoice', 'against_voucher' : self.doc.name, 'account' : self.doc.debit_to, 'is_advance' : 'Yes', 'dr_or_cr' : 'credit', 'unadjusted_amt' : flt(d.advance_amount), 'allocated_amt' : flt(d.allocated_amount) } lst.append(args) if lst: get_obj('GL Control').reconcile_against_document(lst)
def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line): bin = self.get_bin_qty(packing_item_code, warehouse) item = self.get_packing_item_details(packing_item_code) # check if exists exists = 0 for d in getlist(obj.doclist, 'packing_details'): if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name: pi, exists = d, 1 break if not exists: pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', 1, obj.doclist) pi.parent_item = line.item_code pi.item_code = packing_item_code pi.item_name = item['item_name'] pi.parent_detail_docname = line.name pi.description = item['description'] pi.uom = item['stock_uom'] pi.qty = flt(qty) pi.actual_qty = bin and flt(bin['actual_qty']) or 0 pi.projected_qty = bin and flt(bin['projected_qty']) or 0 pi.prevdoc_doctype = line.prevdoc_doctype if not pi.warehouse: pi.warehouse = warehouse if not pi.batch_no: pi.batch_no = cstr(line.batch_no) pi.idx = self.packing_list_idx # saved, since this function is called on_update of delivery note pi.save() self.packing_list_idx += 1
def set_actual_qty(self): for d in getlist(self.doclist, 'delivery_note_details'): if d.item_code and d.warehouse: actual_qty = sql( "select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse)) d.actual_qty = actual_qty and flt(actual_qty[0][0]) or 0
def create_remarks(self): r = [] if self.doc.cheque_no : if self.doc.cheque_date: r.append('Via Reference #%s dated %s' % (self.doc.cheque_no, formatdate(self.doc.cheque_date))) else : msgprint("Please enter Reference date", raise_exception=1) for d in getlist(self.doclist, 'entries'): if d.against_invoice and d.credit: currency = webnotes.conn.get_value("Sales Invoice", d.against_invoice, "currency") r.append('%s %s against Invoice: %s' % (cstr(currency), fmt_money(flt(d.credit)), d.against_invoice)) if d.against_voucher and d.debit: bill_no = webnotes.conn.sql("""select bill_no, bill_date, currency from `tabPurchase Invoice` where name=%s""", d.against_voucher) if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \ not in ['na', 'not applicable', 'none']: r.append('%s %s against Bill %s dated %s' % (cstr(bill_no[0][2]), fmt_money(flt(d.debit)), bill_no[0][0], bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d')) or '')) if self.doc.user_remark: r.append("User Remark : %s"%self.doc.user_remark) if r: self.doc.remark = ("\n").join(r) else: webnotes.msgprint("Remarks is mandatory", raise_exception=1)
def send_notification(new_rv): """Notify concerned persons about recurring invoice generation""" subject = "Invoice : " + new_rv.doc.name com = new_rv.doc.company # webnotes.conn.get_value('Control Panel', '', 'letter_head') hd = '''<div><h2>%s</h2></div> <div><h3>Invoice: %s</h3></div> <table cellspacing= "5" cellpadding="5" width = "100%%"> <tr> <td width = "50%%"><b>Customer</b><br>%s<br>%s</td> <td width = "50%%">Invoice Date : %s<br>Invoice Period : %s to %s <br>Due Date : %s</td> </tr> </table> ''' % (com, new_rv.doc.name, new_rv.doc.customer_name, new_rv.doc.address_display, getdate(new_rv.doc.posting_date).strftime("%d-%m-%Y"), \ getdate(new_rv.doc.invoice_period_from_date).strftime("%d-%m-%Y"), getdate(new_rv.doc.invoice_period_to_date).strftime("%d-%m-%Y"),\ getdate(new_rv.doc.due_date).strftime("%d-%m-%Y")) tbl = '''<table border="1px solid #CCC" width="100%%" cellpadding="0px" cellspacing="0px"> <tr> <td width = "15%%" bgcolor="#CCC" align="left"><b>Item</b></td> <td width = "40%%" bgcolor="#CCC" align="left"><b>Description</b></td> <td width = "15%%" bgcolor="#CCC" align="center"><b>Qty</b></td> <td width = "15%%" bgcolor="#CCC" align="center"><b>Rate</b></td> <td width = "15%%" bgcolor="#CCC" align="center"><b>Amount</b></td> </tr> ''' for d in getlist(new_rv.doclist, 'entries'): tbl += '<tr><td>' + d.item_code +'</td><td>' + d.description+'</td><td>' + cstr(d.qty) +'</td><td>' + cstr(d.basic_rate) +'</td><td>' + cstr(d.amount) +'</td></tr>' tbl += '</table>' totals ='''<table cellspacing= "5" cellpadding="5" width = "100%%"> <tr> <td width = "50%%"></td> <td width = "50%%"> <table width = "100%%"> <tr> <td width = "50%%">Net Total: </td><td>%s </td> </tr><tr> <td width = "50%%">Total Tax: </td><td>%s </td> </tr><tr> <td width = "50%%">Grand Total: </td><td>%s</td> </tr><tr> <td width = "50%%">In Words: </td><td>%s</td> </tr> </table> </td> </tr> <tr><td>Terms and Conditions:</td></tr> <tr><td>%s</td></tr> </table> ''' % (new_rv.doc.net_total, new_rv.doc.other_charges_total,new_rv.doc.grand_total, new_rv.doc.in_words,new_rv.doc.terms) msg = hd + tbl + totals sendmail(new_rv.doc.notification_email_address, subject=subject, msg = msg)
def validate_transfer_qty(self): for d in getlist(self.doclist, 'mtn_details'): if flt(d.transfer_qty) <= 0: msgprint( "Transfer Quantity can not be less than or equal to zero at Row No " + cstr(d.idx)) raise Exception