Merge branch 'develop' into link-to-mr

This commit is contained in:
Marica 2020-10-27 11:49:35 +05:30 committed by GitHub
commit 16a1f7e7e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
163 changed files with 13887 additions and 5454 deletions

View File

@ -51,6 +51,7 @@ frappe.ui.form.on('POS Closing Entry', {
args: {
start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
pos_profile: frm.doc.pos_profile,
user: frm.doc.user
},
callback: (r) => {

View File

@ -14,19 +14,51 @@ from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import
class POSClosingEntry(Document):
def validate(self):
user = frappe.get_all('POS Closing Entry',
filters = { 'user': self.user, 'docstatus': 1 },
if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
self.validate_pos_closing()
self.validate_pos_invoices()
def validate_pos_closing(self):
user = frappe.get_all("POS Closing Entry",
filters = { "user": self.user, "docstatus": 1, "pos_profile": self.pos_profile },
or_filters = {
'period_start_date': ('between', [self.period_start_date, self.period_end_date]),
'period_end_date': ('between', [self.period_start_date, self.period_end_date])
"period_start_date": ("between", [self.period_start_date, self.period_end_date]),
"period_end_date": ("between", [self.period_start_date, self.period_end_date])
})
if user:
frappe.throw(_("POS Closing Entry {} against {} between selected period"
.format(frappe.bold("already exists"), frappe.bold(self.user))), title=_("Invalid Period"))
bold_already_exists = frappe.bold(_("already exists"))
bold_user = frappe.bold(self.user)
frappe.throw(_("POS Closing Entry {} against {} between selected period")
.format(bold_already_exists, bold_user), title=_("Invalid Period"))
def validate_pos_invoices(self):
invalid_rows = []
for d in self.pos_transactions:
invalid_row = {'idx': d.idx}
pos_invoice = frappe.db.get_values("POS Invoice", d.pos_invoice,
["consolidated_invoice", "pos_profile", "docstatus", "owner"], as_dict=1)[0]
if pos_invoice.consolidated_invoice:
invalid_row.setdefault('msg', []).append(_('POS Invoice is {}').format(frappe.bold("already consolidated")))
invalid_rows.append(invalid_row)
continue
if pos_invoice.pos_profile != self.pos_profile:
invalid_row.setdefault('msg', []).append(_("POS Profile doesn't matches {}").format(frappe.bold(self.pos_profile)))
if pos_invoice.docstatus != 1:
invalid_row.setdefault('msg', []).append(_('POS Invoice is not {}').format(frappe.bold("submitted")))
if pos_invoice.owner != self.user:
invalid_row.setdefault('msg', []).append(_("POS Invoice isn't created by user {}").format(frappe.bold(self.owner)))
if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
if invalid_row.get('msg'):
invalid_rows.append(invalid_row)
if not invalid_rows:
return
error_list = [_("Row #{}: {}").format(row.get('idx'), row.get('msg')) for row in invalid_rows]
frappe.throw(error_list, title=_("Invalid POS Invoices"), as_list=True)
def on_submit(self):
merge_pos_invoices(self.pos_transactions)
@ -47,16 +79,15 @@ def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
return [c['user'] for c in cashiers_list]
@frappe.whitelist()
def get_pos_invoices(start, end, user):
def get_pos_invoices(start, end, pos_profile, user):
data = frappe.db.sql("""
select
name, timestamp(posting_date, posting_time) as "timestamp"
from
`tabPOS Invoice`
where
owner = %s and docstatus = 1 and
(consolidated_invoice is NULL or consolidated_invoice = '')
""", (user), as_dict=1)
owner = %s and docstatus = 1 and pos_profile = %s and ifnull(consolidated_invoice,'') = ''
""", (user, pos_profile), as_dict=1)
data = list(filter(lambda d: get_datetime(start) <= get_datetime(d.timestamp) <= get_datetime(end), data))
# need to get taxes and payments so can't avoid get_doc
@ -76,7 +107,8 @@ def make_closing_entry_from_opening(opening_entry):
closing_entry.net_total = 0
closing_entry.total_quantity = 0
invoices = get_pos_invoices(closing_entry.period_start_date, closing_entry.period_end_date, closing_entry.user)
invoices = get_pos_invoices(closing_entry.period_start_date, closing_entry.period_end_date,
closing_entry.pos_profile, closing_entry.user)
pos_transactions = []
taxes = []

View File

@ -7,8 +7,8 @@
"field_order": [
"mode_of_payment",
"opening_amount",
"closing_amount",
"expected_amount",
"closing_amount",
"difference"
],
"fields": [
@ -26,8 +26,7 @@
"in_list_view": 1,
"label": "Expected Amount",
"options": "company:company_currency",
"read_only": 1,
"reqd": 1
"read_only": 1
},
{
"fieldname": "difference",
@ -55,9 +54,10 @@
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-05-29 15:03:34.533607",
"modified": "2020-10-23 16:45:43.662034",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Closing Entry Detail",

View File

@ -9,80 +9,63 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
this._super(doc);
},
onload() {
onload(doc) {
this._super();
if(this.frm.doc.__islocal && this.frm.doc.is_pos) {
//Load pos profile data on the invoice if the default value of Is POS is 1
me.frm.script_manager.trigger("is_pos");
me.frm.refresh_fields();
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
this.frm.script_manager.trigger("is_pos");
this.frm.refresh_fields();
}
},
refresh(doc) {
this._super();
if (doc.docstatus == 1 && !doc.is_return) {
if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__('Return'),
this.make_sales_return, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
}
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create'));
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
}
if (this.frm.doc.is_return) {
if (doc.is_return && doc.__islocal) {
this.frm.return_print_format = "Sales Invoice Return";
cur_frm.set_value('consolidated_invoice', '');
this.frm.set_value('consolidated_invoice', '');
}
},
is_pos: function(frm){
is_pos: function() {
this.set_pos_data();
},
set_pos_data: function() {
set_pos_data: async function() {
if(this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
this.frm.set_value("is_pos", 0);
frappe.msgprint(__("Please specify Company to proceed"));
} else {
var me = this;
return this.frm.call({
doc: me.frm.doc,
const r = await this.frm.call({
doc: this.frm.doc,
method: "set_missing_values",
callback: function(r) {
if(!r.exc) {
if(r.message) {
me.frm.pos_print_format = r.message.print_format || "";
me.frm.meta.default_print_format = r.message.print_format || "";
me.frm.allow_edit_rate = r.message.allow_edit_rate;
me.frm.allow_edit_discount = r.message.allow_edit_discount;
me.frm.doc.campaign = r.message.campaign;
me.frm.allow_print_before_pay = r.message.allow_print_before_pay;
}
me.frm.script_manager.trigger("update_stock");
me.calculate_taxes_and_totals();
if(me.frm.doc.taxes_and_charges) {
me.frm.script_manager.trigger("taxes_and_charges");
}
frappe.model.set_default_values(me.frm.doc);
me.set_dynamic_labels();
}
}
freeze: true
});
if(!r.exc) {
if(r.message) {
this.frm.pos_print_format = r.message.print_format || "";
this.frm.meta.default_print_format = r.message.print_format || "";
this.frm.doc.campaign = r.message.campaign;
this.frm.allow_print_before_pay = r.message.allow_print_before_pay;
}
this.frm.script_manager.trigger("update_stock");
this.calculate_taxes_and_totals();
this.frm.doc.taxes_and_charges && this.frm.script_manager.trigger("taxes_and_charges");
frappe.model.set_default_values(this.frm.doc);
this.set_dynamic_labels();
}
}
}
else this.frm.trigger("refresh");
},
customer() {
if (!this.frm.doc.customer) return
if (this.frm.doc.is_pos){
var pos_profile = this.frm.doc.pos_profile;
}
var me = this;
const pos_profile = this.frm.doc.pos_profile;
if(this.frm.updating_party_details) return;
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
@ -92,8 +75,8 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list,
pos_profile: pos_profile
}, function() {
me.apply_pricing_rule();
}, () => {
this.apply_pricing_rule();
});
},

View File

@ -10,12 +10,10 @@ from erpnext.controllers.selling_controller import SellingController
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
get_loyalty_program_details_with_points, validate_loyalty_points
from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice, get_bank_cash_account, update_multi_mode_option
from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points
from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos
from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice, get_bank_cash_account, update_multi_mode_option, get_mode_of_payment_info
from six import iteritems
@ -30,8 +28,7 @@ class POSInvoice(SalesInvoice):
# run on validate method of selling controller
super(SalesInvoice, self).validate()
self.validate_auto_set_posting_time()
self.validate_pos_paid_amount()
self.validate_pos_return()
self.validate_mode_of_payment()
self.validate_uom_is_integer("stock_uom", "stock_qty")
self.validate_uom_is_integer("uom", "qty")
self.validate_debit_to_acc()
@ -41,11 +38,11 @@ class POSInvoice(SalesInvoice):
self.validate_item_cost_centers()
self.validate_serialised_or_batched_item()
self.validate_stock_availablility()
self.validate_return_items()
self.validate_return_items_qty()
self.set_status()
self.set_account_for_mode_of_payment()
self.validate_pos()
self.verify_payment_amount()
self.validate_payment_amount()
self.validate_loyalty_transaction()
def on_submit(self):
@ -84,70 +81,98 @@ class POSInvoice(SalesInvoice):
return frappe.throw(_("Payment related to {0} is not completed").format(pay.mode_of_payment))
def validate_stock_availablility(self):
allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock')
if self.is_return:
return
allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock')
error_msg = []
for d in self.get('items'):
msg = ""
if d.serial_no:
filters = {
"item_code": d.item_code,
"warehouse": d.warehouse,
"delivery_document_no": "",
"sales_invoice": ""
}
filters = { "item_code": d.item_code, "warehouse": d.warehouse }
if d.batch_no:
filters["batch_no"] = d.batch_no
reserved_serial_nos, unreserved_serial_nos = get_pos_reserved_serial_nos(filters)
serial_nos = d.serial_no.split("\n")
serial_nos = ' '.join(serial_nos).split() # remove whitespaces
invalid_serial_nos = []
for s in serial_nos:
if s in reserved_serial_nos:
invalid_serial_nos.append(s)
if len(invalid_serial_nos):
multiple_nos = 's' if len(invalid_serial_nos) > 1 else ''
frappe.throw(_("Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.").format(
d.idx, multiple_nos, frappe.bold(', '.join(invalid_serial_nos))), title=_("Not Available"))
reserved_serial_nos = get_pos_reserved_serial_nos(filters)
serial_nos = get_serial_nos(d.serial_no)
invalid_serial_nos = [s for s in serial_nos if s in reserved_serial_nos]
bold_invalid_serial_nos = frappe.bold(', '.join(invalid_serial_nos))
if len(invalid_serial_nos) == 1:
msg = (_("Row #{}: Serial No. {} has already been transacted into another POS Invoice. Please select valid serial no.")
.format(d.idx, bold_invalid_serial_nos))
elif invalid_serial_nos:
msg = (_("Row #{}: Serial Nos. {} has already been transacted into another POS Invoice. Please select valid serial no.")
.format(d.idx, bold_invalid_serial_nos))
else:
if allow_negative_stock:
return
available_stock = get_stock_availability(d.item_code, d.warehouse)
if not (flt(available_stock) > 0):
frappe.throw(_('Row #{}: Item Code: {} is not available under warehouse {}.').format(
d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse)), title=_("Not Available"))
item_code, warehouse, qty = frappe.bold(d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty)
if flt(available_stock) <= 0:
msg = (_('Row #{}: Item Code: {} is not available under warehouse {}.').format(d.idx, item_code, warehouse))
elif flt(available_stock) < flt(d.qty):
frappe.msgprint(_('Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.').format(
d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty)), title=_("Not Available"))
msg = (_('Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.')
.format(d.idx, item_code, warehouse, qty))
if msg:
error_msg.append(msg)
if error_msg:
frappe.throw(error_msg, title=_("Item Unavailable"), as_list=True)
def validate_serialised_or_batched_item(self):
error_msg = []
for d in self.get("items"):
serialized = d.get("has_serial_no")
batched = d.get("has_batch_no")
no_serial_selected = not d.get("serial_no")
no_batch_selected = not d.get("batch_no")
msg = ""
item_code = frappe.bold(d.item_code)
if serialized and batched and (no_batch_selected or no_serial_selected):
frappe.throw(_('Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.').format(
d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
msg = (_('Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.')
.format(d.idx, item_code))
if serialized and no_serial_selected:
frappe.throw(_('Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.').format(
d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
msg = (_('Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.')
.format(d.idx, item_code))
if batched and no_batch_selected:
frappe.throw(_('Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.').format(
d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
msg = (_('Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.')
.format(d.idx, item_code))
if msg:
error_msg.append(msg)
def validate_return_items(self):
if error_msg:
frappe.throw(error_msg, title=_("Invalid Item"), as_list=True)
def validate_return_items_qty(self):
if not self.get("is_return"): return
for d in self.get("items"):
if d.get("qty") > 0:
frappe.throw(_("Row #{}: You cannot add postive quantities in a return invoice. Please remove item {} to complete the return.")
.format(d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
frappe.throw(
_("Row #{}: You cannot add postive quantities in a return invoice. Please remove item {} to complete the return.")
.format(d.idx, frappe.bold(d.item_code)), title=_("Invalid Item")
)
if d.get("serial_no"):
serial_nos = get_serial_nos(d.serial_no)
for sr in serial_nos:
serial_no_exists = frappe.db.exists("POS Invoice Item", {
"parent": self.return_against,
"serial_no": ["like", d.get("serial_no")]
})
if not serial_no_exists:
bold_return_against = frappe.bold(self.return_against)
bold_serial_no = frappe.bold(sr)
frappe.throw(
_("Row #{}: Serial No {} cannot be returned since it was not transacted in original invoice {}")
.format(d.idx, bold_serial_no, bold_return_against)
)
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
def validate_mode_of_payment(self):
if len(self.payments) == 0:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
def validate_change_account(self):
@ -165,20 +190,18 @@ class POSInvoice(SalesInvoice):
if flt(self.change_amount) and not self.account_for_change_amount:
frappe.msgprint(_("Please enter Account for Change Amount"), raise_exception=1)
def verify_payment_amount(self):
def validate_payment_amount(self):
total_amount_in_payments = 0
for entry in self.payments:
total_amount_in_payments += entry.amount
if not self.is_return and entry.amount < 0:
frappe.throw(_("Row #{0} (Payment Table): Amount must be positive").format(entry.idx))
if self.is_return and entry.amount > 0:
frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx))
def validate_pos_return(self):
if self.is_pos and self.is_return:
total_amount_in_payments = 0
for payment in self.payments:
total_amount_in_payments += payment.amount
if self.is_return:
invoice_total = self.rounded_total or self.grand_total
if total_amount_in_payments < invoice_total:
if total_amount_in_payments and total_amount_in_payments < invoice_total:
frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total))
def validate_loyalty_transaction(self):
@ -233,55 +256,45 @@ class POSInvoice(SalesInvoice):
pos_profile = get_pos_profile(self.company) or {}
self.pos_profile = pos_profile.get('name')
pos = {}
profile = {}
if self.pos_profile:
pos = frappe.get_doc('POS Profile', self.pos_profile)
profile = frappe.get_doc('POS Profile', self.pos_profile)
if not self.get('payments') and not for_validate:
update_multi_mode_option(self, pos)
if not self.account_for_change_amount:
self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
if pos:
if not for_validate:
self.tax_category = pos.get("tax_category")
update_multi_mode_option(self, profile)
if self.is_return and not for_validate:
add_return_modes(self, profile)
if profile:
if not for_validate and not self.customer:
self.customer = pos.customer
self.customer = profile.customer
self.ignore_pricing_rule = pos.ignore_pricing_rule
if pos.get('account_for_change_amount'):
self.account_for_change_amount = pos.get('account_for_change_amount')
if pos.get('warehouse'):
self.set_warehouse = pos.get('warehouse')
self.ignore_pricing_rule = profile.ignore_pricing_rule
self.account_for_change_amount = profile.get('account_for_change_amount') or self.account_for_change_amount
self.set_warehouse = profile.get('warehouse') or self.set_warehouse
for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
for fieldname in ('currency', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname))
if pos.get("company_address"):
self.company_address = pos.get("company_address")
'write_off_cost_center', 'apply_discount_on', 'cost_center', 'tax_category',
'ignore_pricing_rule', 'company_address', 'update_stock'):
if not for_validate:
self.set(fieldname, profile.get(fieldname))
if self.customer:
customer_price_list, customer_group = frappe.db.get_value("Customer", self.customer, ['default_price_list', 'customer_group'])
customer_group_price_list = frappe.db.get_value("Customer Group", customer_group, 'default_price_list')
selling_price_list = customer_price_list or customer_group_price_list or pos.get('selling_price_list')
selling_price_list = customer_price_list or customer_group_price_list or profile.get('selling_price_list')
else:
selling_price_list = pos.get('selling_price_list')
selling_price_list = profile.get('selling_price_list')
if selling_price_list:
self.set('selling_price_list', selling_price_list)
if not for_validate:
self.update_stock = cint(pos.get("update_stock"))
# set pos values in items
for item in self.get("items"):
if item.get('item_code'):
profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos)
profile_details = get_pos_profile_item_details(profile.get("company"), frappe._dict(item.as_dict()), profile)
for fname, val in iteritems(profile_details):
if (not for_validate) or (for_validate and not item.get(fname)):
item.set(fname, val)
@ -294,10 +307,13 @@ class POSInvoice(SalesInvoice):
if self.taxes_and_charges and not len(self.get("taxes")):
self.set_taxes()
return pos
if not self.account_for_change_amount:
self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
return profile
def set_missing_values(self, for_validate=False):
pos = self.set_pos_fields(for_validate)
profile = self.set_pos_fields(for_validate)
if not self.debit_to:
self.debit_to = get_party_account("Customer", self.customer, self.company)
@ -307,17 +323,15 @@ class POSInvoice(SalesInvoice):
super(SalesInvoice, self).set_missing_values(for_validate)
print_format = pos.get("print_format") if pos else None
print_format = profile.get("print_format") if profile else None
if not print_format and not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')):
print_format = 'POS Invoice'
if pos:
if profile:
return {
"print_format": print_format,
"allow_edit_rate": pos.get("allow_user_to_edit_rate"),
"allow_edit_discount": pos.get("allow_user_to_edit_discount"),
"campaign": pos.get("campaign"),
"allow_print_before_pay": pos.get("allow_print_before_pay")
"campaign": profile.get("campaign"),
"allow_print_before_pay": profile.get("allow_print_before_pay")
}
def set_account_for_mode_of_payment(self):
@ -373,11 +387,9 @@ def get_stock_availability(item_code, warehouse):
sle_qty = latest_sle[0].qty_after_transaction or 0 if latest_sle else 0
pos_sales_qty = pos_sales_qty[0].qty or 0 if pos_sales_qty else 0
if sle_qty and pos_sales_qty and sle_qty > pos_sales_qty:
if sle_qty and pos_sales_qty:
return sle_qty - pos_sales_qty
else:
# when sle_qty is 0
# when sle_qty > 0 and pos_sales_qty is 0
return sle_qty
@frappe.whitelist()
@ -410,4 +422,19 @@ def make_merge_log(invoices):
})
if merge_log.get('pos_invoices'):
return merge_log.as_dict()
return merge_log.as_dict()
def add_return_modes(doc, pos_profile):
def append_payment(payment_mode):
payment = doc.append('payments', {})
payment.default = payment_mode.default
payment.mode_of_payment = payment_mode.parent
payment.account = payment_mode.default_account
payment.type = payment_mode.type
for pos_payment_method in pos_profile.get('payments'):
pos_payment_method = pos_payment_method.as_dict()
mode_of_payment = pos_payment_method.mode_of_payment
if pos_payment_method.allow_in_returns and not [d for d in doc.get('payments') if d.mode_of_payment == mode_of_payment]:
payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company)
append_payment(payment_mode[0])

View File

@ -26,18 +26,25 @@ class POSInvoiceMergeLog(Document):
for d in self.pos_invoices:
status, docstatus, is_return, return_against = frappe.db.get_value(
'POS Invoice', d.pos_invoice, ['status', 'docstatus', 'is_return', 'return_against'])
bold_pos_invoice = frappe.bold(d.pos_invoice)
bold_status = frappe.bold(status)
if docstatus != 1:
frappe.throw(_("Row #{}: POS Invoice {} is not submitted yet").format(d.idx, d.pos_invoice))
frappe.throw(_("Row #{}: POS Invoice {} is not submitted yet").format(d.idx, bold_pos_invoice))
if status == "Consolidated":
frappe.throw(_("Row #{}: POS Invoice {} has been {}").format(d.idx, d.pos_invoice, status))
if is_return and return_against not in [d.pos_invoice for d in self.pos_invoices] and status != "Consolidated":
# if return entry is not getting merged in the current pos closing and if it is not consolidated
frappe.throw(
_("Row #{}: Return Invoice {} cannot be made against unconsolidated invoice. \
You can add original invoice {} manually to proceed.")
.format(d.idx, frappe.bold(d.pos_invoice), frappe.bold(return_against))
)
frappe.throw(_("Row #{}: POS Invoice {} has been {}").format(d.idx, bold_pos_invoice, bold_status))
if is_return and return_against and return_against not in [d.pos_invoice for d in self.pos_invoices]:
bold_return_against = frappe.bold(return_against)
return_against_status = frappe.db.get_value('POS Invoice', return_against, "status")
if return_against_status != "Consolidated":
# if return entry is not getting merged in the current pos closing and if it is not consolidated
bold_unconsolidated = frappe.bold("not Consolidated")
msg = (_("Row #{}: Original Invoice {} of return invoice {} is {}. ")
.format(d.idx, bold_return_against, bold_pos_invoice, bold_unconsolidated))
msg += _("Original invoice should be consolidated before or along with the return invoice.")
msg += "<br><br>"
msg += _("You can add original invoice {} manually to proceed.").format(bold_return_against)
frappe.throw(msg)
def on_submit(self):
pos_invoice_docs = [frappe.get_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices]

View File

@ -17,18 +17,25 @@ class POSOpeningEntry(StatusUpdater):
def validate_pos_profile_and_cashier(self):
if self.company != frappe.db.get_value("POS Profile", self.pos_profile, "company"):
frappe.throw(_("POS Profile {} does not belongs to company {}".format(self.pos_profile, self.company)))
frappe.throw(_("POS Profile {} does not belongs to company {}").format(self.pos_profile, self.company))
if not cint(frappe.db.get_value("User", self.user, "enabled")):
frappe.throw(_("User {} has been disabled. Please select valid user/cashier".format(self.user)))
frappe.throw(_("User {} is disabled. Please select valid user/cashier").format(self.user))
def validate_payment_method_account(self):
invalid_modes = []
for d in self.balance_details:
account = frappe.db.get_value("Mode of Payment Account",
{"parent": d.mode_of_payment, "company": self.company}, "default_account")
if not account:
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
invalid_modes.append(get_link_to_form("Mode of Payment", d.mode_of_payment))
if invalid_modes:
if invalid_modes == 1:
msg = _("Please set default Cash or Bank account in Mode of Payment {}")
else:
msg = _("Please set default Cash or Bank account in Mode of Payments {}")
frappe.throw(msg.format(", ".join(invalid_modes)), title=_("Missing Account"))
def on_submit(self):
self.set_status(update=True)

View File

@ -6,6 +6,7 @@
"engine": "InnoDB",
"field_order": [
"default",
"allow_in_returns",
"mode_of_payment"
],
"fields": [
@ -24,11 +25,19 @@
"label": "Mode of Payment",
"options": "Mode of Payment",
"reqd": 1
},
{
"default": "0",
"fieldname": "allow_in_returns",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allow In Returns"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-05-29 15:08:41.704844",
"modified": "2020-10-20 12:58:46.114456",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Payment Method",

View File

@ -290,28 +290,30 @@
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "Warehouse",
"mandatory_depends_on": "update_stock",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse"
},
{
"default": "0",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock"
"options": "Warehouse",
"reqd": 1
},
{
"default": "0",
"fieldname": "ignore_pricing_rule",
"fieldtype": "Check",
"label": "Ignore Pricing Rule"
},
{
"default": "1",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock",
"read_only": 1
}
],
"icon": "icon-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-10-01 17:29:27.759088",
"modified": "2020-10-20 13:16:50.665081",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@ -56,19 +56,29 @@ class POSProfile(Document):
if not self.payments:
frappe.throw(_("Payment methods are mandatory. Please add at least one payment method."))
default_mode_of_payment = [d.default for d in self.payments if d.default]
if not default_mode_of_payment:
default_mode = [d.default for d in self.payments if d.default]
if not default_mode:
frappe.throw(_("Please select a default mode of payment"))
if len(default_mode_of_payment) > 1:
if len(default_mode) > 1:
frappe.throw(_("You can only select one mode of payment as default"))
invalid_modes = []
for d in self.payments:
account = frappe.db.get_value("Mode of Payment Account",
{"parent": d.mode_of_payment, "company": self.company}, "default_account")
account = frappe.db.get_value(
"Mode of Payment Account",
{"parent": d.mode_of_payment, "company": self.company},
"default_account"
)
if not account:
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
invalid_modes.append(get_link_to_form("Mode of Payment", d.mode_of_payment))
if invalid_modes:
if invalid_modes == 1:
msg = _("Please set default Cash or Bank account in Mode of Payment {}")
else:
msg = _("Please set default Cash or Bank account in Mode of Payments {}")
frappe.throw(msg.format(", ".join(invalid_modes)), title=_("Missing Account"))
def on_update(self):
self.set_defaults()

View File

@ -9,8 +9,7 @@ frappe.ui.form.on('POS Settings', {
get_invoice_fields: function(frm) {
frappe.model.with_doctype("POS Invoice", () => {
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
['Table', 'Button'].includes(d.fieldtype)) {
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 || ['Button'].includes(d.fieldtype)) {
return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
} else {
return null;

View File

@ -151,14 +151,16 @@ class PurchaseInvoice(BuyingController):
["account_type", "report_type", "account_currency"], as_dict=True)
if account.report_type != "Balance Sheet":
frappe.throw(_("Please ensure {} account is a Balance Sheet account. \
You can change the parent account to a Balance Sheet account or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account"))
frappe.throw(
_("Please ensure {} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account")
)
if self.supplier and account.account_type != "Payable":
frappe.throw(_("Please ensure {} account is a Payable account. \
Change the account type to Payable or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account"))
frappe.throw(
_("Please ensure {} account is a Payable account. Change the account type to Payable or select a different account.")
.format(frappe.bold("Credit To")), title=_("Invalid Account")
)
self.party_account_currency = account.account_currency
@ -244,10 +246,10 @@ class PurchaseInvoice(BuyingController):
if self.update_stock and (not item.from_warehouse):
if for_validate and item.expense_account and item.expense_account != warehouse_account[item.warehouse]["account"]:
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} because account {2}
is not linked to warehouse {3} or it is not the default inventory account'''.format(
item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]),
frappe.bold(item.expense_account), frappe.bold(item.warehouse))))
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]))
msg += _("because account {} is not linked to warehouse {} ").format(frappe.bold(item.expense_account), frappe.bold(item.warehouse))
msg += _("or it is not the default inventory account")
frappe.msgprint(msg, title=_("Expense Head Changed"))
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
@ -259,19 +261,19 @@ class PurchaseInvoice(BuyingController):
if negative_expense_booked_in_pr:
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} because
expense is booked against this account in Purchase Receipt {2}'''.format(
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.purchase_receipt))))
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
msg += _("because expense is booked against this account in Purchase Receipt {}").format(frappe.bold(item.purchase_receipt))
frappe.msgprint(msg, title=_("Expense Head Changed"))
item.expense_account = stock_not_billed_account
else:
# If no purchase receipt present then book expense in 'Stock Received But Not Billed'
# This is done in cases when Purchase Invoice is created before Purchase Receipt
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} as no Purchase
Receipt is created against Item {2}. This is done to handle accounting for cases
when Purchase Receipt is created after Purchase Invoice'''.format(
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.item_code))))
msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
msg += _("as no Purchase Receipt is created against Item {}. ").format(frappe.bold(item.item_code))
msg += _("This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice")
frappe.msgprint(msg, title=_("Expense Head Changed"))
item.expense_account = stock_not_billed_account
@ -299,10 +301,11 @@ class PurchaseInvoice(BuyingController):
for d in self.get('items'):
if not d.purchase_order:
throw(_("""Purchase Order Required for item {0}
To submit the invoice without purchase order please set
{1} as {2} in {3}""").format(frappe.bold(d.item_code), frappe.bold(_('Purchase Order Required')),
frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings')))
msg = _("Purchase Order Required for item {}").format(frappe.bold(d.item_code))
msg += "<br><br>"
msg += _("To submit the invoice without purchase order please set {} ").format(frappe.bold(_('Purchase Order Required')))
msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
throw(msg, title=_("Mandatory Purchase Order"))
def pr_required(self):
stock_items = self.get_stock_items()
@ -313,10 +316,11 @@ class PurchaseInvoice(BuyingController):
for d in self.get('items'):
if not d.purchase_receipt and d.item_code in stock_items:
throw(_("""Purchase Receipt Required for item {0}
To submit the invoice without purchase receipt please set
{1} as {2} in {3}""").format(frappe.bold(d.item_code), frappe.bold(_('Purchase Receipt Required')),
frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings')))
msg = _("Purchase Receipt Required for item {}").format(frappe.bold(d.item_code))
msg += "<br><br>"
msg += _("To submit the invoice without purchase receipt please set {} ").format(frappe.bold(_('Purchase Receipt Required')))
msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
throw(msg, title=_("Mandatory Purchase Receipt"))
def validate_write_off_account(self):
if self.write_off_amount and not self.write_off_account:

View File

@ -479,14 +479,14 @@ class SalesInvoice(SellingController):
frappe.throw(_("Debit To is required"), title=_("Account Missing"))
if account.report_type != "Balance Sheet":
frappe.throw(_("Please ensure {} account is a Balance Sheet account. \
You can change the parent account to a Balance Sheet account or select a different account.")
.format(frappe.bold("Debit To")), title=_("Invalid Account"))
msg = _("Please ensure {} account is a Balance Sheet account. ").format(frappe.bold("Debit To"))
msg += _("You can change the parent account to a Balance Sheet account or select a different account.")
frappe.throw(msg, title=_("Invalid Account"))
if self.customer and account.account_type != "Receivable":
frappe.throw(_("Please ensure {} account is a Receivable account. \
Change the account type to Receivable or select a different account.")
.format(frappe.bold("Debit To")), title=_("Invalid Account"))
msg = _("Please ensure {} account is a Receivable account. ").format(frappe.bold("Debit To"))
msg += _("Change the account type to Receivable or select a different account.")
frappe.throw(msg, title=_("Invalid Account"))
self.party_account_currency = account.account_currency
@ -1141,8 +1141,10 @@ class SalesInvoice(SellingController):
where redeem_against=%s''', (lp_entry[0].name), as_dict=1)
if against_lp_entry:
invoice_list = ", ".join([d.invoice for d in against_lp_entry])
frappe.throw(_('''{} can't be cancelled since the Loyalty Points earned has been redeemed.
First cancel the {} No {}''').format(self.doctype, self.doctype, invoice_list))
frappe.throw(
_('''{} can't be cancelled since the Loyalty Points earned has been redeemed. First cancel the {} No {}''')
.format(self.doctype, self.doctype, invoice_list)
)
else:
frappe.db.sql('''delete from `tabLoyalty Point Entry` where invoice=%s''', (self.name))
# Set loyalty program
@ -1613,17 +1615,25 @@ def update_multi_mode_option(doc, pos_profile):
payment.type = payment_mode.type
doc.set('payments', [])
invalid_modes = []
for pos_payment_method in pos_profile.get('payments'):
pos_payment_method = pos_payment_method.as_dict()
payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
if not payment_mode:
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
.format(get_link_to_form("Mode of Payment", pos_payment_method.mode_of_payment)), title=_("Missing Account"))
invalid_modes.append(get_link_to_form("Mode of Payment", pos_payment_method.mode_of_payment))
continue
payment_mode[0].default = pos_payment_method.default
append_payment(payment_mode[0])
if invalid_modes:
if invalid_modes == 1:
msg = _("Please set default Cash or Bank account in Mode of Payment {}")
else:
msg = _("Please set default Cash or Bank account in Mode of Payments {}")
frappe.throw(msg.format(", ".join(invalid_modes)), title=_("Missing Account"))
def get_all_mode_of_payments(doc):
return frappe.db.sql("""
select mpa.default_account, mpa.parent, mp.type as type

View File

@ -307,7 +307,7 @@ def get_accounts(company, root_type):
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
def filter_accounts(accounts, depth=10):
def filter_accounts(accounts, depth=20):
parent_children_map = {}
accounts_by_name = {}
for d in accounts:

View File

@ -19,6 +19,8 @@ from erpnext.controllers.accounts_controller import update_child_qty_rate
from erpnext.controllers.status_updater import OverAllowanceError
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
from erpnext.stock.doctype.batch.test_batch import make_new_batch
from erpnext.controllers.buying_controller import get_backflushed_subcontracted_raw_materials
class TestPurchaseOrder(unittest.TestCase):
def test_make_purchase_receipt(self):
@ -686,7 +688,7 @@ class TestPurchaseOrder(unittest.TestCase):
def test_exploded_items_in_subcontracted(self):
item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code)
make_subcontracted_item(item_code=item_code)
po = create_purchase_order(item_code=item_code, qty=1,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=1)
@ -708,7 +710,7 @@ class TestPurchaseOrder(unittest.TestCase):
def test_backflush_based_on_stock_entry(self):
item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code)
make_subcontracted_item(item_code=item_code)
make_item('Sub Contracted Raw Material 1', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
@ -767,6 +769,129 @@ class TestPurchaseOrder(unittest.TestCase):
update_backflush_based_on("BOM")
def test_backflushed_based_on_for_multiple_batches(self):
item_code = "_Test Subcontracted FG Item 2"
make_item('Sub Contracted Raw Material 2', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
})
make_subcontracted_item(item_code=item_code, has_batch_no=1, create_new_batch=1,
raw_materials=["Sub Contracted Raw Material 2"])
update_backflush_based_on("Material Transferred for Subcontract")
order_qty = 500
po = create_purchase_order(item_code=item_code, qty=order_qty,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 2", qty=552, basic_rate=100)
rm_items = [
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 2","item_name":"_Test Item",
"qty":552,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"}]
rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
se.submit()
for batch in ["ABCD1", "ABCD2", "ABCD3", "ABCD4"]:
make_new_batch(batch_id=batch, item_code=item_code)
pr = make_purchase_receipt(po.name)
# partial receipt
pr.get('items')[0].qty = 30
pr.get('items')[0].batch_no = "ABCD1"
purchase_order = po.name
purchase_order_item = po.items[0].name
for batch_no, qty in {"ABCD2": 60, "ABCD3": 70, "ABCD4":40}.items():
pr.append("items", {
"item_code": pr.get('items')[0].item_code,
"item_name": pr.get('items')[0].item_name,
"uom": pr.get('items')[0].uom,
"stock_uom": pr.get('items')[0].stock_uom,
"warehouse": pr.get('items')[0].warehouse,
"conversion_factor": pr.get('items')[0].conversion_factor,
"cost_center": pr.get('items')[0].cost_center,
"rate": pr.get('items')[0].rate,
"qty": qty,
"batch_no": batch_no,
"purchase_order": purchase_order,
"purchase_order_item": purchase_order_item
})
pr.submit()
pr1 = make_purchase_receipt(po.name)
pr1.get('items')[0].qty = 300
pr1.get('items')[0].batch_no = "ABCD1"
pr1.save()
pr_key = ("Sub Contracted Raw Material 2", po.name)
consumed_qty = get_backflushed_subcontracted_raw_materials([po.name]).get(pr_key)
self.assertTrue(pr1.supplied_items[0].consumed_qty > 0)
self.assertTrue(pr1.supplied_items[0].consumed_qty, flt(552.0) - flt(consumed_qty))
update_backflush_based_on("BOM")
def test_supplied_qty_against_subcontracted_po(self):
item_code = "_Test Subcontracted FG Item 5"
make_item('Sub Contracted Raw Material 4', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
})
make_subcontracted_item(item_code=item_code, raw_materials=["Sub Contracted Raw Material 4"])
update_backflush_based_on("Material Transferred for Subcontract")
order_qty = 250
po = create_purchase_order(item_code=item_code, qty=order_qty,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", do_not_save=True)
# Add same subcontracted items multiple times
po.append("items", {
"item_code": item_code,
"qty": order_qty,
"schedule_date": add_days(nowdate(), 1),
"warehouse": "_Test Warehouse - _TC"
})
po.set_missing_values()
po.submit()
# Material receipt entry for the raw materials which will be send to supplier
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 4", qty=500, basic_rate=100)
rm_items = [
{
"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 4","item_name":"_Test Item",
"qty":250,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name
},
{
"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 4","item_name":"_Test Item",
"qty":250,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[1].name
},
]
# Raw Materials transfer entry from stores to supplier's warehouse
rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
se.submit()
po_doc = frappe.get_doc("Purchase Order", po.name)
for row in po_doc.supplied_items:
# Valid that whether transferred quantity is matching with supplied qty or not in the purchase order
self.assertEqual(row.supplied_qty, 250.0)
update_backflush_based_on("BOM")
def test_advance_payment_entry_unlink_against_purchase_order(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
frappe.db.set_value("Accounts Settings", "Accounts Settings",
@ -839,27 +964,33 @@ def make_pr_against_po(po, received_qty=0):
pr.submit()
return pr
def make_subcontracted_item(item_code):
def make_subcontracted_item(**args):
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
if not frappe.db.exists('Item', item_code):
make_item(item_code, {
args = frappe._dict(args)
if not frappe.db.exists('Item', args.item_code):
make_item(args.item_code, {
'is_stock_item': 1,
'is_sub_contracted_item': 1
'is_sub_contracted_item': 1,
'has_batch_no': args.get("has_batch_no") or 0
})
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
})
if not args.raw_materials:
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
})
if not frappe.db.get_value('BOM', {'item': item_code}, 'name'):
make_bom(item = item_code, raw_materials = ['_Test FG Item', 'Test Extra Item 1'])
args.raw_materials = ['_Test FG Item', 'Test Extra Item 1']
if not frappe.db.get_value('BOM', {'item': args.item_code}, 'name'):
make_bom(item = args.item_code, raw_materials = args.get("raw_materials"))
def update_backflush_based_on(based_on):
doc = frappe.get_doc('Buying Settings')

View File

@ -946,8 +946,10 @@ def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, c
company_currency = frappe.get_cached_value('Company', company, "default_currency")
if not conversion_rate:
throw(_("{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.").format(
conversion_rate_label, currency, company_currency))
throw(
_("{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.")
.format(conversion_rate_label, currency, company_currency)
)
def validate_taxes_and_charges(tax):

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import _, msgprint
from frappe.utils import flt,cint, cstr, getdate
from six import iteritems
from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
@ -112,8 +112,8 @@ class BuyingController(StockController):
"docstatus": 1
})]
if self.is_return and len(not_cancelled_asset):
frappe.throw(_("{} has submitted assets linked to it. You need to cancel the assets to create purchase return.".format(self.return_against)),
title=_("Not Allowed"))
frappe.throw(_("{} has submitted assets linked to it. You need to cancel the assets to create purchase return.")
.format(self.return_against), title=_("Not Allowed"))
def get_asset_items(self):
if self.doctype not in ['Purchase Order', 'Purchase Invoice', 'Purchase Receipt']:
@ -298,10 +298,10 @@ class BuyingController(StockController):
title=_("Limit Crossed"))
transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
# backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
for raw_material in transferred_raw_materials + non_stock_items:
rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order)
rm_item_key = (raw_material.rm_item_code, item.purchase_order)
raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
consumed_qty = raw_material_data.get('qty', 0)
@ -330,8 +330,10 @@ class BuyingController(StockController):
set_serial_nos(raw_material, consumed_serial_nos, qty)
if raw_material.batch_nos:
backflushed_batch_qty_map = raw_material_data.get('consumed_batch', {})
batches_qty = get_batches_with_qty(raw_material.rm_item_code, raw_material.main_item_code,
qty, transferred_batch_qty_map, backflushed_batch_qty_map)
qty, transferred_batch_qty_map, backflushed_batch_qty_map, item.purchase_order)
for batch_data in batches_qty:
qty = batch_data['qty']
raw_material.batch_no = batch_data['batch']
@ -343,6 +345,10 @@ class BuyingController(StockController):
rm = self.append('supplied_items', {})
rm.update(raw_material_data)
if not rm.main_item_code:
rm.main_item_code = fg_item_doc.item_code
rm.reference_name = fg_item_doc.name
rm.required_qty = qty
rm.consumed_qty = qty
@ -792,8 +798,8 @@ class BuyingController(StockController):
asset.set(field, None)
asset.supplier = None
if asset.docstatus == 1 and delete_asset:
frappe.throw(_('Cannot cancel this document as it is linked with submitted asset {0}.\
Please cancel the it to continue.').format(frappe.utils.get_link_to_form('Asset', asset.name)))
frappe.throw(_('Cannot cancel this document as it is linked with submitted asset {0}. Please cancel it to continue.')
.format(frappe.utils.get_link_to_form('Asset', asset.name)))
asset.flags.ignore_validate_update_after_submit = True
asset.flags.ignore_mandatory = True
@ -873,7 +879,7 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND IFNULL(sed.t_warehouse, '') != ''
AND sed.subcontracted_item = %s
AND IFNULL(sed.subcontracted_item, '') in ('', %s)
GROUP BY sed.item_code, sed.subcontracted_item
"""
raw_materials = frappe.db.multisql({
@ -890,39 +896,49 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
return raw_materials
def get_backflushed_subcontracted_raw_materials(purchase_orders):
common_query = """
SELECT
CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key,
SUM(prsi.consumed_qty) AS qty,
{serial_no_concat_syntax} AS serial_nos,
{batch_no_concat_syntax} AS batch_nos
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi
WHERE
pr.name = pri.parent
AND pr.name = prsi.parent
AND pri.purchase_order IN %s
AND pri.item_code = prsi.main_item_code
AND pr.docstatus = 1
GROUP BY prsi.rm_item_code, pri.purchase_order
"""
purchase_receipts = frappe.get_all("Purchase Receipt Item",
fields = ["purchase_order", "item_code", "name", "parent"],
filters={"docstatus": 1, "purchase_order": ("in", list(purchase_orders))})
backflushed_raw_materials = frappe.db.multisql({
'mariadb': common_query.format(
serial_no_concat_syntax="GROUP_CONCAT(prsi.serial_no)",
batch_no_concat_syntax="GROUP_CONCAT(prsi.batch_no)"
),
'postgres': common_query.format(
serial_no_concat_syntax="STRING_AGG(prsi.serial_no, ',')",
batch_no_concat_syntax="STRING_AGG(prsi.batch_no, ',')"
)
}, (purchase_orders, ), as_dict=1)
distinct_purchase_receipts = {}
for pr in purchase_receipts:
key = (pr.purchase_order, pr.item_code, pr.parent)
distinct_purchase_receipts.setdefault(key, []).append(pr.name)
backflushed_raw_materials_map = frappe._dict()
for item in backflushed_raw_materials:
backflushed_raw_materials_map.setdefault(item.item_key, item)
for args, references in iteritems(distinct_purchase_receipts):
purchase_receipt_supplied_items = get_supplied_items(args[1], args[2], references)
for data in purchase_receipt_supplied_items:
pr_key = (data.rm_item_code, args[0])
if pr_key not in backflushed_raw_materials_map:
backflushed_raw_materials_map.setdefault(pr_key, frappe._dict({
"qty": 0.0,
"serial_no": [],
"batch_no": [],
"consumed_batch": {}
}))
row = backflushed_raw_materials_map.get(pr_key)
row.qty += data.consumed_qty
for field in ["serial_no", "batch_no"]:
if data.get(field):
row[field].append(data.get(field))
if data.get("batch_no"):
if data.get("batch_no") in row.consumed_batch:
row.consumed_batch[data.get("batch_no")] += data.consumed_qty
else:
row.consumed_batch[data.get("batch_no")] = data.consumed_qty
return backflushed_raw_materials_map
def get_supplied_items(item_code, purchase_receipt, references):
return frappe.get_all("Purchase Receipt Item Supplied",
fields=["rm_item_code", "consumed_qty", "serial_no", "batch_no"],
filters={"main_item_code": item_code, "parent": purchase_receipt, "reference_name": ("in", references)})
def get_asset_item_details(asset_items):
asset_items_data = {}
for d in frappe.get_all('Item', fields = ["name", "auto_create_assets", "asset_naming_series"],
@ -1004,14 +1020,15 @@ def get_transferred_batch_qty_map(purchase_order, fg_item):
SELECT
sed.batch_no,
SUM(sed.qty) AS qty,
sed.item_code
sed.item_code,
sed.subcontracted_item
FROM `tabStock Entry` se,`tabStock Entry Detail` sed
WHERE
se.name = sed.parent
AND se.docstatus=1
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND sed.subcontracted_item = %s
AND ifnull(sed.subcontracted_item, '') in ('', %s)
AND sed.batch_no IS NOT NULL
GROUP BY
sed.batch_no,
@ -1019,8 +1036,10 @@ def get_transferred_batch_qty_map(purchase_order, fg_item):
""", (purchase_order, fg_item), as_dict=1)
for batch_data in transferred_batches:
transferred_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
transferred_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
key = ((batch_data.item_code, fg_item)
if batch_data.subcontracted_item else (batch_data.item_code, purchase_order))
transferred_batch_qty_map.setdefault(key, {})
transferred_batch_qty_map[key][batch_data.batch_no] = batch_data.qty
return transferred_batch_qty_map
@ -1057,10 +1076,11 @@ def get_backflushed_batch_qty_map(purchase_order, fg_item):
return backflushed_batch_qty_map
def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batch_qty_map):
def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batches, po):
# Returns available batches to be backflushed based on requirements
transferred_batches = transferred_batch_qty_map.get((item_code, fg_item), {})
backflushed_batches = backflushed_batch_qty_map.get((item_code, fg_item), {})
if not transferred_batches:
transferred_batches = transferred_batch_qty_map.get((item_code, po), {})
available_batches = []

View File

@ -49,6 +49,22 @@ data = {
'fieldname': 'reference_dn', 'label': 'Reference Name', 'fieldtype': 'Dynamic Link', 'options': 'reference_dt',
'insert_after': 'reference_dt'
}
],
'Stock Entry': [
{
'fieldname': 'inpatient_medication_entry', 'label': 'Inpatient Medication Entry', 'fieldtype': 'Link', 'options': 'Inpatient Medication Entry',
'insert_after': 'credit_note', 'read_only': True
}
],
'Stock Entry Detail': [
{
'fieldname': 'patient', 'label': 'Patient', 'fieldtype': 'Link', 'options': 'Patient',
'insert_after': 'po_detail', 'read_only': True
},
{
'fieldname': 'inpatient_medication_entry_child', 'label': 'Inpatient Medication Entry Child', 'fieldtype': 'Data',
'insert_after': 'patient', 'read_only': True
}
]
},
'on_setup': 'erpnext.healthcare.setup.setup_healthcare'

View File

@ -7,7 +7,7 @@ import frappe
import json
from frappe import _
from frappe.model.mapper import get_mapped_doc
from frappe.utils import flt, cstr
from frappe.utils import flt, cstr, getdate
from frappe.email.doctype.email_group.email_group import add_subscribers
def get_course(program):
@ -67,6 +67,13 @@ def mark_attendance(students_present, students_absent, course_schedule=None, stu
:param date: Date.
"""
if student_group:
academic_year = frappe.db.get_value('Student Group', student_group, 'academic_year')
if academic_year:
year_start_date, year_end_date = frappe.db.get_value('Academic Year', academic_year, ['year_start_date', 'year_end_date'])
if getdate(date) < getdate(year_start_date) or getdate(date) > getdate(year_end_date):
frappe.throw(_('Attendance cannot be marked outside of Academic Year {0}').format(academic_year))
present = json.loads(students_present)
absent = json.loads(students_absent)

View File

@ -30,6 +30,23 @@ frappe.ui.form.on('Assessment Plan', {
frappe.set_route('Form', 'Assessment Result Tool');
}, __('Tools'));
}
frm.set_query('course', function() {
return {
query: 'erpnext.education.doctype.program_enrollment.program_enrollment.get_program_courses',
filters: {
'program': frm.doc.program
}
};
});
frm.set_query('academic_term', function() {
return {
filters: {
'academic_year': frm.doc.academic_year
}
};
});
},
course: function(frm) {

View File

@ -12,8 +12,8 @@
"assessment_group",
"grading_scale",
"column_break_2",
"course",
"program",
"course",
"academic_year",
"academic_term",
"section_break_5",
@ -198,7 +198,7 @@
],
"is_submittable": 1,
"links": [],
"modified": "2020-05-09 14:56:26.746988",
"modified": "2020-10-23 15:55:35.076251",
"modified_by": "Administrator",
"module": "Education",
"name": "Assessment Plan",

View File

@ -7,6 +7,23 @@ frappe.ui.form.on('Assessment Result', {
frm.trigger('setup_chart');
}
frm.set_df_property('details', 'read_only', 1);
frm.set_query('course', function() {
return {
query: 'erpnext.education.doctype.program_enrollment.program_enrollment.get_program_courses',
filters: {
'program': frm.doc.program
}
};
});
frm.set_query('academic_term', function() {
return {
filters: {
'academic_year': frm.doc.academic_year
}
};
});
},
onload: function(frm) {

View File

@ -41,5 +41,24 @@ frappe.ui.form.on("Instructor", {
}
};
});
frm.set_query("academic_term", "instructor_log", function(_doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: {
"academic_year": d.academic_year
}
};
});
frm.set_query("course", "instructor_log", function(_doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
query: "erpnext.education.doctype.program_enrollment.program_enrollment.get_program_courses",
filters: {
"program": d.program
}
};
});
}
});

View File

@ -1,336 +1,88 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-12-27 08:55:52.680284",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"creation": "2017-12-27 08:55:52.680284",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"academic_year",
"academic_term",
"department",
"column_break_3",
"program",
"course",
"student_group",
"section_break_8",
"other_details"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Academic Year",
"length": 0,
"no_copy": 0,
"options": "Academic Year",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "academic_year",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Academic Year",
"options": "Academic Year",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Academic Term",
"length": 0,
"no_copy": 0,
"options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "academic_term",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Academic Term",
"options": "Academic Term"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Department",
"length": 0,
"no_copy": 0,
"options": "Department",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "department",
"fieldtype": "Link",
"label": "Department",
"options": "Department"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "program",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Program",
"length": 0,
"no_copy": 0,
"options": "Program",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "program",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Program",
"options": "Program",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Course",
"length": 0,
"no_copy": 0,
"options": "Course",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "course",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Course",
"options": "Course"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Student Group",
"length": 0,
"no_copy": 0,
"options": "Student Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "student_group",
"fieldtype": "Link",
"label": "Student Group",
"options": "Student Group"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "section_break_8",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "other_details",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Other details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldname": "other_details",
"fieldtype": "Small Text",
"label": "Other details"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-11-04 03:38:30.902942",
"modified_by": "Administrator",
"module": "Education",
"name": "Instructor Log",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
],
"istable": 1,
"links": [],
"modified": "2020-10-23 15:15:50.759657",
"modified_by": "Administrator",
"module": "Education",
"name": "Instructor Log",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"restrict_to_domain": "Education",
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -6,13 +6,13 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.utils import get_link_to_form
from frappe.utils import get_link_to_form, getdate
from erpnext.education.api import get_student_group_students
class StudentAttendance(Document):
def validate(self):
self.validate_mandatory()
self.validate_date()
self.set_date()
self.set_student_group()
self.validate_student()
@ -27,6 +27,18 @@ class StudentAttendance(Document):
frappe.throw(_('{0} or {1} is mandatory').format(frappe.bold('Student Group'),
frappe.bold('Course Schedule')), title=_('Mandatory Fields'))
def validate_date(self):
if not self.leave_application and getdate(self.date) > getdate():
frappe.throw(_('Attendance cannot be marked for future dates.'))
if self.student_group:
academic_year = frappe.db.get_value('Student Group', self.student_group, 'academic_year')
if academic_year:
year_start_date, year_end_date = frappe.db.get_value('Academic Year', academic_year, ['year_start_date', 'year_end_date'])
if year_start_date and year_end_date:
if getdate(self.date) < getdate(year_start_date) or getdate(self.date) > getdate(year_end_date):
frappe.throw(_('Attendance cannot be marked outside of Academic Year {0}').format(academic_year))
def set_student_group(self):
if self.course_schedule:
self.student_group = frappe.db.get_value('Course Schedule', self.course_schedule, 'student_group')

View File

@ -52,6 +52,8 @@ frappe.ui.form.on('Student Attendance Tool', {
},
date: function(frm) {
if (frm.doc.date > frappe.datetime.get_today())
frappe.throw(__("Cannot mark attendance for future dates."));
frm.trigger("student_group");
},
@ -133,8 +135,8 @@ education.StudentsEditor = Class.extend({
return !stud.disabled && !stud.checked;
});
frappe.confirm(__("Do you want to update attendance?<br>Present: {0}\
<br>Absent: {1}", [students_present.length, students_absent.length]),
frappe.confirm(__("Do you want to update attendance? <br> Present: {0} <br> Absent: {1}",
[students_present.length, students_absent.length]),
function() { //ifyes
if(!frappe.request.ajax_count) {
frappe.call({

View File

@ -1,333 +1,118 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-11-16 17:12:46.437539",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"allow_copy": 1,
"creation": "2016-11-16 17:12:46.437539",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"based_on",
"group_based_on",
"column_break_2",
"student_group",
"academic_year",
"academic_term",
"course_schedule",
"date",
"attendance",
"students_html"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "based_on",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Based On",
"length": 0,
"no_copy": 0,
"options": "Student Group\nCourse Schedule",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "based_on",
"fieldtype": "Select",
"label": "Based On",
"options": "Student Group\nCourse Schedule"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Batch",
"depends_on": "eval:doc.based_on == \"Student Group\"",
"fieldname": "group_based_on",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Group Based On",
"length": 0,
"no_copy": 0,
"options": "Batch\nCourse\nActivity",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "Batch",
"depends_on": "eval:doc.based_on == \"Student Group\"",
"fieldname": "group_based_on",
"fieldtype": "Select",
"label": "Group Based On",
"options": "Batch\nCourse\nActivity"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "column_break_2",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.based_on ==\"Student Group\"",
"fieldname": "student_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Student Group",
"length": 0,
"no_copy": 0,
"options": "Student Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"depends_on": "eval:doc.based_on ==\"Student Group\"",
"fieldname": "student_group",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Student Group",
"options": "Student Group",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.based_on ==\"Course Schedule\"",
"fieldname": "course_schedule",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Course Schedule",
"length": 0,
"no_copy": 0,
"options": "Course Schedule",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"depends_on": "eval:doc.based_on ==\"Course Schedule\"",
"fieldname": "course_schedule",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Course Schedule",
"options": "Course Schedule",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.based_on ==\"Student Group\"",
"fieldname": "date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"depends_on": "eval:doc.based_on ==\"Student Group\"",
"fieldname": "date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Date",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval: (doc.course_schedule \n|| (doc.student_group && doc.date))",
"fieldname": "attendance",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Attendance",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"depends_on": "eval: (doc.course_schedule \n|| (doc.student_group && doc.date))",
"fieldname": "attendance",
"fieldtype": "Section Break",
"label": "Attendance"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "students_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Students HTML",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "students_html",
"fieldtype": "HTML",
"label": "Students HTML"
},
{
"fetch_from": "student_group.academic_year",
"fieldname": "academic_year",
"fieldtype": "Link",
"label": "Academic Year",
"options": "Academic Year",
"read_only": 1
},
{
"fetch_from": "student_group.academic_term",
"fieldname": "academic_term",
"fieldtype": "Link",
"label": "Academic Term",
"options": "Academic Term",
"read_only": 1
}
],
"has_web_view": 0,
"hide_heading": 1,
"hide_toolbar": 1,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-11-10 18:55:36.168044",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Attendance Tool",
"name_case": "",
"owner": "Administrator",
],
"hide_toolbar": 1,
"issingle": 1,
"links": [],
"modified": "2020-10-23 17:52:28.078971",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Attendance Tool",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Instructor",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"create": 1,
"read": 1,
"role": "Instructor",
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Academics User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"create": 1,
"read": 1,
"role": "Academics User",
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
],
"restrict_to_domain": "Education",
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -43,7 +43,8 @@
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Dosage",
"options": "Prescription Dosage"
"options": "Prescription Dosage",
"reqd": 1
},
{
"fieldname": "period",
@ -51,14 +52,16 @@
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Period",
"options": "Prescription Duration"
"options": "Prescription Duration",
"reqd": 1
},
{
"fieldname": "dosage_form",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Dosage Form",
"options": "Dosage Form"
"options": "Dosage Form",
"reqd": 1
},
{
"fieldname": "column_break_7",
@ -72,7 +75,7 @@
"label": "Comment"
},
{
"depends_on": "use_interval",
"depends_on": "usage_interval",
"fieldname": "interval",
"fieldtype": "Int",
"in_list_view": 1,
@ -80,6 +83,7 @@
},
{
"default": "1",
"depends_on": "usage_interval",
"fieldname": "update_schedule",
"fieldtype": "Check",
"hidden": 1,
@ -99,12 +103,13 @@
"default": "0",
"fieldname": "usage_interval",
"fieldtype": "Check",
"hidden": 1,
"label": "Dosage by Time Interval"
}
],
"istable": 1,
"links": [],
"modified": "2020-02-26 17:02:42.741338",
"modified": "2020-09-30 23:32:09.495288",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Drug Prescription",

View File

@ -0,0 +1,37 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Inpatient Medication Entry', {
refresh: function(frm) {
// Ignore cancellation of doctype on cancel all
frm.ignore_doctypes_on_cancel_all = ['Stock Entry'];
frm.set_query('item_code', () => {
return {
filters: {
is_stock_item: 1
}
};
});
frm.set_query('drug_code', 'medication_orders', () => {
return {
filters: {
is_stock_item: 1
}
};
});
},
get_medication_orders: function(frm) {
frappe.call({
method: 'get_medication_orders',
doc: frm.doc,
freeze: true,
freeze_message: __('Fetching Pending Medication Orders'),
callback: function() {
refresh_field('medication_orders');
}
});
}
});

View File

@ -0,0 +1,203 @@
{
"actions": [],
"autoname": "naming_series:",
"creation": "2020-09-25 14:13:20.111906",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"naming_series",
"company",
"column_break_3",
"posting_date",
"status",
"filters_section",
"item_code",
"assigned_to_practitioner",
"patient",
"practitioner",
"service_unit",
"column_break_11",
"from_date",
"to_date",
"from_time",
"to_time",
"select_medication_orders_section",
"get_medication_orders",
"medication_orders",
"section_break_18",
"update_stock",
"warehouse",
"amended_from"
],
"fields": [
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"options": "HLC-IME-.YYYY.-"
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"options": "Company",
"reqd": 1
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "posting_date",
"fieldtype": "Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Posting Date",
"reqd": 1
},
{
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"options": "\nDraft\nSubmitted\nPending\nIn Process\nCompleted\nCancelled",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "filters_section",
"fieldtype": "Section Break",
"label": "Filters"
},
{
"fieldname": "item_code",
"fieldtype": "Link",
"label": "Item Code (Drug)",
"options": "Item"
},
{
"depends_on": "update_stock",
"description": "Warehouse from where medication stock should be consumed",
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "Medication Warehouse",
"mandatory_depends_on": "update_stock",
"options": "Warehouse"
},
{
"fieldname": "patient",
"fieldtype": "Link",
"label": "Patient",
"options": "Patient"
},
{
"fieldname": "service_unit",
"fieldtype": "Link",
"label": "Healthcare Service Unit",
"options": "Healthcare Service Unit"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"fieldname": "from_date",
"fieldtype": "Date",
"label": "From Date"
},
{
"fieldname": "to_date",
"fieldtype": "Date",
"label": "To Date"
},
{
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Inpatient Medication Entry",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "practitioner",
"fieldtype": "Link",
"label": "Healthcare Practitioner",
"options": "Healthcare Practitioner"
},
{
"fieldname": "select_medication_orders_section",
"fieldtype": "Section Break",
"label": "Medication Orders"
},
{
"fieldname": "medication_orders",
"fieldtype": "Table",
"label": "Inpatient Medication Orders",
"options": "Inpatient Medication Entry Detail",
"read_only": 1,
"reqd": 1
},
{
"depends_on": "eval:doc.docstatus!==1",
"fieldname": "get_medication_orders",
"fieldtype": "Button",
"label": "Get Pending Medication Orders",
"print_hide": 1
},
{
"fieldname": "assigned_to_practitioner",
"fieldtype": "Link",
"label": "Assigned To",
"options": "User"
},
{
"fieldname": "section_break_18",
"fieldtype": "Section Break",
"label": "Stock Details"
},
{
"default": "1",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock"
},
{
"fieldname": "from_time",
"fieldtype": "Time",
"label": "From Time"
},
{
"fieldname": "to_time",
"fieldtype": "Time",
"label": "To Time"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2020-09-30 23:40:45.528715",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Inpatient Medication Entry",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,273 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import flt, get_link_to_form, getdate, nowtime
from erpnext.stock.utils import get_latest_stock_qty
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account
class InpatientMedicationEntry(Document):
def validate(self):
self.validate_medication_orders()
def get_medication_orders(self):
self.validate_datetime_filters()
# pull inpatient medication orders based on selected filters
orders = get_pending_medication_orders(self)
if orders:
self.add_mo_to_table(orders)
return self
else:
self.set('medication_orders', [])
frappe.msgprint(_('No pending medication orders found for selected criteria'))
def validate_datetime_filters(self):
if self.from_date and self.to_date:
self.validate_from_to_dates('from_date', 'to_date')
if self.from_date and getdate(self.from_date) > getdate():
frappe.throw(_('From Date cannot be after the current date.'))
if self.to_date and getdate(self.to_date) > getdate():
frappe.throw(_('To Date cannot be after the current date.'))
if self.from_time and self.from_time > nowtime():
frappe.throw(_('From Time cannot be after the current time.'))
if self.to_time and self.to_time > nowtime():
frappe.throw(_('To Time cannot be after the current time.'))
def add_mo_to_table(self, orders):
# Add medication orders in the child table
self.set('medication_orders', [])
for data in orders:
self.append('medication_orders', {
'patient': data.patient,
'patient_name': data.patient_name,
'inpatient_record': data.inpatient_record,
'service_unit': data.service_unit,
'datetime': "%s %s" % (data.date, data.time or "00:00:00"),
'drug_code': data.drug,
'drug_name': data.drug_name,
'dosage': data.dosage,
'dosage_form': data.dosage_form,
'against_imo': data.parent,
'against_imoe': data.name
})
def on_submit(self):
self.validate_medication_orders()
success_msg = ""
if self.update_stock:
stock_entry = self.process_stock()
success_msg += _('Stock Entry {0} created and ').format(
frappe.bold(get_link_to_form('Stock Entry', stock_entry)))
self.update_medication_orders()
success_msg += _('Inpatient Medication Orders updated successfully')
frappe.msgprint(success_msg, title=_('Success'), indicator='green')
def validate_medication_orders(self):
for entry in self.medication_orders:
docstatus, is_completed = frappe.db.get_value('Inpatient Medication Order Entry', entry.against_imoe,
['docstatus', 'is_completed'])
if docstatus == 2:
frappe.throw(_('Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1}').format(
entry.idx, get_link_to_form(entry.against_imo)))
if is_completed:
frappe.throw(_('Row {0}: This Medication Order is already marked as completed').format(
entry.idx))
def on_cancel(self):
self.cancel_stock_entries()
self.update_medication_orders(on_cancel=True)
def process_stock(self):
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
if not allow_negative_stock:
self.check_stock_qty()
return self.make_stock_entry()
def update_medication_orders(self, on_cancel=False):
orders, order_entry_map = self.get_order_entry_map()
# mark completion status
is_completed = 1
if on_cancel:
is_completed = 0
frappe.db.sql("""
UPDATE `tabInpatient Medication Order Entry`
SET is_completed = %(is_completed)s
WHERE name IN %(orders)s
""", {'orders': orders, 'is_completed': is_completed})
# update status and completed orders count
for order, count in order_entry_map.items():
medication_order = frappe.get_doc('Inpatient Medication Order', order)
completed_orders = flt(count)
current_value = frappe.db.get_value('Inpatient Medication Order', order, 'completed_orders')
if on_cancel:
completed_orders = flt(current_value) - flt(count)
else:
completed_orders = flt(current_value) + flt(count)
medication_order.db_set('completed_orders', completed_orders)
medication_order.set_status()
def get_order_entry_map(self):
# for marking order completion status
orders = []
# orders mapped
order_entry_map = dict()
for entry in self.medication_orders:
orders.append(entry.against_imoe)
parent = entry.against_imo
if not order_entry_map.get(parent):
order_entry_map[parent] = 0
order_entry_map[parent] += 1
return orders, order_entry_map
def check_stock_qty(self):
from erpnext.stock.stock_ledger import NegativeStockError
drug_availability = dict()
for d in self.medication_orders:
if not drug_availability.get(d.drug_code):
drug_availability[d.drug_code] = 0
drug_availability[d.drug_code] += flt(d.dosage)
for drug, dosage in drug_availability.items():
available_qty = get_latest_stock_qty(drug, self.warehouse)
# validate qty
if flt(available_qty) < flt(dosage):
frappe.throw(_('Quantity not available for {0} in warehouse {1}').format(
frappe.bold(drug), frappe.bold(self.warehouse))
+ '<br><br>' + _('Available quantity is {0}, you need {1}').format(
frappe.bold(available_qty), frappe.bold(dosage))
+ '<br><br>' + _('Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.'),
NegativeStockError, title=_('Insufficient Stock'))
def make_stock_entry(self):
stock_entry = frappe.new_doc('Stock Entry')
stock_entry.purpose = 'Material Issue'
stock_entry.set_stock_entry_type()
stock_entry.from_warehouse = self.warehouse
stock_entry.company = self.company
stock_entry.inpatient_medication_entry = self.name
cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
for entry in self.medication_orders:
se_child = stock_entry.append('items')
se_child.item_code = entry.drug_code
se_child.item_name = entry.drug_name
se_child.uom = frappe.db.get_value('Item', entry.drug_code, 'stock_uom')
se_child.stock_uom = se_child.uom
se_child.qty = flt(entry.dosage)
# in stock uom
se_child.conversion_factor = 1
se_child.cost_center = cost_center
se_child.expense_account = expense_account
# references
se_child.patient = entry.patient
se_child.inpatient_medication_entry_child = entry.name
stock_entry.submit()
return stock_entry.name
def cancel_stock_entries(self):
stock_entries = frappe.get_all('Stock Entry', {'inpatient_medication_entry': self.name})
for entry in stock_entries:
doc = frappe.get_doc('Stock Entry', entry.name)
doc.cancel()
def get_pending_medication_orders(entry):
filters, values = get_filters(entry)
data = frappe.db.sql("""
SELECT
ip.inpatient_record, ip.patient, ip.patient_name,
entry.name, entry.parent, entry.drug, entry.drug_name,
entry.dosage, entry.dosage_form, entry.date, entry.time, entry.instructions
FROM
`tabInpatient Medication Order` ip
INNER JOIN
`tabInpatient Medication Order Entry` entry
ON
ip.name = entry.parent
WHERE
ip.docstatus = 1 and
ip.company = %(company)s and
entry.is_completed = 0
{0}
ORDER BY
entry.date, entry.time
""".format(filters), values, as_dict=1)
for doc in data:
inpatient_record = doc.inpatient_record
doc['service_unit'] = get_current_healthcare_service_unit(inpatient_record)
if entry.service_unit and doc.service_unit != entry.service_unit:
data.remove(doc)
return data
def get_filters(entry):
filters = ''
values = dict(company=entry.company)
if entry.from_date:
filters += ' and entry.date >= %(from_date)s'
values['from_date'] = entry.from_date
if entry.to_date:
filters += ' and entry.date <= %(to_date)s'
values['to_date'] = entry.to_date
if entry.from_time:
filters += ' and entry.time >= %(from_time)s'
values['from_time'] = entry.from_time
if entry.to_time:
filters += ' and entry.time <= %(to_time)s'
values['to_time'] = entry.to_time
if entry.patient:
filters += ' and ip.patient = %(patient)s'
values['patient'] = entry.patient
if entry.practitioner:
filters += ' and ip.practitioner = %(practitioner)s'
values['practitioner'] = entry.practitioner
if entry.item_code:
filters += ' and entry.drug = %(item_code)s'
values['item_code'] = entry.item_code
if entry.assigned_to_practitioner:
filters += ' and ip._assign LIKE %(assigned_to)s'
values['assigned_to'] = '%' + entry.assigned_to_practitioner + '%'
return filters, values
def get_current_healthcare_service_unit(inpatient_record):
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
return ip_record.inpatient_occupancies[-1].service_unit

View File

@ -0,0 +1,16 @@
from __future__ import unicode_literals
from frappe import _
def get_data():
return {
'fieldname': 'against_imoe',
'internal_links': {
'Inpatient Medication Order': ['medication_orders', 'against_imo']
},
'transactions': [
{
'label': _('Reference'),
'items': ['Inpatient Medication Order']
}
]
}

View File

@ -0,0 +1,125 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import add_days, getdate, now_datetime
from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import create_ipmo, create_ipme
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account
class TestInpatientMedicationEntry(unittest.TestCase):
def setUp(self):
frappe.db.sql("""delete from `tabInpatient Record`""")
frappe.db.sql("""delete from `tabInpatient Medication Order`""")
frappe.db.sql("""delete from `tabInpatient Medication Entry`""")
self.patient = create_patient()
# Admit
ip_record = create_inpatient(self.patient)
ip_record.expected_length_of_stay = 0
ip_record.save()
ip_record.reload()
service_unit = get_healthcare_service_unit()
admit_patient(ip_record, service_unit, now_datetime())
self.ip_record = ip_record
def test_filters_for_fetching_pending_mo(self):
ipmo = create_ipmo(self.patient)
ipmo.submit()
ipmo.reload()
date = add_days(getdate(), -1)
filters = frappe._dict(
from_date=date,
to_date=date,
from_time='',
to_time='',
item_code='Dextromethorphan',
patient=self.patient
)
ipme = create_ipme(filters, update_stock=0)
# 3 dosages per day
self.assertEqual(len(ipme.medication_orders), 3)
self.assertEqual(getdate(ipme.medication_orders[0].datetime), date)
def test_ipme_with_stock_update(self):
ipmo = create_ipmo(self.patient)
ipmo.submit()
ipmo.reload()
date = add_days(getdate(), -1)
filters = frappe._dict(
from_date=date,
to_date=date,
from_time='',
to_time='',
item_code='Dextromethorphan',
patient=self.patient
)
make_stock_entry()
ipme = create_ipme(filters, update_stock=1)
ipme.submit()
ipme.reload()
# test order completed
is_order_completed = frappe.db.get_value('Inpatient Medication Order Entry',
ipme.medication_orders[0].against_imoe, 'is_completed')
self.assertEqual(is_order_completed, 1)
# test stock entry
stock_entry = frappe.db.exists('Stock Entry', {'inpatient_medication_entry': ipme.name})
self.assertTrue(stock_entry)
# check references
stock_entry = frappe.get_doc('Stock Entry', stock_entry)
self.assertEqual(stock_entry.items[0].patient, self.patient)
self.assertEqual(stock_entry.items[0].inpatient_medication_entry_child, ipme.medication_orders[0].name)
def tearDown(self):
# cleanup - Discharge
schedule_discharge(frappe.as_json({'patient': self.patient}))
self.ip_record.reload()
mark_invoiced_inpatient_occupancy(self.ip_record)
self.ip_record.reload()
discharge_patient(self.ip_record)
for entry in frappe.get_all('Inpatient Medication Entry'):
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
doc.cancel()
frappe.db.delete('Stock Entry', {'inpatient_medication_entry': doc.name})
doc.delete()
for entry in frappe.get_all('Inpatient Medication Order'):
doc = frappe.get_doc('Inpatient Medication Order', entry.name)
doc.cancel()
doc.delete()
def make_stock_entry():
frappe.db.set_value('Company', '_Test Company', {
'stock_adjustment_account': 'Stock Adjustment - _TC',
'default_inventory_account': 'Stock In Hand - _TC'
})
stock_entry = frappe.new_doc('Stock Entry')
stock_entry.stock_entry_type = 'Material Receipt'
stock_entry.company = '_Test Company'
stock_entry.to_warehouse = 'Stores - _TC'
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', '_Test Company')
se_child = stock_entry.append('items')
se_child.item_code = 'Dextromethorphan'
se_child.item_name = 'Dextromethorphan'
se_child.uom = 'Nos'
se_child.stock_uom = 'Nos'
se_child.qty = 6
se_child.t_warehouse = 'Stores - _TC'
# in stock uom
se_child.conversion_factor = 1.0
se_child.expense_account = expense_account
stock_entry.submit()

View File

@ -0,0 +1,163 @@
{
"actions": [],
"creation": "2020-09-25 14:56:32.636569",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"patient",
"patient_name",
"inpatient_record",
"column_break_4",
"service_unit",
"datetime",
"medication_details_section",
"drug_code",
"drug_name",
"dosage",
"available_qty",
"dosage_form",
"column_break_10",
"instructions",
"references_section",
"against_imo",
"against_imoe"
],
"fields": [
{
"columns": 2,
"fieldname": "patient",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Patient",
"options": "Patient",
"reqd": 1
},
{
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"fieldtype": "Data",
"label": "Patient Name",
"read_only": 1
},
{
"columns": 2,
"fieldname": "drug_code",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Drug Code",
"options": "Item",
"reqd": 1
},
{
"fetch_from": "drug_code.item_name",
"fieldname": "drug_name",
"fieldtype": "Data",
"label": "Drug Name",
"read_only": 1
},
{
"columns": 1,
"fieldname": "dosage",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Dosage",
"reqd": 1
},
{
"fieldname": "dosage_form",
"fieldtype": "Link",
"label": "Dosage Form",
"options": "Dosage Form"
},
{
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"fieldtype": "Link",
"label": "Inpatient Record",
"options": "Inpatient Record",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "references_section",
"fieldtype": "Section Break",
"label": "References"
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"fieldname": "medication_details_section",
"fieldtype": "Section Break",
"label": "Medication Details"
},
{
"fieldname": "column_break_10",
"fieldtype": "Column Break"
},
{
"columns": 3,
"fieldname": "datetime",
"fieldtype": "Datetime",
"in_list_view": 1,
"label": "Datetime",
"reqd": 1
},
{
"fieldname": "instructions",
"fieldtype": "Small Text",
"label": "Instructions"
},
{
"columns": 2,
"fieldname": "service_unit",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Service Unit",
"options": "Healthcare Service Unit",
"read_only": 1,
"reqd": 1
},
{
"fieldname": "against_imo",
"fieldtype": "Link",
"label": "Against Inpatient Medication Order",
"no_copy": 1,
"options": "Inpatient Medication Order",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "against_imoe",
"fieldtype": "Data",
"label": "Against Inpatient Medication Order Entry",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "available_qty",
"fieldtype": "Float",
"hidden": 1,
"label": "Available Qty",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-09-30 14:48:23.648223",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Inpatient Medication Entry Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class InpatientMedicationEntryDetail(Document):
pass

View File

@ -0,0 +1,106 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Inpatient Medication Order', {
refresh: function(frm) {
if (frm.doc.docstatus === 1) {
frm.trigger("show_progress");
}
frm.events.show_medication_order_button(frm);
frm.set_query('patient', () => {
return {
filters: {
'inpatient_record': ['!=', '']
}
};
});
},
show_medication_order_button: function(frm) {
frm.fields_dict['medication_orders'].grid.wrapper.find('.grid-add-row').hide();
frm.fields_dict['medication_orders'].grid.add_custom_button(__('Add Medication Orders'), () => {
let d = new frappe.ui.Dialog({
title: __('Add Medication Orders'),
fields: [
{
fieldname: 'drug_code',
label: __('Drug'),
fieldtype: 'Link',
options: 'Item',
reqd: 1,
"get_query": function () {
return {
filters: {'is_stock_item': 1}
};
}
},
{
fieldname: 'dosage',
label: __('Dosage'),
fieldtype: 'Link',
options: 'Prescription Dosage',
reqd: 1
},
{
fieldname: 'period',
label: __('Period'),
fieldtype: 'Link',
options: 'Prescription Duration',
reqd: 1
},
{
fieldname: 'dosage_form',
label: __('Dosage Form'),
fieldtype: 'Link',
options: 'Dosage Form',
reqd: 1
}
],
primary_action_label: __('Add'),
primary_action: () => {
let values = d.get_values();
if (values) {
frm.call({
doc: frm.doc,
method: 'add_order_entries',
args: {
order: values
},
freeze: true,
freeze_message: __('Adding Order Entries'),
callback: function() {
frm.refresh_field('medication_orders');
}
});
}
},
});
d.show();
});
},
show_progress: function(frm) {
let bars = [];
let message = '';
// completed sessions
let title = __('{0} medication orders completed', [frm.doc.completed_orders]);
if (frm.doc.completed_orders === 1) {
title = __('{0} medication order completed', [frm.doc.completed_orders]);
}
title += __(' out of {0}', [frm.doc.total_orders]);
bars.push({
'title': title,
'width': (frm.doc.completed_orders / frm.doc.total_orders * 100) + '%',
'progress_class': 'progress-bar-success'
});
if (bars[0].width == '0%') {
bars[0].width = '0.5%';
}
message = title;
frm.dashboard.add_progress(__('Status'), bars, message);
}
});

View File

@ -0,0 +1,196 @@
{
"actions": [],
"autoname": "naming_series:",
"creation": "2020-09-14 18:33:56.715736",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"patient_details_section",
"naming_series",
"patient_encounter",
"patient",
"patient_name",
"patient_age",
"inpatient_record",
"column_break_6",
"company",
"status",
"practitioner",
"start_date",
"end_date",
"medication_orders_section",
"medication_orders",
"section_break_16",
"total_orders",
"column_break_18",
"completed_orders",
"amended_from"
],
"fields": [
{
"fieldname": "patient_details_section",
"fieldtype": "Section Break",
"label": "Patient Details"
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"options": "HLC-IMO-.YYYY.-"
},
{
"fieldname": "patient_encounter",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Patient Encounter",
"options": "Patient Encounter"
},
{
"fetch_from": "patient_encounter.patient",
"fieldname": "patient",
"fieldtype": "Link",
"label": "Patient",
"options": "Patient",
"read_only_depends_on": "patient_encounter",
"reqd": 1
},
{
"fetch_from": "patient.patient_name",
"fieldname": "patient_name",
"fieldtype": "Data",
"label": "Patient Name",
"read_only": 1
},
{
"fieldname": "patient_age",
"fieldtype": "Data",
"label": "Patient Age",
"read_only": 1
},
{
"fieldname": "column_break_6",
"fieldtype": "Column Break"
},
{
"fetch_from": "patient.inpatient_record",
"fieldname": "inpatient_record",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Inpatient Record",
"options": "Inpatient Record",
"read_only": 1,
"reqd": 1
},
{
"fetch_from": "patient_encounter.practitioner",
"fieldname": "practitioner",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Healthcare Practitioner",
"options": "Healthcare Practitioner",
"read_only_depends_on": "patient_encounter"
},
{
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Start Date",
"reqd": 1
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"label": "End Date",
"read_only": 1
},
{
"depends_on": "eval: doc.patient && doc.start_date",
"fieldname": "medication_orders_section",
"fieldtype": "Section Break",
"label": "Medication Orders"
},
{
"fieldname": "medication_orders",
"fieldtype": "Table",
"label": "Medication Orders",
"options": "Inpatient Medication Order Entry"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"reqd": 1
},
{
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Inpatient Medication Order",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"options": "\nDraft\nSubmitted\nPending\nIn Process\nCompleted\nCancelled",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "section_break_16",
"fieldtype": "Section Break",
"label": "Other Details"
},
{
"fieldname": "total_orders",
"fieldtype": "Float",
"label": "Total Orders",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "column_break_18",
"fieldtype": "Column Break"
},
{
"fieldname": "completed_orders",
"fieldtype": "Float",
"label": "Completed Orders",
"no_copy": 1,
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2020-09-30 21:53:27.128591",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Inpatient Medication Order",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"search_fields": "patient_encounter, patient",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "patient",
"track_changes": 1
}

View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import cstr
from erpnext.healthcare.doctype.patient_encounter.patient_encounter import get_prescription_dates
class InpatientMedicationOrder(Document):
def validate(self):
self.validate_inpatient()
self.validate_duplicate()
self.set_total_orders()
self.set_status()
def on_submit(self):
self.validate_inpatient()
self.set_status()
def on_cancel(self):
self.set_status()
def validate_inpatient(self):
if not self.inpatient_record:
frappe.throw(_('No Inpatient Record found against patient {0}').format(self.patient))
def validate_duplicate(self):
existing_mo = frappe.db.exists('Inpatient Medication Order', {
'patient_encounter': self.patient_encounter,
'docstatus': ('!=', 2),
'name': ('!=', self.name)
})
if existing_mo:
frappe.throw(_('An Inpatient Medication Order {0} against Patient Encounter {1} already exists.').format(
existing_mo, self.patient_encounter), frappe.DuplicateEntryError)
def set_total_orders(self):
self.db_set('total_orders', len(self.medication_orders))
def set_status(self):
status = {
"0": "Draft",
"1": "Submitted",
"2": "Cancelled"
}[cstr(self.docstatus or 0)]
if self.docstatus == 1:
if not self.completed_orders:
status = 'Pending'
elif self.completed_orders < self.total_orders:
status = 'In Process'
else:
status = 'Completed'
self.db_set('status', status)
def add_order_entries(self, order):
if order.get('drug_code'):
dosage = frappe.get_doc('Prescription Dosage', order.get('dosage'))
dates = get_prescription_dates(order.get('period'), self.start_date)
for date in dates:
for dose in dosage.dosage_strength:
entry = self.append('medication_orders')
entry.drug = order.get('drug_code')
entry.drug_name = frappe.db.get_value('Item', order.get('drug_code'), 'item_name')
entry.dosage = dose.strength
entry.dosage_form = order.get('dosage_form')
entry.date = date
entry.time = dose.strength_time
self.end_date = dates[-1]
return

View File

@ -0,0 +1,16 @@
frappe.listview_settings['Inpatient Medication Order'] = {
add_fields: ["status"],
filters: [["status", "!=", "Cancelled"]],
get_indicator: function(doc) {
if (doc.status === "Pending") {
return [__("Pending"), "orange", "status,=,Pending"];
} else if (doc.status === "In Process") {
return [__("In Process"), "blue", "status,=,In Process"];
} else if (doc.status === "Completed") {
return [__("Completed"), "green", "status,=,Completed"];
}
}
};

View File

@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import add_days, getdate, now_datetime
from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
class TestInpatientMedicationOrder(unittest.TestCase):
def setUp(self):
frappe.db.sql("""delete from `tabInpatient Record`""")
self.patient = create_patient()
# Admit
ip_record = create_inpatient(self.patient)
ip_record.expected_length_of_stay = 0
ip_record.save()
ip_record.reload()
service_unit = get_healthcare_service_unit()
admit_patient(ip_record, service_unit, now_datetime())
self.ip_record = ip_record
def test_order_creation(self):
ipmo = create_ipmo(self.patient)
ipmo.submit()
ipmo.reload()
# 3 dosages per day for 2 days
self.assertEqual(len(ipmo.medication_orders), 6)
self.assertEqual(ipmo.medication_orders[0].date, add_days(getdate(), -1))
prescription_dosage = frappe.get_doc('Prescription Dosage', '1-1-1')
for i in range(len(prescription_dosage.dosage_strength)):
self.assertEqual(ipmo.medication_orders[i].time, prescription_dosage.dosage_strength[i].strength_time)
self.assertEqual(ipmo.medication_orders[3].date, getdate())
def test_inpatient_validation(self):
# Discharge
schedule_discharge(frappe.as_json({'patient': self.patient}))
self.ip_record.reload()
mark_invoiced_inpatient_occupancy(self.ip_record)
self.ip_record.reload()
discharge_patient(self.ip_record)
ipmo = create_ipmo(self.patient)
# inpatient validation
self.assertRaises(frappe.ValidationError, ipmo.insert)
def test_status(self):
ipmo = create_ipmo(self.patient)
ipmo.submit()
ipmo.reload()
self.assertEqual(ipmo.status, 'Pending')
filters = frappe._dict(from_date=add_days(getdate(), -1), to_date=add_days(getdate(), -1), from_time='', to_time='')
ipme = create_ipme(filters)
ipme.submit()
ipmo.reload()
self.assertEqual(ipmo.status, 'In Process')
filters = frappe._dict(from_date=getdate(), to_date=getdate(), from_time='', to_time='')
ipme = create_ipme(filters)
ipme.submit()
ipmo.reload()
self.assertEqual(ipmo.status, 'Completed')
def tearDown(self):
if frappe.db.get_value('Patient', self.patient, 'inpatient_record'):
# cleanup - Discharge
schedule_discharge(frappe.as_json({'patient': self.patient}))
self.ip_record.reload()
mark_invoiced_inpatient_occupancy(self.ip_record)
self.ip_record.reload()
discharge_patient(self.ip_record)
for entry in frappe.get_all('Inpatient Medication Entry'):
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
doc.cancel()
doc.delete()
for entry in frappe.get_all('Inpatient Medication Order'):
doc = frappe.get_doc('Inpatient Medication Order', entry.name)
doc.cancel()
doc.delete()
def create_dosage_form():
if not frappe.db.exists('Dosage Form', 'Tablet'):
frappe.get_doc({
'doctype': 'Dosage Form',
'dosage_form': 'Tablet'
}).insert()
def create_drug(item=None):
if not item:
item = 'Dextromethorphan'
drug = frappe.db.exists('Item', {'item_code': 'Dextromethorphan'})
if not drug:
drug = frappe.get_doc({
'doctype': 'Item',
'item_code': 'Dextromethorphan',
'item_name': 'Dextromethorphan',
'item_group': 'Products',
'stock_uom': 'Nos',
'is_stock_item': 1,
'valuation_rate': 50,
'opening_stock': 20
}).insert()
def get_orders():
create_dosage_form()
create_drug()
return {
'drug_code': 'Dextromethorphan',
'drug_name': 'Dextromethorphan',
'dosage': '1-1-1',
'dosage_form': 'Tablet',
'period': '2 Day'
}
def create_ipmo(patient):
orders = get_orders()
ipmo = frappe.new_doc('Inpatient Medication Order')
ipmo.patient = patient
ipmo.company = '_Test Company'
ipmo.start_date = add_days(getdate(), -1)
ipmo.add_order_entries(orders)
return ipmo
def create_ipme(filters, update_stock=0):
ipme = frappe.new_doc('Inpatient Medication Entry')
ipme.company = '_Test Company'
ipme.posting_date = getdate()
ipme.update_stock = update_stock
if update_stock:
ipme.warehouse = 'Stores - _TC'
for key, value in filters.items():
ipme.set(key, value)
ipme = ipme.get_medication_orders()
return ipme

View File

@ -0,0 +1,94 @@
{
"actions": [],
"creation": "2020-09-14 21:51:30.259164",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"drug",
"drug_name",
"dosage",
"dosage_form",
"instructions",
"column_break_4",
"date",
"time",
"is_completed"
],
"fields": [
{
"fieldname": "drug",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Drug",
"options": "Item",
"reqd": 1
},
{
"fetch_from": "drug.item_name",
"fieldname": "drug_name",
"fieldtype": "Data",
"label": "Drug Name",
"read_only": 1
},
{
"fieldname": "dosage",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Dosage",
"reqd": 1
},
{
"fieldname": "dosage_form",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Dosage Form",
"options": "Dosage Form",
"reqd": 1
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"fieldname": "date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Date",
"reqd": 1
},
{
"fieldname": "time",
"fieldtype": "Time",
"in_list_view": 1,
"label": "Time",
"reqd": 1
},
{
"default": "0",
"fieldname": "is_completed",
"fieldtype": "Check",
"label": "Is Order Completed",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "instructions",
"fieldtype": "Small Text",
"label": "Instructions"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-09-30 14:03:26.755925",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Inpatient Medication Order Entry",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class InpatientMedicationOrderEntry(Document):
pass

View File

@ -83,6 +83,7 @@ def get_healthcare_service_unit():
if not service_unit:
service_unit = frappe.new_doc("Healthcare Service Unit")
service_unit.healthcare_service_unit_name = "Test Service Unit Ip Occupancy"
service_unit.company = "_Test Company"
service_unit.service_unit_type = get_service_unit_type()
service_unit.inpatient_occupancy = 1
service_unit.occupancy_status = "Vacant"

View File

@ -58,6 +58,14 @@ frappe.ui.form.on('Patient Encounter', {
create_procedure(frm);
},'Create');
if (frm.doc.drug_prescription && frm.doc.inpatient_record && frm.doc.inpatient_status === "Admitted") {
frm.add_custom_button(__('Inpatient Medication Order'), function() {
frappe.model.open_mapped_doc({
method: 'erpnext.healthcare.doctype.patient_encounter.patient_encounter.make_ip_medication_order',
frm: frm
});
}, 'Create');
}
}
frm.set_query('patient', function() {

View File

@ -6,8 +6,9 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import cstr
from frappe.utils import cstr, getdate, add_days
from frappe import _
from frappe.model.mapper import get_mapped_doc
class PatientEncounter(Document):
def validate(self):
@ -22,20 +23,69 @@ class PatientEncounter(Document):
insert_encounter_to_medical_record(self)
def on_submit(self):
update_encounter_medical_record(self)
if self.therapies:
create_therapy_plan(self)
def on_cancel(self):
if self.appointment:
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
delete_medical_record(self)
def on_submit(self):
create_therapy_plan(self)
if self.inpatient_record and self.drug_prescription:
delete_ip_medication_order(self)
delete_medical_record(self)
def set_title(self):
self.title = _('{0} with {1}').format(self.patient_name or self.patient,
self.practitioner_name or self.practitioner)[:100]
@frappe.whitelist()
def make_ip_medication_order(source_name, target_doc=None):
def set_missing_values(source, target):
target.start_date = source.encounter_date
for entry in source.drug_prescription:
if entry.drug_code:
dosage = frappe.get_doc('Prescription Dosage', entry.dosage)
dates = get_prescription_dates(entry.period, target.start_date)
for date in dates:
for dose in dosage.dosage_strength:
order = target.append('medication_orders')
order.drug = entry.drug_code
order.drug_name = entry.drug_name
order.dosage = dose.strength
order.instructions = entry.comment
order.dosage_form = entry.dosage_form
order.date = date
order.time = dose.strength_time
target.end_date = dates[-1]
doc = get_mapped_doc('Patient Encounter', source_name, {
'Patient Encounter': {
'doctype': 'Inpatient Medication Order',
'field_map': {
'name': 'patient_encounter',
'patient': 'patient',
'patient_name': 'patient_name',
'patient_age': 'patient_age',
'inpatient_record': 'inpatient_record',
'practitioner': 'practitioner',
'start_date': 'encounter_date'
},
}
}, target_doc, set_missing_values)
return doc
def get_prescription_dates(period, start_date):
prescription_duration = frappe.get_doc('Prescription Duration', period)
days = prescription_duration.get_days()
dates = [start_date]
for i in range(1, days):
dates.append(add_days(getdate(start_date), i))
return dates
def create_therapy_plan(encounter):
if len(encounter.therapies):
doc = frappe.new_doc('Therapy Plan')
@ -51,6 +101,7 @@ def create_therapy_plan(encounter):
encounter.db_set('therapy_plan', doc.name)
frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
def insert_encounter_to_medical_record(doc):
subject = set_subject_field(doc)
medical_record = frappe.new_doc('Patient Medical Record')
@ -63,6 +114,7 @@ def insert_encounter_to_medical_record(doc):
medical_record.reference_owner = doc.owner
medical_record.save(ignore_permissions=True)
def update_encounter_medical_record(encounter):
medical_record_id = frappe.db.exists('Patient Medical Record', {'reference_name': encounter.name})
@ -72,8 +124,17 @@ def update_encounter_medical_record(encounter):
else:
insert_encounter_to_medical_record(encounter)
def delete_medical_record(encounter):
frappe.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
record = frappe.db.exists('Patient Medical Record', {'reference_name', encounter.name})
if record:
frappe.delete_doc('Patient Medical Record', record, force=1)
def delete_ip_medication_order(encounter):
record = frappe.db.exists('Inpatient Medication Order', {'patient_encounter': encounter.name})
if record:
frappe.delete_doc('Inpatient Medication Order', record, force=1)
def set_subject_field(encounter):
subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'

View File

@ -5,12 +5,18 @@ def get_data():
return {
'fieldname': 'encounter',
'non_standard_fieldnames': {
'Patient Medical Record': 'reference_name'
'Patient Medical Record': 'reference_name',
'Inpatient Medication Order': 'patient_encounter'
},
'transactions': [
{
'label': _('Records'),
'items': ['Vital Signs', 'Patient Medical Record']
},
]
{
'label': _('Orders'),
'items': ['Inpatient Medication Order']
}
],
'disable_create_buttons': ['Inpatient Medication Order']
}

View File

@ -5,9 +5,9 @@ from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import getdate
from frappe.utils import getdate, flt
from erpnext.healthcare.doctype.therapy_type.test_therapy_type import create_therapy_type
from erpnext.healthcare.doctype.therapy_plan.therapy_plan import make_therapy_session
from erpnext.healthcare.doctype.therapy_plan.therapy_plan import make_therapy_session, make_sales_invoice
from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_patient
class TestTherapyPlan(unittest.TestCase):
@ -20,25 +20,45 @@ class TestTherapyPlan(unittest.TestCase):
plan = create_therapy_plan()
self.assertEquals(plan.status, 'Not Started')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
frappe.get_doc(session).submit()
self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
frappe.get_doc(session).submit()
self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
def test_therapy_plan_from_template(self):
patient = create_patient()
template = create_therapy_plan_template()
# check linked item
self.assertTrue(frappe.db.exists('Therapy Plan Template', {'linked_item': 'Complete Rehab'}))
def create_therapy_plan():
plan = create_therapy_plan(template)
# invoice
si = make_sales_invoice(plan.name, patient, '_Test Company', template)
si.save()
therapy_plan_template_amt = frappe.db.get_value('Therapy Plan Template', template, 'total_amount')
self.assertEquals(si.items[0].amount, therapy_plan_template_amt)
def create_therapy_plan(template=None):
patient = create_patient()
therapy_type = create_therapy_type()
plan = frappe.new_doc('Therapy Plan')
plan.patient = patient
plan.start_date = getdate()
plan.append('therapy_plan_details', {
'therapy_type': therapy_type.name,
'no_of_sessions': 2
})
if template:
plan.therapy_plan_template = template
plan = plan.set_therapy_details_from_template()
else:
plan.append('therapy_plan_details', {
'therapy_type': therapy_type.name,
'no_of_sessions': 2
})
plan.save()
return plan
@ -55,3 +75,22 @@ def create_encounter(patient, medical_department, practitioner):
encounter.save()
encounter.submit()
return encounter
def create_therapy_plan_template():
template_name = frappe.db.exists('Therapy Plan Template', 'Complete Rehab')
if not template_name:
therapy_type = create_therapy_type()
template = frappe.new_doc('Therapy Plan Template')
template.plan_name = template.item_code = template.item_name = 'Complete Rehab'
template.item_group = 'Services'
rate = frappe.db.get_value('Therapy Type', therapy_type.name, 'rate')
template.append('therapy_types', {
'therapy_type': therapy_type.name,
'no_of_sessions': 2,
'rate': rate,
'amount': 2 * flt(rate)
})
template.save()
template_name = template.name
return template_name

View File

@ -37,7 +37,8 @@ frappe.ui.form.on('Therapy Plan', {
args: {
therapy_plan: frm.doc.name,
patient: frm.doc.patient,
therapy_type: data.therapy_type
therapy_type: data.therapy_type,
company: frm.doc.company
},
freeze: true,
callback: function(r) {
@ -49,13 +50,53 @@ frappe.ui.form.on('Therapy Plan', {
});
}, __('Select Therapy Type'), __('Create'));
}, __('Create'));
if (frm.doc.therapy_plan_template && !frm.doc.invoiced) {
frm.add_custom_button(__('Sales Invoice'), function() {
frm.trigger('make_sales_invoice');
}, __('Create'));
}
}
if (frm.doc.therapy_plan_template) {
frappe.meta.get_docfield('Therapy Plan Detail', 'therapy_type', frm.doc.name).read_only = 1;
frappe.meta.get_docfield('Therapy Plan Detail', 'no_of_sessions', frm.doc.name).read_only = 1;
}
},
make_sales_invoice: function(frm) {
frappe.call({
args: {
'reference_name': frm.doc.name,
'patient': frm.doc.patient,
'company': frm.doc.company,
'therapy_plan_template': frm.doc.therapy_plan_template
},
method: 'erpnext.healthcare.doctype.therapy_plan.therapy_plan.make_sales_invoice',
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
}
});
},
therapy_plan_template: function(frm) {
if (frm.doc.therapy_plan_template) {
frappe.call({
method: 'set_therapy_details_from_template',
doc: frm.doc,
freeze: true,
freeze_message: __('Fetching Template Details'),
callback: function() {
refresh_field('therapy_plan_details');
}
});
}
},
show_progress_for_therapies: function(frm) {
let bars = [];
let message = '';
let added_min = false;
// completed sessions
let title = __('{0} sessions completed', [frm.doc.total_sessions_completed]);
@ -71,7 +112,6 @@ frappe.ui.form.on('Therapy Plan', {
});
if (bars[0].width == '0%') {
bars[0].width = '0.5%';
added_min = 0.5;
}
message = title;
frm.dashboard.add_progress(__('Status'), bars, message);

View File

@ -9,11 +9,13 @@
"naming_series",
"patient",
"patient_name",
"invoiced",
"column_break_4",
"company",
"status",
"start_date",
"section_break_3",
"therapy_plan_template",
"therapy_plan_details",
"title",
"section_break_9",
@ -46,6 +48,7 @@
"fieldtype": "Table",
"label": "Therapy Plan Details",
"options": "Therapy Plan Detail",
"read_only_depends_on": "therapy_plan_template",
"reqd": 1
},
{
@ -105,11 +108,27 @@
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Company",
"options": "Company"
"options": "Company",
"reqd": 1
},
{
"fieldname": "therapy_plan_template",
"fieldtype": "Link",
"label": "Therapy Plan Template",
"options": "Therapy Plan Template"
},
{
"default": "0",
"fieldname": "invoiced",
"fieldtype": "Check",
"label": "Invoiced",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"links": [],
"modified": "2020-05-25 14:38:53.649315",
"modified": "2020-10-23 01:27:42.128855",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Therapy Plan",

View File

@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils import today
from frappe.utils import flt, today
class TherapyPlan(Document):
def validate(self):
@ -33,13 +33,26 @@ class TherapyPlan(Document):
self.db_set('total_sessions', total_sessions)
self.db_set('total_sessions_completed', total_sessions_completed)
def set_therapy_details_from_template(self):
# Add therapy types in the child table
self.set('therapy_plan_details', [])
therapy_plan_template = frappe.get_doc('Therapy Plan Template', self.therapy_plan_template)
for data in therapy_plan_template.therapy_types:
self.append('therapy_plan_details', {
'therapy_type': data.therapy_type,
'no_of_sessions': data.no_of_sessions
})
return self
@frappe.whitelist()
def make_therapy_session(therapy_plan, patient, therapy_type):
def make_therapy_session(therapy_plan, patient, therapy_type, company):
therapy_type = frappe.get_doc('Therapy Type', therapy_type)
therapy_session = frappe.new_doc('Therapy Session')
therapy_session.therapy_plan = therapy_plan
therapy_session.company = company
therapy_session.patient = patient
therapy_session.therapy_type = therapy_type.name
therapy_session.duration = therapy_type.default_duration
@ -48,4 +61,39 @@ def make_therapy_session(therapy_plan, patient, therapy_type):
if frappe.flags.in_test:
therapy_session.start_date = today()
return therapy_session.as_dict()
return therapy_session.as_dict()
@frappe.whitelist()
def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
from erpnext.stock.get_item_details import get_item_details
si = frappe.new_doc('Sales Invoice')
si.company = company
si.patient = patient
si.customer = frappe.db.get_value('Patient', patient, 'customer')
item = frappe.db.get_value('Therapy Plan Template', therapy_plan_template, 'linked_item')
price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0]
args = {
'doctype': 'Sales Invoice',
'item_code': item,
'company': company,
'customer': si.customer,
'selling_price_list': price_list,
'price_list_currency': price_list_currency,
'plc_conversion_rate': 1.0,
'conversion_rate': 1.0
}
item_line = si.append('items', {})
item_details = get_item_details(args)
item_line.item_code = item
item_line.qty = 1
item_line.rate = item_details.price_list_rate
item_line.amount = flt(item_line.rate) * flt(item_line.qty)
item_line.reference_dt = 'Therapy Plan'
item_line.reference_dn = reference_name
item_line.description = item_details.description
si.set_missing_values(for_validate = True)
return si

View File

@ -4,10 +4,18 @@ from frappe import _
def get_data():
return {
'fieldname': 'therapy_plan',
'non_standard_fieldnames': {
'Sales Invoice': 'reference_dn'
},
'transactions': [
{
'label': _('Therapy Sessions'),
'items': ['Therapy Session']
},
{
'label': _('Billing'),
'items': ['Sales Invoice']
}
]
],
'disable_create_buttons': ['Sales Invoice']
}

View File

@ -35,7 +35,7 @@
],
"istable": 1,
"links": [],
"modified": "2020-03-30 22:02:01.740109",
"modified": "2020-10-08 01:17:34.778028",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Therapy Plan Detail",

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestTherapyPlanTemplate(unittest.TestCase):
pass

View File

@ -0,0 +1,57 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Therapy Plan Template', {
refresh: function(frm) {
frm.set_query('therapy_type', 'therapy_types', () => {
return {
filters: {
'is_billable': 1
}
};
});
},
set_totals: function(frm) {
let total_sessions = 0;
let total_amount = 0.0;
frm.doc.therapy_types.forEach((d) => {
if (d.no_of_sessions) total_sessions += cint(d.no_of_sessions);
if (d.amount) total_amount += flt(d.amount);
});
frm.set_value('total_sessions', total_sessions);
frm.set_value('total_amount', total_amount);
frm.refresh_fields();
}
});
frappe.ui.form.on('Therapy Plan Template Detail', {
therapy_type: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
frappe.call('frappe.client.get', {
doctype: 'Therapy Type',
name: row.therapy_type
}).then((res) => {
row.rate = res.message.rate;
if (!row.no_of_sessions)
row.no_of_sessions = 1;
row.amount = flt(row.rate) * cint(row.no_of_sessions);
frm.refresh_field('therapy_types');
frm.trigger('set_totals');
});
},
no_of_sessions: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.amount = flt(row.rate) * cint(row.no_of_sessions);
frm.refresh_field('therapy_types');
frm.trigger('set_totals');
},
rate: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.amount = flt(row.rate) * cint(row.no_of_sessions);
frm.refresh_field('therapy_types');
frm.trigger('set_totals');
}
});

View File

@ -0,0 +1,132 @@
{
"actions": [],
"autoname": "field:plan_name",
"creation": "2020-09-22 17:51:38.861055",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"plan_name",
"linked_item_details_section",
"item_code",
"item_name",
"item_group",
"column_break_6",
"description",
"linked_item",
"therapy_types_section",
"therapy_types",
"section_break_11",
"total_sessions",
"column_break_13",
"total_amount"
],
"fields": [
{
"fieldname": "plan_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Plan Name",
"reqd": 1,
"unique": 1
},
{
"fieldname": "therapy_types_section",
"fieldtype": "Section Break",
"label": "Therapy Types"
},
{
"fieldname": "therapy_types",
"fieldtype": "Table",
"label": "Therapy Types",
"options": "Therapy Plan Template Detail",
"reqd": 1
},
{
"fieldname": "linked_item",
"fieldtype": "Link",
"label": "Linked Item",
"options": "Item",
"read_only": 1
},
{
"fieldname": "linked_item_details_section",
"fieldtype": "Section Break",
"label": "Linked Item Details"
},
{
"fieldname": "item_code",
"fieldtype": "Data",
"label": "Item Code",
"reqd": 1,
"set_only_once": 1
},
{
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
"reqd": 1
},
{
"fieldname": "item_group",
"fieldtype": "Link",
"label": "Item Group",
"options": "Item Group",
"reqd": 1
},
{
"fieldname": "column_break_6",
"fieldtype": "Column Break"
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Item Description"
},
{
"fieldname": "total_amount",
"fieldtype": "Currency",
"label": "Total Amount",
"read_only": 1
},
{
"fieldname": "section_break_11",
"fieldtype": "Section Break"
},
{
"fieldname": "total_sessions",
"fieldtype": "Int",
"label": "Total Sessions",
"read_only": 1
},
{
"fieldname": "column_break_13",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-10-08 00:56:58.062105",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Therapy Plan Template",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils import cint, flt
from erpnext.healthcare.doctype.therapy_type.therapy_type import make_item_price
class TherapyPlanTemplate(Document):
def after_insert(self):
self.create_item_from_template()
def validate(self):
self.set_totals()
def on_update(self):
doc_before_save = self.get_doc_before_save()
if not doc_before_save: return
if doc_before_save.item_name != self.item_name or doc_before_save.item_group != self.item_group \
or doc_before_save.description != self.description:
self.update_item()
if doc_before_save.therapy_types != self.therapy_types:
self.update_item_price()
def set_totals(self):
total_sessions = 0
total_amount = 0
for entry in self.therapy_types:
total_sessions += cint(entry.no_of_sessions)
total_amount += flt(entry.amount)
self.total_sessions = total_sessions
self.total_amount = total_amount
def create_item_from_template(self):
uom = frappe.db.exists('UOM', 'Nos') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
item = frappe.get_doc({
'doctype': 'Item',
'item_code': self.item_code,
'item_name': self.item_name,
'item_group': self.item_group,
'description': self.description,
'is_sales_item': 1,
'is_service_item': 1,
'is_purchase_item': 0,
'is_stock_item': 0,
'show_in_website': 0,
'is_pro_applicable': 0,
'stock_uom': uom
}).insert(ignore_permissions=True, ignore_mandatory=True)
make_item_price(item.name, self.total_amount)
self.db_set('linked_item', item.name)
def update_item(self):
item_doc = frappe.get_doc('Item', {'item_code': self.linked_item})
item_doc.item_name = self.item_name
item_doc.item_group = self.item_group
item_doc.description = self.description
item_doc.ignore_mandatory = True
item_doc.save(ignore_permissions=True)
def update_item_price(self):
item_price = frappe.get_doc('Item Price', {'item_code': self.linked_item})
item_price.item_name = self.item_name
item_price.price_list_rate = self.total_amount
item_price.ignore_mandatory = True
item_price.save(ignore_permissions=True)

View File

@ -0,0 +1,13 @@
from __future__ import unicode_literals
from frappe import _
def get_data():
return {
'fieldname': 'therapy_plan_template',
'transactions': [
{
'label': _('Therapy Plans'),
'items': ['Therapy Plan']
}
]
}

View File

@ -0,0 +1,54 @@
{
"actions": [],
"creation": "2020-10-07 23:04:44.373381",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"therapy_type",
"no_of_sessions",
"rate",
"amount"
],
"fields": [
{
"fieldname": "therapy_type",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Therapy Type",
"options": "Therapy Type",
"reqd": 1
},
{
"fieldname": "no_of_sessions",
"fieldtype": "Int",
"in_list_view": 1,
"label": "No of Sessions"
},
{
"fieldname": "rate",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Rate"
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"read_only": 1
}
],
"istable": 1,
"links": [],
"modified": "2020-10-07 23:46:54.296322",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Therapy Plan Template Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class TherapyPlanTemplateDetail(Document):
pass

View File

@ -92,7 +92,8 @@ frappe.ui.form.on('Therapy Session', {
'start_date': data.message.appointment_date,
'start_time': data.message.appointment_time,
'service_unit': data.message.service_unit,
'company': data.message.company
'company': data.message.company,
'duration': data.message.duration
};
frm.set_value(values);
}
@ -107,6 +108,7 @@ frappe.ui.form.on('Therapy Session', {
'start_date': '',
'start_time': '',
'service_unit': '',
'duration': ''
};
frm.set_value(values);
}

View File

@ -47,7 +47,8 @@
"fieldname": "appointment",
"fieldtype": "Link",
"label": "Appointment",
"options": "Patient Appointment"
"options": "Patient Appointment",
"set_only_once": 1
},
{
"fieldname": "patient",
@ -90,7 +91,8 @@
"fetch_from": "therapy_template.default_duration",
"fieldname": "duration",
"fieldtype": "Int",
"label": "Duration"
"label": "Duration",
"reqd": 1
},
{
"fieldname": "location",
@ -220,7 +222,7 @@
],
"is_submittable": 1,
"links": [],
"modified": "2020-06-30 10:56:10.354268",
"modified": "2020-10-22 23:10:21.178644",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Therapy Session",

View File

@ -4,16 +4,41 @@
from __future__ import unicode_literals
import frappe
import datetime
from frappe.model.document import Document
from frappe.utils import get_time, flt
from frappe.model.mapper import get_mapped_doc
from frappe import _
from frappe.utils import cstr, getdate
from frappe.utils import cstr, getdate, get_link_to_form
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
class TherapySession(Document):
def validate(self):
self.validate_duplicate()
self.set_total_counts()
def validate_duplicate(self):
end_time = datetime.datetime.combine(getdate(self.start_date), get_time(self.start_time)) \
+ datetime.timedelta(minutes=flt(self.duration))
overlaps = frappe.db.sql("""
select
name
from
`tabTherapy Session`
where
start_date=%s and name!=%s and docstatus!=2
and (practitioner=%s or patient=%s) and
((start_time<%s and start_time + INTERVAL duration MINUTE>%s) or
(start_time>%s and start_time<%s) or
(start_time=%s))
""", (self.start_date, self.name, self.practitioner, self.patient,
self.start_time, end_time.time(), self.start_time, end_time.time(), self.start_time))
if overlaps:
overlapping_details = _('Therapy Session overlaps with {0}').format(get_link_to_form('Therapy Session', overlaps[0][0]))
frappe.throw(overlapping_details, title=_('Therapy Sessions Overlapping'))
def on_submit(self):
self.update_sessions_count_in_therapy_plan()
insert_session_medical_record(self)

View File

@ -41,7 +41,7 @@ class TherapyType(Document):
if self.rate:
item_price = frappe.get_doc('Item Price', {'item_code': self.item})
item_price.item_name = self.item_name
item_price.price_list_name = self.rate
item_price.price_list_rate = self.rate
item_price.ignore_mandatory = True
item_price.save()

View File

@ -23,9 +23,9 @@ def get_healthcare_services_to_invoice(patient, company):
items_to_invoice += get_lab_tests_to_invoice(patient, company)
items_to_invoice += get_clinical_procedures_to_invoice(patient, company)
items_to_invoice += get_inpatient_services_to_invoice(patient, company)
items_to_invoice += get_therapy_plans_to_invoice(patient, company)
items_to_invoice += get_therapy_sessions_to_invoice(patient, company)
return items_to_invoice
@ -35,6 +35,7 @@ def validate_customer_created(patient):
msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
frappe.throw(msg, title=_('Customer Not Found'))
def get_appointments_to_invoice(patient, company):
appointments_to_invoice = []
patient_appointments = frappe.get_list(
@ -246,12 +247,44 @@ def get_inpatient_services_to_invoice(patient, company):
return services_to_invoice
def get_therapy_plans_to_invoice(patient, company):
therapy_plans_to_invoice = []
therapy_plans = frappe.get_list(
'Therapy Plan',
fields=['therapy_plan_template', 'name'],
filters={
'patient': patient.name,
'invoiced': 0,
'company': company,
'therapy_plan_template': ('!=', '')
}
)
for plan in therapy_plans:
therapy_plans_to_invoice.append({
'reference_type': 'Therapy Plan',
'reference_name': plan.name,
'service': frappe.db.get_value('Therapy Plan Template', plan.therapy_plan_template, 'linked_item')
})
return therapy_plans_to_invoice
def get_therapy_sessions_to_invoice(patient, company):
therapy_sessions_to_invoice = []
therapy_plans = frappe.db.get_all('Therapy Plan', {'therapy_plan_template': ('!=', '')})
therapy_plans_created_from_template = []
for entry in therapy_plans:
therapy_plans_created_from_template.append(entry.name)
therapy_sessions = frappe.get_list(
'Therapy Session',
fields='*',
filters={'patient': patient.name, 'invoiced': 0, 'company': company}
filters={
'patient': patient.name,
'invoiced': 0,
'company': company,
'therapy_plan': ('not in', therapy_plans_created_from_template)
}
)
for therapy in therapy_sessions:
if not therapy.appointment:
@ -368,8 +401,8 @@ def validate_invoiced_on_submit(item):
else:
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'invoiced')
if is_invoiced:
frappe.throw(_('The item referenced by {0} - {1} is already invoiced'\
).format(item.reference_dt, item.reference_dn))
frappe.throw(_('The item referenced by {0} - {1} is already invoiced').format(
item.reference_dt, item.reference_dn))
def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):

View File

@ -282,7 +282,8 @@ doc_events = {
# to maintain data integrity we exempted payment entry. it will un-link when sales invoice get cancelled.
# if payment entry not in auto cancel exempted doctypes it will cancel payment entry.
auto_cancel_exempted_doctypes= [
"Payment Entry"
"Payment Entry",
"Inpatient Medication Entry"
]
scheduler_events = {

View File

@ -731,3 +731,4 @@ erpnext.patches.v13_0.change_default_pos_print_format
erpnext.patches.v13_0.set_youtube_video_id
erpnext.patches.v13_0.print_uom_after_quantity_patch
erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account
erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail

View File

@ -0,0 +1,10 @@
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from erpnext.domains.healthcare import data
def execute():
if 'Healthcare' not in frappe.get_active_domains():
return
if data['custom_fields']:
create_custom_fields(data['custom_fields'])

View File

@ -210,6 +210,7 @@
[data-route="point-of-sale"] .item-summary-wrapper:last-child { border-bottom: none; }
[data-route="point-of-sale"] .total-summary-wrapper:last-child { border-bottom: none; }
[data-route="point-of-sale"] .invoices-container .invoice-wrapper:last-child { border-bottom: none; }
[data-route="point-of-sale"] .new-btn { background-color: #5e64ff; color: white; border: none;}
[data-route="point-of-sale"] .summary-btns:last-child { margin-right: 0px; }
[data-route="point-of-sale"] ::-webkit-scrollbar { width: 1px }

View File

@ -6,6 +6,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
apply_pricing_rule_on_item: function(item){
let effective_item_rate = item.price_list_rate;
let item_rate = item.rate;
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
@ -17,15 +18,17 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
item.rate = flt(item.rate_with_margin , precision("rate", item));
item_rate = flt(item.rate_with_margin , precision("rate", item));
if(item.discount_percentage){
item.discount_amount = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
}
if (item.discount_amount) {
item.rate = flt((item.rate_with_margin) - (item.discount_amount), precision('rate', item));
item_rate = flt((item.rate_with_margin) - (item.discount_amount), precision('rate', item));
}
frappe.model.set_value(item.doctype, item.name, "rate", item_rate);
},
calculate_taxes_and_totals: function(update_paid_amount) {
@ -88,11 +91,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
if(this.frm.doc.currency == company_currency) {
this.frm.set_value("conversion_rate", 1);
} else {
const err_message = __('{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}', [
conversion_rate_label,
this.frm.doc.currency,
company_currency
]);
const subs = [conversion_rate_label, this.frm.doc.currency, company_currency];
const err_message = __('{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}', subs);
frappe.throw(err_message);
}
}

View File

@ -1049,14 +1049,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(item.item_code && item.uom) {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_conversion_factor",
child: item,
args: {
item_code: item.item_code,
uom: item.uom
},
callback: function(r) {
if(!r.exc) {
me.conversion_factor(me.frm.doc, cdt, cdn);
frappe.model.set_value(cdt, cdn, 'conversion_factor', r.message.conversion_factor);
}
}
});

View File

@ -75,7 +75,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
fieldtype:'Float',
read_only: me.has_batch && !me.has_serial_no,
label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'),
default: 0
default: flt(me.item.stock_qty),
},
{
fieldname: 'auto_fetch_button',
@ -91,7 +91,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
qty: qty,
item_code: me.item_code,
warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
batch_no: me.item.batch_no || null
batch_no: me.item.batch_no || null,
posting_date: me.frm.doc.posting_date || me.frm.doc.transaction_date
}
});
@ -100,11 +101,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
let records_length = auto_fetched_serial_numbers.length;
if (!records_length) {
const warehouse = me.dialog.fields_dict.warehouse.get_value().bold();
frappe.msgprint(__(`Serial numbers unavailable for Item ${me.item.item_code.bold()}
under warehouse ${warehouse}. Please try changing warehouse.`));
frappe.msgprint(
__('Serial numbers unavailable for Item {0} under warehouse {1}. Please try changing warehouse.', [me.item.item_code.bold(), warehouse])
);
}
if (records_length < qty) {
frappe.msgprint(__(`Fetched only ${records_length} available serial numbers.`));
frappe.msgprint(__('Fetched only {0} available serial numbers.', [records_length]));
}
let serial_no_list_field = this.dialog.fields_dict.serial_no;
numbers = auto_fetched_serial_numbers.join('\n');
@ -189,15 +191,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
if(this.has_batch && !this.has_serial_no) {
if(values.batches.length === 0 || !values.batches) {
frappe.throw(__("Please select batches for batched item "
+ values.item_code));
return false;
frappe.throw(__("Please select batches for batched item {0}", [values.item_code]));
}
values.batches.map((batch, i) => {
if(!batch.selected_qty || batch.selected_qty === 0 ) {
if (!this.show_dialog) {
frappe.throw(__("Please select quantity on row " + (i+1)));
return false;
frappe.throw(__("Please select quantity on row {0}", [i+1]));
}
}
});
@ -206,9 +205,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else {
let serial_nos = values.serial_no || '';
if (!serial_nos || !serial_nos.replace(/\s/g, '').length) {
frappe.throw(__("Please enter serial numbers for serialized item "
+ values.item_code));
return false;
frappe.throw(__("Please enter serial numbers for serialized item {0}", [values.item_code]));
}
return true;
}
@ -355,8 +352,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
});
if (selected_batches.includes(val)) {
this.set_value("");
frappe.throw(__(`Batch ${val} already selected.`));
return;
frappe.throw(__('Batch {0} already selected.', [val]));
}
if (me.warehouse_details.name) {
@ -375,8 +371,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else {
this.set_value("");
frappe.throw(__(`Please select a warehouse to get available
quantities`));
frappe.throw(__('Please select a warehouse to get available quantities'));
}
// e.stopImmediatePropagation();
}
@ -411,8 +406,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
parseFloat(available_qty) < parseFloat(selected_qty)) {
this.set_value('0');
frappe.throw(__(`For transfer from source, selected quantity cannot be
greater than available quantity`));
frappe.throw(__('For transfer from source, selected quantity cannot be greater than available quantity'));
} else {
this.grid.refresh();
}
@ -451,20 +445,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
frappe.call({
method: "erpnext.stock.doctype.serial_no.serial_no.get_pos_reserved_serial_nos",
args: {
item_code: me.item_code,
warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : ''
filters: {
item_code: me.item_code,
warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
}
}
}).then((data) => {
if (!data.message[1].length) {
this.showing_reserved_serial_nos_error = true;
const warehouse = me.dialog.fields_dict.warehouse.get_value().bold();
const d = frappe.msgprint(__(`Serial numbers unavailable for Item ${me.item.item_code.bold()}
under warehouse ${warehouse}. Please try changing warehouse.`));
d.get_close_btn().on('click', () => {
this.showing_reserved_serial_nos_error = false;
d.hide();
});
}
serial_no_filters['name'] = ["not in", data.message[0]]
})
}

View File

@ -441,6 +441,7 @@ class TestSalesOrder(unittest.TestCase):
def test_update_child_qty_rate_with_workflow(self):
from frappe.model.workflow import apply_workflow
frappe.set_user("Administrator")
workflow = make_sales_order_workflow()
so = make_sales_order(item_code= "_Test Item", qty=1, rate=150, do_not_submit=1)
apply_workflow(so, 'Approve')

View File

@ -12,4 +12,12 @@ frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
window.cur_pos = wrapper.pos;
};
};
frappe.pages['point-of-sale'].refresh = function(wrapper) {
if (document.scannerDetectionData) {
onScan.detachFrom(document);
wrapper.pos.wrapper.html("");
wrapper.pos.check_opening_entry();
}
}

View File

@ -11,54 +11,67 @@ from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availabil
from six import string_types
@frappe.whitelist()
def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None):
def get_items(start, page_length, price_list, item_group, pos_profile, search_value=""):
data = dict()
warehouse = ""
result = []
warehouse, show_only_available_items = "", False
if pos_profile:
warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse'])
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
if not allow_negative_stock:
warehouse, show_only_available_items = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'show_only_available_items'])
if not frappe.db.exists('Item Group', item_group):
item_group = get_root_of('Item Group')
if search_value:
data = search_serial_or_batch_or_barcode_number(search_value)
item_code = data.get("item_code") if data.get("item_code") else search_value
serial_no = data.get("serial_no") if data.get("serial_no") else ""
batch_no = data.get("batch_no") if data.get("batch_no") else ""
barcode = data.get("barcode") if data.get("barcode") else ""
condition = get_conditions(item_code, serial_no, batch_no, barcode)
if data:
item_info = frappe.db.get_value(
"Item", data.get("item_code"),
["name as item_code", "item_name", "description", "stock_uom", "image as item_image", "is_stock_item"]
, as_dict=1)
item_info.setdefault('serial_no', serial_no)
item_info.setdefault('batch_no', batch_no)
item_info.setdefault('barcode', barcode)
if pos_profile:
condition += get_item_group_condition(pos_profile)
return { 'items': [item_info] }
condition = get_conditions(item_code, serial_no, batch_no, barcode)
condition += get_item_group_condition(pos_profile)
lft, rgt = frappe.db.get_value('Item Group', item_group, ['lft', 'rgt'])
# locate function is used to sort by closest match from the beginning of the value
result = []
bin_join_selection, bin_join_condition = "", ""
if show_only_available_items:
bin_join_selection = ", `tabBin` bin"
bin_join_condition = "AND bin.warehouse = %(warehouse)s AND bin.item_code = item.name AND bin.actual_qty > 0"
items_data = frappe.db.sql("""
SELECT
name AS item_code,
item_name,
description,
stock_uom,
image AS item_image,
idx AS idx,
is_stock_item
item.name AS item_code,
item.item_name,
item.description,
item.stock_uom,
item.image AS item_image,
item.is_stock_item
FROM
`tabItem`
`tabItem` item {bin_join_selection}
WHERE
disabled = 0
AND has_variants = 0
AND is_sales_item = 1
AND is_fixed_asset = 0
AND item_group in (SELECT name FROM `tabItem Group` WHERE lft >= {lft} AND rgt <= {rgt})
AND {condition}
item.disabled = 0
AND item.has_variants = 0
AND item.is_sales_item = 1
AND item.is_fixed_asset = 0
AND item.item_group in (SELECT name FROM `tabItem Group` WHERE lft >= {lft} AND rgt <= {rgt})
AND {condition}
{bin_join_condition}
ORDER BY
name asc
item.name asc
LIMIT
{start}, {page_length}"""
.format(
@ -66,8 +79,10 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p
page_length=page_length,
lft=lft,
rgt=rgt,
condition=condition
), as_dict=1)
condition=condition,
bin_join_selection=bin_join_selection,
bin_join_condition=bin_join_condition
), {'warehouse': warehouse}, as_dict=1)
if items_data:
items = [d.item_code for d in items_data]
@ -82,46 +97,24 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p
for item in items_data:
item_code = item.item_code
item_price = item_prices.get(item_code) or {}
item_stock_qty = get_stock_availability(item_code, warehouse)
if not item_stock_qty:
pass
if not allow_negative_stock:
item_stock_qty = frappe.db.sql("""select ifnull(sum(actual_qty), 0) from `tabBin` where item_code = %s""", item_code)[0][0]
else:
row = {}
row.update(item)
row.update({
'price_list_rate': item_price.get('price_list_rate'),
'currency': item_price.get('currency'),
'actual_qty': item_stock_qty,
})
result.append(row)
item_stock_qty = get_stock_availability(item_code, warehouse)
row = {}
row.update(item)
row.update({
'price_list_rate': item_price.get('price_list_rate'),
'currency': item_price.get('currency'),
'actual_qty': item_stock_qty,
})
result.append(row)
res = {
'items': result
}
if len(res['items']) == 1:
res['items'][0].setdefault('serial_no', serial_no)
res['items'][0].setdefault('batch_no', batch_no)
res['items'][0].setdefault('barcode', barcode)
return res
if serial_no:
res.update({
'serial_no': serial_no
})
if batch_no:
res.update({
'batch_no': batch_no
})
if barcode:
res.update({
'barcode': barcode
})
return res
@frappe.whitelist()
@ -145,16 +138,16 @@ def search_serial_or_batch_or_barcode_number(search_value):
def get_conditions(item_code, serial_no, batch_no, barcode):
if serial_no or batch_no or barcode:
return "name = {0}".format(frappe.db.escape(item_code))
return "item.name = {0}".format(frappe.db.escape(item_code))
return """(name like {item_code}
or item_name like {item_code})""".format(item_code = frappe.db.escape('%' + item_code + '%'))
return """(item.name like {item_code}
or item.item_name like {item_code})""".format(item_code = frappe.db.escape('%' + item_code + '%'))
def get_item_group_condition(pos_profile):
cond = "and 1=1"
item_groups = get_item_groups(pos_profile)
if item_groups:
cond = "and item_group in (%s)"%(', '.join(['%s']*len(item_groups)))
cond = "and item.item_group in (%s)"%(', '.join(['%s']*len(item_groups)))
return cond % tuple(item_groups)

View File

@ -20,27 +20,58 @@ erpnext.PointOfSale.Controller = class {
frappe.require(['assets/erpnext/css/pos.css'], this.check_opening_entry.bind(this));
}
fetch_opening_entry() {
return frappe.call("erpnext.selling.page.point_of_sale.point_of_sale.check_opening_entry", { "user": frappe.session.user });
}
check_opening_entry() {
return frappe.call("erpnext.selling.page.point_of_sale.point_of_sale.check_opening_entry", { "user": frappe.session.user })
.then((r) => {
if (r.message.length) {
// assuming only one opening voucher is available for the current user
this.prepare_app_defaults(r.message[0]);
} else {
this.create_opening_voucher();
}
});
this.fetch_opening_entry().then((r) => {
if (r.message.length) {
// assuming only one opening voucher is available for the current user
this.prepare_app_defaults(r.message[0]);
} else {
this.create_opening_voucher();
}
});
}
create_opening_voucher() {
const table_fields = [
{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 },
{ fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount",
options: "company:company_currency" }
{
fieldname: "mode_of_payment", fieldtype: "Link",
in_list_view: 1, label: "Mode of Payment",
options: "Mode of Payment", reqd: 1
},
{
fieldname: "opening_amount", fieldtype: "Currency",
in_list_view: 1, label: "Opening Amount",
options: "company:company_currency",
change: function () {
dialog.fields_dict.balance_details.df.data.some(d => {
if (d.idx == this.doc.idx) {
d.opening_amount = this.value;
dialog.fields_dict.balance_details.grid.refresh();
return true;
}
});
}
}
];
const fetch_pos_payment_methods = () => {
const pos_profile = dialog.fields_dict.pos_profile.get_value();
if (!pos_profile) return;
frappe.db.get_doc("POS Profile", pos_profile).then(({ payments }) => {
dialog.fields_dict.balance_details.df.data = [];
payments.forEach(pay => {
const { mode_of_payment } = pay;
dialog.fields_dict.balance_details.df.data.push({ mode_of_payment, opening_amount: '0' });
});
dialog.fields_dict.balance_details.grid.refresh();
});
}
const dialog = new frappe.ui.Dialog({
title: __('Create POS Opening Entry'),
static: true,
fields: [
{
fieldtype: 'Link', label: __('Company'), default: frappe.defaults.get_default('company'),
@ -49,20 +80,7 @@ erpnext.PointOfSale.Controller = class {
{
fieldtype: 'Link', label: __('POS Profile'),
options: 'POS Profile', fieldname: 'pos_profile', reqd: 1,
onchange: () => {
const pos_profile = dialog.fields_dict.pos_profile.get_value();
if (!pos_profile) return;
frappe.db.get_doc("POS Profile", pos_profile).then(doc => {
dialog.fields_dict.balance_details.df.data = [];
doc.payments.forEach(pay => {
const { mode_of_payment } = pay;
dialog.fields_dict.balance_details.df.data.push({ mode_of_payment });
});
dialog.fields_dict.balance_details.grid.refresh();
});
}
onchange: () => fetch_pos_payment_methods()
},
{
fieldname: "balance_details",
@ -75,25 +93,18 @@ erpnext.PointOfSale.Controller = class {
fields: table_fields
}
],
primary_action: ({ company, pos_profile, balance_details }) => {
primary_action: async ({ company, pos_profile, balance_details }) => {
if (!balance_details.length) {
frappe.show_alert({
message: __("Please add Mode of payments and opening balance details."),
indicator: 'red'
})
frappe.utils.play_sound("error");
return;
return frappe.utils.play_sound("error");
}
frappe.dom.freeze();
return frappe.call("erpnext.selling.page.point_of_sale.point_of_sale.create_opening_voucher",
{ pos_profile, company, balance_details })
.then((r) => {
frappe.dom.unfreeze();
dialog.hide();
if (r.message) {
this.prepare_app_defaults(r.message);
}
})
const method = "erpnext.selling.page.point_of_sale.point_of_sale.create_opening_voucher";
const res = await frappe.call({ method, args: { pos_profile, company, balance_details }, freeze:true });
!res.exc && this.prepare_app_defaults(res.message);
dialog.hide();
},
primary_action_label: __('Submit')
});
@ -145,8 +156,8 @@ erpnext.PointOfSale.Controller = class {
}
prepare_dom() {
this.wrapper.append(`
<div class="app grid grid-cols-10 pt-8 gap-6"></div>`
this.wrapper.append(
`<div class="app grid grid-cols-10 pt-8 gap-6"></div>`
);
this.$components_wrapper = this.wrapper.find('.app');
@ -162,26 +173,25 @@ erpnext.PointOfSale.Controller = class {
}
prepare_menu() {
var me = this;
this.page.clear_menu();
this.page.add_menu_item(__("Form View"), function () {
frappe.model.sync(me.frm.doc);
frappe.set_route("Form", me.frm.doc.doctype, me.frm.doc.name);
});
this.page.add_menu_item(__("Open Form View"), this.open_form_view.bind(this), false, 'Ctrl+F');
this.page.add_menu_item(__("Toggle Recent Orders"), () => {
const show = this.recent_order_list.$component.hasClass('d-none');
this.toggle_recent_order_list(show);
});
this.page.add_menu_item(__("Toggle Recent Orders"), this.toggle_recent_order.bind(this), false, 'Ctrl+O');
this.page.add_menu_item(__("Save as Draft"), this.save_draft_invoice.bind(this));
this.page.add_menu_item(__("Save as Draft"), this.save_draft_invoice.bind(this), false, 'Ctrl+S');
frappe.ui.keys.on("ctrl+s", this.save_draft_invoice.bind(this));
this.page.add_menu_item(__('Close the POS'), this.close_pos.bind(this), false, 'Shift+Ctrl+C');
}
this.page.add_menu_item(__('Close the POS'), this.close_pos.bind(this));
open_form_view() {
frappe.model.sync(this.frm.doc);
frappe.set_route("Form", this.frm.doc.doctype, this.frm.doc.name);
}
frappe.ui.keys.on("shift+ctrl+s", this.close_pos.bind(this));
toggle_recent_order() {
const show = this.recent_order_list.$component.hasClass('d-none');
this.toggle_recent_order_list(show);
}
save_draft_invoice() {
@ -356,13 +366,12 @@ erpnext.PointOfSale.Controller = class {
submit_invoice: () => {
this.frm.savesubmit()
.then((r) => {
// this.set_invoice_status();
this.toggle_components(false);
this.order_summary.toggle_component(true);
this.order_summary.load_summary_of(this.frm.doc, true);
frappe.show_alert({
indicator: 'green',
message: __(`POS invoice ${r.doc.name} created succesfully`)
message: __('POS invoice {0} created succesfully', [r.doc.name])
});
});
}
@ -495,31 +504,7 @@ erpnext.PointOfSale.Controller = class {
if (this.pos_profile && !this.frm.doc.pos_profile) this.frm.doc.pos_profile = this.pos_profile;
if (!this.frm.doc.company) return;
return new Promise(resolve => {
return this.frm.call({
doc: this.frm.doc,
method: "set_missing_values",
}).then((r) => {
if(!r.exc) {
if (!this.frm.doc.pos_profile) {
frappe.dom.unfreeze();
this.raise_exception_for_pos_profile();
}
this.frm.trigger("update_stock");
this.frm.trigger('calculate_taxes_and_totals');
if(this.frm.doc.taxes_and_charges) this.frm.script_manager.trigger("taxes_and_charges");
frappe.model.set_default_values(this.frm.doc);
if (r.message) {
this.frm.pos_print_format = r.message.print_format || "";
this.frm.meta.default_print_format = r.message.print_format || "";
this.frm.allow_edit_rate = r.message.allow_edit_rate;
this.frm.allow_edit_discount = r.message.allow_edit_discount;
this.frm.doc.campaign = r.message.campaign;
}
}
resolve();
});
});
return this.frm.trigger("set_pos_data");
}
raise_exception_for_pos_profile() {
@ -529,11 +514,11 @@ erpnext.PointOfSale.Controller = class {
set_invoice_status() {
const [status, indicator] = frappe.listview_settings["POS Invoice"].get_indicator(this.frm.doc);
this.page.set_indicator(__(`${status}`), indicator);
this.page.set_indicator(status, indicator);
}
set_pos_profile_status() {
this.page.set_indicator(__(`${this.pos_profile}`), "blue");
this.page.set_indicator(this.pos_profile, "blue");
}
async on_cart_update(args) {
@ -550,8 +535,10 @@ erpnext.PointOfSale.Controller = class {
field === 'qty' && (value = flt(value));
if (field === 'qty' && value > 0 && !this.allow_negative_stock)
await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse);
if (['qty', 'conversion_factor'].includes(field) && value > 0 && !this.allow_negative_stock) {
const qty_needed = field === 'qty' ? value * item_row.conversion_factor : item_row.qty * value;
await this.check_stock_availability(item_row, qty_needed, this.frm.doc.set_warehouse);
}
if (this.is_current_item_being_edited(item_row) || item_selected_from_selector) {
await frappe.model.set_value(item_row.doctype, item_row.name, field, value);
@ -572,7 +559,10 @@ erpnext.PointOfSale.Controller = class {
const args = { item_code, batch_no, [field]: value };
if (serial_no) args['serial_no'] = serial_no;
if (serial_no) {
await this.check_serial_no_availablilty(item_code, this.frm.doc.set_warehouse, serial_no);
args['serial_no'] = serial_no;
}
if (field === 'serial_no') args['qty'] = value.split(`\n`).length || 0;
@ -633,29 +623,47 @@ erpnext.PointOfSale.Controller = class {
}
async trigger_new_item_events(item_row) {
await this.frm.script_manager.trigger('item_code', item_row.doctype, item_row.name)
await this.frm.script_manager.trigger('qty', item_row.doctype, item_row.name)
await this.frm.script_manager.trigger('item_code', item_row.doctype, item_row.name);
await this.frm.script_manager.trigger('qty', item_row.doctype, item_row.name);
}
async check_stock_availability(item_row, qty_needed, warehouse) {
const available_qty = (await this.get_available_stock(item_row.item_code, warehouse)).message;
frappe.dom.unfreeze();
const bold_item_code = item_row.item_code.bold();
const bold_warehouse = warehouse.bold();
const bold_available_qty = available_qty.toString().bold()
if (!(available_qty > 0)) {
frappe.model.clear_doc(item_row.doctype, item_row.name);
frappe.throw(__(`Item Code: ${item_row.item_code.bold()} is not available under warehouse ${warehouse.bold()}.`))
frappe.throw({
title: _("Not Available"),
message: __('Item Code: {0} is not available under warehouse {1}.', [bold_item_code, bold_warehouse])
})
} else if (available_qty < qty_needed) {
frappe.show_alert({
message: __(`Stock quantity not enough for Item Code: ${item_row.item_code.bold()} under warehouse ${warehouse.bold()}.
Available quantity ${available_qty.toString().bold()}.`),
message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.',
[bold_item_code, bold_warehouse, bold_available_qty]),
indicator: 'orange'
});
frappe.utils.play_sound("error");
this.item_details.qty_control.set_value(flt(available_qty));
}
frappe.dom.freeze();
}
async check_serial_no_availablilty(item_code, warehouse, serial_no) {
const method = "erpnext.stock.doctype.serial_no.serial_no.get_pos_reserved_serial_nos";
const args = {filters: { item_code, warehouse }}
const res = await frappe.call({ method, args });
if (res.message.includes(serial_no)) {
frappe.throw({
title: __("Not Available"),
message: __('Serial No: {0} has already been transacted into another POS Invoice.', [serial_no.bold()])
});
}
}
get_available_stock(item_code, warehouse) {
const me = this;
return frappe.call({

View File

@ -223,6 +223,8 @@ erpnext.PointOfSale.ItemCart = class {
attach_shortcuts() {
for (let row of this.number_pad.keys) {
for (let btn of row) {
if (typeof btn !== 'string') continue; // do not make shortcuts for numbers
let shortcut_key = `ctrl+${frappe.scrub(String(btn))[0]}`;
if (btn === 'Delete') shortcut_key = 'ctrl+backspace';
if (btn === 'Remove') shortcut_key = 'shift+ctrl+backspace'
@ -232,6 +234,10 @@ erpnext.PointOfSale.ItemCart = class {
const fieldname = this.number_pad.fieldnames[btn] ? this.number_pad.fieldnames[btn] :
typeof btn === 'string' ? frappe.scrub(btn) : btn;
let shortcut_label = shortcut_key.split('+').map(frappe.utils.to_title_case).join('+');
shortcut_label = frappe.utils.is_mac() ? shortcut_label.replace('Ctrl', '⌘') : shortcut_label;
this.$numpad_section.find(`.numpad-btn[data-button-value="${fieldname}"]`).attr("title", shortcut_label);
frappe.ui.keys.on(`${shortcut_key}`, () => {
const cart_is_visible = this.$component.is(":visible");
if (cart_is_visible && this.item_is_selected && this.$numpad_section.is(":visible")) {
@ -240,12 +246,36 @@ erpnext.PointOfSale.ItemCart = class {
})
}
}
frappe.ui.keys.on("ctrl+enter", () => {
const cart_is_visible = this.$component.is(":visible");
const payment_section_hidden = this.$totals_section.find('.edit-cart-btn').hasClass('d-none');
if (cart_is_visible && payment_section_hidden) {
this.$component.find(".checkout-btn").click();
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
this.$component.find(".checkout-btn").attr("title", `${ctrl_label}+Enter`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+enter",
action: () => this.$component.find(".checkout-btn").click(),
condition: () => this.$component.is(":visible") && this.$totals_section.find('.edit-cart-btn').hasClass('d-none'),
description: __("Checkout Order / Submit Order / New Order"),
ignore_inputs: true,
page: cur_page.page.page
});
this.$component.find(".edit-cart-btn").attr("title", `${ctrl_label}+E`);
frappe.ui.keys.on("ctrl+e", () => {
const item_cart_visible = this.$component.is(":visible");
if (item_cart_visible && this.$totals_section.find('.checkout-btn').hasClass('d-none')) {
this.$component.find(".edit-cart-btn").click()
}
});
this.$component.find(".add-discount").attr("title", `${ctrl_label}+D`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+d",
action: () => this.$component.find(".add-discount").click(),
condition: () => this.$add_discount_elem.is(":visible"),
description: __("Add Order Discount"),
ignore_inputs: true,
page: cur_page.page.page
});
frappe.ui.keys.on("escape", () => {
const item_cart_visible = this.$component.is(":visible");
if (item_cart_visible && this.discount_field && this.discount_field.parent.is(":visible")) {
this.discount_field.set_value(0);
}
});
}
@ -343,8 +373,7 @@ erpnext.PointOfSale.ItemCart = class {
show_discount_control() {
this.$add_discount_elem.removeClass("pr-4 pl-4");
this.$add_discount_elem.html(
`<div class="add-dicount-field flex flex-1 items-center"></div>
<div class="submit-field flex items-center"></div>`
`<div class="add-discount-field flex flex-1 items-center"></div>`
);
const me = this;
@ -354,14 +383,18 @@ erpnext.PointOfSale.ItemCart = class {
fieldtype: 'Data',
placeholder: __('Enter discount percentage.'),
onchange: function() {
if (this.value || this.value == 0) {
const frm = me.events.get_frm();
const frm = me.events.get_frm();
if (this.value.length || this.value === 0) {
frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', flt(this.value));
me.hide_discount_control(this.value);
} else {
frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', 0);
me.$add_discount_elem.html(`+ Add Discount`);
me.discount_field = undefined;
}
},
},
parent: this.$add_discount_elem.find('.add-dicount-field'),
parent: this.$add_discount_elem.find('.add-discount-field'),
render_input: true,
});
this.discount_field.toggle_label(false);
@ -369,17 +402,24 @@ erpnext.PointOfSale.ItemCart = class {
}
hide_discount_control(discount) {
this.$add_discount_elem.addClass('pr-4 pl-4');
this.$add_discount_elem.html(
`<svg class="mr-2" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
</svg>
<div class="edit-discount p-1 pr-3 pl-3 text-dark-grey rounded w-fit bg-green-200 mb-2">
${String(discount).bold()}% off
</div>
`
);
if (!discount) {
this.$add_discount_elem.removeClass("pr-4 pl-4");
this.$add_discount_elem.html(
`<div class="add-discount-field flex flex-1 items-center"></div>`
);
} else {
this.$add_discount_elem.addClass('pr-4 pl-4');
this.$add_discount_elem.html(
`<svg class="mr-2" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
</svg>
<div class="edit-discount p-1 pr-3 pl-3 text-dark-grey rounded w-fit bg-green-200 mb-2">
${String(discount).bold()}% off
</div>
`
);
}
}
update_customer_section() {
@ -475,19 +515,20 @@ erpnext.PointOfSale.ItemCart = class {
const currency = this.events.get_frm().doc.currency;
this.$totals_section.find('.taxes').html(
`<div class="flex items-center justify-between h-16 pr-8 pl-8 border-b-grey">
<div class="flex">
<div class="flex overflow-hidden whitespace-nowrap">
<div class="text-md text-dark-grey text-bold w-fit">Tax Charges</div>
<div class="flex ml-6 text-dark-grey">
<div class="flex ml-4 text-dark-grey">
${
taxes.map((t, i) => {
let margin_left = '';
if (i !== 0) margin_left = 'ml-2';
return `<span class="border-grey p-1 pl-2 pr-2 rounded ${margin_left}">${t.description}</span>`
const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`;
return `<span class="border-grey p-1 pl-2 pr-2 rounded ${margin_left}">${description}</span>`
}).join('')
}
</div>
</div>
<div class="flex flex-col text-right">
<div class="flex flex-col text-right f-shrink-0 ml-4">
<div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
</div>
</div>`

View File

@ -177,7 +177,7 @@ erpnext.PointOfSale.ItemDetails = class {
}
get_form_fields(item) {
const fields = ['qty', 'uom', 'rate', 'price_list_rate', 'discount_percentage', 'warehouse', 'actual_qty'];
const fields = ['qty', 'uom', 'rate', 'conversion_factor', 'discount_percentage', 'warehouse', 'actual_qty', 'price_list_rate'];
if (item.has_serial_no) fields.push('serial_no');
if (item.has_batch_no) fields.push('batch_no');
return fields;
@ -208,7 +208,7 @@ erpnext.PointOfSale.ItemDetails = class {
const me = this;
if (this.rate_control) {
this.rate_control.df.onchange = function() {
if (this.value) {
if (this.value || flt(this.value) === 0) {
me.events.form_updated(me.doctype, me.name, 'rate', this.value).then(() => {
const item_row = frappe.get_doc(me.doctype, me.name);
const doc = me.events.get_frm().doc;
@ -234,24 +234,22 @@ erpnext.PointOfSale.ItemDetails = class {
})
} else if (available_qty === 0) {
me.warehouse_control.set_value('');
frappe.throw(__(`Item Code: ${me.item_row.item_code.bold()} is not available under warehouse ${this.value.bold()}.`));
const bold_item_code = me.item_row.item_code.bold();
const bold_warehouse = this.value.bold();
frappe.throw(
__('Item Code: {0} is not available under warehouse {1}.', [bold_item_code, bold_warehouse])
);
}
me.actual_qty_control.set_value(available_qty);
});
}
}
this.warehouse_control.refresh();
}
if (this.discount_percentage_control) {
this.discount_percentage_control.df.onchange = function() {
if (this.value) {
me.events.form_updated(me.doctype, me.name, 'discount_percentage', this.value).then(() => {
const item_row = frappe.get_doc(me.doctype, me.name);
me.rate_control.set_value(item_row.rate);
});
this.warehouse_control.df.get_query = () => {
return {
filters: { company: this.events.get_frm().doc.company }
}
}
};
this.warehouse_control.refresh();
}
if (this.serial_no_control) {
@ -270,7 +268,8 @@ erpnext.PointOfSale.ItemDetails = class {
query: 'erpnext.controllers.queries.get_batch_no',
filters: {
item_code: me.item_row.item_code,
warehouse: me.item_row.warehouse
warehouse: me.item_row.warehouse,
posting_date: me.events.get_frm().doc.posting_date
}
}
};
@ -287,8 +286,20 @@ erpnext.PointOfSale.ItemDetails = class {
me.events.set_value_in_current_cart_item('uom', this.value);
me.events.form_updated(me.doctype, me.name, 'uom', this.value);
me.current_item.uom = this.value;
const item_row = frappe.get_doc(me.doctype, me.name);
me.conversion_factor_control.df.read_only = (item_row.stock_uom == this.value);
me.conversion_factor_control.refresh();
}
}
frappe.model.on("POS Invoice Item", "*", (fieldname, value, item_row) => {
const field_control = me[`${fieldname}_control`];
if (field_control) {
field_control.set_value(value);
cur_pos.update_cart_html(item_row);
}
});
}
async auto_update_batch_no() {
@ -337,6 +348,7 @@ erpnext.PointOfSale.ItemDetails = class {
}
attach_shortcuts() {
this.wrapper.find('.close-btn').attr("title", "Esc");
frappe.ui.keys.on("escape", () => {
const item_details_visible = this.$component.is(":visible");
if (item_details_visible) {
@ -358,8 +370,10 @@ erpnext.PointOfSale.ItemDetails = class {
bind_auto_serial_fetch_event() {
this.$form_container.on('click', '.auto-fetch-btn', () => {
this.batch_no_control.set_value('');
this.batch_no_control && this.batch_no_control.set_value('');
let qty = this.qty_control.get_value();
let expiry_date = this.item_row.has_batch_no ? this.events.get_frm().doc.posting_date : "";
let numbers = frappe.call({
method: "erpnext.stock.doctype.serial_no.serial_no.auto_fetch_serial_number",
args: {
@ -367,6 +381,7 @@ erpnext.PointOfSale.ItemDetails = class {
item_code: this.current_item.item_code,
warehouse: this.warehouse_control.get_value() || '',
batch_nos: this.current_item.batch_no || '',
posting_date: expiry_date,
for_doctype: 'POS Invoice'
}
});
@ -376,10 +391,14 @@ erpnext.PointOfSale.ItemDetails = class {
let records_length = auto_fetched_serial_numbers.length;
if (!records_length) {
const warehouse = this.warehouse_control.get_value().bold();
frappe.msgprint(__(`Serial numbers unavailable for Item ${this.current_item.item_code.bold()}
under warehouse ${warehouse}. Please try changing warehouse.`));
const item_code = this.current_item.item_code.bold();
frappe.msgprint(
__('Serial numbers unavailable for Item {0} under warehouse {1}. Please try changing warehouse.', [item_code, warehouse])
);
} else if (records_length < qty) {
frappe.msgprint(`Fetched only ${records_length} available serial numbers.`);
frappe.msgprint(
__('Fetched only {0} available serial numbers.', [records_length])
);
this.qty_control.set_value(records_length);
}
numbers = auto_fetched_serial_numbers.join(`\n`);

View File

@ -76,7 +76,7 @@ erpnext.PointOfSale.ItemSelector = class {
get_item_html(item) {
const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
const indicator_color = actual_qty > 10 ? "green" : actual_qty !== 0 ? "orange" : "red";
const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange";
function get_item_image_html() {
if (item_image) {
@ -184,15 +184,24 @@ erpnext.PointOfSale.ItemSelector = class {
}
attach_shortcuts() {
frappe.ui.keys.on("ctrl+i", () => {
const selector_is_visible = this.$component.is(':visible');
if (!selector_is_visible) return;
this.search_field.set_focus();
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
this.search_field.parent.attr("title", `${ctrl_label}+I`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+i",
action: () => this.search_field.set_focus(),
condition: () => this.$component.is(':visible'),
description: __("Focus on search input"),
ignore_inputs: true,
page: cur_page.page.page
});
frappe.ui.keys.on("ctrl+g", () => {
const selector_is_visible = this.$component.is(':visible');
if (!selector_is_visible) return;
this.item_group_field.set_focus();
this.item_group_field.parent.attr("title", `${ctrl_label}+G`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+g",
action: () => this.item_group_field.set_focus(),
condition: () => this.$component.is(':visible'),
description: __("Focus on Item Group filter"),
ignore_inputs: true,
page: cur_page.page.page
});
// for selecting the last filtered item on search
frappe.ui.keys.on("enter", () => {

View File

@ -1,55 +1,55 @@
erpnext.PointOfSale.PastOrderList = class {
constructor({ wrapper, events }) {
this.wrapper = wrapper;
this.events = events;
constructor({ wrapper, events }) {
this.wrapper = wrapper;
this.events = events;
this.init_component();
}
this.init_component();
}
init_component() {
this.prepare_dom();
this.make_filter_section();
this.bind_events();
}
init_component() {
this.prepare_dom();
this.make_filter_section();
this.bind_events();
}
prepare_dom() {
this.wrapper.append(
`<section class="col-span-4 flex flex-col shadow rounded past-order-list bg-white mx-h-70 h-100 d-none">
<div class="flex flex-col rounded w-full scroll-y">
<div class="filter-section flex flex-col p-8 pb-2 bg-white sticky z-100">
<div class="search-field flex items-center text-grey"></div>
<div class="status-field flex items-center text-grey text-bold"></div>
</div>
<div class="flex flex-1 flex-col p-8 pt-2">
<div class="text-grey mb-6">RECENT ORDERS</div>
<div class="invoices-container rounded border grid grid-cols-1"></div>
</div>
</div>
</section>`
)
prepare_dom() {
this.wrapper.append(
`<section class="col-span-4 flex flex-col shadow rounded past-order-list bg-white mx-h-70 h-100 d-none">
<div class="flex flex-col rounded w-full scroll-y">
<div class="filter-section flex flex-col p-8 pb-2 bg-white sticky z-100">
<div class="search-field flex items-center text-grey"></div>
<div class="status-field flex items-center text-grey text-bold"></div>
</div>
<div class="flex flex-1 flex-col p-8 pt-2">
<div class="text-grey mb-6">RECENT ORDERS</div>
<div class="invoices-container rounded border grid grid-cols-1"></div>
</div>
</div>
</section>`
);
this.$component = this.wrapper.find('.past-order-list');
this.$invoices_container = this.$component.find('.invoices-container');
}
this.$component = this.wrapper.find('.past-order-list');
this.$invoices_container = this.$component.find('.invoices-container');
}
bind_events() {
this.search_field.$input.on('input', (e) => {
bind_events() {
this.search_field.$input.on('input', (e) => {
clearTimeout(this.last_search);
this.last_search = setTimeout(() => {
const search_term = e.target.value;
this.refresh_list(search_term, this.status_field.get_value());
const search_term = e.target.value;
this.refresh_list(search_term, this.status_field.get_value());
}, 300);
});
const me = this;
this.$invoices_container.on('click', '.invoice-wrapper', function() {
const invoice_name = unescape($(this).attr('data-invoice-name'));
});
const me = this;
this.$invoices_container.on('click', '.invoice-wrapper', function() {
const invoice_name = unescape($(this).attr('data-invoice-name'));
me.events.open_invoice_data(invoice_name);
})
}
me.events.open_invoice_data(invoice_name);
});
}
make_filter_section() {
const me = this;
make_filter_section() {
const me = this;
this.search_field = frappe.ui.form.make_control({
df: {
label: __('Search'),
@ -58,73 +58,71 @@ erpnext.PointOfSale.PastOrderList = class {
},
parent: this.$component.find('.search-field'),
render_input: true,
});
});
this.status_field = frappe.ui.form.make_control({
df: {
label: __('Invoice Status'),
fieldtype: 'Select',
fieldtype: 'Select',
options: `Draft\nPaid\nConsolidated\nReturn`,
placeholder: __('Filter by invoice status'),
onchange: function() {
me.refresh_list(me.search_field.get_value(), this.value);
}
placeholder: __('Filter by invoice status'),
onchange: function() {
me.refresh_list(me.search_field.get_value(), this.value);
}
},
parent: this.$component.find('.status-field'),
parent: this.$component.find('.status-field'),
render_input: true,
});
this.search_field.toggle_label(false);
this.status_field.toggle_label(false);
this.status_field.set_value('Paid');
}
toggle_component(show) {
show ?
this.$component.removeClass('d-none') && this.refresh_list() :
this.$component.addClass('d-none');
}
});
this.search_field.toggle_label(false);
this.status_field.toggle_label(false);
this.status_field.set_value('Draft');
}
refresh_list() {
frappe.dom.freeze();
this.events.reset_summary();
const search_term = this.search_field.get_value();
const status = this.status_field.get_value();
toggle_component(show) {
show ? this.$component.removeClass('d-none') && this.refresh_list() : this.$component.addClass('d-none');
}
this.$invoices_container.html('');
refresh_list() {
frappe.dom.freeze();
this.events.reset_summary();
const search_term = this.search_field.get_value();
const status = this.status_field.get_value();
return frappe.call({
this.$invoices_container.html('');
return frappe.call({
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_past_order_list",
freeze: true,
args: { search_term, status },
callback: (response) => {
frappe.dom.unfreeze();
response.message.forEach(invoice => {
const invoice_html = this.get_invoice_html(invoice);
this.$invoices_container.append(invoice_html);
});
}
});
}
args: { search_term, status },
callback: (response) => {
frappe.dom.unfreeze();
response.message.forEach(invoice => {
const invoice_html = this.get_invoice_html(invoice);
this.$invoices_container.append(invoice_html);
});
}
});
}
get_invoice_html(invoice) {
const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
return (
`<div class="invoice-wrapper flex p-4 justify-between border-b-grey pointer no-select" data-invoice-name="${escape(invoice.name)}">
<div class="flex flex-col justify-end">
<div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
<div class="flex items-center">
<div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
<svg class="mr-2" width="12" height="12" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
</svg>
${invoice.customer}
</div>
</div>
</div>
<div class="flex flex-col text-right">
<div class="f-shrink-0 text-lg text-dark-grey text-bold ml-4">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
<div class="f-shrink-0 text-grey ml-4">${posting_datetime}</div>
</div>
</div>`
)
}
}
get_invoice_html(invoice) {
const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
return (
`<div class="invoice-wrapper flex p-4 justify-between border-b-grey pointer no-select" data-invoice-name="${escape(invoice.name)}">
<div class="flex flex-col justify-end">
<div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
<div class="flex items-center">
<div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
<svg class="mr-2" width="12" height="12" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
</svg>
${invoice.customer}
</div>
</div>
</div>
<div class="flex flex-col text-right">
<div class="f-shrink-0 text-lg text-dark-grey text-bold ml-4">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
<div class="f-shrink-0 text-grey ml-4">${posting_datetime}</div>
</div>
</div>`
);
}
};

View File

@ -1,456 +1,476 @@
erpnext.PointOfSale.PastOrderSummary = class {
constructor({ wrapper, events }) {
this.wrapper = wrapper;
this.events = events;
constructor({ wrapper, events }) {
this.wrapper = wrapper;
this.events = events;
this.init_component();
}
this.init_component();
}
init_component() {
this.prepare_dom();
this.init_child_components();
this.bind_events();
this.attach_shortcuts();
}
init_component() {
this.prepare_dom();
this.init_child_components();
this.bind_events();
this.attach_shortcuts();
}
prepare_dom() {
this.wrapper.append(
`<section class="col-span-6 flex flex-col items-center shadow rounded past-order-summary bg-white mx-h-70 h-100 d-none">
<div class="no-summary-placeholder flex flex-1 items-center justify-center p-16">
<div class="no-item-wrapper flex items-center h-18 pr-4 pl-4">
<div class="flex-1 text-center text-grey">Select an invoice to load summary data</div>
</div>
</div>
<div class="summary-wrapper d-none flex-1 w-66 text-dark-grey relative">
<div class="summary-container absolute flex flex-col pt-16 pb-16 pr-8 pl-8 w-full h-full"></div>
</div>
</section>`
)
prepare_dom() {
this.wrapper.append(
`<section class="col-span-6 flex flex-col items-center shadow rounded past-order-summary bg-white mx-h-70 h-100 d-none">
<div class="no-summary-placeholder flex flex-1 items-center justify-center p-16">
<div class="no-item-wrapper flex items-center h-18 pr-4 pl-4">
<div class="flex-1 text-center text-grey">Select an invoice to load summary data</div>
</div>
</div>
<div class="summary-wrapper d-none flex-1 w-66 text-dark-grey relative">
<div class="summary-container absolute flex flex-col pt-16 pb-16 pr-8 pl-8 w-full h-full"></div>
</div>
</section>`
);
this.$component = this.wrapper.find('.past-order-summary');
this.$summary_wrapper = this.$component.find('.summary-wrapper');
this.$summary_container = this.$component.find('.summary-container');
}
this.$component = this.wrapper.find('.past-order-summary');
this.$summary_wrapper = this.$component.find('.summary-wrapper');
this.$summary_container = this.$component.find('.summary-container');
}
init_child_components() {
this.init_upper_section();
this.init_items_summary();
this.init_totals_summary();
this.init_payments_summary();
this.init_summary_buttons();
this.init_email_print_dialog();
}
init_child_components() {
this.init_upper_section();
this.init_items_summary();
this.init_totals_summary();
this.init_payments_summary();
this.init_summary_buttons();
this.init_email_print_dialog();
}
init_upper_section() {
this.$summary_container.append(
`<div class="flex upper-section justify-between w-full h-24"></div>`
);
init_upper_section() {
this.$summary_container.append(
`<div class="flex upper-section justify-between w-full h-24"></div>`
);
this.$upper_section = this.$summary_container.find('.upper-section');
}
this.$upper_section = this.$summary_container.find('.upper-section');
}
init_items_summary() {
this.$summary_container.append(
`<div class="flex flex-col flex-1 mt-6 w-full scroll-y">
<div class="text-grey mb-4 sticky bg-white">ITEMS</div>
<div class="items-summary-container border rounded flex flex-col w-full"></div>
</div>`
)
init_items_summary() {
this.$summary_container.append(
`<div class="flex flex-col flex-1 mt-6 w-full scroll-y">
<div class="text-grey mb-4 sticky bg-white">ITEMS</div>
<div class="items-summary-container border rounded flex flex-col w-full"></div>
</div>`
);
this.$items_summary_container = this.$summary_container.find('.items-summary-container');
}
this.$items_summary_container = this.$summary_container.find('.items-summary-container');
}
init_totals_summary() {
this.$summary_container.append(
`<div class="flex flex-col mt-6 w-full f-shrink-0">
<div class="text-grey mb-4">TOTALS</div>
<div class="summary-totals-container border rounded flex flex-col w-full"></div>
</div>`
)
init_totals_summary() {
this.$summary_container.append(
`<div class="flex flex-col mt-6 w-full f-shrink-0">
<div class="text-grey mb-4">TOTALS</div>
<div class="summary-totals-container border rounded flex flex-col w-full"></div>
</div>`
);
this.$totals_summary_container = this.$summary_container.find('.summary-totals-container');
}
this.$totals_summary_container = this.$summary_container.find('.summary-totals-container');
}
init_payments_summary() {
this.$summary_container.append(
`<div class="flex flex-col mt-6 w-full f-shrink-0">
<div class="text-grey mb-4">PAYMENTS</div>
<div class="payments-summary-container border rounded flex flex-col w-full mb-4"></div>
</div>`
)
init_payments_summary() {
this.$summary_container.append(
`<div class="flex flex-col mt-6 w-full f-shrink-0">
<div class="text-grey mb-4">PAYMENTS</div>
<div class="payments-summary-container border rounded flex flex-col w-full mb-4"></div>
</div>`
);
this.$payment_summary_container = this.$summary_container.find('.payments-summary-container');
}
this.$payment_summary_container = this.$summary_container.find('.payments-summary-container');
}
init_summary_buttons() {
this.$summary_container.append(
`<div class="summary-btns flex summary-btns justify-between w-full f-shrink-0"></div>`
)
init_summary_buttons() {
this.$summary_container.append(
`<div class="summary-btns flex summary-btns justify-between w-full f-shrink-0"></div>`
);
this.$summary_btns = this.$summary_container.find('.summary-btns');
}
this.$summary_btns = this.$summary_container.find('.summary-btns');
}
init_email_print_dialog() {
const email_dialog = new frappe.ui.Dialog({
title: 'Email Receipt',
fields: [
{fieldname:'email_id', fieldtype:'Data', options: 'Email', label:'Email ID'},
// {fieldname:'remarks', fieldtype:'Text', label:'Remarks (if any)'}
],
primary_action: () => {
this.send_email();
},
primary_action_label: __('Send'),
});
this.email_dialog = email_dialog;
init_email_print_dialog() {
const email_dialog = new frappe.ui.Dialog({
title: 'Email Receipt',
fields: [
{fieldname:'email_id', fieldtype:'Data', options: 'Email', label:'Email ID'},
// {fieldname:'remarks', fieldtype:'Text', label:'Remarks (if any)'}
],
primary_action: () => {
this.send_email();
},
primary_action_label: __('Send'),
});
this.email_dialog = email_dialog;
const print_dialog = new frappe.ui.Dialog({
title: 'Print Receipt',
fields: [
{fieldname:'print', fieldtype:'Data', label:'Print Preview'}
],
primary_action: () => {
const frm = this.events.get_frm();
frm.doc = this.doc;
frm.print_preview.lang_code = frm.doc.language;
frm.print_preview.printit(true);
},
primary_action_label: __('Print'),
});
this.print_dialog = print_dialog;
}
const print_dialog = new frappe.ui.Dialog({
title: 'Print Receipt',
fields: [
{fieldname:'print', fieldtype:'Data', label:'Print Preview'}
],
primary_action: () => {
const frm = this.events.get_frm();
frm.doc = this.doc;
frm.print_preview.lang_code = frm.doc.language;
frm.print_preview.printit(true);
},
primary_action_label: __('Print'),
});
this.print_dialog = print_dialog;
}
get_upper_section_html(doc) {
const { status } = doc; let indicator_color = '';
get_upper_section_html(doc) {
const { status } = doc; let indicator_color = '';
in_list(['Paid', 'Consolidated'], status) && (indicator_color = 'green');
status === 'Draft' && (indicator_color = 'red');
status === 'Return' && (indicator_color = 'grey');
in_list(['Paid', 'Consolidated'], status) && (indicator_color = 'green');
status === 'Draft' && (indicator_color = 'red');
status === 'Return' && (indicator_color = 'grey');
return `<div class="flex flex-col items-start justify-end pr-4">
<div class="text-lg text-bold pt-2">${doc.customer}</div>
<div class="text-grey">${this.customer_email}</div>
<div class="text-grey mt-auto">Sold by: ${doc.owner}</div>
</div>
<div class="flex flex-col flex-1 items-end justify-between">
<div class="text-2-5xl text-bold">${format_currency(doc.paid_amount, doc.currency)}</div>
<div class="flex justify-between">
<div class="text-grey mr-4">${doc.name}</div>
<div class="text-grey text-bold indicator ${indicator_color}">${doc.status}</div>
</div>
</div>`
}
return `<div class="flex flex-col items-start justify-end pr-4">
<div class="text-lg text-bold pt-2">${doc.customer}</div>
<div class="text-grey">${this.customer_email}</div>
<div class="text-grey mt-auto">Sold by: ${doc.owner}</div>
</div>
<div class="flex flex-col flex-1 items-end justify-between">
<div class="text-2-5xl text-bold">${format_currency(doc.paid_amount, doc.currency)}</div>
<div class="flex justify-between">
<div class="text-grey mr-4">${doc.name}</div>
<div class="text-grey text-bold indicator ${indicator_color}">${doc.status}</div>
</div>
</div>`;
}
get_discount_html(doc) {
if (doc.discount_amount) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap mr-2">
Discount
</div>
<span class="text-grey">(${doc.additional_discount_percentage} %)</span>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.discount_amount, doc.currency)}</div>
</div>
</div>`;
} else {
return ``;
}
}
get_discount_html(doc) {
if (doc.discount_amount) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap mr-2">
Discount
</div>
<span class="text-grey">(${doc.additional_discount_percentage} %)</span>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.discount_amount, doc.currency)}</div>
</div>
</div>`;
} else {
return ``;
}
}
get_net_total_html(doc) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
Net Total
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.net_total, doc.currency)}</div>
</div>
</div>`
}
get_net_total_html(doc) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
Net Total
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.net_total, doc.currency)}</div>
</div>
</div>`;
}
get_taxes_html(doc) {
return `<div class="total-summary-wrapper flex items-center justify-between h-12 pr-4 pl-4 border-b-grey">
<div class="flex">
<div class="text-md-0 text-dark-grey text-bold w-fit">Tax Charges</div>
<div class="flex ml-6 text-dark-grey">
${
doc.taxes.map((t, i) => {
let margin_left = '';
if (i !== 0) margin_left = 'ml-2';
return `<span class="pl-2 pr-2 ${margin_left}">${t.description} @${t.rate}%</span>`
}).join('')
}
</div>
</div>
<div class="flex flex-col text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.base_total_taxes_and_charges, doc.currency)}</div>
</div>
</div>`
}
get_taxes_html(doc) {
const taxes = doc.taxes.map((t, i) => {
let margin_left = '';
if (i !== 0) margin_left = 'ml-2';
return `<span class="pl-2 pr-2 ${margin_left}">${t.description} @${t.rate}%</span>`;
}).join('');
get_grand_total_html(doc) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
Grand Total
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.grand_total, doc.currency)}</div>
</div>
</div>`
}
return `
<div class="total-summary-wrapper flex items-center justify-between h-12 pr-4 pl-4 border-b-grey">
<div class="flex">
<div class="text-md-0 text-dark-grey text-bold w-fit">Tax Charges</div>
<div class="flex ml-6 text-dark-grey">${taxes}</div>
</div>
<div class="flex flex-col text-right">
<div class="text-md-0 text-dark-grey text-bold">
${format_currency(doc.base_total_taxes_and_charges, doc.currency)}
</div>
</div>
</div>`;
}
get_item_html(doc, item_data) {
return `<div class="item-summary-wrapper flex items-center h-12 pr-4 pl-4 border-b-grey pointer no-select">
<div class="flex w-6 h-6 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
<span>${item_data.qty || 0}</span>
</div>
<div class="flex flex-col f-shrink-1">
<div class="text-md text-dark-grey text-bold overflow-hidden whitespace-nowrap">
${item_data.item_name}
</div>
</div>
<div class="flex f-shrink-0 ml-auto text-right">
${get_rate_discount_html()}
</div>
</div>`
get_grand_total_html(doc) {
return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
Grand Total
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.grand_total, doc.currency)}</div>
</div>
</div>`;
}
function get_rate_discount_html() {
if (item_data.rate && item_data.price_list_rate && item_data.rate !== item_data.price_list_rate) {
return `<span class="text-grey mr-2">(${item_data.discount_percentage}% off)</span>
<div class="text-md-0 text-dark-grey text-bold">${format_currency(item_data.rate, doc.currency)}</div>`
} else {
return `<div class="text-md-0 text-dark-grey text-bold">${format_currency(item_data.price_list_rate || item_data.rate, doc.currency)}</div>`
}
}
}
get_item_html(doc, item_data) {
return `<div class="item-summary-wrapper flex items-center h-12 pr-4 pl-4 border-b-grey pointer no-select">
<div class="flex w-6 h-6 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
<span>${item_data.qty || 0}</span>
</div>
<div class="flex flex-col f-shrink-1">
<div class="text-md text-dark-grey text-bold overflow-hidden whitespace-nowrap">
${item_data.item_name}
</div>
</div>
<div class="flex f-shrink-0 ml-auto text-right">
${get_rate_discount_html()}
</div>
</div>`;
get_payment_html(doc, payment) {
return `<div class="payment-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
${payment.mode_of_payment}
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(payment.amount, doc.currency)}</div>
</div>
</div>`
}
function get_rate_discount_html() {
if (item_data.rate && item_data.price_list_rate && item_data.rate !== item_data.price_list_rate) {
return `<span class="text-grey mr-2">
(${item_data.discount_percentage}% off)
</span>
<div class="text-md-0 text-dark-grey text-bold">
${format_currency(item_data.rate, doc.currency)}
</div>`;
} else {
return `<div class="text-md-0 text-dark-grey text-bold">
${format_currency(item_data.price_list_rate || item_data.rate, doc.currency)}
</div>`;
}
}
}
bind_events() {
this.$summary_container.on('click', '.return-btn', () => {
this.events.process_return(this.doc.name);
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
get_payment_html(doc, payment) {
return `<div class="payment-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
<div class="flex f-shrink-1 items-center">
<div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
${payment.mode_of_payment}
</div>
</div>
<div class="flex flex-col f-shrink-0 ml-auto text-right">
<div class="text-md-0 text-dark-grey text-bold">${format_currency(payment.amount, doc.currency)}</div>
</div>
</div>`;
}
this.$summary_container.on('click', '.edit-btn', () => {
this.events.edit_order(this.doc.name);
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
bind_events() {
this.$summary_container.on('click', '.return-btn', () => {
this.events.process_return(this.doc.name);
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
this.$summary_container.on('click', '.new-btn', () => {
this.events.new_order();
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
this.$summary_container.on('click', '.edit-btn', () => {
this.events.edit_order(this.doc.name);
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
this.$summary_container.on('click', '.email-btn', () => {
this.email_dialog.fields_dict.email_id.set_value(this.customer_email);
this.email_dialog.show();
});
this.$summary_container.on('click', '.new-btn', () => {
this.events.new_order();
this.toggle_component(false);
this.$component.find('.no-summary-placeholder').removeClass('d-none');
this.$summary_wrapper.addClass('d-none');
});
this.$summary_container.on('click', '.print-btn', () => {
// this.print_dialog.show();
const frm = this.events.get_frm();
frm.doc = this.doc;
frm.print_preview.lang_code = frm.doc.language;
frm.print_preview.printit(true);
});
}
this.$summary_container.on('click', '.email-btn', () => {
this.email_dialog.fields_dict.email_id.set_value(this.customer_email);
this.email_dialog.show();
});
attach_shortcuts() {
frappe.ui.keys.on("ctrl+p", () => {
const print_btn_visible = this.$summary_container.find('.print-btn').is(":visible");
const summary_visible = this.$component.is(":visible");
if (!summary_visible || !print_btn_visible) return;
this.$summary_container.on('click', '.print-btn', () => {
const frm = this.events.get_frm();
frm.doc = this.doc;
frm.print_preview.lang_code = frm.doc.language;
frm.print_preview.printit(true);
});
}
this.$summary_container.find('.print-btn').click();
});
}
attach_shortcuts() {
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
this.$summary_container.find('.print-btn').attr("title", `${ctrl_label}+P`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+p",
action: () => this.$summary_container.find('.print-btn').click(),
condition: () => this.$component.is(':visible') && this.$summary_container.find('.print-btn').is(":visible"),
description: __("Print Receipt"),
page: cur_page.page.page
});
this.$summary_container.find('.new-btn').attr("title", `${ctrl_label}+Enter`);
frappe.ui.keys.on("ctrl+enter", () => {
const summary_is_visible = this.$component.is(":visible");
if (summary_is_visible && this.$summary_container.find('.new-btn').is(":visible")) {
this.$summary_container.find('.new-btn').click();
}
});
this.$summary_container.find('.edit-btn').attr("title", `${ctrl_label}+E`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+e",
action: () => this.$summary_container.find('.edit-btn').click(),
condition: () => this.$component.is(':visible') && this.$summary_container.find('.edit-btn').is(":visible"),
description: __("Edit Receipt"),
page: cur_page.page.page
});
}
toggle_component(show) {
show ?
this.$component.removeClass('d-none') :
this.$component.addClass('d-none');
}
toggle_component(show) {
show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
}
send_email() {
const frm = this.events.get_frm();
const recipients = this.email_dialog.get_values().recipients;
const doc = this.doc || frm.doc;
const print_format = frm.pos_print_format;
send_email() {
const frm = this.events.get_frm();
const recipients = this.email_dialog.get_values().recipients;
const doc = this.doc || frm.doc;
const print_format = frm.pos_print_format;
frappe.call({
method:"frappe.core.doctype.communication.email.make",
args: {
recipients: recipients,
subject: __(frm.meta.name) + ': ' + doc.name,
doctype: doc.doctype,
name: doc.name,
send_email: 1,
print_format,
sender_full_name: frappe.user.full_name(),
_lang : doc.language
},
callback: r => {
if(!r.exc) {
frappe.utils.play_sound("email");
if(r.message["emails_not_sent_to"]) {
frappe.msgprint(__("Email not sent to {0} (unsubscribed / disabled)",
[ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) );
} else {
frappe.show_alert({
message: __('Email sent successfully.'),
indicator: 'green'
});
}
this.email_dialog.hide();
} else {
frappe.msgprint(__("There were errors while sending email. Please try again."));
}
}
});
}
frappe.call({
method:"frappe.core.doctype.communication.email.make",
args: {
recipients: recipients,
subject: __(frm.meta.name) + ': ' + doc.name,
doctype: doc.doctype,
name: doc.name,
send_email: 1,
print_format,
sender_full_name: frappe.user.full_name(),
_lang : doc.language
},
callback: r => {
if(!r.exc) {
frappe.utils.play_sound("email");
if(r.message["emails_not_sent_to"]) {
frappe.msgprint(__("Email not sent to {0} (unsubscribed / disabled)",
[ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) );
} else {
frappe.show_alert({
message: __('Email sent successfully.'),
indicator: 'green'
});
}
this.email_dialog.hide();
} else {
frappe.msgprint(__("There were errors while sending email. Please try again."));
}
}
});
}
add_summary_btns(map) {
this.$summary_btns.html('');
map.forEach(m => {
if (m.condition) {
m.visible_btns.forEach(b => {
const class_name = b.split(' ')[0].toLowerCase();
this.$summary_btns.append(
`<div class="${class_name}-btn border rounded h-14 flex flex-1 items-center mr-4 justify-center text-md text-bold no-select pointer">
${b}
</div>`
)
});
}
});
this.$summary_btns.children().last().removeClass('mr-4');
}
add_summary_btns(map) {
this.$summary_btns.html('');
map.forEach(m => {
if (m.condition) {
m.visible_btns.forEach(b => {
const class_name = b.split(' ')[0].toLowerCase();
this.$summary_btns.append(
`<div class="${class_name}-btn border rounded h-14 flex flex-1 items-center mr-4 justify-center text-md text-bold no-select pointer">
${b}
</div>`
);
});
}
});
this.$summary_btns.children().last().removeClass('mr-4');
}
show_summary_placeholder() {
this.$summary_wrapper.addClass("d-none");
this.$component.find('.no-summary-placeholder').removeClass('d-none');
}
show_summary_placeholder() {
this.$summary_wrapper.addClass("d-none");
this.$component.find('.no-summary-placeholder').removeClass('d-none');
}
switch_to_post_submit_summary() {
// switch to full width view
this.$component.removeClass('col-span-6').addClass('col-span-10');
this.$summary_wrapper.removeClass('w-66').addClass('w-40');
switch_to_post_submit_summary() {
// switch to full width view
this.$component.removeClass('col-span-6').addClass('col-span-10');
this.$summary_wrapper.removeClass('w-66').addClass('w-40');
// switch place holder with summary container
this.$component.find('.no-summary-placeholder').addClass('d-none');
this.$summary_wrapper.removeClass('d-none');
}
// switch place holder with summary container
this.$component.find('.no-summary-placeholder').addClass('d-none');
this.$summary_wrapper.removeClass('d-none');
}
switch_to_recent_invoice_summary() {
// switch full width view with 60% view
this.$component.removeClass('col-span-10').addClass('col-span-6');
this.$summary_wrapper.removeClass('w-40').addClass('w-66');
switch_to_recent_invoice_summary() {
// switch full width view with 60% view
this.$component.removeClass('col-span-10').addClass('col-span-6');
this.$summary_wrapper.removeClass('w-40').addClass('w-66');
// switch place holder with summary container
this.$component.find('.no-summary-placeholder').addClass('d-none');
this.$summary_wrapper.removeClass('d-none');
}
// switch place holder with summary container
this.$component.find('.no-summary-placeholder').addClass('d-none');
this.$summary_wrapper.removeClass('d-none');
}
get_condition_btn_map(after_submission) {
if (after_submission)
return [{ condition: true, visible_btns: ['Print Receipt', 'Email Receipt', 'New Order'] }];
get_condition_btn_map(after_submission) {
if (after_submission)
return [{ condition: true, visible_btns: ['Print Receipt', 'Email Receipt', 'New Order'] }];
return [
{ condition: this.doc.docstatus === 0, visible_btns: ['Edit Order'] },
{ condition: !this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt', 'Return']},
{ condition: this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt']}
];
}
return [
{ condition: this.doc.docstatus === 0, visible_btns: ['Edit Order'] },
{ condition: !this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt', 'Return']},
{ condition: this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt']}
];
}
load_summary_of(doc, after_submission=false) {
this.$summary_wrapper.removeClass("d-none");
load_summary_of(doc, after_submission=false) {
this.$summary_wrapper.removeClass("d-none");
after_submission ?
this.switch_to_post_submit_summary() : this.switch_to_recent_invoice_summary();
after_submission ?
this.switch_to_post_submit_summary() : this.switch_to_recent_invoice_summary();
this.doc = doc;
this.doc = doc;
this.attach_basic_info(doc);
this.attach_basic_info(doc);
this.attach_items_info(doc);
this.attach_items_info(doc);
this.attach_totals_info(doc);
this.attach_totals_info(doc);
this.attach_payments_info(doc);
this.attach_payments_info(doc);
const condition_btns_map = this.get_condition_btn_map(after_submission);
const condition_btns_map = this.get_condition_btn_map(after_submission);
this.add_summary_btns(condition_btns_map);
}
this.add_summary_btns(condition_btns_map);
}
attach_basic_info(doc) {
frappe.db.get_value('Customer', this.doc.customer, 'email_id').then(({ message }) => {
this.customer_email = message.email_id || '';
const upper_section_dom = this.get_upper_section_html(doc);
this.$upper_section.html(upper_section_dom);
});
}
attach_basic_info(doc) {
frappe.db.get_value('Customer', this.doc.customer, 'email_id').then(({ message }) => {
this.customer_email = message.email_id || '';
const upper_section_dom = this.get_upper_section_html(doc);
this.$upper_section.html(upper_section_dom);
});
}
attach_items_info(doc) {
this.$items_summary_container.html('');
doc.items.forEach(item => {
const item_dom = this.get_item_html(doc, item);
this.$items_summary_container.append(item_dom);
});
}
attach_items_info(doc) {
this.$items_summary_container.html('');
doc.items.forEach(item => {
const item_dom = this.get_item_html(doc, item);
this.$items_summary_container.append(item_dom);
});
}
attach_payments_info(doc) {
this.$payment_summary_container.html('');
doc.payments.forEach(p => {
if (p.amount) {
const payment_dom = this.get_payment_html(doc, p);
this.$payment_summary_container.append(payment_dom);
}
});
if (doc.redeem_loyalty_points && doc.loyalty_amount) {
const payment_dom = this.get_payment_html(doc, {
mode_of_payment: 'Loyalty Points',
amount: doc.loyalty_amount,
});
this.$payment_summary_container.append(payment_dom);
}
}
attach_payments_info(doc) {
this.$payment_summary_container.html('');
doc.payments.forEach(p => {
if (p.amount) {
const payment_dom = this.get_payment_html(doc, p);
this.$payment_summary_container.append(payment_dom);
}
});
if (doc.redeem_loyalty_points && doc.loyalty_amount) {
const payment_dom = this.get_payment_html(doc, {
mode_of_payment: 'Loyalty Points',
amount: doc.loyalty_amount,
});
this.$payment_summary_container.append(payment_dom);
}
}
attach_totals_info(doc) {
this.$totals_summary_container.html('');
attach_totals_info(doc) {
this.$totals_summary_container.html('');
const discount_dom = this.get_discount_html(doc);
const net_total_dom = this.get_net_total_html(doc);
const taxes_dom = this.get_taxes_html(doc);
const grand_total_dom = this.get_grand_total_html(doc);
this.$totals_summary_container.append(discount_dom);
this.$totals_summary_container.append(net_total_dom);
this.$totals_summary_container.append(taxes_dom);
this.$totals_summary_container.append(grand_total_dom);
}
}
const discount_dom = this.get_discount_html(doc);
const net_total_dom = this.get_net_total_html(doc);
const taxes_dom = this.get_taxes_html(doc);
const grand_total_dom = this.get_grand_total_html(doc);
this.$totals_summary_container.append(discount_dom);
this.$totals_summary_container.append(net_total_dom);
this.$totals_summary_container.append(taxes_dom);
this.$totals_summary_container.append(grand_total_dom);
}
};

View File

@ -26,7 +26,7 @@ erpnext.PointOfSale.Payment = class {
<div class="payment-modes flex flex-wrap"></div>
<div class="invoice-details-section"></div>
<div class="flex mt-auto justify-center w-full">
<div class="flex flex-col justify-center flex-1 ml-4">
<div class="flex flex-col justify-center flex-1 ml-4">
<div class="flex w-full">
<div class="totals-remarks items-end justify-end flex flex-1">
<div class="remarks text-md-0 text-grey mr-auto"></div>
@ -170,7 +170,8 @@ erpnext.PointOfSale.Payment = class {
me.selected_mode = me[`${mode}_control`];
const doc = me.events.get_frm().doc;
me.selected_mode?.$input?.get(0).focus();
!me.selected_mode?.get_value() ? me.selected_mode?.set_value(doc.grand_total - doc.paid_amount) : '';
const current_value = me.selected_mode?.get_value()
!current_value && doc.grand_total > doc.paid_amount ? me.selected_mode?.set_value(doc.grand_total - doc.paid_amount) : '';
}
})
@ -197,10 +198,6 @@ erpnext.PointOfSale.Payment = class {
me.selected_mode.set_value(value);
})
// this.$totals_remarks.on('click', '.remarks', () => {
// this.toggle_remarks_control();
// })
this.$component.on('click', '.submit-order', () => {
const doc = this.events.get_frm().doc;
const paid_amount = doc.paid_amount;
@ -233,7 +230,7 @@ erpnext.PointOfSale.Payment = class {
frappe.ui.form.on("Sales Invoice Payment", "amount", (frm, cdt, cdn) => {
// for setting correct amount after loyalty points are redeemed
const default_mop = locals[cdt][cdn];
const mode = default_mop.mode_of_payment.replace(' ', '_').toLowerCase();
const mode = default_mop.mode_of_payment.replace(/ +/g, "_").toLowerCase();
if (this[`${mode}_control`] && this[`${mode}_control`].get_value() != default_mop.amount) {
this[`${mode}_control`].set_value(default_mop.amount);
}
@ -254,6 +251,8 @@ erpnext.PointOfSale.Payment = class {
}
attach_shortcuts() {
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
this.$component.find('.submit-order').attr("title", `${ctrl_label}+Enter`);
frappe.ui.keys.on("ctrl+enter", () => {
const payment_is_visible = this.$component.is(":visible");
const active_mode = this.$payment_modes.find(".border-primary");
@ -262,21 +261,28 @@ erpnext.PointOfSale.Payment = class {
}
});
frappe.ui.keys.on("tab", () => {
const payment_is_visible = this.$component.is(":visible");
const mode_of_payments = Array.from(this.$payment_modes.find(".mode-of-payment")).map(m => $(m).attr("data-mode"));
let active_mode = this.$payment_modes.find(".border-primary");
active_mode = active_mode.length ? active_mode.attr("data-mode") : undefined;
if (!active_mode) return;
const mode_index = mode_of_payments.indexOf(active_mode);
const next_mode_index = (mode_index + 1) % mode_of_payments.length;
const next_mode_to_be_clicked = this.$payment_modes.find(`.mode-of-payment[data-mode="${mode_of_payments[next_mode_index]}"]`);
if (payment_is_visible && mode_index != next_mode_index) {
next_mode_to_be_clicked.click();
}
frappe.ui.keys.add_shortcut({
shortcut: "tab",
action: () => {
const payment_is_visible = this.$component.is(":visible");
let active_mode = this.$payment_modes.find(".border-primary");
active_mode = active_mode.length ? active_mode.attr("data-mode") : undefined;
if (!active_mode) return;
const mode_of_payments = Array.from(this.$payment_modes.find(".mode-of-payment")).map(m => $(m).attr("data-mode"));
const mode_index = mode_of_payments.indexOf(active_mode);
const next_mode_index = (mode_index + 1) % mode_of_payments.length;
const next_mode_to_be_clicked = this.$payment_modes.find(`.mode-of-payment[data-mode="${mode_of_payments[next_mode_index]}"]`);
if (payment_is_visible && mode_index != next_mode_index) {
next_mode_to_be_clicked.click();
}
},
condition: () => this.$component.is(':visible') && this.$payment_modes.find(".border-primary").length,
description: __("Switch Between Payment Modes"),
ignore_inputs: true,
page: cur_page.page.page
});
}
@ -336,7 +342,7 @@ erpnext.PointOfSale.Payment = class {
this.$payment_modes.html(
`${
payments.map((p, i) => {
const mode = p.mode_of_payment.replace(' ', '_').toLowerCase();
const mode = p.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const payment_type = p.type;
const margin = i % 2 === 0 ? 'pr-2' : 'pl-2';
const amount = p.amount > 0 ? format_currency(p.amount, currency) : '';
@ -356,13 +362,13 @@ erpnext.PointOfSale.Payment = class {
)
payments.forEach(p => {
const mode = p.mode_of_payment.replace(' ', '_').toLowerCase();
const mode = p.mode_of_payment.replace(/ +/g, "_").toLowerCase();
const me = this;
this[`${mode}_control`] = frappe.ui.form.make_control({
df: {
label: __(`${p.mode_of_payment}`),
label: p.mode_of_payment,
fieldtype: 'Currency',
placeholder: __(`Enter ${p.mode_of_payment} amount.`),
placeholder: __('Enter {0} amount.', [p.mode_of_payment]),
onchange: function() {
if (this.value || this.value == 0) {
frappe.model.set_value(p.doctype, p.name, 'amount', flt(this.value))
@ -440,11 +446,11 @@ erpnext.PointOfSale.Payment = class {
let description, read_only, max_redeemable_amount;
if (!loyalty_points) {
description = __(`You don't have enough points to redeem.`);
description = __("You don't have enough points to redeem.");
read_only = true;
} else {
max_redeemable_amount = flt(flt(loyalty_points) * flt(conversion_factor), precision("loyalty_amount", doc))
description = __(`You can redeem upto ${format_currency(max_redeemable_amount)}.`);
description = __("You can redeem upto {0}.", [format_currency(max_redeemable_amount)]);
read_only = false;
}
@ -464,9 +470,9 @@ erpnext.PointOfSale.Payment = class {
this['loyalty-amount_control'] = frappe.ui.form.make_control({
df: {
label: __('Redeem Loyalty Points'),
label: __("Redeem Loyalty Points"),
fieldtype: 'Currency',
placeholder: __(`Enter amount to be redeemed.`),
placeholder: __("Enter amount to be redeemed."),
options: 'company:currency',
read_only,
onchange: async function() {
@ -474,7 +480,7 @@ erpnext.PointOfSale.Payment = class {
if (this.value > max_redeemable_amount) {
frappe.show_alert({
message: __(`You cannot redeem more than ${format_currency(max_redeemable_amount)}.`),
message: __("You cannot redeem more than {0}.", [format_currency(max_redeemable_amount)]),
indicator: "red"
});
frappe.utils.play_sound("submit");

View File

@ -256,3 +256,18 @@ class TestBatch(unittest.TestCase):
batch.insert()
return batch
def make_new_batch(**args):
args = frappe._dict(args)
try:
batch = frappe.get_doc({
"doctype": "Batch",
"batch_id": args.batch_id,
"item": args.item_code,
}).insert()
except frappe.DuplicateEntryError:
batch = frappe.get_doc("Batch", args.batch_id)
return batch

View File

@ -1188,8 +1188,7 @@ def invalidate_item_variants_cache_for_website(doc):
if item_code:
item_cache = ItemVariantsCacheManager(item_code)
item_cache.clear_cache()
item_cache.rebuild_cache()
def check_stock_uom_with_bin(item, stock_uom):
if stock_uom == frappe.db.get_value("Item", item, "stock_uom"):

View File

@ -174,7 +174,7 @@ class TestPurchaseReceipt(unittest.TestCase):
update_backflush_based_on("Material Transferred for Subcontract")
item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code)
make_subcontracted_item(item_code=item_code)
po = create_purchase_order(item_code=item_code, qty=1,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
@ -717,6 +717,66 @@ class TestPurchaseReceipt(unittest.TestCase):
# Allowed to submit for other company's PR
self.assertEqual(pr.docstatus, 1)
def test_subcontracted_pr_for_multi_transfer_batches(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry, make_purchase_receipt
from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on,
create_purchase_order)
update_backflush_based_on("Material Transferred for Subcontract")
item_code = "_Test Subcontracted FG Item 3"
make_item('Sub Contracted Raw Material 3', {
'is_stock_item': 1,
'is_sub_contracted_item': 1,
'has_batch_no': 1,
'create_new_batch': 1
})
create_subcontracted_item(item_code=item_code, has_batch_no=1,
raw_materials=["Sub Contracted Raw Material 3"])
order_qty = 500
po = create_purchase_order(item_code=item_code, qty=order_qty,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
ste1=make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 3", qty=300, basic_rate=100)
ste2=make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 3", qty=200, basic_rate=100)
transferred_batch = {
ste1.items[0].batch_no : 300,
ste2.items[0].batch_no : 200
}
rm_items = [
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item",
"qty":300,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name},
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item",
"qty":200,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name}
]
rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string))
self.assertEqual(len(se.items), 2)
se.items[0].batch_no = ste1.items[0].batch_no
se.items[1].batch_no = ste2.items[0].batch_no
se.submit()
supplied_qty = frappe.db.get_value("Purchase Order Item Supplied",
{"parent": po.name, "rm_item_code": "Sub Contracted Raw Material 3"}, "supplied_qty")
self.assertEqual(supplied_qty, 500.00)
pr = make_purchase_receipt(po.name)
pr.save()
self.assertEqual(len(pr.supplied_items), 2)
for row in pr.supplied_items:
self.assertEqual(transferred_batch.get(row.batch_no), row.consumed_qty)
update_backflush_based_on("BOM")
def get_sl_entries(voucher_type, voucher_no):
return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference
@ -858,6 +918,33 @@ def make_purchase_receipt(**args):
pr.submit()
return pr
def create_subcontracted_item(**args):
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
args = frappe._dict(args)
if not frappe.db.exists('Item', args.item_code):
make_item(args.item_code, {
'is_stock_item': 1,
'is_sub_contracted_item': 1,
'has_batch_no': args.get("has_batch_no") or 0
})
if not args.raw_materials:
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
})
args.raw_materials = ['_Test FG Item', 'Test Extra Item 1']
if not frappe.db.get_value('BOM', {'item': args.item_code}, 'name'):
make_bom(item = args.item_code, raw_materials = args.get("raw_materials"))
test_dependencies = ["BOM", "Item Price", "Location"]
test_records = frappe.get_test_records('Purchase Receipt')

View File

@ -12,6 +12,7 @@ from erpnext.stock.get_item_details import get_reserved_qty_for_so
from frappe import _, ValidationError
from erpnext.controllers.stock_controller import StockController
from six import string_types
from six.moves import map
class SerialNoCannotCreateDirectError(ValidationError): pass
class SerialNoCannotCannotChangeError(ValidationError): pass
@ -285,8 +286,10 @@ def validate_serial_no(sle, item_det):
if sle.voucher_type == "Sales Invoice":
if not frappe.db.exists("Sales Invoice Item", {"parent": sle.voucher_no,
"item_code": sle.item_code, "sales_order": sr.sales_order}):
frappe.throw(_("Cannot deliver Serial No {0} of item {1} as it is reserved \
to fullfill Sales Order {2}").format(sr.name, sle.item_code, sr.sales_order))
frappe.throw(
_("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}")
.format(sr.name, sle.item_code, sr.sales_order)
)
elif sle.voucher_type == "Delivery Note":
if not frappe.db.exists("Delivery Note Item", {"parent": sle.voucher_no,
"item_code": sle.item_code, "against_sales_order": sr.sales_order}):
@ -295,8 +298,10 @@ def validate_serial_no(sle, item_det):
if not invoice or frappe.db.exists("Sales Invoice Item",
{"parent": invoice, "item_code": sle.item_code,
"sales_order": sr.sales_order}):
frappe.throw(_("Cannot deliver Serial No {0} of item {1} as it is reserved to \
fullfill Sales Order {2}").format(sr.name, sle.item_code, sr.sales_order))
frappe.throw(
_("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}")
.format(sr.name, sle.item_code, sr.sales_order)
)
# if Sales Order reference in Delivery Note or Invoice validate SO reservations for item
if sle.voucher_type == "Sales Invoice":
sales_order = frappe.db.get_value("Sales Invoice Item", {"parent": sle.voucher_no,
@ -336,11 +341,13 @@ def validate_material_transfer_entry(sle_doc):
else:
sle_doc.skip_serial_no_validaiton = True
def validate_so_serial_no(sr, sales_order,):
def validate_so_serial_no(sr, sales_order):
if not sr.sales_order or sr.sales_order!= sales_order:
frappe.throw(_("""Sales Order {0} has reservation for item {1}, you can
only deliver reserved {1} against {0}. Serial No {2} cannot
be delivered""").format(sales_order, sr.item_code, sr.name))
msg = (_("Sales Order {0} has reservation for the item {1}, you can only deliver reserved {1} against {0}.")
.format(sales_order, sr.item_code))
frappe.throw(_("""{0} Serial No {1} cannot be delivered""")
.format(msg, sr.name))
def has_duplicate_serial_no(sn, sle):
if (sn.warehouse and not sle.skip_serial_no_validaiton
@ -443,6 +450,9 @@ def get_item_details(item_code):
from tabItem where name=%s""", item_code, as_dict=True)[0]
def get_serial_nos(serial_no):
if isinstance(serial_no, list):
return serial_no
return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n')
if s.strip()]
@ -538,54 +548,81 @@ def get_delivery_note_serial_no(item_code, qty, delivery_note):
return serial_nos
@frappe.whitelist()
def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None, for_doctype=None):
filters = {
"item_code": item_code,
"warehouse": warehouse,
"delivery_document_no": "",
"sales_invoice": ""
}
def auto_fetch_serial_number(qty, item_code, warehouse, posting_date=None, batch_nos=None, for_doctype=None):
filters = { "item_code": item_code, "warehouse": warehouse }
if batch_nos:
try:
filters["batch_no"] = ["in", json.loads(batch_nos)]
filters["batch_no"] = json.loads(batch_nos)
except:
filters["batch_no"] = ["in", [batch_nos]]
filters["batch_no"] = [batch_nos]
if posting_date:
filters["expiry_date"] = posting_date
serial_numbers = []
if for_doctype == 'POS Invoice':
reserved_serial_nos, unreserved_serial_nos = get_pos_reserved_serial_nos(filters, qty)
return unreserved_serial_nos
reserved_sr_nos = get_pos_reserved_serial_nos(filters)
serial_numbers = fetch_serial_numbers(filters, qty, do_not_include=reserved_sr_nos)
else:
serial_numbers = fetch_serial_numbers(filters, qty)
serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
return [item['name'] for item in serial_numbers]
return [d.get('name') for d in serial_numbers]
@frappe.whitelist()
def get_pos_reserved_serial_nos(filters, qty=None):
batch_no_cond = ""
if filters.get("batch_no"):
batch_no_cond = "and item.batch_no = {}".format(frappe.db.escape(filters.get('batch_no')))
def get_pos_reserved_serial_nos(filters):
if isinstance(filters, string_types):
filters = json.loads(filters)
reserved_serial_nos_str = [d.serial_no for d in frappe.db.sql("""select item.serial_no as serial_no
pos_transacted_sr_nos = frappe.db.sql("""select item.serial_no as serial_no
from `tabPOS Invoice` p, `tabPOS Invoice Item` item
where p.name = item.parent
and p.consolidated_invoice is NULL
where p.name = item.parent
and p.consolidated_invoice is NULL
and p.docstatus = 1
and item.docstatus = 1
and item.item_code = %s
and item.warehouse = %s
{}
""".format(batch_no_cond), [filters.get('item_code'), filters.get('warehouse')], as_dict=1)]
and item.item_code = %(item_code)s
and item.warehouse = %(warehouse)s
and item.serial_no is NOT NULL and item.serial_no != ''
""", filters, as_dict=1)
reserved_serial_nos = []
for s in reserved_serial_nos_str:
if not s: continue
reserved_sr_nos = []
for d in pos_transacted_sr_nos:
reserved_sr_nos += get_serial_nos(d.serial_no)
serial_nos = s.split("\n")
serial_nos = ' '.join(serial_nos).split() # remove whitespaces
if len(serial_nos): reserved_serial_nos += serial_nos
return reserved_sr_nos
filters["name"] = ["not in", reserved_serial_nos]
serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
unreserved_serial_nos = [item['name'] for item in serial_numbers]
def fetch_serial_numbers(filters, qty, do_not_include=[]):
batch_join_selection = ""
batch_no_condition = ""
batch_nos = filters.get("batch_no")
expiry_date = filters.get("expiry_date")
if batch_nos:
batch_no_condition = """and sr.batch_no in ({}) """.format(', '.join(["'%s'" % d for d in batch_nos]))
return reserved_serial_nos, unreserved_serial_nos
if expiry_date:
batch_join_selection = "LEFT JOIN `tabBatch` batch on sr.batch_no = batch.name "
expiry_date_cond = "AND ifnull(batch.expiry_date, '2500-12-31') >= %(expiry_date)s "
batch_no_condition += expiry_date_cond
excluded_sr_nos = ", ".join(["" + frappe.db.escape(sr) + "" for sr in do_not_include]) or "''"
serial_numbers = frappe.db.sql("""
SELECT sr.name FROM `tabSerial No` sr {batch_join_selection}
WHERE
sr.name not in ({excluded_sr_nos}) AND
sr.item_code = %(item_code)s AND
sr.warehouse = %(warehouse)s AND
ifnull(sr.sales_invoice,'') = '' AND
ifnull(sr.delivery_document_no, '') = ''
{batch_no_condition}
ORDER BY
sr.creation
LIMIT
{qty}
""".format(
excluded_sr_nos=excluded_sr_nos,
qty=qty or 1,
batch_join_selection=batch_join_selection,
batch_no_condition=batch_no_condition
), filters, as_dict=1)
return serial_numbers

View File

@ -571,8 +571,9 @@ class StockEntry(StockController):
qty_allowance = flt(frappe.db.get_single_value("Buying Settings",
"over_transfer_allowance"))
if (self.purpose == "Send to Subcontractor" and self.purchase_order and
backflush_raw_materials_based_on == 'BOM'):
if not (self.purpose == "Send to Subcontractor" and self.purchase_order): return
if (backflush_raw_materials_based_on == 'BOM'):
purchase_order = frappe.get_doc("Purchase Order", self.purchase_order)
for se_item in self.items:
item_code = se_item.original_item or se_item.item_code
@ -609,6 +610,11 @@ class StockEntry(StockController):
if flt(total_supplied, precision) > flt(total_allowed, precision):
frappe.throw(_("Row {0}# Item {1} cannot be transferred more than {2} against Purchase Order {3}")
.format(se_item.idx, se_item.item_code, total_allowed, self.purchase_order))
elif backflush_raw_materials_based_on == "Material Transferred for Subcontract":
for row in self.items:
if not row.subcontracted_item:
frappe.throw(_("Row {0}: Subcontracted Item is mandatory for the raw material {1}")
.format(row.idx, frappe.bold(row.item_code)))
def validate_bom(self):
for d in self.get('items'):
@ -817,6 +823,13 @@ class StockEntry(StockController):
ret.get('has_batch_no') and not args.get('batch_no')):
args.batch_no = get_batch_no(args['item_code'], args['s_warehouse'], args['qty'])
if self.purpose == "Send to Subcontractor" and self.get("purchase_order") and args.get('item_code'):
subcontract_items = frappe.get_all("Purchase Order Item Supplied",
{"parent": self.purchase_order, "rm_item_code": args.get('item_code')}, "main_item_code")
if subcontract_items and len(subcontract_items) == 1:
ret["subcontracted_item"] = subcontract_items[0].main_item_code
return ret
def set_items_for_stock_in(self):
@ -1288,9 +1301,16 @@ class StockEntry(StockController):
#Update Supplied Qty in PO Supplied Items
frappe.db.sql("""UPDATE `tabPurchase Order Item Supplied` pos
SET pos.supplied_qty = (SELECT ifnull(sum(transfer_qty), 0) FROM `tabStock Entry Detail` sed
WHERE pos.name = sed.po_detail and sed.docstatus = 1)
WHERE pos.docstatus = 1 and pos.parent = %s""", self.purchase_order)
SET
pos.supplied_qty = IFNULL((SELECT ifnull(sum(transfer_qty), 0)
FROM
`tabStock Entry Detail` sed, `tabStock Entry` se
WHERE
pos.name = sed.po_detail AND pos.rm_item_code = sed.item_code
AND pos.parent = se.purchase_order AND sed.docstatus = 1
AND se.name = sed.parent and se.purchase_order = %(po)s
), 0)
WHERE pos.docstatus = 1 and pos.parent = %(po)s""", {"po": self.purchase_order})
#Update reserved sub contracted quantity in bin based on Supplied Item Details and
for d in self.get("items"):

View File

@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-03-29 18:22:12",
"doctype": "DocType",
@ -16,6 +15,7 @@
"item_code",
"col_break2",
"item_name",
"subcontracted_item",
"section_break_8",
"description",
"column_break_10",
@ -57,7 +57,6 @@
"material_request",
"material_request_item",
"original_item",
"subcontracted_item",
"reference_section",
"against_stock_entry",
"ste_detail",
@ -415,6 +414,7 @@
"read_only": 1
},
{
"depends_on": "eval:parent.purpose == 'Send to Subcontractor'",
"fieldname": "subcontracted_item",
"fieldtype": "Link",
"label": "Subcontracted Item",
@ -504,7 +504,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-09-22 17:55:03.384138",
"modified": "2020-09-23 17:55:03.384138",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",

View File

@ -7,6 +7,7 @@ import frappe
from frappe.utils import cint, flt
from erpnext.stock.utils import update_included_uom_in_report
from frappe import _
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
def execute(filters=None):
include_uom = filters.get("include_uom")
@ -24,6 +25,7 @@ def execute(filters=None):
actual_qty = stock_value = 0
available_serial_nos = {}
for sle in sl_entries:
item_detail = item_details[sle.item_code]
@ -47,6 +49,9 @@ def execute(filters=None):
"out_qty": min(sle.actual_qty, 0)
})
if sle.serial_no:
update_available_serial_nos(available_serial_nos, sle)
data.append(sle)
if include_uom:
@ -55,6 +60,26 @@ def execute(filters=None):
update_included_uom_in_report(columns, data, include_uom, conversion_factors)
return columns, data
def update_available_serial_nos(available_serial_nos, sle):
serial_nos = get_serial_nos(sle.serial_no)
key = (sle.item_code, sle.warehouse)
if key not in available_serial_nos:
available_serial_nos.setdefault(key, [])
existing_serial_no = available_serial_nos[key]
for sn in serial_nos:
if sle.actual_qty > 0:
if sn in existing_serial_no:
existing_serial_no.remove(sn)
else:
existing_serial_no.append(sn)
else:
if sn in existing_serial_no:
existing_serial_no.remove(sn)
else:
existing_serial_no.append(sn)
sle.balance_serial_no = '\n'.join(existing_serial_no)
def get_columns():
columns = [
@ -76,7 +101,8 @@ def get_columns():
{"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 110},
{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 100},
{"label": _("Batch"), "fieldname": "batch_no", "fieldtype": "Link", "options": "Batch", "width": 100},
{"label": _("Serial #"), "fieldname": "serial_no", "fieldtype": "Link", "options": "Serial No", "width": 100},
{"label": _("Serial No"), "fieldname": "serial_no", "fieldtype": "Link", "options": "Serial No", "width": 100},
{"label": _("Balance Serial No"), "fieldname": "balance_serial_no", "width": 100},
{"label": _("Project"), "fieldname": "project", "fieldtype": "Link", "options": "Project", "width": 100},
{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 110}
]

View File

@ -6,10 +6,17 @@ import frappe
from frappe import _
def execute(filters=None):
validate_warehouse(filters)
columns = get_columns()
data = get_data(filters.warehouse)
return columns, data
def validate_warehouse(filters):
company = filters.company
warehouse = filters.warehouse
if not frappe.db.exists("Warehouse", {"name": warehouse, "company": company}):
frappe.throw(_("Warehouse: {0} does not belong to {1}").format(warehouse, company))
def get_columns():
columns = [
{

View File

@ -110,7 +110,6 @@ Actual qty in stock,Werklike hoeveelheid in voorraad,
Actual type tax cannot be included in Item rate in row {0},Werklike tipe belasting kan nie in Itemkoers in ry {0} ingesluit word nie.,
Add,Voeg,
Add / Edit Prices,Voeg pryse by,
Add All Suppliers,Voeg alle verskaffers by,
Add Comment,Voeg kommentaar by,
Add Customers,Voeg kliënte by,
Add Employees,Voeg werknemers by,
@ -480,7 +479,6 @@ Cannot produce more Item {0} than Sales Order quantity {1},Kan nie meer item {0}
Cannot promote Employee with status Left,Kan nie werknemer bevorder met status links nie,
Cannot refer row number greater than or equal to current row number for this Charge type,Kan nie rynommer groter as of gelyk aan huidige rynommer vir hierdie Laai tipe verwys nie,
Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,Kan lading tipe nie as &#39;Op vorige rybedrag&#39; of &#39;Op vorige ry totale&#39; vir eerste ry kies nie,
Cannot set a received RFQ to No Quote,Kan nie &#39;n RFQ vir geen kwotasie opstel nie,
Cannot set as Lost as Sales Order is made.,Kan nie as verlore gestel word nie aangesien verkoopsbestelling gemaak is.,
Cannot set authorization on basis of Discount for {0},Kan nie magtiging instel op grond van Korting vir {0},
Cannot set multiple Item Defaults for a company.,Kan nie verskeie itemvoorkeure vir &#39;n maatskappy stel nie.,
@ -934,7 +932,6 @@ Employee Referral,Werknemer verwysing,
Employee Transfer cannot be submitted before Transfer Date ,Werknemeroordrag kan nie voor die Oordragdatum ingedien word nie,
Employee cannot report to himself.,Werknemer kan nie aan homself rapporteer nie.,
Employee relieved on {0} must be set as 'Left',Werknemer verlig op {0} moet gestel word as &#39;Links&#39;,
Employee status cannot be set to 'Left' as following employees are currently reporting to this employee:&nbsp;,"Werknemerstatus kan nie op &#39;Links&#39; gestel word nie, aangesien die volgende werknemers tans aan hierdie werknemer rapporteer:",
Employee {0} already submited an apllication {1} for the payroll period {2},Werknemer {0} het reeds &#39;n aantekening {1} ingedien vir die betaalperiode {2},
Employee {0} has already applied for {1} between {2} and {3} : ,Werknemer {0} het reeds aansoek gedoen vir {1} tussen {2} en {3}:,
Employee {0} has no maximum benefit amount,Werknemer {0} het geen maksimum voordeelbedrag nie,
@ -1456,7 +1453,6 @@ Leave application {0} already exists against the student {1},Laat aansoek {0} be
"Leave cannot be allocated before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","Verlof kan nie voor {0} toegeken word nie, aangesien verlofbalans reeds in die toekomstige verlofrekordrekord {1} oorgedra is.",
"Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","Verlof kan nie voor {0} toegepas / gekanselleer word nie, aangesien verlofbalans reeds in die toekomstige verlofrekordrekord {1} oorgedra is.",
Leave of type {0} cannot be longer than {1},Verlof van tipe {0} kan nie langer wees as {1},
Leave the field empty to make purchase orders for all suppliers,Los die veld leeg om bestellings vir alle verskaffers te maak,
Leaves,blare,
Leaves Allocated Successfully for {0},Blare suksesvol toegeken vir {0},
Leaves has been granted sucessfully,Blare is suksesvol toegeken,
@ -1699,7 +1695,6 @@ No Items to pack,Geen items om te pak nie,
No Items with Bill of Materials to Manufacture,Geen items met die materiaal om te vervaardig,
No Items with Bill of Materials.,Geen voorwerpe met materiaalbriewe nie.,
No Permission,Geen toestemming nie,
No Quote,Geen kwotasie nie,
No Remarks,Geen opmerkings,
No Result to submit,Geen resultaat om in te dien nie,
No Salary Structure assigned for Employee {0} on given date {1},Geen Salarisstruktuur toegeken vir Werknemer {0} op gegewe datum {1},
@ -1856,7 +1851,6 @@ Overlap in scoring between {0} and {1},Oorvleuel in die telling tussen {0} en {1
Overlapping conditions found between:,Oorvleuelende toestande tussen:,
Owner,Eienaar,
PAN,PAN,
PO already created for all sales order items,Pos reeds geskep vir alle verkope bestellingsitems,
POS,POS,
POS Profile,POS Profiel,
POS Profile is required to use Point-of-Sale,POS-profiel is nodig om Punt van Verkope te gebruik,
@ -2502,7 +2496,6 @@ Row {0}: Quality Inspection rejected for item {1},Ry {0}: Gehalte-inspeksie verw
Row {0}: UOM Conversion Factor is mandatory,Ry {0}: UOM Gesprekfaktor is verpligtend,
Row {0}: select the workstation against the operation {1},Ry {0}: kies die werkstasie teen die operasie {1},
Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.,Ry {0}: {1} Serial nommers benodig vir item {2}. U het {3} verskaf.,
Row {0}: {1} is required to create the Opening {2} Invoices,Ry {0}: {1} is nodig om die openings {2} fakture te skep,
Row {0}: {1} must be greater than 0,Ry {0}: {1} moet groter as 0 wees,
Row {0}: {1} {2} does not match with {3},Ry {0}: {1} {2} stem nie ooreen met {3},
Row {0}:Start Date must be before End Date,Ry {0}: Begindatum moet voor Einddatum wees,
@ -2642,7 +2635,6 @@ Selling Rate,Verkoopprys,
Send Grant Review Email,Stuur Grant Review Email,
Send Now,Stuur nou,
Send SMS,Stuur SMS,
Send Supplier Emails,Stuur verskaffer e-pos,
Send mass SMS to your contacts,Stuur massa-SMS na jou kontakte,
Sensitivity,sensitiwiteit,
Sent,gestuur,
@ -3443,7 +3435,6 @@ on,op,
{0} variants created.,{0} variante geskep.,
{0} {1} created,{0} {1} geskep,
{0} {1} does not exist,{0} {1} bestaan nie,
{0} {1} does not exist.,{0} {1} bestaan nie.,
{0} {1} has been modified. Please refresh.,{0} {1} is gewysig. Herlaai asseblief.,
{0} {1} has not been submitted so the action cannot be completed,"{0} {1} is nie ingedien nie, sodat die aksie nie voltooi kan word nie",
"{0} {1} is associated with {2}, but Party Account is {3}","{0} {1} word geassosieer met {2}, maar Partyrekening is {3}",
@ -3480,6 +3471,7 @@ on,op,
{0}: {1} does not exists,{0}: {1} bestaan nie,
{0}: {1} not found in Invoice Details table,{0}: {1} word nie in die faktuurbesonderhede-tabel gevind nie,
{} of {},{} van {},
Assigned To,Toevertrou aan,
Chat,chat,
Completed By,Voltooi deur,
Conditions,voorwaardes,
@ -3502,6 +3494,7 @@ Merge with existing,Voeg saam met bestaande,
Office,kantoor,
Orientation,geaardheid,
Passive,passiewe,
Payment Failed,Betaling misluk,
Percent,persent,
Permanent,permanente,
Personal,persoonlike,
@ -3566,6 +3559,8 @@ Naming Series,Naming Series,
No data to export,Geen data om uit te voer nie,
Portrait,Portret,
Print Heading,Drukopskrif,
Scheduler Inactive,Skeduleerder onaktief,
Scheduler is inactive. Cannot import data.,Planner is onaktief. Kan nie data invoer nie.,
Show Document,Wys dokument,
Show Traceback,Wys terugsporing,
Video,video,
@ -3691,7 +3686,6 @@ Create Pick List,Skep kieslys,
Create Quality Inspection for Item {0},Skep kwaliteitsinspeksie vir item {0},
Creating Accounts...,Skep rekeninge ...,
Creating bank entries...,Skep tans bankinskrywings ...,
Creating {0},Skep {0},
Credit limit is already defined for the Company {0},Kredietlimiet is reeds gedefinieër vir die maatskappy {0},
Ctrl + Enter to submit,Ctrl + Enter om in te dien,
Ctrl+Enter to submit,Ctrl + Enter om in te dien,
@ -4524,31 +4518,22 @@ Closed Documents,Geslote Dokumente,
Accounts Settings,Rekeninge Instellings,
Settings for Accounts,Instellings vir rekeninge,
Make Accounting Entry For Every Stock Movement,Maak Rekeningkundige Inskrywing Vir Elke Voorraadbeweging,
"If enabled, the system will post accounting entries for inventory automatically.","Indien geaktiveer, sal die stelsel outomaties rekeningkundige inskrywings vir voorraad plaas.",
Accounts Frozen Upto,Rekeninge Bevrore Upto,
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","Rekeningkundige inskrywing wat tot op hierdie datum gevries is, kan niemand toelaat / verander nie, behalwe die rol wat hieronder gespesifiseer word.",
Role Allowed to Set Frozen Accounts & Edit Frozen Entries,Rol toegelaat om bevrore rekeninge in te stel en Bevrore Inskrywings te wysig,
Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,Gebruikers met hierdie rol word toegelaat om gevriesde rekeninge te stel en rekeningkundige inskrywings teen bevrore rekeninge te skep / te verander,
Determine Address Tax Category From,Bepaal adresbelastingkategorie vanaf,
Address used to determine Tax Category in transactions.,Adres wat gebruik word om belastingkategorie in transaksies te bepaal.,
Over Billing Allowance (%),Toelae oor fakturering (%),
Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.,"Persentasie waarop u toegelaat word om meer te betaal teen die bestelde bedrag. Byvoorbeeld: As die bestelwaarde $ 100 is vir &#39;n artikel en die verdraagsaamheid as 10% is, kan u $ 110 faktureer.",
Credit Controller,Kredietbeheerder,
Role that is allowed to submit transactions that exceed credit limits set.,Rol wat toegelaat word om transaksies voor te lê wat groter is as kredietlimiete.,
Check Supplier Invoice Number Uniqueness,Kontroleer Verskaffer-faktuurnommer Uniekheid,
Make Payment via Journal Entry,Betaal via Joernaal Inskrywing,
Unlink Payment on Cancellation of Invoice,Ontkoppel betaling met kansellasie van faktuur,
Book Asset Depreciation Entry Automatically,Boekbate-waardeverminderinginskrywing outomaties,
Automatically Add Taxes and Charges from Item Tax Template,Belasting en heffings word outomaties bygevoeg vanaf die itembelastingsjabloon,
Automatically Fetch Payment Terms,Haal betalingsvoorwaardes outomaties aan,
Show Inclusive Tax In Print,Wys Inklusiewe Belasting In Druk,
Show Payment Schedule in Print,Wys betalingskedule in druk,
Currency Exchange Settings,Geldruilinstellings,
Allow Stale Exchange Rates,Staaf wisselkoerse toe,
Stale Days,Stale Days,
Report Settings,Verslaginstellings,
Use Custom Cash Flow Format,Gebruik aangepaste kontantvloeiformaat,
Only select if you have setup Cash Flow Mapper documents,Kies slegs as u instellings vir kontantvloeimappers opstel,
Allowed To Transact With,Toegelaat om mee te doen,
SWIFT number,SWIFT-nommer,
Branch Code,Takkode,
@ -5485,8 +5470,6 @@ Settings for Buying Module,Instellings vir koopmodule,
Supplier Naming By,Verskaffer Naming By,
Default Supplier Group,Verstekverskaffergroep,
Default Buying Price List,Verstek kooppryslys,
Maintain same rate throughout purchase cycle,Handhaaf dieselfde koers deur die hele aankoopsiklus,
Allow Item to be added multiple times in a transaction,Laat item toe om verskeie kere in &#39;n transaksie te voeg,
Backflush Raw Materials of Subcontract Based On,Backflush Grondstowwe van Subkontraktering gebaseer op,
Material Transferred for Subcontract,Materiaal oorgedra vir subkontrakteur,
Over Transfer Allowance (%),Toelaag vir oordrag (%),
@ -5530,7 +5513,6 @@ Purchase Receipt Item Supplied,Aankoopontvangste Item verskaf,
Current Stock,Huidige voorraad,
PUR-RFQ-.YYYY.-,PUR-VOK-.YYYY.-,
For individual supplier,Vir individuele verskaffer,
Supplier Detail,Verskaffer Detail,
Link to Material Requests,Skakel na materiaalversoeke,
Message for Supplier,Boodskap vir Verskaffer,
Request for Quotation Item,Versoek vir kwotasie-item,
@ -6724,10 +6706,7 @@ HR Settings,HR instellings,
Employee Settings,Werknemer instellings,
Retirement Age,Aftree-ouderdom,
Enter retirement age in years,Gee aftree-ouderdom in jare,
Employee Records to be created by,Werknemersrekords wat geskep moet word deur,
Employee record is created using selected field. ,Werknemer rekord is geskep met behulp van geselekteerde veld.,
Stop Birthday Reminders,Stop verjaardag herinnerings,
Don't send Employee Birthday Reminders,Moenie Werknemer Verjaarsdag Herinnerings stuur nie,
Expense Approver Mandatory In Expense Claim,Uitgawe Goedkeuring Verpligte Uitgawe Eis,
Payroll Settings,Loonstaatinstellings,
Leave,Verlaat,
@ -6749,7 +6728,6 @@ Role Allowed to Create Backdated Leave Application,Die rol wat toegelaat word om
Leave Approver Mandatory In Leave Application,Verlaat Goedkeuring Verpligtend In Verlof Aansoek,
Show Leaves Of All Department Members In Calendar,Toon blare van alle Departementslede in die Jaarboek,
Auto Leave Encashment,Verlaat omhulsel outomaties,
Restrict Backdated Leave Application,Beperk aansoeke vir die verouderde verlof,
Hiring Settings,Instellings huur,
Check Vacancies On Job Offer Creation,Kyk na vakatures met die skep van werksaanbiedinge,
Identification Document Type,Identifikasiedokument Tipe,
@ -7283,28 +7261,21 @@ Completed Qty,Voltooide aantal,
Manufacturing Settings,Vervaardigingsinstellings,
Raw Materials Consumption,Verbruik van grondstowwe,
Allow Multiple Material Consumption,Laat veelvuldige materiaalverbruik toe,
Allow multiple Material Consumption against a Work Order,Laat veelvuldige materiaalverbruik toe teen &#39;n werkorder,
Backflush Raw Materials Based On,Backflush Grondstowwe gebaseer op,
Material Transferred for Manufacture,Materiaal oorgedra vir Vervaardiging,
Capacity Planning,Kapasiteitsbeplanning,
Disable Capacity Planning,Skakel kapasiteitsbeplanning uit,
Allow Overtime,Laat Oortyd toe,
Plan time logs outside Workstation Working Hours.,Beplan tydstamme buite werkstasie werksure.,
Allow Production on Holidays,Laat produksie toe op vakansie,
Capacity Planning For (Days),Kapasiteitsbeplanning vir (Dae),
Try planning operations for X days in advance.,Probeer beplanningsaktiwiteite vir X dae van vooraf.,
Time Between Operations (in mins),Tyd tussen bedrywighede (in mins),
Default 10 mins,Verstek 10 minute,
Default Warehouses for Production,Standaard pakhuise vir produksie,
Default Work In Progress Warehouse,Verstek werk in voortgang Warehouse,
Default Finished Goods Warehouse,Standaard voltooide goedere pakhuis,
Default Scrap Warehouse,Standaard skroot pakhuis,
Over Production for Sales and Work Order,Oorproduksie vir verkoops- en werkbestelling,
Overproduction Percentage For Sales Order,Oorproduksie persentasie vir verkoopsbestelling,
Overproduction Percentage For Work Order,Oorproduksie Persentasie Vir Werk Orde,
Other Settings,Ander instellings,
Update BOM Cost Automatically,Dateer BOM koste outomaties op,
"Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.","Werk BOM koste outomaties via Scheduler, gebaseer op die jongste waarderings koers / prys lys koers / laaste aankoop koers van grondstowwe.",
Material Request Plan Item,Materiaal Versoek Plan Item,
Material Request Type,Materiaal Versoek Tipe,
Material Issue,Materiële Uitgawe,
@ -7771,15 +7742,9 @@ Campaign Naming By,Veldtog naam deur,
Default Customer Group,Verstek kliënt groep,
Default Territory,Standaard Territorium,
Close Opportunity After Days,Sluit geleentheid na dae,
Auto close Opportunity after 15 days,Vakansie sluit geleentheid na 15 dae,
Default Quotation Validity Days,Standaard Kwotasie Geldigheidsdae,
Sales Update Frequency,Verkope Update Frekwensie,
How often should project and company be updated based on Sales Transactions.,Hoe gereeld moet projek en maatskappy opgedateer word gebaseer op verkoops transaksies.,
Each Transaction,Elke transaksie,
Allow user to edit Price List Rate in transactions,Laat gebruiker toe om Pryslyskoers te wysig in transaksies,
Allow multiple Sales Orders against a Customer's Purchase Order,Laat meerdere verkope bestellings toe teen &#39;n kliënt se aankoopbestelling,
Validate Selling Price for Item against Purchase Rate or Valuation Rate,Valideer Verkoopprys vir Item teen Aankoopprys of Waardasietarief,
Hide Customer's Tax Id from Sales Transactions,Versteek Kliënt se Belasting-ID van Verkoopstransaksies,
SMS Center,Sms sentrum,
Send To,Stuur na,
All Contact,Alle Kontak,
@ -8388,24 +8353,14 @@ Default Item Group,Standaard Itemgroep,
Default Stock UOM,Standaard Voorraad UOM,
Sample Retention Warehouse,Sample Retention Warehouse,
Default Valuation Method,Verstekwaardasiemetode,
Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.,"Persentasie wat u mag ontvang of meer lewer teen die hoeveelheid bestel. Byvoorbeeld: As jy 100 eenhede bestel het. en u toelae is 10%, dan mag u 110 eenhede ontvang.",
Action if Quality inspection is not submitted,Optrede indien kwaliteitsinspeksie nie ingedien word nie,
Show Barcode Field,Toon strepieskode veld,
Convert Item Description to Clean HTML,Omskep itembeskrywing om HTML skoon te maak,
Auto insert Price List rate if missing,Voer outomaties pryslys in indien dit ontbreek,
Allow Negative Stock,Laat negatiewe voorraad toe,
Automatically Set Serial Nos based on FIFO,Stel Serial Nos outomaties gebaseer op FIFO,
Set Qty in Transactions based on Serial No Input,Stel aantal in Transaksies gebaseer op Serial No Input,
Auto Material Request,Auto Materiaal Versoek,
Raise Material Request when stock reaches re-order level,Verhoog Materiaal Versoek wanneer voorraad bereik herbestellingsvlak bereik,
Notify by Email on creation of automatic Material Request,Stel per e-pos in kennis van die skepping van outomatiese materiaalversoek,
Inter Warehouse Transfer Settings,Inter Warehouse-oordraginstellings,
Allow Material Transfer From Delivery Note and Sales Invoice,Laat materiaaloordrag toe vanaf afleweringsnota en verkoopsfaktuur,
Allow Material Transfer From Purchase Receipt and Purchase Invoice,Laat materiaaloordrag toe vanaf aankoopbewys en aankoopfaktuur,
Freeze Stock Entries,Vries Voorraadinskrywings,
Stock Frozen Upto,Voorraad Bevrore Upto,
Freeze Stocks Older Than [Days],Vries Voorrade Ouer As [Dae],
Role Allowed to edit frozen stock,Rol Toegestaan om gevriesde voorraad te wysig,
Batch Identification,Batch Identification,
Use Naming Series,Gebruik Naming Series,
Naming Series Prefix,Benaming van die reeksreeks,
@ -8731,11 +8686,9 @@ Published on,Gepubliseer op,
Service Received But Not Billed,"Diens ontvang, maar nie gefaktureer nie",
Deferred Accounting Settings,Uitgestelde rekeningkundige instellings,
Book Deferred Entries Based On,Boek uitgestelde inskrywings gebaseer op,
"If ""Months"" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.","As &#39;Maande&#39; gekies word, word die vaste bedrag vir elke maand as uitgestelde inkomste of uitgawe geboek, ongeag die aantal dae in &#39;n maand. Dit sal oorweeg word as uitgestelde inkomste of uitgawes vir &#39;n hele maand nie bespreek word nie.",
Days,Dae,
Months,Maande,
Book Deferred Entries Via Journal Entry,Boek uitgestelde inskrywings via joernaalinskrywing,
If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense,"As dit nie gemerk is nie, sal GL-inskrywings geskep word om uitgestelde inkomste / uitgawes te bespreek",
Submit Journal Entries,Dien joernaalinskrywings in,
If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,"As dit nie gemerk is nie, word die joernaalinskrywings in &#39;n konseptoestand gestoor en moet dit handmatig ingedien word",
Enable Distributed Cost Center,Aktiveer verspreide kostesentrum,
@ -8880,8 +8833,6 @@ Source State,Bronstaat,
Is Inter State,Is Interstaat,
Purchase Details,Aankoopbesonderhede,
Depreciation Posting Date,Datum van afskrywing,
Purchase Order Required for Purchase Invoice & Receipt Creation,Bestelling benodig vir aankoop van fakture en ontvangsbewyse,
Purchase Receipt Required for Purchase Invoice Creation,Aankoopbewys benodig vir die skep van aankoopfakture,
"By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ",Die verskaffersnaam word standaard ingestel volgens die opgegeven verskaffersnaam. As u wil hê dat verskaffers deur a genoem moet word,
choose the 'Naming Series' option.,kies die opsie &#39;Naamreeks&#39;.,
Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,Stel die standaardpryslys op wanneer u &#39;n nuwe aankooptransaksie skep. Itempryse word uit hierdie pryslys gehaal.,
@ -9142,8 +9093,6 @@ Conditions and Formula variable and example,Voorwaardes en formule veranderlike
Feedback By,Terugvoer deur,
MTNG-.YYYY.-.MM.-.DD.-,MTNG-.YYYY .-. MM .-. DD.-,
Manufacturing Section,Vervaardigingsafdeling,
Sales Order Required for Sales Invoice & Delivery Note Creation,Verkooporder benodig vir die maak van fakture en afleweringsnotas,
Delivery Note Required for Sales Invoice Creation,Afleweringsnota benodig vir die skep van verkoopsfakture,
"By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ",Die kliëntnaam word standaard ingestel volgens die volledige naam wat ingevoer is. As u wil hê dat klante deur &#39;n,
Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,Stel die standaardpryslys op wanneer u &#39;n nuwe verkoopstransaksie skep. Itempryse word uit hierdie pryslys gehaal.,
"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.","As hierdie opsie &#39;Ja&#39; is ingestel, sal ERPNext u verhinder om &#39;n verkoopfaktuur of afleweringsnota te maak sonder om eers &#39;n bestelling te skep. Hierdie konfigurasie kan vir &#39;n bepaalde klant oorskry word deur die &#39;Laat skepping van faktuur sonder verkooporder&#39; in die kliënt-hoof aan te skakel.",
@ -9367,8 +9316,6 @@ Courses updated,Kursusse opgedateer,
{0} {1} has been added to all the selected topics successfully.,{0} {1} is suksesvol by al die geselekteerde onderwerpe gevoeg.,
Topics updated,Onderwerpe is opgedateer,
Academic Term and Program,Akademiese termyn en program,
Last Stock Transaction for item {0} was on {1}.,Laaste voorraadtransaksie vir item {0} was op {1}.,
Stock Transactions for Item {0} cannot be posted before this time.,Voorraadtransaksies vir item {0} kan nie voor hierdie tyd gepos word nie.,
Please remove this item and try to submit again or update the posting time.,Verwyder hierdie item en probeer weer om dit in te dien of die tyd van die plasing op te dateer.,
Failed to Authenticate the API key.,Kon nie die API-sleutel verifieer nie.,
Invalid Credentials,Ongeldige magtigingsbewyse,
@ -9615,7 +9562,6 @@ Remember to set {field_label}. It is required by {regulation}.,Onthou om {field_
Enrollment Date cannot be before the Start Date of the Academic Year {0},Inskrywingsdatum kan nie voor die begindatum van die akademiese jaar wees nie {0},
Enrollment Date cannot be after the End Date of the Academic Term {0},Inskrywingsdatum kan nie na die einddatum van die akademiese termyn {0} wees nie,
Enrollment Date cannot be before the Start Date of the Academic Term {0},Inskrywingsdatum kan nie voor die begindatum van die akademiese termyn {0} wees nie,
Posting future transactions are not allowed due to Immutable Ledger,As gevolg van Immutable Ledger word toekomstige transaksies nie toegelaat nie,
Future Posting Not Allowed,Toekomstige plasing word nie toegelaat nie,
"To enable Capital Work in Progress Accounting, ","Om rekeningkundige kapitaalwerk moontlik te maak,",
you must select Capital Work in Progress Account in accounts table,u moet Capital Work in Progress-rekening in die rekeningtabel kies,
@ -9632,3 +9578,157 @@ Company Not Linked,Maatskappy nie gekoppel nie,
Import Chart of Accounts from CSV / Excel files,Voer rekeningrekeninge in vanaf CSV / Excel-lêers,
Completed Qty cannot be greater than 'Qty to Manufacture',Voltooide hoeveelheid kan nie groter wees as &#39;hoeveelheid om te vervaardig&#39;,
"Row {0}: For Supplier {1}, Email Address is Required to send an email",Ry {0}: Vir verskaffer {1} word e-posadres vereis om &#39;n e-pos te stuur,
"If enabled, the system will post accounting entries for inventory automatically","As dit geaktiveer is, sal die stelsel outomaties rekeningkundige inskrywings vir voorraad plaas",
Accounts Frozen Till Date,Rekeninge Bevrore tot op datum,
Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,"Rekeningkundige inskrywings word tot op hierdie datum gevries. Niemand kan inskrywings skep of wysig nie, behalwe gebruikers met die onderstaande rol",
Role Allowed to Set Frozen Accounts and Edit Frozen Entries,Rol toegelaat om bevrore rekeninge op te stel en bevrore inskrywings te wysig,
Address used to determine Tax Category in transactions,Adres wat gebruik word om belastingkategorie in transaksies te bepaal,
"The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ","Die persentasie waarop u toegelaat word om meer te faktureer teen die bedrag wat u bestel. As die bestelwaarde byvoorbeeld $ 100 vir &#39;n artikel is en die toleransie op 10% gestel word, mag u tot $ 110 faktureer",
This role is allowed to submit transactions that exceed credit limits,Hierdie rol word toegelaat om transaksies in te dien wat die kredietlimiete oorskry,
"If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month","As &#39;Maande&#39; gekies word, word &#39;n vaste bedrag vir elke maand as uitgestelde inkomste of uitgawe geboek, ongeag die aantal dae in &#39;n maand. Dit sal oorweeg word as uitgestelde inkomste of uitgawes vir &#39;n hele maand nie bespreek word nie",
"If this is unchecked, direct GL entries will be created to book deferred revenue or expense","As dit nie gemerk is nie, sal direkte GL-inskrywings geskep word om uitgestelde inkomste of uitgawes te bespreek",
Show Inclusive Tax in Print,Toon inklusiewe belasting in druk,
Only select this if you have set up the Cash Flow Mapper documents,Kies dit slegs as u die Cash Flow Mapper-dokumente opgestel het,
Payment Channel,Betalingskanaal,
Is Purchase Order Required for Purchase Invoice & Receipt Creation?,Is &#39;n bestelling nodig vir die skep van fakture en ontvangsbewyse?,
Is Purchase Receipt Required for Purchase Invoice Creation?,Is aankoopbewys nodig vir die skep van aankoopfakture?,
Maintain Same Rate Throughout the Purchase Cycle,Handhaaf dieselfde koers gedurende die aankoopsiklus,
Allow Item To Be Added Multiple Times in a Transaction,Laat toe dat items meerdere kere bygevoeg word in &#39;n transaksie,
Suppliers,Verskaffers,
Send Emails to Suppliers,Stuur e-posse na verskaffers,
Select a Supplier,Kies &#39;n verskaffer,
Cannot mark attendance for future dates.,Kan nie bywoning vir toekomstige datums merk nie.,
Do you want to update attendance? <br> Present: {0} <br> Absent: {1},Wil u die bywoning bywerk?<br> Aanwesig: {0}<br> Afwesig: {1},
Mpesa Settings,Mpesa-instellings,
Initiator Name,Inisieerder Naam,
Till Number,Tot nommer,
Sandbox,Sandbak,
Online PassKey,Aanlyn PassKey,
Security Credential,Sekuriteitsbewys,
Get Account Balance,Kry rekeningbalans,
Please set the initiator name and the security credential,Stel die naam van die inisieerder en die sekuriteitsbewys in,
Inpatient Medication Entry,Toelating tot medikasie vir binnepasiënte,
HLC-IME-.YYYY.-,HLC-IME-.JJJJ.-,
Item Code (Drug),Itemkode (dwelm),
Medication Orders,Medisyne bestellings,
Get Pending Medication Orders,Kry hangende medisyne-bestellings,
Inpatient Medication Orders,Mediese bestellings vir binnepasiënte,
Medication Warehouse,Medikasiepakhuis,
Warehouse from where medication stock should be consumed,Pakhuis vanwaar medisyne gebruik moet word,
Fetching Pending Medication Orders,Haal hangende medisyne-bestellings op,
Inpatient Medication Entry Detail,Inskrywingsdetail vir binnemedikasie,
Medication Details,Medikasiebesonderhede,
Drug Code,Dwelmkode,
Drug Name,Dwelmsnaam,
Against Inpatient Medication Order,Teen medikasiebevel vir binnepasiënte,
Against Inpatient Medication Order Entry,Tegniese bestellings vir medikasie vir binnepasiënte,
Inpatient Medication Order,Medikasiebevel vir binnepasiënte,
HLC-IMO-.YYYY.-,HLC-IMO-.JJJJ.-,
Total Orders,Totale bestellings,
Completed Orders,Voltooide bestellings,
Add Medication Orders,Voeg medisyne bestellings by,
Adding Order Entries,Bestelinskrywings byvoeg,
{0} medication orders completed,{0} medisyne-bestellings voltooi,
{0} medication order completed,{0} medisyne-bestelling voltooi,
Inpatient Medication Order Entry,Invoer vir medikasie vir binnepasiënte,
Is Order Completed,Is bestelling voltooi,
Employee Records to Be Created By,Werknemersrekords om deur te skep,
Employee records are created using the selected field,Werknemersrekords word met behulp van die geselekteerde veld geskep,
Don't send employee birthday reminders,Moenie werknemers se verjaardagaanmanings stuur nie,
Restrict Backdated Leave Applications,Beperk teruggedateerde verlofaansoeke,
Sequence ID,Volgorde ID,
Sequence Id,Volgorde Id,
Allow multiple material consumptions against a Work Order,Laat veelvuldige materiële verbruik teen &#39;n werkorder toe,
Plan time logs outside Workstation working hours,Beplan tydlêers buite werksure vir werkstasies,
Plan operations X days in advance,Beplan bedrywighede X dae voor die tyd,
Time Between Operations (Mins),Tyd tussen bewerkings (min.),
Default: 10 mins,Verstek: 10 minute,
Overproduction for Sales and Work Order,Oorproduksie vir verkope en werkbestelling,
"Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials","Werk BOM-koste outomaties op via die skeduleerder, gebaseer op die nuutste waardasietarief / pryslyskoers / laaste aankoopprys van grondstowwe",
Purchase Order already created for all Sales Order items,Aankooporder wat reeds vir alle verkooporderitems gemaak is,
Select Items,Kies Items,
Against Default Supplier,Teen verstekverskaffer,
Auto close Opportunity after the no. of days mentioned above,Geleentheid outomaties sluit na die nr. van die dae hierbo genoem,
Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Is verkoopsorder benodig vir die skep van verkoopsfakture en afleweringsnotas?,
Is Delivery Note Required for Sales Invoice Creation?,Is afleweringsnota nodig vir die skep van verkoopsfakture?,
How often should Project and Company be updated based on Sales Transactions?,Hoe gereeld moet Projek en Maatskappy op grond van verkoopstransaksies opgedateer word?,
Allow User to Edit Price List Rate in Transactions,Laat gebruikers toe om pryslystrate in transaksies te wysig,
Allow Item to Be Added Multiple Times in a Transaction,Laat toe dat items meerdere kere bygevoeg word in &#39;n transaksie,
Allow Multiple Sales Orders Against a Customer's Purchase Order,Laat veelvuldige verkope bestellings toe teen &#39;n klant se bestelling,
Validate Selling Price for Item Against Purchase Rate or Valuation Rate,Valideer verkoopprys vir artikel teen aankoopprys of waardasie,
Hide Customer's Tax ID from Sales Transactions,Versteek die belasting-ID van die klant van die verkoopstransaksies,
"The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.","Die persentasie wat u mag ontvang of meer aflewer teen die hoeveelheid wat u bestel. As u byvoorbeeld 100 eenhede bestel het, en u toelae 10% is, mag u 110 eenhede ontvang.",
Action If Quality Inspection Is Not Submitted,Optrede as kwaliteitsinspeksie nie ingedien word nie,
Auto Insert Price List Rate If Missing,Voeg pryslyskoers outomaties in indien ontbreek,
Automatically Set Serial Nos Based on FIFO,Stel serienummers outomaties op grond van EIEU,
Set Qty in Transactions Based on Serial No Input,Stel hoeveelheid in transaksies op basis van reeksinvoer nie,
Raise Material Request When Stock Reaches Re-order Level,Verhoog die materiaalversoek wanneer die voorraad die herbestellingsvlak bereik,
Notify by Email on Creation of Automatic Material Request,Stel dit per e-pos in kennis oor die skep van outomatiese materiaalversoek,
Allow Material Transfer from Delivery Note to Sales Invoice,Laat materiaaloordrag toe van afleweringsnota na verkoopsfaktuur,
Allow Material Transfer from Purchase Receipt to Purchase Invoice,Laat materiaaloordrag toe van aankoopbewys na aankoopfaktuur,
Freeze Stocks Older Than (Days),Vriesvoorrade ouer as (dae),
Role Allowed to Edit Frozen Stock,Rol toegelaat om bevrore voorraad te wysig,
The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,"Die bedrag wat nie toegeken is nie, is groter as die bedrag wat die banktransaksie nie toeken nie",
Payment Received,Betaling ontvang,
Attendance cannot be marked outside of Academic Year {0},Bywoning kan nie buite die akademiese jaar {0} gemerk word nie,
Student is already enrolled via Course Enrollment {0},Student is reeds ingeskryf via kursusinskrywing {0},
Attendance cannot be marked for future dates.,Bywoning kan nie gemerk word vir toekomstige datums nie.,
Please add programs to enable admission application.,Voeg asseblief programme by om die aansoek om toelating moontlik te maak.,
The following employees are currently still reporting to {0}:,Die volgende werknemers meld tans nog aan by {0}:,
Please make sure the employees above report to another Active employee.,Maak asseblief seker dat die werknemers hierbo aan &#39;n ander aktiewe werknemer rapporteer.,
Cannot Relieve Employee,Kan nie werknemer ontslaan nie,
Please enter {0},Voer asseblief {0} in,
Please select another payment method. Mpesa does not support transactions in currency '{0}',Kies &#39;n ander betaalmetode. Mpesa ondersteun nie transaksies in die geldeenheid &#39;{0}&#39;,
Transaction Error,Transaksiefout,
Mpesa Express Transaction Error,Mpesa Express-transaksiefout,
"Issue detected with Mpesa configuration, check the error logs for more details","Probleem opgespoor met Mpesa-konfigurasie, kyk na die foutlêers vir meer besonderhede",
Mpesa Express Error,Mpesa Express-fout,
Account Balance Processing Error,Verwerking van rekeningbalansfout,
Please check your configuration and try again,Gaan u konfigurasie na en probeer weer,
Mpesa Account Balance Processing Error,Verwerking van Mpesa-rekeningbalansfout,
Balance Details,Balansbesonderhede,
Current Balance,Huidige balaans,
Available Balance,Beskikbare balans,
Reserved Balance,Gereserveerde balans,
Uncleared Balance,Onduidelike balans,
Payment related to {0} is not completed,Betaling wat verband hou met {0} is nie voltooi nie,
Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.,Ry # {}: reeksnommer {}. {} is reeds oorgedra na &#39;n ander POS-faktuur. Kies &#39;n geldige reeksnr.,
Row #{}: Item Code: {} is not available under warehouse {}.,Ry # {}: Itemkode: {} is nie beskikbaar onder pakhuis {} nie.,
Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.,Ry # {}: voorraadhoeveelheid nie genoeg vir artikelkode: {} onder pakhuis {}. Beskikbare hoeveelheid {}.,
Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.,Ry # {}: kies &#39;n reeksnommer en &#39;n bondel teenoor item: {} of verwyder dit om die transaksie te voltooi.,
Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.,Ry # {}: Geen reeksnommer is gekies teenoor item nie: {}. Kies een of verwyder dit om die transaksie te voltooi.,
Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.,Ry # {}: Geen groep gekies teenoor item nie: {}. Kies &#39;n groep of verwyder dit om die transaksie te voltooi.,
Payment amount cannot be less than or equal to 0,Betalingsbedrag kan nie kleiner as of gelyk aan 0 wees nie,
Please enter the phone number first,Voer eers die telefoonnommer in,
Row #{}: {} {} does not exist.,Ry # {}: {} {} bestaan nie.,
Row #{0}: {1} is required to create the Opening {2} Invoices,Ry # {0}: {1} is nodig om die openingsfakture {2} te skep,
You had {} errors while creating opening invoices. Check {} for more details,Daar was {} foute tydens die skep van openingsfakture. Gaan na {} vir meer besonderhede,
Error Occured,Fout het voorgekom,
Opening Invoice Creation In Progress,Die opening van die skep van fakture aan die gang,
Creating {} out of {} {},Skep tans {} uit {} {},
(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,"(Serienommer: {0}) kan nie verbruik word nie, aangesien dit gereserveer is vir die volledige bestelling {1}.",
Item {0} {1},Item {0} {1},
Last Stock Transaction for item {0} under warehouse {1} was on {2}.,Laaste voorraadtransaksie vir item {0} onder pakhuis {1} was op {2}.,
Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,Voorraadtransaksies vir item {0} onder pakhuis {1} kan nie voor hierdie tyd gepos word nie.,
Posting future stock transactions are not allowed due to Immutable Ledger,"As gevolg van Onveranderlike Grootboek, word toekomstige aandeletransaksies nie toegelaat nie",
A BOM with name {0} already exists for item {1}.,&#39;N BOM met die naam {0} bestaan reeds vir item {1}.,
{0}{1} Did you rename the item? Please contact Administrator / Tech support,{0} {1} Het jy die item hernoem? Kontak administrateur / tegniese ondersteuning,
At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},Op ry # {0}: die volgorde-ID {1} mag nie kleiner wees as die vorige ryvolg-ID {2},
The {0} ({1}) must be equal to {2} ({3}),Die {0} ({1}) moet gelyk wees aan {2} ({3}),
"{0}, complete the operation {1} before the operation {2}.","{0}, voltooi die bewerking {1} voor die bewerking {2}.",
Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No.,"Kan nie verseker dat aflewering per reeksnr. Nie, aangesien artikel {0} bygevoeg word met en sonder versekering deur afleweringnr.",
Item {0} has no Serial No. Only serilialized items can have delivery based on Serial No,Item {0} het geen reeksnommer nie. Slegs geassosialiseerde items kan afgelewer word op grond van reeksnr,
No active BOM found for item {0}. Delivery by Serial No cannot be ensured,Geen aktiewe BOM vir item {0} gevind nie. Aflewering per reeksnommer kan nie verseker word nie,
No pending medication orders found for selected criteria,Geen hangende medikasiebestellings vir geselekteerde kriteria gevind nie,
From Date cannot be after the current date.,Vanaf datum kan nie na die huidige datum wees nie.,
To Date cannot be after the current date.,To Date kan nie na die huidige datum wees nie.,
From Time cannot be after the current time.,Van tyd kan nie na die huidige tyd wees nie.,
To Time cannot be after the current time.,To Time kan nie na die huidige tyd wees nie.,
Stock Entry {0} created and ,Voorraadinskrywing {0} geskep en,
Inpatient Medication Orders updated successfully,Mediese bestellings vir binnepasiënte is suksesvol opgedateer,
Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1},Ry {0}: kan nie inskrywingsmedikasie-inskrywing skep teen die gekanselleerde bestelling vir binnepasiëntmedikasie nie {1},
Row {0}: This Medication Order is already marked as completed,Ry {0}: hierdie medisyne-bestelling is reeds as voltooi gemerk,
Quantity not available for {0} in warehouse {1},Hoeveelheid nie beskikbaar vir {0} in pakhuis {1},
Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.,Aktiveer asseblief Laat negatiewe voorraad toe in voorraadinstellings of skep voorraadinskrywing om voort te gaan.,
No Inpatient Record found against patient {0},Geen pasiëntrekord gevind teen pasiënt nie {0},
An Inpatient Medication Order {0} against Patient Encounter {1} already exists.,Daar bestaan reeds &#39;n medikasiebevel vir binnepasiënte {0} teen pasiëntontmoeting {1}.,

Can't render this file because it is too large.

View File

@ -110,7 +110,6 @@ Actual qty in stock,በክምችት ውስጥ ትክክለኛው ብዛት,
Actual type tax cannot be included in Item rate in row {0},ትክክለኛው ዓይነት የግብር ረድፍ ውስጥ ንጥል ተመን ውስጥ ሊካተቱ አይችሉም {0},
Add,አክል,
Add / Edit Prices,/ አርትዕ ዋጋዎች አክል,
Add All Suppliers,ሁሉንም አቅራቢዎች አክል,
Add Comment,አስተያየት ያክሉ,
Add Customers,ደንበኞች ያክሉ,
Add Employees,ሰራተኞችን አክል,
@ -480,7 +479,6 @@ Cannot produce more Item {0} than Sales Order quantity {1},የሽያጭ ትዕ
Cannot promote Employee with status Left,በአስተዳዳሪ ሁኔታ ወደ ሠራተኛ ማስተዋወቅ አይቻልም,
Cannot refer row number greater than or equal to current row number for this Charge type,ይህ የክፍያ ዓይነት የአሁኑ ረድፍ ቁጥር ይበልጣል ወይም እኩል ረድፍ ቁጥር ሊያመለክት አይችልም,
Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,የመጀመሪያውን ረድፍ ለ &#39;ቀዳሚ ረድፍ ጠቅላላ ላይ&#39; &#39;ቀዳሚ የረድፍ መጠን ላይ&#39; እንደ ክፍያ አይነት መምረጥ ወይም አይቻልም,
Cannot set a received RFQ to No Quote,የተቀበሉት አር.ኤም.ፒ. ወደ &quot;ምንም&quot; የለም,
Cannot set as Lost as Sales Order is made.,የሽያጭ ትዕዛዝ ነው እንደ የጠፋ እንደ ማዘጋጀት አልተቻለም.,
Cannot set authorization on basis of Discount for {0},ለ ቅናሽ ላይ የተመሠረተ ፈቃድ ማዘጋጀት አይቻልም {0},
Cannot set multiple Item Defaults for a company.,የአንድ ኩባንያ ብዙ ንጥል ነባሪዎችን ማዘጋጀት አይቻልም.,
@ -934,7 +932,6 @@ Employee Referral,ሠራተኛ ሪፈራል,
Employee Transfer cannot be submitted before Transfer Date ,የተቀጣሪ ዝውውሩ ከመሸጋገሪያ ቀን በፊት መቅረብ አይችልም,
Employee cannot report to himself.,የተቀጣሪ ራሱን ሪፖርት አይችልም.,
Employee relieved on {0} must be set as 'Left',{0} መዘጋጀት አለበት ላይ እፎይታ ሠራተኛ &#39;ግራ&#39; እንደ,
Employee status cannot be set to 'Left' as following employees are currently reporting to this employee:&nbsp;,የሚከተሉት ሠራተኞች በአሁኑ ወቅት ለዚህ ሠራተኛ ሪፖርት እያደረጉ ስለሆነ የሰራተኛ ሁኔታ ወደ &#39;ግራ&#39; መደረግ አይችልም ፡፡,
Employee {0} already submited an apllication {1} for the payroll period {2},ተቀጣሪ {0} ለደመወዙ ጊዜ {,
Employee {0} has already applied for {1} between {2} and {3} : ,ተቀጣሪ {0} ቀድሞውኑ በ {2} እና በ {3} መካከል በ {1} አመልክቷል:,
Employee {0} has no maximum benefit amount,ተቀጣሪ / ሰራተኛ {0} ከፍተኛውን ጥቅም የለውም,
@ -1456,7 +1453,6 @@ Leave application {0} already exists against the student {1},መተግበሪያ
"Leave cannot be allocated before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","በፊት የተመደበ አይችልም ይተዉት {0}, ፈቃድ ቀሪ አስቀድሞ የማስቀመጫ-በሚተላለፈው ወደፊት ፈቃድ አመዳደብ መዝገብ ውስጥ ቆይቷል እንደ {1}",
"Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}",ፈቃድ ቀሪ አስቀድሞ የማስቀመጫ-በሚተላለፈው ወደፊት ፈቃድ አመዳደብ መዝገብ ውስጥ ቆይቷል እንደ በፊት {0} ቀርቷል / መተግበር አይችልም ተወው {1},
Leave of type {0} cannot be longer than {1},አይነት ፈቃድ {0} በላይ ሊሆን አይችልም {1},
Leave the field empty to make purchase orders for all suppliers,ለሁሉም አቅራቢዎች የግዢ ትዕዛዞችን ለማድረግ መስኩን ባዶ ይተዉት,
Leaves,ቅጠሎች,
Leaves Allocated Successfully for {0},ለ በተሳካ ሁኔታ የተመደበ ማምለኩን {0},
Leaves has been granted sucessfully,ቅጠሎች በተሳካ ሁኔታ ተሰጥተዋል,
@ -1699,7 +1695,6 @@ No Items to pack,ምንም ንጥሎች ለመሸከፍ,
No Items with Bill of Materials to Manufacture,ዕቃዎች መካከል ቢል ጋር ምንም ንጥሎች ለማምረት,
No Items with Bill of Materials.,በቢል ቁሳቁሶች ከቁጥሮች ጋር ምንም ዕቃዎች የሉም ፡፡,
No Permission,ምንም ፍቃድ,
No Quote,ምንም መግለጫ የለም,
No Remarks,ምንም መግለጫዎች,
No Result to submit,ለማስገባት ምንም ውጤት የለም,
No Salary Structure assigned for Employee {0} on given date {1},በተሰጠው ቀን {0} ላይ ለተቀጠረ ተቀጣሪ {0} የተመደበ ደመወዝ,
@ -1856,7 +1851,6 @@ Overlap in scoring between {0} and {1},በ {0} እና በ {1} መካከል በ
Overlapping conditions found between:,መካከል ተገኝቷል ከተደራቢ ሁኔታ:,
Owner,ባለቤት,
PAN,PAN,
PO already created for all sales order items,ፖስታው ቀድሞውኑ ለሁሉም የሽያጭ ነገዶች እቃዎች ተፈጥሯል,
POS,POS,
POS Profile,POS መገለጫ,
POS Profile is required to use Point-of-Sale,POS የመሸጫ ቦታን ለመጠቀም POS የመጠየቅ ግዴታ አለበት,
@ -2502,7 +2496,6 @@ Row {0}: Quality Inspection rejected for item {1},ረድፍ {0}: የጥራት
Row {0}: UOM Conversion Factor is mandatory,ረድፍ {0}: UOM የልወጣ ምክንያት የግዴታ ነው,
Row {0}: select the workstation against the operation {1},ረድፍ {0}: ከግዜው ላይ {1},
Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.,ረድፍ {0}: {1} የቁጥር ቁጥሮች ለ Item {2} ያስፈልጋሉ. {3} ሰጥተሃል.,
Row {0}: {1} is required to create the Opening {2} Invoices,ረድፍ {0}: ክፍት {2} ደረሰኞችን ለመፍጠር {1} ያስፈልጋል,
Row {0}: {1} must be greater than 0,ረድፍ {0}: {1} ከ 0 በላይ መሆን አለበት,
Row {0}: {1} {2} does not match with {3},ረድፍ {0}: {1} {2} ጋር አይዛመድም {3},
Row {0}:Start Date must be before End Date,ረድፍ {0}: የመጀመሪያ ቀን ከመጨረሻ ቀን በፊት መሆን አለበት,
@ -2642,7 +2635,6 @@ Selling Rate,የሽያጭ ፍጥነት,
Send Grant Review Email,የእርዳታ ግምገማን ኢሜይል ላክ,
Send Now,አሁን ላክ,
Send SMS,ኤስ ኤም ኤስ ላክ,
Send Supplier Emails,አቅራቢው ኢሜይሎች ላክ,
Send mass SMS to your contacts,የመገናኛ ኤስ የእርስዎን እውቂያዎች ላክ,
Sensitivity,ትብነት,
Sent,ተልኳል,
@ -3443,7 +3435,6 @@ on,ላይ,
{0} variants created.,{0} ፈጣሪዎች ተፈጥረዋል.,
{0} {1} created,{0} {1} ተፈጥሯል,
{0} {1} does not exist,{0} {1} የለም,
{0} {1} does not exist.,{0} {1} የለም.,
{0} {1} has been modified. Please refresh.,{0} {1} ተቀይሯል. እባክዎ ያድሱ.,
{0} {1} has not been submitted so the action cannot be completed,"{0} {1} እርምጃ ሊጠናቀቅ አልቻለም, ስለዚህ ገብቷል አልተደረገም",
"{0} {1} is associated with {2}, but Party Account is {3}",{0} {1} ከ {2} ጋር የተያያዘ ነው ነገር ግን የፓርቲ መለያ {3},
@ -3480,6 +3471,7 @@ on,ላይ,
{0}: {1} does not exists,{0}: {1} ነው አይደለም አለ,
{0}: {1} not found in Invoice Details table,{0}: {1} የደረሰኝ ዝርዝሮች ሠንጠረዥ ውስጥ አልተገኘም,
{} of {},{} ከ {},
Assigned To,የተመደበ,
Chat,ውይይት,
Completed By,ተጠናቅቋል,
Conditions,ሁኔታዎች,
@ -3502,6 +3494,7 @@ Merge with existing,ነባር ጋር አዋህድ,
Office,ቢሮ,
Orientation,አቀማመጥ,
Passive,የማይሠራ,
Payment Failed,ክፍያ አልተሳካም,
Percent,መቶኛ,
Permanent,ቋሚ,
Personal,የግል,
@ -3566,6 +3559,8 @@ Naming Series,መሰየምን ተከታታይ,
No data to export,ወደ ውጭ ለመላክ ምንም ውሂብ የለም።,
Portrait,ፎቶግራፍ,
Print Heading,አትም HEADING,
Scheduler Inactive,መርሐግብር አስያዥ ንቁ ያልሆነ።,
Scheduler is inactive. Cannot import data.,መርሐግብር አስያዥ ንቁ አይደለም። ውሂብ ማስመጣት አልተቻለም።,
Show Document,ሰነድ አሳይ።,
Show Traceback,Traceback አሳይ።,
Video,ቪዲዮ ፡፡,
@ -3691,7 +3686,6 @@ Create Pick List,ይምረጡ ዝርዝር ይፍጠሩ።,
Create Quality Inspection for Item {0},ለእቃው ጥራት ምርመራን ይፍጠሩ {0},
Creating Accounts...,መለያዎችን በመፍጠር ላይ ...,
Creating bank entries...,የባንክ ግቤቶችን በመፍጠር ላይ ...,
Creating {0},{0} በመፍጠር ላይ,
Credit limit is already defined for the Company {0},የብድር መጠን ለድርጅቱ ቀድሞውኑ ተገልጻል {0},
Ctrl + Enter to submit,ለማስገባት Ctrl + ያስገቡ,
Ctrl+Enter to submit,ለማስገባት Ctrl + Enter ይጫኑ,
@ -4524,31 +4518,22 @@ Closed Documents,የተዘጉ ሰነዶች,
Accounts Settings,ቅንብሮች መለያዎች,
Settings for Accounts,መለያዎች ቅንብሮች,
Make Accounting Entry For Every Stock Movement,እያንዳንዱ የአክሲዮን ንቅናቄ ለ በአካውንቲንግ የሚመዘገብ አድርግ,
"If enabled, the system will post accounting entries for inventory automatically.","የነቃ ከሆነ, ስርዓት በራስ ሰር ክምችት ለ የሂሳብ ግቤቶች መለጠፍ ነው.",
Accounts Frozen Upto,Frozen እስከሁለት መለያዎች,
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","ከዚህ ቀን ድረስ በበረዶ ዲግሪ ግቤት, ማንም / ማድረግ ከዚህ በታች በተጠቀሰው ሚና በስተቀር ግቤት መቀየር ይችላል.",
Role Allowed to Set Frozen Accounts & Edit Frozen Entries,ሚና Frozen መለያዎች &amp; አርትዕ Frozen ግቤቶችን አዘጋጅ የሚፈቀድለት,
Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,ይህን ሚና ያላቸው ተጠቃሚዎች የታሰሩ መለያዎች ላይ የሂሳብ ግቤቶች የታሰሩ መለያዎች ማዘጋጀት እና ለመፍጠር ቀይር / የተፈቀደላቸው,
Determine Address Tax Category From,የአድራሻ ግብር ምድብ ከ,
Address used to determine Tax Category in transactions.,በግብይቶች ውስጥ የግብር ምድብን ለመለየት የሚያገለግል አድራሻ።,
Over Billing Allowance (%),ከሂሳብ አበል በላይ (%),
Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.,በሚታዘዘው መጠን ላይ ተጨማሪ ሂሳብ እንዲከፍሉ ተፈቅዶልዎታል። ለምሳሌ-የትእዛዝ ዋጋ ለአንድ ነገር $ 100 ዶላር ከሆነ እና መቻቻል 10% ሆኖ ከተቀናበረ $ 110 እንዲከፍሉ ይፈቀድልዎታል።,
Credit Controller,የብድር መቆጣጠሪያ,
Role that is allowed to submit transactions that exceed credit limits set.,ካልተዋቀረ የብድር ገደብ መብለጥ መሆኑን ግብይቶችን ማቅረብ አይፈቀድም ነው ሚና.,
Check Supplier Invoice Number Uniqueness,ማጣሪያ አቅራቢው የደረሰኝ ቁጥር ልዩ,
Make Payment via Journal Entry,ጆርናል Entry በኩል ክፍያ አድርግ,
Unlink Payment on Cancellation of Invoice,የደረሰኝ ስረዛ ላይ ክፍያ አታገናኝ,
Book Asset Depreciation Entry Automatically,መጽሐፍ የንብረት ዋጋ መቀነስ Entry ሰር,
Automatically Add Taxes and Charges from Item Tax Template,ከእቃው ግብር አብነት ግብርን እና ክፍያዎች በራስ-ሰር ያክሉ።,
Automatically Fetch Payment Terms,የክፍያ ውሎችን በራስ-ሰር ያውጡ።,
Show Inclusive Tax In Print,Inclusive Tax In Print ውስጥ አሳይ,
Show Payment Schedule in Print,የክፍያ ዕቅድ በ Print ውስጥ አሳይ,
Currency Exchange Settings,የምንዛሬ ልውውጥ ቅንብሮች,
Allow Stale Exchange Rates,የተለመዱ ትውልዶች ፍቀድ,
Stale Days,የቆዳ ቀናቶች,
Report Settings,ሪፖርት ቅንብሮችን ሪፖርት አድርግ,
Use Custom Cash Flow Format,ብጁ የገንዘብ ፍሰት ቅርጸት ተጠቀም,
Only select if you have setup Cash Flow Mapper documents,የ &quot;Cash Flow Mapper&quot; ሰነዶች ካለህ ብቻ ምረጥ,
Allowed To Transact With,ለማስተላለፍ የተፈቀደለት,
SWIFT number,SWIFT ቁጥር,
Branch Code,የቅርንጫፍ ኮድ,
@ -5485,8 +5470,6 @@ Settings for Buying Module,ሞዱል ስለመግዛት ቅንብሮች,
Supplier Naming By,በ አቅራቢው አሰያየም,
Default Supplier Group,ነባሪ የአቅራቢ ቡድን,
Default Buying Price List,ነባሪ መግዛትና ዋጋ ዝርዝር,
Maintain same rate throughout purchase cycle,የግዢ ዑደት ውስጥ ተመሳሳይ መጠን ይኑራችሁ,
Allow Item to be added multiple times in a transaction,ንጥል አንድ ግብይት ውስጥ በርካታ ጊዜያት መታከል ፍቀድ,
Backflush Raw Materials of Subcontract Based On,የቢሮ ውጣ ውረጅ ቁሳቁስ,
Material Transferred for Subcontract,ለንዐስ ኮንትራቱ የተሸጋገሩ ቁሳቁሶች,
Over Transfer Allowance (%),ከ የማስተላለፍ አበል (%),
@ -5530,7 +5513,6 @@ Purchase Receipt Item Supplied,የግዢ ደረሰኝ ንጥል አቅርቦት,
Current Stock,የአሁኑ የአክሲዮን,
PUR-RFQ-.YYYY.-,PUR-RFQ-yYYY.-,
For individual supplier,ግለሰብ አቅራቢ ለ,
Supplier Detail,በአቅራቢዎች ዝርዝር,
Link to Material Requests,ወደ ቁሳዊ ጥያቄዎች አገናኝ,
Message for Supplier,አቅራቢ ለ መልዕክት,
Request for Quotation Item,ትዕምርተ ንጥል ጥያቄ,
@ -6724,10 +6706,7 @@ HR Settings,የሰው ኃይል ቅንብሮች,
Employee Settings,የሰራተኛ ቅንብሮች,
Retirement Age,ጡረታ ዕድሜ,
Enter retirement age in years,ዓመታት ውስጥ ጡረታ ዕድሜ ያስገቡ,
Employee Records to be created by,ሠራተኛ መዛግብት መፈጠር አለበት,
Employee record is created using selected field. ,የተቀጣሪ መዝገብ የተመረጠው መስክ በመጠቀም የተፈጠረ ነው.,
Stop Birthday Reminders,አቁም የልደት ቀን አስታዋሾች,
Don't send Employee Birthday Reminders,የተቀጣሪ የልደት አስታዋሾች አትላክ,
Expense Approver Mandatory In Expense Claim,የወጪ ፍቃድ አስገዳጅ በክፍያ ጥያቄ,
Payroll Settings,ከደመወዝ ክፍያ ቅንብሮች,
Leave,ተወው,
@ -6749,7 +6728,6 @@ Role Allowed to Create Backdated Leave Application,የቀደመ ፈቃድ ማመ
Leave Approver Mandatory In Leave Application,ፈቃድ ሰጪ አመልካች ትተው ማመልከቻ ማመልከቻ,
Show Leaves Of All Department Members In Calendar,በቀን መቁጠሪያ ውስጥ የሁሉም የመጓጓዣ አባላት ቅጠሎች ያሳዩ,
Auto Leave Encashment,ራስ-ሰር ማጠናከሪያ,
Restrict Backdated Leave Application,የተለቀቀውን የመልቀቂያ ማመልከቻን ገድብ,
Hiring Settings,የቅጥር ቅንጅቶች,
Check Vacancies On Job Offer Creation,በሥራ አቅርቦት ፈጠራ ላይ ክፍት ቦታዎችን ይፈትሹ ፡፡,
Identification Document Type,የመታወቂያ ሰነድ ዓይነት,
@ -7283,28 +7261,21 @@ Completed Qty,ተጠናቋል ብዛት,
Manufacturing Settings,ማኑፋክቸሪንግ ቅንብሮች,
Raw Materials Consumption,ጥሬ ዕቃዎች ፍጆታ,
Allow Multiple Material Consumption,በርካታ የቁሳቁሶችን ፍቃድን ይፍቀዱ,
Allow multiple Material Consumption against a Work Order,ከአንድ የስራ ትዕዛዝ በላይ ብዙ ቁሳቁሶችን ይፍቀዱ,
Backflush Raw Materials Based On,Backflush ጥሬ እቃዎች ላይ የተመረኮዘ ላይ,
Material Transferred for Manufacture,ቁሳዊ ማምረት ለ ተላልፈዋል,
Capacity Planning,የአቅም ዕቅድ,
Disable Capacity Planning,የአቅም ማቀድን ያሰናክሉ,
Allow Overtime,የትርፍ ሰዓት ፍቀድ,
Plan time logs outside Workstation Working Hours.,ከገቢር የሥራ ሰዓት ውጪ ጊዜ መዝገቦች ያቅዱ.,
Allow Production on Holidays,በዓላት ላይ ምርት ፍቀድ,
Capacity Planning For (Days),(ቀኖች) ያህል አቅም ዕቅድ,
Try planning operations for X days in advance.,አስቀድሞ X ቀኖች ለ ቀዶ ዕቅድ ይሞክሩ.,
Time Between Operations (in mins),(ደቂቃዎች ውስጥ) ክወናዎች መካከል ሰዓት,
Default 10 mins,10 ደቂቃ ነባሪ,
Default Warehouses for Production,ለምርት ነባሪ መጋዘኖች,
Default Work In Progress Warehouse,የሂደት መጋዘን ውስጥ ነባሪ ሥራ,
Default Finished Goods Warehouse,ነባሪ ጨርሷል ዕቃዎች መጋዘን,
Default Scrap Warehouse,ነባሪ የስዕል መለጠፊያ መጋዘን,
Over Production for Sales and Work Order,ለሽያጭ እና ለሥራ ትዕዛዝ ከ ምርት በላይ,
Overproduction Percentage For Sales Order,የሽያጭ ምርት በመቶኛ ለሽያጭ ትእዛዝ,
Overproduction Percentage For Work Order,ለስራ ቅደም ተከተል የማካካሻ ምርቶች መቶኛ,
Other Settings,ሌሎች ቅንብሮች,
Update BOM Cost Automatically,የቤቶች ዋጋ በራስ-ሰር ያዘምኑ,
"Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.",በቅርብ ጊዜ የተመን ዋጋ / የዋጋ ዝርዝር / በመጨረሻው የጥሬ ዕቃ ዋጋ ላይ በመመርኮዝ የወኪል ማስተካከያውን በጊዜ መርሐግብር በኩል በራስሰር ያስከፍላል.,
Material Request Plan Item,የቁሳዊ እሴት ጥያቄ እቅድ,
Material Request Type,ቁሳዊ ጥያቄ አይነት,
Material Issue,ቁሳዊ ችግር,
@ -7771,15 +7742,9 @@ Campaign Naming By,በ የዘመቻ አሰያየም,
Default Customer Group,ነባሪ የደንበኛ ቡድን,
Default Territory,ነባሪ ግዛት,
Close Opportunity After Days,ቀናት በኋላ ዝጋ አጋጣሚ,
Auto close Opportunity after 15 days,15 ቀናት በኋላ ራስ የቅርብ አጋጣሚ,
Default Quotation Validity Days,ነባሪ ትዕዛዝ ዋጋ መስጫ ቀናት,
Sales Update Frequency,የሽያጭ የማሻሻያ ድግግሞሽ,
How often should project and company be updated based on Sales Transactions.,በሽርክም ትራንስፖርቶች መሠረት ፕሮጀክቱ እና ኩባንያው በየስንት ጊዜ ማዘመን አለባቸው.,
Each Transaction,እያንዳንዱ ግብይት,
Allow user to edit Price List Rate in transactions,የተጠቃሚ ግብይቶችን የዋጋ ዝርዝር ተመን አርትዕ ለማድረግ ፍቀድ,
Allow multiple Sales Orders against a Customer's Purchase Order,አንድ የደንበኛ የግዢ ትዕዛዝ ላይ በርካታ የሽያጭ ትዕዛዞች ፍቀድ,
Validate Selling Price for Item against Purchase Rate or Valuation Rate,የግዢ Rate ወይም ግምቱ ተመን ላይ ንጥል ለ ሽያጭ ዋጋ Validate,
Hide Customer's Tax Id from Sales Transactions,የሽያጭ ግብይቶች ከ የደንበኛ የግብር መታወቂያ ደብቅ,
SMS Center,ኤስ ኤም ኤስ ማዕከል,
Send To,ወደ ላክ,
All Contact,ሁሉም እውቂያ,
@ -8388,24 +8353,14 @@ Default Item Group,ነባሪ ንጥል ቡድን,
Default Stock UOM,ነባሪ የክምችት UOM,
Sample Retention Warehouse,የናሙና ማቆያ መደብር,
Default Valuation Method,ነባሪ ዋጋ ትመና ዘዴው,
Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.,መቶኛ መቀበል ወይም አዘዘ መጠን ላይ ተጨማሪ ማድረስ ይፈቀዳል. ለምሳሌ: 100 ቤቶች ትእዛዝ ከሆነ. እና በል ከዚያም 110 ቤቶች ለመቀበል የተፈቀደላቸው 10% ነው.,
Action if Quality inspection is not submitted,የጥራት ምርመራ ካልተደረገ እርምጃ,
Show Barcode Field,አሳይ ባርኮድ መስክ,
Convert Item Description to Clean HTML,የኤች ቲ ኤም ኤል ን የእርሳስ መግለጫ ቀይር,
Auto insert Price List rate if missing,ራስ-ያስገቡ ዋጋ ዝርዝር መጠን ይጎድለዋል ከሆነ,
Allow Negative Stock,አሉታዊ የአክሲዮን ፍቀድ,
Automatically Set Serial Nos based on FIFO,በራስ-ሰር FIFO ላይ የተመሠረተ ቁጥሮች መለያ አዘጋጅ,
Set Qty in Transactions based on Serial No Input,በ Serial No Entput ላይ በመመርኮዝ ስንት ግምት ያዘጋጁ,
Auto Material Request,ራስ-ሐሳብ ያለው ጥያቄ,
Raise Material Request when stock reaches re-order level,የአክሲዮን ዳግም-ትዕዛዝ ደረጃ ላይ ሲደርስ የቁሳዊ ጥያቄ ላይ አንሥታችሁ,
Notify by Email on creation of automatic Material Request,ራስ-ሰር የቁስ ጥያቄ መፍጠር ላይ በኢሜይል አሳውቅ,
Inter Warehouse Transfer Settings,የኢንተር መጋዘን ማስተላለፍ ቅንብሮች,
Allow Material Transfer From Delivery Note and Sales Invoice,ከመላኪያ ማስታወሻ እና ከሽያጭ ደረሰኝ ላይ ቁሳቁስ ማስተላለፍን ይፍቀዱ,
Allow Material Transfer From Purchase Receipt and Purchase Invoice,የቁሳቁስ ሽግግር ከግዢ ደረሰኝ እና የግዢ ደረሰኝ ይፍቀዱ,
Freeze Stock Entries,አርጋ Stock ግቤቶችን,
Stock Frozen Upto,የክምችት Frozen እስከሁለት,
Freeze Stocks Older Than [Days],እሰር አክሲዮኖች የቆየ ይልቅ [ቀኖች],
Role Allowed to edit frozen stock,ሚና የታሰረው የአክሲዮን አርትዕ ማድረግ ተፈቅዷል,
Batch Identification,የቡድን መለያ,
Use Naming Series,ስም መስጠት ስሞችን ተጠቀም,
Naming Series Prefix,የሶስት ቅንጅቶችን ስም በማውጣት ላይ,
@ -8731,11 +8686,9 @@ Published on,ታትሟል,
Service Received But Not Billed,አገልግሎት ተቀበለ ግን አልተከፈለም,
Deferred Accounting Settings,የዘገየ የሂሳብ አያያዝ ቅንብሮች,
Book Deferred Entries Based On,በመጽሐፍ ላይ ተመስርተው የተዘገዩ ግቤዎች,
"If ""Months"" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",&quot;ወሮች&quot; ከተመረጠ ከዚያ የተወሰነ መጠን በአንድ ወር ውስጥ የቀኖች ብዛት ምንም ይሁን ምን ለእያንዳንዱ ወር እንደዘገየ ገቢ ወይም ወጪ ይቆጠራሉ። የተዘገዘ ገቢ ወይም ወጪ ለአንድ ወር በሙሉ ካልተያዘ ይረጋገጣል።,
Days,ቀናት,
Months,ወሮች,
Book Deferred Entries Via Journal Entry,የመጽሔት መዘግየት ግቤቶች በጆርናል መግቢያ በኩል,
If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense,ይህ ካልተመረመረ ቀጥታ የ GL ግቤቶች የተዘገዘ ገቢ / ወጪን ለማስያዝ ይፈጠራሉ,
Submit Journal Entries,የጆርናል ግቤቶችን ያስገቡ,
If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,ይህ ካልተመረመረ የጆርናል ግቤቶች በረቂቅ ሁኔታ ውስጥ ይቀመጣሉ እና በእጅ መቅረብ አለባቸው,
Enable Distributed Cost Center,የተሰራጨ የወጪ ማዕከልን ያንቁ,
@ -8880,8 +8833,6 @@ Source State,ምንጭ ግዛት,
Is Inter State,የኢንተር ግዛት ነው,
Purchase Details,የግዢ ዝርዝሮች,
Depreciation Posting Date,የዋጋ ቅናሽ መለጠፊያ ቀን,
Purchase Order Required for Purchase Invoice & Receipt Creation,ለግዢ መጠየቂያ እና ደረሰኝ ፈጠራ የግዢ ትዕዛዝ ያስፈልጋል,
Purchase Receipt Required for Purchase Invoice Creation,የግዢ ደረሰኝ ለመፍጠር የግዢ ደረሰኝ ያስፈልጋል,
"By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ",በነባሪነት የአቅራቢው ስም እንደገባው በአቅራቢው ስም ይዋቀራል ፡፡ አቅራቢዎች በ እንዲሰየሙ ከፈለጉ,
choose the 'Naming Series' option.,የ “ስያሜ ተከታታይ” ን ይምረጡ።,
Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,አዲስ የግዢ ግብይት ሲፈጥሩ ነባሪውን የዋጋ ዝርዝር ያዋቅሩ። የእቃ ዋጋዎች ከዚህ የዋጋ ዝርዝር ውስጥ ይፈለጋሉ።,
@ -9142,8 +9093,6 @@ Conditions and Formula variable and example,ሁኔታዎች እና የቀመር
Feedback By,ግብረመልስ በ,
MTNG-.YYYY.-.MM.-.DD.-,MTNG-.YYYY.-MM. - ዲ.ዲ.-,
Manufacturing Section,የማምረቻ ክፍል,
Sales Order Required for Sales Invoice & Delivery Note Creation,ለሽያጭ መጠየቂያ እና አቅርቦት የማስረከቢያ ማስታወሻ የሽያጭ ትዕዛዝ ያስፈልጋል,
Delivery Note Required for Sales Invoice Creation,የመላኪያ ማስታወሻ ለሽያጭ መጠየቂያ ደረሰኝ ፈጠራ ያስፈልጋል,
"By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ",በነባሪነት የደንበኛው ስም እንደገባው ሙሉ ስም ይዋቀራል ፡፡ ደንበኞች በ እንዲሰየሙ ከፈለጉ,
Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,አዲስ የሽያጭ ግብይት ሲፈጥሩ ነባሪውን የዋጋ ዝርዝር ያዋቅሩ። የእቃ ዋጋዎች ከዚህ የዋጋ ዝርዝር ውስጥ ይፈለጋሉ።,
"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.",ይህ አማራጭ ‹አዎ› ከተዋቀረ ERPNext በመጀመሪያ የሽያጭ ትዕዛዝ ሳይፈጥሩ የሽያጭ መጠየቂያ መጠየቂያ ወይም የማስረከቢያ ማስታወሻ እንዳይፈጥሩ ይከለክልዎታል ፡፡ በደንበኛው ማስተር ውስጥ የ ‹የሽያጭ መጠየቂያ መጠየቂያ ያለ የሽያጭ ትዕዛዝ ፍቀድ› አመልካች ሳጥንን በማንቃት ይህ ውቅር ለአንድ የተወሰነ ደንበኛ ሊተካ ይችላል ፡፡,
@ -9367,8 +9316,6 @@ Courses updated,ትምህርቶች ተዘምነዋል,
{0} {1} has been added to all the selected topics successfully.,{0} {1} በተሳካ ሁኔታ ወደ ሁሉም በተመረጡት ርዕሶች ታክሏል,
Topics updated,ርዕሶች ዘምነዋል,
Academic Term and Program,የትምህርት ጊዜ እና ፕሮግራም,
Last Stock Transaction for item {0} was on {1}.,ለንጥል {0} የመጨረሻው የአክሲዮን ግብይት በ {1} ላይ ነበር።,
Stock Transactions for Item {0} cannot be posted before this time.,የንጥል ክምችት ግብይቶች {0} ከዚህ ጊዜ በፊት መለጠፍ አይቻልም።,
Please remove this item and try to submit again or update the posting time.,እባክዎ ይህንን ንጥል ያስወግዱ እና እንደገና ለማስገባት ይሞክሩ ወይም የመለጠፍ ጊዜውን ያዘምኑ።,
Failed to Authenticate the API key.,የኤፒአይ ቁልፍን ማረጋገጥ አልተሳካም።,
Invalid Credentials,ልክ ያልሆኑ ምስክርነቶች,
@ -9615,7 +9562,6 @@ Remember to set {field_label}. It is required by {regulation}.,{Field_label} ን
Enrollment Date cannot be before the Start Date of the Academic Year {0},የምዝገባ ቀን ከአካዳሚክ አመቱ መጀመሪያ ቀን በፊት መሆን አይችልም {0},
Enrollment Date cannot be after the End Date of the Academic Term {0},የመመዝገቢያ ቀን ከትምህርታዊ ጊዜ ማብቂያ ቀን በኋላ መሆን አይችልም {0},
Enrollment Date cannot be before the Start Date of the Academic Term {0},የምዝገባ ቀን ከትምህርቱ ዘመን መጀመሪያ ቀን በፊት መሆን አይችልም {0},
Posting future transactions are not allowed due to Immutable Ledger,በሚተላለፍ ሊደር ምክንያት የወደፊት ግብይቶችን መለጠፍ አይፈቀድም,
Future Posting Not Allowed,የወደፊቱ መለጠፍ አልተፈቀደም,
"To enable Capital Work in Progress Accounting, ",በሂሳብ አያያዝ ውስጥ የካፒታል ሥራን ለማንቃት ፣,
you must select Capital Work in Progress Account in accounts table,በሂሳብ ሰንጠረዥ ውስጥ በሂሳብ መዝገብ ውስጥ ካፒታል ሥራን መምረጥ አለብዎት,
@ -9632,3 +9578,157 @@ Company Not Linked,ኩባንያ አልተያያዘም,
Import Chart of Accounts from CSV / Excel files,የመለያዎች ገበታ ከ CSV / Excel ፋይሎች ያስመጡ,
Completed Qty cannot be greater than 'Qty to Manufacture',የተጠናቀቀው ኪቲ ከ Qty to Manufacturere ሊበልጥ አይችልም ፡፡,
"Row {0}: For Supplier {1}, Email Address is Required to send an email",ረድፍ {0} ለአቅራቢ {1} ኢሜል ለመላክ የኢሜል አድራሻ ያስፈልጋል,
"If enabled, the system will post accounting entries for inventory automatically",ከነቃ ሲስተሙ ለሂሳብ ዝርዝር የሂሳብ መዝገብ ግቤቶችን በራስ-ሰር ይለጥፋል,
Accounts Frozen Till Date,መለያዎች የቀዘቀዙ እስከ ቀን,
Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,የሂሳብ ምዝገባዎች ምዝገባዎች እስከዚህ ቀን ድረስ ቀዝቅዘዋል። ከዚህ በታች ከተጠቀሰው ሚና ጋር ከተጠቃሚዎች በስተቀር ግቤቶችን ማንም መፍጠር ወይም ማሻሻል አይችልም,
Role Allowed to Set Frozen Accounts and Edit Frozen Entries,የቀዘቀዙ መለያዎችን ለማዘጋጀት እና የቀዘቀዙ ግቤቶችን ለማርትዕ የተፈቀደ ሚና,
Address used to determine Tax Category in transactions,በግብይቶች ውስጥ የግብር ምድብን ለመወሰን የሚያገለግል አድራሻ,
"The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ",ከታዘዘው መጠን የበለጠ እንዲከፍሉ የተፈቀደልዎ መቶኛ። ለምሳሌ ፣ የትእዛዝ ዋጋ ለአንድ ነገር $ 100 ከሆነ እና መቻቻል 10% ሆኖ ከተቀመጠ እስከ 110 ዶላር ድረስ እንዲከፍሉ ይፈቀድልዎታል,
This role is allowed to submit transactions that exceed credit limits,ይህ ሚና ከብድር ገደቦች በላይ የሆኑ ግብይቶችን እንዲያቀርብ ይፈቀድለታል,
"If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month",“ወሮች” ከተመረጠ በአንድ ወር ውስጥ ያሉት ቀናት ብዛት ምንም ይሁን ምን አንድ የተወሰነ መጠን እንደ ተዘገዘ ገቢ ወይም ወጪ በወር ይመዘገባል። የተዘገዘ ገቢ ወይም ወጪ ለአንድ ወር በሙሉ ካልተያዘ ይረጋገጣል,
"If this is unchecked, direct GL entries will be created to book deferred revenue or expense",ይህ ቁጥጥር ካልተደረገበት የቀዘቀዘ ገቢን ወይም ወጪን ለማስያዝ ቀጥተኛ የ GL ግቤቶች ይፈጠራሉ,
Show Inclusive Tax in Print,በህትመት ውስጥ ሁሉን አቀፍ ግብርን አሳይ,
Only select this if you have set up the Cash Flow Mapper documents,የገንዘብ ፍሰት ካርታ ሰነዶችን ካዘጋጁ ብቻ ይህንን ይምረጡ,
Payment Channel,የክፍያ ሰርጥ,
Is Purchase Order Required for Purchase Invoice & Receipt Creation?,የግዢ መጠየቂያ እና ደረሰኝ ፈጠራ የግዢ ትዕዛዝ ያስፈልጋል?,
Is Purchase Receipt Required for Purchase Invoice Creation?,የግዢ ደረሰኝ ለመፍጠር የግዢ ደረሰኝ ያስፈልጋል?,
Maintain Same Rate Throughout the Purchase Cycle,በግዢው ዑደት ውስጥ ሁሉ ተመሳሳይ ተመን ይኑርዎት,
Allow Item To Be Added Multiple Times in a Transaction,ንጥል በአንድ ግብይት ውስጥ ብዙ ጊዜ እንዲታከል ይፍቀዱ,
Suppliers,አቅራቢዎች,
Send Emails to Suppliers,ለአቅራቢዎች ኢሜሎችን ይላኩ,
Select a Supplier,አቅራቢ ይምረጡ,
Cannot mark attendance for future dates.,ለወደፊቱ ቀናት መገኘትን ምልክት ማድረግ አይቻልም።,
Do you want to update attendance? <br> Present: {0} <br> Absent: {1},ተገኝነትን ማዘመን ይፈልጋሉ?<br> ያቅርቡ: {0}<br> የለም: {1},
Mpesa Settings,Mpesa ቅንብሮች,
Initiator Name,የመነሻ ስም,
Till Number,እስከ ቁጥር,
Sandbox,ማጠሪያ,
Online PassKey,በመስመር ላይ PassKey,
Security Credential,የደህንነት ማረጋገጫ,
Get Account Balance,የሂሳብ ሚዛን ያግኙ,
Please set the initiator name and the security credential,እባክዎን የአስጀማሪውን ስም እና የደህንነት ማረጋገጫውን ያዘጋጁ,
Inpatient Medication Entry,የታካሚ መድኃኒት መግቢያ,
HLC-IME-.YYYY.-,ኤች.ሲ.ኤል-አይኤም-.YYYY.-,
Item Code (Drug),የእቃ ኮድ (መድሃኒት),
Medication Orders,የመድኃኒት ትዕዛዞች,
Get Pending Medication Orders,በመጠባበቅ ላይ ያሉ የሕክምና ትዕዛዞችን ያግኙ,
Inpatient Medication Orders,የታካሚ መድኃኒት ማዘዣዎች,
Medication Warehouse,የመድኃኒት መጋዘን,
Warehouse from where medication stock should be consumed,የመድኃኒት ክምችት ከሚበላበት መጋዘን,
Fetching Pending Medication Orders,በመጠባበቅ ላይ ያሉ የሕክምና ትዕዛዞችን ማምጣት,
Inpatient Medication Entry Detail,የታካሚ ህክምና መድሃኒት ዝርዝር ዝርዝር,
Medication Details,የመድኃኒት ዝርዝሮች,
Drug Code,የመድኃኒት ኮድ,
Drug Name,የመድኃኒት ስም,
Against Inpatient Medication Order,በሆስፒታሎች የመድኃኒት ማዘዣ ላይ,
Against Inpatient Medication Order Entry,በሆስፒታሎች የመድኃኒት ማዘዣ መግቢያ ላይ,
Inpatient Medication Order,የታካሚ መድኃኒት ማዘዣ,
HLC-IMO-.YYYY.-,ኤች.ሲ.ኤል-አይሞ-.YYYY.-,
Total Orders,ጠቅላላ ትዕዛዞች,
Completed Orders,የተጠናቀቁ ትዕዛዞች,
Add Medication Orders,የመድኃኒት ትዕዛዞችን ያክሉ,
Adding Order Entries,የትዕዛዝ ግቤቶችን በማከል ላይ,
{0} medication orders completed,{0} የመድኃኒት ትዕዛዞች ተጠናቅቀዋል,
{0} medication order completed,{0} የመድኃኒት ትዕዛዝ ተጠናቅቋል,
Inpatient Medication Order Entry,የታካሚ መድኃኒት ማዘዣ መግቢያ,
Is Order Completed,ትዕዛዝ ተጠናቅቋል,
Employee Records to Be Created By,እንዲፈጠሩ የሰራተኛ መዝገቦች በ,
Employee records are created using the selected field,የሰራተኛ መዝገቦች በተመረጠው መስክ በመጠቀም ይፈጠራሉ,
Don't send employee birthday reminders,የሰራተኛ የልደት ቀን ማስታወሻዎችን አይላኩ,
Restrict Backdated Leave Applications,ጊዜ ያለፈበት ፈቃድ መተግበሪያዎችን ይገድቡ,
Sequence ID,የቅደም ተከተል መታወቂያ,
Sequence Id,የቅደም ተከተል መታወቂያ,
Allow multiple material consumptions against a Work Order,በስራ ትዕዛዝ ላይ በርካታ የቁሳቁስ ፍጆታዎች ይፍቀዱ,
Plan time logs outside Workstation working hours,ከሥራ መስሪያ የሥራ ሰዓት ውጭ የጊዜ ምዝግብ ማስታወሻዎችን ያቅዱ,
Plan operations X days in advance,ሥራዎችን ከ X ቀናት በፊት ያቅዱ,
Time Between Operations (Mins),በኦፕሬሽንስ (ማይንስ) መካከል ያለው ጊዜ,
Default: 10 mins,ነባሪ: 10 ደቂቃዎች,
Overproduction for Sales and Work Order,ለሽያጭ እና ለሥራ ትዕዛዝ ትርፍ ምርት,
"Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials",በመጨረሻው የዋጋ ተመን / የዋጋ ዝርዝር ተመን / ጥሬ ዕቃዎች የመጨረሻ ግዢ ዋጋ ላይ በመመርኮዝ የ BOM ወጪን በራስ-ሰር በፕሮግራም በኩል ያዘምኑ,
Purchase Order already created for all Sales Order items,ለሁሉም የሽያጭ ትዕዛዝ ዕቃዎች አስቀድሞ የተፈጠረ የግዢ ትዕዛዝ,
Select Items,ንጥሎችን ይምረጡ,
Against Default Supplier,በነባሪ አቅራቢ ላይ,
Auto close Opportunity after the no. of days mentioned above,ከቁጥር በኋላ በራስ-ሰር ዕድል ይዝጉ። ከላይ የተጠቀሱትን ቀናት,
Is Sales Order Required for Sales Invoice & Delivery Note Creation?,የሽያጭ መጠየቂያ እና የማስረከቢያ ማስታወሻ መፍጠር የሽያጭ ትዕዛዝ ያስፈልጋል?,
Is Delivery Note Required for Sales Invoice Creation?,ለሽያጭ መጠየቂያ ደረሰኝ ፈጠራ የማስረከቢያ ማስታወሻ ይፈለጋል?,
How often should Project and Company be updated based on Sales Transactions?,በሽያጭ ግብይቶች ላይ በመመርኮዝ ፕሮጀክት እና ኩባንያ ምን ያህል ጊዜ መዘመን አለባቸው?,
Allow User to Edit Price List Rate in Transactions,በተጠቃሚዎች ውስጥ የዋጋ ዝርዝር ተመን እንዲያርትዕ ለተጠቃሚ ይፍቀዱለት,
Allow Item to Be Added Multiple Times in a Transaction,ንጥል በአንድ ግብይት ውስጥ ብዙ ጊዜ እንዲታከል ይፍቀዱ,
Allow Multiple Sales Orders Against a Customer's Purchase Order,በደንበኞች ግዢ ትዕዛዝ ላይ ብዙ የሽያጭ ትዕዛዞችን ይፍቀዱ,
Validate Selling Price for Item Against Purchase Rate or Valuation Rate,ለግዢ ዋጋ ወይም የዋጋ ተመን ለእቃው የሽያጭ ዋጋን ያረጋግጡ,
Hide Customer's Tax ID from Sales Transactions,የደንበኞችን የግብር መታወቂያ ከሽያጭ ግብይቶች ይደብቁ,
"The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.",ከታዘዘው ብዛት የበለጠ እንዲቀበሉ ወይም እንዲያቀርቡ የተፈቀደልዎ መቶኛ። ለምሳሌ ፣ 100 አሃዶችን ካዘዙ እና አበልዎ 10% ከሆነ ከዚያ 110 ክፍሎችን ለመቀበል ይፈቀድልዎታል።,
Action If Quality Inspection Is Not Submitted,እርምጃ የጥራት ምርመራ ካልተላለፈ,
Auto Insert Price List Rate If Missing,ከጎደለ ራስ-ሰር የዋጋ ዝርዝር ተመን ያስገቡ,
Automatically Set Serial Nos Based on FIFO,በ FIFO ላይ የተመሠረተ ተከታታይ ቁጥሮችን በራስ-ሰር ያዘጋጁ,
Set Qty in Transactions Based on Serial No Input,በተከታታይ ግብዓት ላይ በመመስረት ግብይቶችን Qty ያቀናብሩ,
Raise Material Request When Stock Reaches Re-order Level,ክምችት እንደገና ሲታዘዝ የቁሳዊ ጥያቄን ከፍ ያድርጉ,
Notify by Email on Creation of Automatic Material Request,የራስ-ሰር ቁሳቁስ ጥያቄን በመፍጠር በኢሜል ያሳውቁ,
Allow Material Transfer from Delivery Note to Sales Invoice,ከመላኪያ ማስታወሻ ወደ ሽያጭ መጠየቂያ ደረሰኝ ቁሳቁስ ማስተላለፍ ይፍቀዱ,
Allow Material Transfer from Purchase Receipt to Purchase Invoice,የቁሳቁስ ሽግግር ከግዢ ደረሰኝ እስከ የግዢ ደረሰኝ ይፍቀዱ,
Freeze Stocks Older Than (Days),ከቀኖች የበለጠ የቀዘቀዙ አክሲዮኖች,
Role Allowed to Edit Frozen Stock,የቀዘቀዘ ክምችት ለማርትዕ የተፈቀደ ሚና,
The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,ያልተመደበው የክፍያ ግቤት መጠን {0} ከባንኩ ግብይት ያልተመደበ መጠን ይበልጣል,
Payment Received,ክፍያ ደርሷል,
Attendance cannot be marked outside of Academic Year {0},መገኘት ከትምህርታዊ ዓመት {0} ውጭ ምልክት ሊደረግበት አይችልም,
Student is already enrolled via Course Enrollment {0},ተማሪ ቀድሞውኑ በኮርስ ምዝገባ በኩል ተመዝግቧል {0},
Attendance cannot be marked for future dates.,ለወደፊቱ ቀናት መገኘትን ምልክት ማድረግ አይቻልም ፡፡,
Please add programs to enable admission application.,የመግቢያ ማመልከቻን ለማንቃት እባክዎ ፕሮግራሞችን ያክሉ።,
The following employees are currently still reporting to {0}:,የሚከተሉት ሰራተኞች በአሁኑ ጊዜ ለ {0} ሪፖርት እያደረጉ ነው-,
Please make sure the employees above report to another Active employee.,እባክዎ ከላይ ያሉት ሠራተኞች ለሌላ ንቁ ሠራተኛ ሪፖርት ማድረጉን ያረጋግጡ ፡፡,
Cannot Relieve Employee,ሰራተኛን ማቃለል አልተቻለም,
Please enter {0},እባክዎ ያስገቡ {0},
Please select another payment method. Mpesa does not support transactions in currency '{0}',እባክዎ ሌላ የመክፈያ ዘዴ ይምረጡ። Mpesa በ {0} ምንዛሬ ውስጥ ግብይቶችን አይደግፍም,
Transaction Error,የግብይት ስህተት,
Mpesa Express Transaction Error,Mpesa Express የግብይት ስህተት,
"Issue detected with Mpesa configuration, check the error logs for more details",በ Mpesa ውቅር የተገኘ ችግር ፣ ለተጨማሪ ዝርዝሮች የስህተት ምዝግብ ማስታወሻዎችን ይፈትሹ,
Mpesa Express Error,የፓፒሳ ኤክስፕረስ ስህተት,
Account Balance Processing Error,የመለያ ሚዛን ማስኬድ ስህተት,
Please check your configuration and try again,እባክዎ ውቅርዎን ይፈትሹ እና እንደገና ይሞክሩ,
Mpesa Account Balance Processing Error,የፓፒሳ ሂሳብ ሚዛን ማስኬድ ስህተት,
Balance Details,ሚዛናዊ ዝርዝሮች,
Current Balance,የአሁኑ ሒሳብ,
Available Balance,የሚገኝ ሚዛን,
Reserved Balance,የተጠበቀ ሚዛን,
Uncleared Balance,ያልተስተካከለ ሚዛን,
Payment related to {0} is not completed,ከ {0} ጋር የተገናኘ ክፍያ አልተጠናቀቀም,
Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.,ረድፍ # {}: ተከታታይ ቁጥር {}. {} ቀድሞውኑ ወደ ሌላ POS ደረሰኝ ተቀይሯል። እባክዎ ትክክለኛ ተከታታይ ቁጥር ይምረጡ።,
Row #{}: Item Code: {} is not available under warehouse {}.,ረድፍ # {} ንጥል ኮድ {} በመጋዘን ስር አይገኝም {}።,
Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.,ረድፍ # {}: ለዕቃው ኮድ በቂ ያልሆነ የአክሲዮን ብዛት {} ከመጋዘን በታች {}። የሚገኝ ብዛት {},
Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.,ረድፍ # {}: እባክዎ ተከታታይ ቁጥርን ይምረጡ እና በንጥል ላይ ድምርን ይምረጡ ፦ {} ወይም ግብይቱን ለማጠናቀቅ ያስወግዱት።,
Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.,ረድፍ # {}: በንጥል ላይ ምንም የመለያ ቁጥር አልተመረጠም: {}. ግብይቱን ለማጠናቀቅ እባክዎ አንዱን ይምረጡ ወይም ያስወግዱት።,
Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.,ረድፍ # {}: በንጥል ላይ ምንም ስብስብ አልተመረጠም {}። ግብይቱን ለማጠናቀቅ እባክዎ አንድ ቡድን ይምረጡ ወይም ያስወግዱት።,
Payment amount cannot be less than or equal to 0,የክፍያ መጠን ከ 0 በታች ወይም እኩል ሊሆን አይችልም,
Please enter the phone number first,እባክዎን መጀመሪያ የስልክ ቁጥሩን ያስገቡ,
Row #{}: {} {} does not exist.,ረድፍ # {}: {} {} የለም።,
Row #{0}: {1} is required to create the Opening {2} Invoices,ረድፍ # {0}: የመክፈቻ {2} ደረሰኞችን ለመፍጠር {1} ያስፈልጋል,
You had {} errors while creating opening invoices. Check {} for more details,የመክፈቻ መጠየቂያዎችን ሲፈጥሩ {} ስህተቶች ነበሩዎት። ለተጨማሪ ዝርዝሮች {} ን ይፈትሹ,
Error Occured,ስህተት ተከስቷል,
Opening Invoice Creation In Progress,የክፍያ መጠየቂያ ፈጠራ በሂደት ላይ,
Creating {} out of {} {},{} ከ {} {} መፍጠር,
(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,(ተከታታይ ቁጥር: {0}) ወደ ሙሉ ሙላ የሽያጭ ትዕዛዝ የተስተካከለ ስለሆነ ሊወሰድ አይችልም {1}።,
Item {0} {1},ንጥል {0} {1},
Last Stock Transaction for item {0} under warehouse {1} was on {2}.,የመጨረሻው የንጥል ግብይት ግብይት {0} ከመጋዘን በታች {1} በ {2} ላይ ነበር።,
Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,ለእቃው የአክሲዮን ግብይቶች {0} ከመጋዘን በታች {1} ከዚህ ጊዜ በፊት መለጠፍ አይቻልም።,
Posting future stock transactions are not allowed due to Immutable Ledger,ለወደፊቱ የማይለዋወጥ ሌደር ምክንያት የወደፊት የአክሲዮን ግብይቶችን መለጠፍ አይፈቀድም,
A BOM with name {0} already exists for item {1}.,ስም ያለው BOM {0} አስቀድሞ ለንጥል {1} አለ።,
{0}{1} Did you rename the item? Please contact Administrator / Tech support,{0} {1} ንጥሉን ቀይረውታል? እባክዎን የአስተዳዳሪ / ቴክ ድጋፍን ያነጋግሩ,
At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},በረድፍ # {0} ላይ - የቅደም ተከተል መታወቂያ {1} ከቀዳሚው ረድፍ ቅደም ተከተል መታወቂያ በታች መሆን አይችልም {2},
The {0} ({1}) must be equal to {2} ({3}),{0} ({1}) ከ {2} ({3}) ጋር እኩል መሆን አለበት,
"{0}, complete the operation {1} before the operation {2}.",{0} ፣ ከቀዶ ጥገናው በፊት {1} ክዋኔውን ያጠናቅቁ {2}።,
Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No.,ንጥል {0} በመደመር እና በመረጃ አቅርቦት ማድረጉን ማረጋገጥ ስለ ተጨመረ በ Serial No ማድረስን ማረጋገጥ አልተቻለም,
Item {0} has no Serial No. Only serilialized items can have delivery based on Serial No,ንጥል {0} በተከታታይ ቁጥር የለውም በመለያ ቁጥር ላይ በመመስረት መላኪያ ሊኖራቸው የሚችለው በተከታታይ የተሰሩ ንጥሎች ብቻ ናቸው,
No active BOM found for item {0}. Delivery by Serial No cannot be ensured,ለንጥል {0} ምንም ንቁ BOM አልተገኘም። ማድረስ በተከታታይ ቁጥር ማረጋገጥ አይቻልም,
No pending medication orders found for selected criteria,ለተመረጡት መመዘኛዎች በመጠባበቅ ላይ ያሉ የመድኃኒት ትዕዛዞች አልተገኙም,
From Date cannot be after the current date.,ከቀን ከአሁኑ ቀን በኋላ መሆን አይችልም።,
To Date cannot be after the current date.,እስከዛሬ ከአሁኑ ቀን በኋላ መሆን አይችልም።,
From Time cannot be after the current time.,ከጊዜው ከአሁኑ ሰዓት በኋላ ሊሆን አይችልም ፡፡,
To Time cannot be after the current time.,ለጊዜ ከአሁኑ ሰዓት በኋላ ሊሆን አይችልም ፡፡,
Stock Entry {0} created and ,የአክሲዮን ግቤት {0} ተፈጥሯል እና,
Inpatient Medication Orders updated successfully,የታካሚ መድኃኒት ማዘዣ ትዕዛዞች በተሳካ ሁኔታ ተዘምነዋል,
Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1},ረድፍ {0} ፦ ከተሰረዘ የታመመ የመድኃኒት ማዘዣ ትእዛዝ ጋር የታካሚ መድኃኒት ግቤት መፍጠር አልተቻለም {1},
Row {0}: This Medication Order is already marked as completed,ረድፍ {0} ይህ የመድኃኒት ትእዛዝ አስቀድሞ እንደተጠናቀቀ ምልክት ተደርጎበታል,
Quantity not available for {0} in warehouse {1},ብዛት ለ {0} መጋዘን ውስጥ {1} አይገኝም,
Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.,እባክዎ በክምችት ቅንብሮች ውስጥ አሉታዊ ክምችት ይፍቀዱ ወይም ለመቀጠል የአክሲዮን ግባ ይፍጠሩ።,
No Inpatient Record found against patient {0},በታካሚው {0} ላይ ምንም የታካሚ መዝገብ አልተገኘም,
An Inpatient Medication Order {0} against Patient Encounter {1} already exists.,የታካሚ ገጠመኝን {0} የታካሚ ገጠመኝ መድኃኒት {1} ቀድሞውኑ አለ።,

Can't render this file because it is too large.

View File

@ -110,7 +110,6 @@ Actual qty in stock,الكمية الفعلية في المخزون,
Actual type tax cannot be included in Item rate in row {0},نوع الضريبة الفعلي لا يمكن تضمينه في معدل الصنف في الصف {0},
Add,إضافة,
Add / Edit Prices,إضافة و تعديل الأسعار,
Add All Suppliers,إضافة جميع الموردين,
Add Comment,أضف تعليق,
Add Customers,إضافة العملاء,
Add Employees,إضافة موظفين,
@ -480,7 +479,6 @@ Cannot produce more Item {0} than Sales Order quantity {1},لا يمكن أن ت
Cannot promote Employee with status Left,لا يمكن ترقية موظف بحالة مغادرة,
Cannot refer row number greater than or equal to current row number for this Charge type,لا يمكن أن يشير رقم الصف أكبر من أو يساوي رقم الصف الحالي لهذا النوع المسؤول,
Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,"لا يمكن تحديد نوع التهمة باسم ' في الصف السابق المبلغ ' أو ' في السابق صف إجمالي "" ل لصف الأول",
Cannot set a received RFQ to No Quote,لا يمكن تعيين رفق وردت إلى أي اقتباس,
Cannot set as Lost as Sales Order is made.,لا يمكن أن تعين كخسارة لأنه تم تقديم أمر البيع. <br>Cannot set as Lost as Sales Order is made.,
Cannot set authorization on basis of Discount for {0},لا يمكن تحديد التخويل على أساس الخصم ل {0},
Cannot set multiple Item Defaults for a company.,لا يمكن تعيين عدة عناصر افتراضية لأي شركة.,
@ -934,7 +932,6 @@ Employee Referral,إحالة موظف,
Employee Transfer cannot be submitted before Transfer Date ,لا يمكن تقديم نقل الموظف قبل تاريخ النقل,
Employee cannot report to himself.,الموظف لا يمكن أن يقدم تقريرا إلى نفسه.\n<br>\nEmployee cannot report to himself.,
Employee relieved on {0} must be set as 'Left',الموظف الذي ترك العمل في {0} يجب أن يتم تحديده ' مغادر ',
Employee status cannot be set to 'Left' as following employees are currently reporting to this employee:&nbsp;,لا يمكن تعيين حالة الموظف على &quot;يسار&quot; لأن الموظفين التاليين يقومون حاليًا بإبلاغ هذا الموظف:,
Employee {0} already submited an apllication {1} for the payroll period {2},قام الموظف {0} بالفعل بإرسال apllication {1} لفترة المرتبات {2},
Employee {0} has already applied for {1} between {2} and {3} : ,الموظف {0} قد طبق بالفعل على {1} بين {2} و {3}:,
Employee {0} has no maximum benefit amount,الموظف {0} ليس لديه الحد الأقصى لمبلغ الاستحقاق,
@ -1456,7 +1453,6 @@ Leave application {0} already exists against the student {1},ترك التطبي
"Leave cannot be allocated before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}",لا يمكن تخصيص اجازة قبل {0}، لان رصيد الإجازات قد تم تحوبله الي سجل تخصيص اجازات مستقبلي {1},
"Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}",الاجازة لا يمكن تطبيقها او إلغائها قبل {0}، لان رصيد الإجازات قد تم تحويله الي سجل تخصيص إجازات مستقبلي {1},
Leave of type {0} cannot be longer than {1},يجب أن لا يتجاوز عدد أيام اﻹجازة من نوع {0} عدد {1} يوم.\n<br>\nLeave of type {0} cannot be longer than {1},
Leave the field empty to make purchase orders for all suppliers,اترك الحقل فارغًا لإجراء أوامر الشراء لجميع الموردين,
Leaves,الاجازات,
Leaves Allocated Successfully for {0},تم تخصيص اﻹجازات بنجاح ل {0}\n<br>\nLeaves Allocated Successfully for {0},
Leaves has been granted sucessfully,تم منح الأوراق بنجاح,
@ -1699,7 +1695,6 @@ No Items to pack,لا عناصر لحزمة\n<br>\nNo Items to pack,
No Items with Bill of Materials to Manufacture,لا توجد بنود في قائمة المواد للتصنيع,
No Items with Bill of Materials.,لا توجد عناصر مع جدول المواد.,
No Permission,لا يوجد تصريح,
No Quote,لا اقتباس,
No Remarks,لا ملاحظات,
No Result to submit,لا توجد نتيجة لإرسال,
No Salary Structure assigned for Employee {0} on given date {1},لا يتم تحديد هيكل الراتب للموظف {0} في تاريخ معين {1},
@ -1856,7 +1851,6 @@ Overlap in scoring between {0} and {1},التداخل في التسجيل بين
Overlapping conditions found between:,الشروط المتداخله التي تم العثور عليها بين:\n<br>\nOverlapping conditions found between:,
Owner,مالك,
PAN,مقلاة,
PO already created for all sales order items,PO تم إنشاؤها بالفعل لجميع عناصر أمر المبيعات,
POS,نقطة البيع,
POS Profile,الملف الشخصي لنقطة البيع,
POS Profile is required to use Point-of-Sale,مطلوب بوس الشخصي لاستخدام نقطة البيع,
@ -2502,7 +2496,6 @@ Row {0}: Quality Inspection rejected for item {1},الصف {0}: تم رفض فح
Row {0}: UOM Conversion Factor is mandatory,الصف {0}: عامل تحويل UOM إلزامي\n<br>\nRow {0}: UOM Conversion Factor is mandatory,
Row {0}: select the workstation against the operation {1},الصف {0}: حدد محطة العمل مقابل العملية {1},
Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.,الصف {0}: {1} الأرقام التسلسلية المطلوبة للبند {2}. لقد قدمت {3}.,
Row {0}: {1} is required to create the Opening {2} Invoices,الصف {0}: {1} مطلوب لإنشاء الفواتير الافتتاحية {2},
Row {0}: {1} must be greater than 0,الصف {0}: يجب أن يكون {1} أكبر من 0,
Row {0}: {1} {2} does not match with {3},الصف {0}: {1} {2} لا يتطابق مع {3},
Row {0}:Start Date must be before End Date,الصف {0}: يجب أن يكون تاريخ البدء أقل من تاريخ الانتهاء\n<br>\nRow {0}:Start Date must be before End Date,
@ -2642,7 +2635,6 @@ Selling Rate,معدل البيع,
Send Grant Review Email,إرسال بريد إلكتروني منح مراجعة,
Send Now,أرسل الآن,
Send SMS,SMS أرسل رسالة,
Send Supplier Emails,إرسال رسائل البريد الإلكتروني مزود,
Send mass SMS to your contacts,إرسال SMS الشامل لجهات الاتصال الخاصة بك,
Sensitivity,حساسية,
Sent,أرسلت,
@ -3443,7 +3435,6 @@ on,في,
{0} variants created.,تم إنشاء المتغيرات {0}.,
{0} {1} created,{0} {1} إنشاء,
{0} {1} does not exist,{0} {1} غير موجود\n<br>\n{0} {1} does not exist,
{0} {1} does not exist.,{0} {1} غير موجود.,
{0} {1} has been modified. Please refresh.,تم تعديل {0} {1}، يرجى تحديث الصفحة من المتصفح,
{0} {1} has not been submitted so the action cannot be completed,{0} {1} لم يتم إرسالها، ولذلك لا يمكن إكمال الإجراء,
"{0} {1} is associated with {2}, but Party Account is {3}",{0} {1} مرتبط ب {2}، ولكن حساب الطرف هو {3},
@ -3480,6 +3471,7 @@ on,في,
{0}: {1} does not exists,{0}: {1} غير موجود,
{0}: {1} not found in Invoice Details table,{0}: {1} غير موجود في جدول تفاصيل الفواتير,
{} of {},{} من {},
Assigned To,كلف إلى,
Chat,الدردشة,
Completed By,اكتمل بواسطة,
Conditions,الظروف,
@ -3502,6 +3494,7 @@ Merge with existing,دمج مع الحالي,
Office,مكتب,
Orientation,توجيه,
Passive,غير فعال,
Payment Failed,عملية الدفع فشلت,
Percent,في المئة,
Permanent,دائم,
Personal,الشخصية,
@ -3566,6 +3559,8 @@ Naming Series,سلسلة التسمية,
No data to export,لا توجد بيانات للتصدير,
Portrait,صورة,
Print Heading,طباعة الرأسية,
Scheduler Inactive,المجدول غير نشط,
Scheduler is inactive. Cannot import data.,المجدول غير نشط. لا يمكن استيراد البيانات.,
Show Document,عرض المستند,
Show Traceback,إظهار التتبع,
Video,فيديو,
@ -3691,7 +3686,6 @@ Create Pick List,إنشاء قائمة انتقاء,
Create Quality Inspection for Item {0},إنشاء فحص الجودة للعنصر {0},
Creating Accounts...,إنشاء حسابات ...,
Creating bank entries...,إنشاء إدخالات بنكية ...,
Creating {0},إنشاء {0},
Credit limit is already defined for the Company {0},تم تحديد حد الائتمان بالفعل للشركة {0},
Ctrl + Enter to submit,Ctrl + Enter للتقديم,
Ctrl+Enter to submit,Ctrl + Enter للإرسال,
@ -4524,31 +4518,22 @@ Closed Documents,وثائق مغلقة,
Accounts Settings,إعدادات الحسابات,
Settings for Accounts,إعدادات الحسابات,
Make Accounting Entry For Every Stock Movement,اعمل قيد محاسبي لكل حركة للمخزون,
"If enabled, the system will post accounting entries for inventory automatically.",إذا تم التمكين، سيقوم النظام بترحيل القيود المحاسبية الخاصة بالمخزون تلقائيا.,
Accounts Frozen Upto,حسابات مجمدة حتى,
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",القيود المحاسبية مجمده حتى هذا التاريخ، لا أحد يستطيع أن ينشئ أو يعدل القييد باستثناء الدور المحدد أدناه.,
Role Allowed to Set Frozen Accounts & Edit Frozen Entries,الدور الوظيفي يسمح له بتجميد الحسابات و تعديل القيود المجمدة,
Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,يسمح للمستخدمين مع هذا الدور لضبط الحسابات المجمدة و إنشاء / تعديل القيود المحاسبية على حسابات مجمدة,
Determine Address Tax Category From,تحديد عنوان ضريبة الفئة من,
Address used to determine Tax Category in transactions.,العنوان المستخدم لتحديد الفئة الضريبية في المعاملات.,
Over Billing Allowance (%),زيادة الفواتير المسموح بها (٪),
Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.,النسبة المئوية المسموح لك بدفعها أكثر مقابل المبلغ المطلوب. على سبيل المثال: إذا كانت قيمة الطلبية 100 دولار للعنصر وتم تعيين التسامح على 10 ٪ ، فيُسمح لك بدفع فاتورة بمبلغ 110 دولارات.,
Credit Controller,مراقب الرصيد دائن,
Role that is allowed to submit transactions that exceed credit limits set.,الدور الوظيفي الذي يسمح له بتقديم المعاملات التي تتجاوز حدود الدين المحددة.,
Check Supplier Invoice Number Uniqueness,التحقق من رقم الفتورة المرسلة من المورد مميز (ليس متكرر),
Make Payment via Journal Entry,قم بالدفع عن طريق قيد دفتر اليومية,
Unlink Payment on Cancellation of Invoice,إلغاء ربط الدفع على إلغاء الفاتورة,
Book Asset Depreciation Entry Automatically,كتاب اهلاك الأُصُول المدخلة تلقائيا,
Automatically Add Taxes and Charges from Item Tax Template,إضافة الضرائب والرسوم تلقائيا من قالب الضريبة البند,
Automatically Fetch Payment Terms,جلب شروط الدفع تلقائيًا,
Show Inclusive Tax In Print,عرض الضريبة الشاملة في الطباعة,
Show Payment Schedule in Print,عرض جدول الدفع في الطباعة,
Currency Exchange Settings,إعدادات صرف العملات,
Allow Stale Exchange Rates,السماح لأسعار الصرف الثابتة,
Stale Days,أيام قديمة,
Report Settings,إعدادات التقرير,
Use Custom Cash Flow Format,استخدم تنسيق التدفق النقدي المخصص,
Only select if you have setup Cash Flow Mapper documents,حدد فقط إذا كان لديك إعداد مخطط مخطط التدفق النقدي,
Allowed To Transact With,سمح للاعتماد مع,
SWIFT number,رقم سويفت,
Branch Code,رمز الفرع,
@ -5485,8 +5470,6 @@ Settings for Buying Module,إعدادات لشراء وحدة,
Supplier Naming By,المورد تسمية بواسطة,
Default Supplier Group,مجموعة الموردين الافتراضية,
Default Buying Price List,قائمة اسعار الشراء الافتراضية,
Maintain same rate throughout purchase cycle,الحفاظ على نفس السعر طوال دورة الشراء,
Allow Item to be added multiple times in a transaction,السماح بإضافة صنف لأكثر من مرة في عملية تجارية,
Backflush Raw Materials of Subcontract Based On,Backflush المواد الخام من العقد من الباطن,
Material Transferred for Subcontract,المواد المنقولة للعقود من الباطن,
Over Transfer Allowance (%),بدل النقل (٪),
@ -5530,7 +5513,6 @@ Purchase Receipt Item Supplied,شراء السلعة استلام الموردة
Current Stock,المخزون الحالية,
PUR-RFQ-.YYYY.-,PUR-RFQ-.YYYY.-,
For individual supplier,عن مورد فردي,
Supplier Detail,المورد التفاصيل,
Link to Material Requests,رابط لطلبات المواد,
Message for Supplier,رسالة لمزود,
Request for Quotation Item,طلب تسعيرة البند,
@ -6724,10 +6706,7 @@ HR Settings,إعدادات الموارد البشرية,
Employee Settings,إعدادات الموظف,
Retirement Age,سن التقاعد,
Enter retirement age in years,أدخل سن التقاعد بالسنوات,
Employee Records to be created by,سجلات الموظفين المراد إنشاؤها من قبل,
Employee record is created using selected field. ,يتم إنشاء سجل الموظف باستخدام الحقل المحدد.,
Stop Birthday Reminders,ايقاف التذكير بأعياد الميلاد,
Don't send Employee Birthday Reminders,عدم ارسال تذكير للموضفين بأعياد الميلاد,
Expense Approver Mandatory In Expense Claim,الموافقة على المصروفات إلزامية في مطالبة النفقات,
Payroll Settings,إعدادات دفع الرواتب,
Leave,غادر,
@ -6749,7 +6728,6 @@ Role Allowed to Create Backdated Leave Application,الدور المسموح ب
Leave Approver Mandatory In Leave Application,إجازة الموافقة إلزامية في طلب الإجازة,
Show Leaves Of All Department Members In Calendar,إظهار أوراق جميع أعضاء القسم في التقويم,
Auto Leave Encashment,إجازة مغادرة السيارات,
Restrict Backdated Leave Application,تقييد طلب الإجازة المتأخرة,
Hiring Settings,إعدادات التوظيف,
Check Vacancies On Job Offer Creation,التحقق من الوظائف الشاغرة عند إنشاء عرض العمل,
Identification Document Type,نوع وثيقة التعريف,
@ -7283,28 +7261,21 @@ Completed Qty,الكمية المكتملة,
Manufacturing Settings,إعدادات التصنيع,
Raw Materials Consumption,استهلاك المواد الخام,
Allow Multiple Material Consumption,السماح باستهلاك المواد المتعددة,
Allow multiple Material Consumption against a Work Order,السماح باستهلاك المواد المتعددة مقابل طلب العمل,
Backflush Raw Materials Based On,Backflush المواد الخام مبني على,
Material Transferred for Manufacture,المواد المنقولة لغرض صناعة,
Capacity Planning,القدرة على التخطيط,
Disable Capacity Planning,تعطيل تخطيط القدرات,
Allow Overtime,تسمح العمل الإضافي,
Plan time logs outside Workstation Working Hours.,تخطيط سجلات الوقت خارج ساعات العمل محطة العمل.,
Allow Production on Holidays,السماح الإنتاج على عطلات,
Capacity Planning For (Days),القدرة على التخطيط لل(أيام),
Try planning operations for X days in advance.,محاولة التخطيط لعمليات لX أيام مقدما.,
Time Between Operations (in mins),الوقت بين العمليات (في دقيقة),
Default 10 mins,افتراضي 10 دقيقة,
Default Warehouses for Production,المستودعات الافتراضية للإنتاج,
Default Work In Progress Warehouse,افتراضي العمل في مستودع التقدم,
Default Finished Goods Warehouse,المخزن الافتراضي للبضائع التامة الصنع,
Default Scrap Warehouse,مستودع الخردة الافتراضي,
Over Production for Sales and Work Order,أكثر من الإنتاج للمبيعات وأمر العمل,
Overproduction Percentage For Sales Order,نسبة الإنتاج الزائد لأمر المبيعات,
Overproduction Percentage For Work Order,نسبة الإنتاج الزائد لأمر العمل,
Other Settings,اعدادات اخرى,
Update BOM Cost Automatically,تحديث بوم التكلفة تلقائيا,
"Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.",تحديث تكلفة بوم تلقائيا عبر جدولة، استنادا إلى أحدث معدل التقييم / سعر قائمة معدل / آخر معدل شراء المواد الخام.,
Material Request Plan Item,المادة طلب خطة البند,
Material Request Type,نوع طلب المواد,
Material Issue,صرف مواد,
@ -7771,15 +7742,9 @@ Campaign Naming By,حملة التسمية بواسطة,
Default Customer Group,المجموعة الافتراضية العملاء,
Default Territory,الإقليم الافتراضي,
Close Opportunity After Days,فرصة قريبة بعد يوم,
Auto close Opportunity after 15 days,اغلاق تلقائي للفرص بعد 15 يوما,
Default Quotation Validity Days,عدد أيام صلاحية عرض الأسعار الافتراضي,
Sales Update Frequency,تردد تحديث المبيعات,
How often should project and company be updated based on Sales Transactions.,كم مرة يجب تحديث المشروع والشركة استنادًا إلى معاملات المبيعات.,
Each Transaction,كل عملية,
Allow user to edit Price List Rate in transactions,تسمح للمستخدم لتحرير الأسعار قائمة قيم في المعاملات,
Allow multiple Sales Orders against a Customer's Purchase Order,السماح بعدة أوامر البيع ضد طلب شراء العميل,
Validate Selling Price for Item against Purchase Rate or Valuation Rate,تحقق من سعر البيع للالبند ضد سعر الشراء أو معدل التقييم,
Hide Customer's Tax Id from Sales Transactions,إخفاء المعرف الضريبي للعملاء من معاملات مبيعات,
SMS Center,مركز رسائل SMS,
Send To,أرسل إلى,
All Contact,جميع جهات الاتصال,
@ -8388,24 +8353,14 @@ Default Item Group,المجموعة الافتراضية للمواد,
Default Stock UOM,افتراضي وحدة قياس السهم,
Sample Retention Warehouse,مستودع الاحتفاظ بالعينات,
Default Valuation Method,أسلوب التقييم الافتراضي,
Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.,النسبة المئوية يسمح لك لتلقي أو تقديم المزيد من ضد الكمية المطلوبة. على سبيل المثال: إذا كنت قد أمرت 100 وحدة. و10٪ ثم يسمح بدل الخاص بك لتلقي 110 وحدة.,
Action if Quality inspection is not submitted,الإجراء إذا لم يتم تقديم فحص الجودة,
Show Barcode Field,مشاهدة الباركود الميدان,
Convert Item Description to Clean HTML,تحويل وصف السلعة لتنظيف هتمل,
Auto insert Price List rate if missing,إدراج تلقائي لقائمة الأسعار إن لم تكن موجودة,
Allow Negative Stock,السماح بالقيم السالبة للمخزون,
Automatically Set Serial Nos based on FIFO,حدد الرقم التسلسلي بناءً على FIFO,
Set Qty in Transactions based on Serial No Input,تعيين الكمية في المعاملات استناداً إلى Serial No Input,
Auto Material Request,طلب مواد تلقائي,
Raise Material Request when stock reaches re-order level,رفع طلب المواد عند الأسهم تصل إلى مستوى إعادة الطلب,
Notify by Email on creation of automatic Material Request,إبلاغ عن طريق البريد الإلكتروني عند انشاء طلب مواد تلقائي,
Inter Warehouse Transfer Settings,إعدادات نقل المستودعات الداخلية,
Allow Material Transfer From Delivery Note and Sales Invoice,السماح بنقل المواد من مذكرة التسليم وفاتورة المبيعات,
Allow Material Transfer From Purchase Receipt and Purchase Invoice,السماح بنقل المواد من إيصال الشراء وفاتورة الشراء,
Freeze Stock Entries,تجميد مقالات المالية,
Stock Frozen Upto,المخزون المجمدة لغاية,
Freeze Stocks Older Than [Days],تجميد الأرصدة أقدم من [ أيام],
Role Allowed to edit frozen stock,صلاحية السماح بتحرير الأسهم المجمدة,
Batch Identification,تحديد الدفعة,
Use Naming Series,استخدام سلسلة التسمية,
Naming Series Prefix,بادئة سلسلة التسمية,
@ -8731,11 +8686,9 @@ Published on,نشرت في,
Service Received But Not Billed,تم استلام الخدمة ولكن لم يتم دفع الفاتورة,
Deferred Accounting Settings,إعدادات المحاسبة المؤجلة,
Book Deferred Entries Based On,حجز إدخالات مؤجلة على أساس,
"If ""Months"" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",إذا تم تحديد &quot;الأشهر&quot; ، فسيتم حجز المبلغ الثابت كإيرادات أو مصروفات مؤجلة لكل شهر بغض النظر عن عدد الأيام في الشهر. سيتم تقسيمها بالتناسب إذا لم يتم حجز الإيرادات أو المصروفات المؤجلة لمدة شهر كامل.,
Days,أيام,
Months,الشهور,
Book Deferred Entries Via Journal Entry,كتاب مؤجل إدخالات عن طريق إدخال دفتر اليومية,
If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense,إذا كان هذا غير محدد ، فسيتم إنشاء إدخالات دفتر الأستاذ العام المباشرة لحجز الإيرادات / المصاريف المؤجلة,
Submit Journal Entries,إرسال إدخالات دفتر اليومية,
If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,إذا كان هذا غير محدد ، فسيتم حفظ إدخالات دفتر اليومية في حالة المسودة وسيتعين إرسالها يدويًا,
Enable Distributed Cost Center,تمكين مركز التكلفة الموزعة,
@ -8880,8 +8833,6 @@ Source State,دولة المصدر,
Is Inter State,هو Inter State,
Purchase Details,تفاصيل شراء,
Depreciation Posting Date,تاريخ ترحيل الإهلاك,
Purchase Order Required for Purchase Invoice & Receipt Creation,أمر الشراء مطلوب لإنشاء فاتورة الشراء والإيصال,
Purchase Receipt Required for Purchase Invoice Creation,مطلوب إيصال الشراء لإنشاء فاتورة الشراء,
"By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ",بشكل افتراضي ، يتم تعيين اسم المورد وفقًا لاسم المورد الذي تم إدخاله. إذا كنت تريد تسمية الموردين بواسطة أ,
choose the 'Naming Series' option.,اختر خيار &quot;سلسلة التسمية&quot;.,
Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,تكوين قائمة الأسعار الافتراضية عند إنشاء معاملة شراء جديدة. سيتم جلب أسعار العناصر من قائمة الأسعار هذه.,
@ -9142,8 +9093,6 @@ Conditions and Formula variable and example,متغير الشروط والصيغ
Feedback By,ردود الفعل من,
MTNG-.YYYY.-.MM.-.DD.-,MTNG-.YYYY .-. MM .-. DD.-,
Manufacturing Section,قسم التصنيع,
Sales Order Required for Sales Invoice & Delivery Note Creation,مطلوب أمر المبيعات لإنشاء فاتورة المبيعات وإشعار التسليم,
Delivery Note Required for Sales Invoice Creation,مطلوب مذكرة التسليم لإنشاء فاتورة المبيعات,
"By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ",بشكل افتراضي ، يتم تعيين اسم العميل وفقًا للاسم الكامل الذي تم إدخاله. إذا كنت تريد تسمية العملاء بواسطة أ,
Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,تكوين قائمة الأسعار الافتراضية عند إنشاء معاملة مبيعات جديدة. سيتم جلب أسعار العناصر من قائمة الأسعار هذه.,
"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.",إذا تم تكوين هذا الخيار &quot;نعم&quot; ، سيمنعك ERPNext من إنشاء فاتورة مبيعات أو مذكرة تسليم دون إنشاء أمر مبيعات أولاً. يمكن تجاوز هذا التكوين لعميل معين عن طريق تمكين مربع الاختيار &quot;السماح بإنشاء فاتورة المبيعات بدون طلب مبيعات&quot; في مدير العميل.,
@ -9367,8 +9316,6 @@ Courses updated,تم تحديث الدورات,
{0} {1} has been added to all the selected topics successfully.,تمت إضافة {0} {1} إلى كافة الموضوعات المحددة بنجاح.,
Topics updated,تم تحديث المواضيع,
Academic Term and Program,الفصل الدراسي والبرنامج,
Last Stock Transaction for item {0} was on {1}.,كانت آخر معاملة مخزون للعنصر {0} في {1}.,
Stock Transactions for Item {0} cannot be posted before this time.,لا يمكن ترحيل معاملات المخزون الخاصة بالعنصر {0} قبل هذا الوقت.,
Please remove this item and try to submit again or update the posting time.,يرجى إزالة هذا العنصر ومحاولة الإرسال مرة أخرى أو تحديث وقت النشر.,
Failed to Authenticate the API key.,فشل مصادقة مفتاح API.,
Invalid Credentials,بيانات الاعتماد غير صالحة,
@ -9615,7 +9562,6 @@ Remember to set {field_label}. It is required by {regulation}.,تذكر أن ت
Enrollment Date cannot be before the Start Date of the Academic Year {0},لا يمكن أن يكون تاريخ التسجيل قبل تاريخ بدء العام الأكاديمي {0},
Enrollment Date cannot be after the End Date of the Academic Term {0},لا يمكن أن يكون تاريخ التسجيل بعد تاريخ انتهاء الفصل الدراسي {0},
Enrollment Date cannot be before the Start Date of the Academic Term {0},لا يمكن أن يكون تاريخ التسجيل قبل تاريخ بدء الفصل الدراسي {0},
Posting future transactions are not allowed due to Immutable Ledger,لا يُسمح بنشر المعاملات المستقبلية بسبب دفتر الأستاذ غير القابل للتغيير,
Future Posting Not Allowed,النشر في المستقبل غير مسموح به,
"To enable Capital Work in Progress Accounting, ",لتمكين محاسبة الأعمال الرأسمالية الجارية ،,
you must select Capital Work in Progress Account in accounts table,يجب عليك تحديد حساب رأس المال قيد التقدم في جدول الحسابات,
@ -9632,3 +9578,157 @@ Company Not Linked,شركة غير مرتبطة,
Import Chart of Accounts from CSV / Excel files,استيراد مخطط الحسابات من ملفات CSV / Excel,
Completed Qty cannot be greater than 'Qty to Manufacture',لا يمكن أن تكون الكمية المكتملة أكبر من &quot;الكمية إلى التصنيع&quot;,
"Row {0}: For Supplier {1}, Email Address is Required to send an email",الصف {0}: للمورد {1} ، مطلوب عنوان البريد الإلكتروني لإرسال بريد إلكتروني,
"If enabled, the system will post accounting entries for inventory automatically",في حالة التمكين ، سيقوم النظام بترحيل إدخالات المحاسبة للمخزون تلقائيًا,
Accounts Frozen Till Date,الحسابات المجمدة حتى تاريخ,
Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,تم تجميد قيود المحاسبة حتى هذا التاريخ. لا يمكن لأي شخص إنشاء أو تعديل الإدخالات باستثناء المستخدمين الذين لديهم الدور المحدد أدناه,
Role Allowed to Set Frozen Accounts and Edit Frozen Entries,الدور مسموح به لتعيين حسابات مجمدة وتعديل الإدخالات المجمدة,
Address used to determine Tax Category in transactions,العنوان المستخدم لتحديد فئة الضريبة في المعاملات,
"The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ",النسبة المئوية المسموح لك بدفعها مقابل المبلغ المطلوب. على سبيل المثال ، إذا كانت قيمة الأمر 100 دولار أمريكي لأحد العناصر ، وتم تعيين التفاوت بنسبة 10٪ ، فيُسمح لك بدفع ما يصل إلى 110 دولارات أمريكية.,
This role is allowed to submit transactions that exceed credit limits,يُسمح لهذا الدور بإرسال المعاملات التي تتجاوز حدود الائتمان,
"If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month",إذا تم تحديد &quot;الأشهر&quot; ، فسيتم حجز مبلغ ثابت كإيرادات أو مصروفات مؤجلة لكل شهر بغض النظر عن عدد الأيام في الشهر. سيتم تقسيمها إذا لم يتم حجز الإيرادات أو المصاريف المؤجلة لمدة شهر كامل,
"If this is unchecked, direct GL entries will be created to book deferred revenue or expense",إذا لم يتم تحديد ذلك ، فسيتم إنشاء إدخالات دفتر الأستاذ العام المباشرة لحجز الإيرادات أو المصاريف المؤجلة,
Show Inclusive Tax in Print,عرض الضرائب الشاملة في المطبوعات,
Only select this if you have set up the Cash Flow Mapper documents,حدد هذا فقط إذا كنت قد قمت بإعداد مستندات مخطط التدفق النقدي,
Payment Channel,قناة الدفع,
Is Purchase Order Required for Purchase Invoice & Receipt Creation?,هل طلب الشراء مطلوب لإنشاء فاتورة الشراء والإيصال؟,
Is Purchase Receipt Required for Purchase Invoice Creation?,هل إيصال الشراء مطلوب لإنشاء فاتورة الشراء؟,
Maintain Same Rate Throughout the Purchase Cycle,حافظ على نفس السعر طوال دورة الشراء,
Allow Item To Be Added Multiple Times in a Transaction,السماح بإضافة العنصر عدة مرات في المعاملة,
Suppliers,الموردين,
Send Emails to Suppliers,إرسال رسائل البريد الإلكتروني إلى الموردين,
Select a Supplier,حدد المورد,
Cannot mark attendance for future dates.,لا يمكن تحديد الحضور للتواريخ المستقبلية.,
Do you want to update attendance? <br> Present: {0} <br> Absent: {1},هل تريد تحديث الحضور؟<br> الحاضر: {0}<br> غائب: {1},
Mpesa Settings,إعدادات Mpesa,
Initiator Name,اسم البادئ,
Till Number,حتى رقم,
Sandbox,صندوق الرمل,
Online PassKey,مفتاح المرور عبر الإنترنت,
Security Credential,الاعتماد الأمني,
Get Account Balance,احصل على رصيد الحساب,
Please set the initiator name and the security credential,يرجى تعيين اسم البادئ وبيانات اعتماد الأمان,
Inpatient Medication Entry,إدخال الأدوية للمرضى الداخليين,
HLC-IME-.YYYY.-,HLC-IME-.YYYY.-,
Item Code (Drug),كود البند (المخدرات),
Medication Orders,أوامر الدواء,
Get Pending Medication Orders,احصل على طلبات الأدوية المعلقة,
Inpatient Medication Orders,طلبات الأدوية للمرضى الداخليين,
Medication Warehouse,مستودع الأدوية,
Warehouse from where medication stock should be consumed,المستودع الذي يجب استهلاك مخزون الأدوية منه,
Fetching Pending Medication Orders,إحضار أوامر الأدوية المعلقة,
Inpatient Medication Entry Detail,تفاصيل إدخال الأدوية للمرضى الداخليين,
Medication Details,تفاصيل الدواء,
Drug Code,كود الدواء,
Drug Name,اسم الدواء,
Against Inpatient Medication Order,ضد طلب الأدوية للمرضى الداخليين,
Against Inpatient Medication Order Entry,ضد إدخال طلب الأدوية للمرضى الداخليين,
Inpatient Medication Order,طلب الأدوية للمرضى الداخليين,
HLC-IMO-.YYYY.-,HLC-IMO-.YYYY.-,
Total Orders,إجمالي الطلبات,
Completed Orders,الطلبات المكتملة,
Add Medication Orders,أضف طلبات الأدوية,
Adding Order Entries,إضافة إدخالات الطلب,
{0} medication orders completed,تم إكمال {0} من طلبات الأدوية,
{0} medication order completed,اكتمل طلب الدواء {0},
Inpatient Medication Order Entry,إدخال طلب الأدوية للمرضى الداخليين,
Is Order Completed,هل اكتمل الطلب,
Employee Records to Be Created By,سجلات الموظفين التي سيتم إنشاؤها بواسطة,
Employee records are created using the selected field,يتم إنشاء سجلات الموظفين باستخدام الحقل المحدد,
Don't send employee birthday reminders,لا ترسل تذكيرات عيد ميلاد الموظف,
Restrict Backdated Leave Applications,تقييد طلبات الإجازة القديمة,
Sequence ID,معرف التسلسل,
Sequence Id,معرف التسلسل,
Allow multiple material consumptions against a Work Order,السماح باستهلاكات متعددة للمواد مقابل طلب العمل,
Plan time logs outside Workstation working hours,سجلات وقت الخطة خارج ساعات عمل محطة العمل,
Plan operations X days in advance,خطط العمليات قبل X من الأيام,
Time Between Operations (Mins),الوقت بين العمليات (بالدقائق),
Default: 10 mins,الافتراضي: 10 دقائق,
Overproduction for Sales and Work Order,زيادة الإنتاج للمبيعات وطلب العمل,
"Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials",قم بتحديث تكلفة قائمة المواد تلقائيًا عبر المجدول ، استنادًا إلى أحدث معدل تقييم / سعر قائمة الأسعار / آخر سعر شراء للمواد الخام,
Purchase Order already created for all Sales Order items,تم إنشاء أمر الشراء بالفعل لجميع بنود أوامر المبيعات,
Select Items,اختيار العناصر,
Against Default Supplier,ضد المورد الافتراضي,
Auto close Opportunity after the no. of days mentioned above,فرصة الإغلاق التلقائي بعد لا. من الأيام المذكورة أعلاه,
Is Sales Order Required for Sales Invoice & Delivery Note Creation?,هل طلب المبيعات مطلوب لإنشاء فاتورة المبيعات ومذكرة التسليم؟,
Is Delivery Note Required for Sales Invoice Creation?,هل مطلوب مذكرة التسليم لإنشاء فاتورة المبيعات؟,
How often should Project and Company be updated based on Sales Transactions?,كم مرة يجب تحديث المشروع والشركة بناءً على معاملات المبيعات؟,
Allow User to Edit Price List Rate in Transactions,السماح للمستخدم بتحرير سعر قائمة الأسعار في المعاملات,
Allow Item to Be Added Multiple Times in a Transaction,السماح بإضافة العنصر عدة مرات في المعاملة,
Allow Multiple Sales Orders Against a Customer's Purchase Order,السماح بأوامر مبيعات متعددة مقابل طلب الشراء الخاص بالعميل,
Validate Selling Price for Item Against Purchase Rate or Valuation Rate,تحقق من صحة سعر البيع للسلعة مقابل معدل الشراء أو معدل التقييم,
Hide Customer's Tax ID from Sales Transactions,إخفاء المعرّف الضريبي للعميل من معاملات المبيعات,
"The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.",النسبة المئوية المسموح لك باستلامها أو تسليم المزيد مقابل الكمية المطلوبة. على سبيل المثال ، إذا كنت قد طلبت 100 وحدة ، وكان مخصصك 10٪ ، فيُسمح لك باستلام 110 وحدة.,
Action If Quality Inspection Is Not Submitted,الإجراء إذا لم يتم تقديم استقصاء الجودة,
Auto Insert Price List Rate If Missing,إدراج سعر قائمة الأسعار تلقائيًا إذا كان مفقودًا,
Automatically Set Serial Nos Based on FIFO,قم بتعيين الأرقام التسلسلية تلقائيًا استنادًا إلى ما يرد أولاً يصرف أولاً,
Set Qty in Transactions Based on Serial No Input,قم بتعيين الكمية في المعاملات بناءً على عدم إدخال تسلسلي,
Raise Material Request When Stock Reaches Re-order Level,رفع طلب المواد عندما يصل المخزون إلى مستوى إعادة الطلب,
Notify by Email on Creation of Automatic Material Request,الإخطار عن طريق البريد الإلكتروني عند إنشاء طلب المواد تلقائيًا,
Allow Material Transfer from Delivery Note to Sales Invoice,السماح بنقل المواد من مذكرة التسليم إلى فاتورة المبيعات,
Allow Material Transfer from Purchase Receipt to Purchase Invoice,السماح بنقل المواد من إيصال الشراء إلى فاتورة الشراء,
Freeze Stocks Older Than (Days),تجميد المخزونات أقدم من (أيام),
Role Allowed to Edit Frozen Stock,الدور المسموح به لتحرير المخزون المجمد,
The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,المبلغ غير المخصص لإدخال الدفع {0} أكبر من المبلغ غير المخصص للمعاملة المصرفية,
Payment Received,تم استلام الدفعة,
Attendance cannot be marked outside of Academic Year {0},لا يمكن وضع علامة على الحضور خارج العام الدراسي {0},
Student is already enrolled via Course Enrollment {0},تم تسجيل الطالب بالفعل عن طريق التسجيل في الدورة التدريبية {0},
Attendance cannot be marked for future dates.,لا يمكن تحديد الحضور للتواريخ المستقبلية.,
Please add programs to enable admission application.,الرجاء إضافة برامج لتمكين تطبيق القبول.,
The following employees are currently still reporting to {0}:,لا يزال الموظفون التالي ذكرهم يتبعون حاليًا {0}:,
Please make sure the employees above report to another Active employee.,يرجى التأكد من أن الموظفين أعلاه يقدمون تقارير إلى موظف نشط آخر.,
Cannot Relieve Employee,لا يمكن إعفاء الموظف,
Please enter {0},الرجاء إدخال {0},
Please select another payment method. Mpesa does not support transactions in currency '{0}',الرجاء تحديد طريقة دفع أخرى. لا تدعم Mpesa المعاملات بالعملة &quot;{0}&quot;,
Transaction Error,خطأ في المعاملة,
Mpesa Express Transaction Error,خطأ معاملة Mpesa Express,
"Issue detected with Mpesa configuration, check the error logs for more details",تم اكتشاف مشكلة في تكوين Mpesa ، تحقق من سجلات الأخطاء لمزيد من التفاصيل,
Mpesa Express Error,خطأ Mpesa Express,
Account Balance Processing Error,خطأ في معالجة رصيد الحساب,
Please check your configuration and try again,يرجى التحقق من التكوين الخاص بك وحاول مرة أخرى,
Mpesa Account Balance Processing Error,خطأ في معالجة رصيد حساب Mpesa,
Balance Details,تفاصيل الرصيد,
Current Balance,الرصيد الحالي,
Available Balance,الرصيد المتوفر,
Reserved Balance,رصيد محجوز,
Uncleared Balance,رصيد غير مصفى,
Payment related to {0} is not completed,الدفع المتعلق بـ {0} لم يكتمل,
Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.,الصف # {}: الرقم التسلسلي {}. تم بالفعل تحويل {} إلى فاتورة نقطة بيع أخرى. الرجاء تحديد رقم تسلسلي صالح.,
Row #{}: Item Code: {} is not available under warehouse {}.,الصف # {}: رمز العنصر: {} غير متوفر ضمن المستودع {}.,
Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.,الصف # {}: كمية المخزون غير كافية لرمز الصنف: {} تحت المستودع {}. الكمية المتوفرة {}.,
Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.,الصف # {}: الرجاء تحديد رقم تسلسلي ودفعة مقابل العنصر: {} أو إزالته لإكمال المعاملة.,
Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.,الصف # {}: لم يتم تحديد رقم تسلسلي مقابل العنصر: {}. يرجى تحديد واحد أو إزالته لإكمال الصفقة.,
Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.,الصف رقم {}: لم يتم تحديد دُفعة مقابل العنصر: {}. يرجى تحديد دفعة أو إزالتها لإكمال المعاملة.,
Payment amount cannot be less than or equal to 0,لا يمكن أن يكون مبلغ الدفعة أقل من أو يساوي 0,
Please enter the phone number first,الرجاء إدخال رقم الهاتف أولاً,
Row #{}: {} {} does not exist.,الصف رقم {}: {} {} غير موجود.,
Row #{0}: {1} is required to create the Opening {2} Invoices,الصف رقم {0}: {1} مطلوب لإنشاء فواتير الافتتاح {2},
You had {} errors while creating opening invoices. Check {} for more details,كان لديك {} من الأخطاء أثناء إنشاء الفواتير الافتتاحية. تحقق من {} لمزيد من التفاصيل,
Error Occured,حدث خطأ,
Opening Invoice Creation In Progress,جاري إنشاء الفاتورة الافتتاحية,
Creating {} out of {} {},إنشاء {} من {} {},
(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,(الرقم التسلسلي: {0}) لا يمكن استهلاكه لأنه محجوز لملء طلب المبيعات {1}.,
Item {0} {1},العنصر {0} {1},
Last Stock Transaction for item {0} under warehouse {1} was on {2}.,كانت آخر معاملة مخزون للبند {0} تحت المستودع {1} في {2}.,
Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,لا يمكن ترحيل معاملات المخزون للبند {0} تحت المستودع {1} قبل هذا الوقت.,
Posting future stock transactions are not allowed due to Immutable Ledger,لا يُسمح بترحيل معاملات الأسهم المستقبلية بسبب دفتر الأستاذ غير القابل للتغيير,
A BOM with name {0} already exists for item {1}.,يوجد BOM بالاسم {0} بالفعل للعنصر {1}.,
{0}{1} Did you rename the item? Please contact Administrator / Tech support,{0} {1} هل أعدت تسمية العنصر؟ يرجى الاتصال بالدعم الفني / المسؤول,
At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},في الصف # {0}: لا يمكن أن يكون معرف التسلسل {1} أقل من معرف تسلسل الصف السابق {2},
The {0} ({1}) must be equal to {2} ({3}),يجب أن يكون {0} ({1}) مساويًا لـ {2} ({3}),
"{0}, complete the operation {1} before the operation {2}.",{0} ، أكمل العملية {1} قبل العملية {2}.,
Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No.,لا يمكن ضمان التسليم بواسطة Serial No حيث أن العنصر {0} مضاف مع وبدون ضمان التسليم بواسطة Serial No.,
Item {0} has no Serial No. Only serilialized items can have delivery based on Serial No,لا يحتوي العنصر {0} على رقم مسلسل. يمكن فقط تسليم العناصر المسلسلة بناءً على الرقم التسلسلي,
No active BOM found for item {0}. Delivery by Serial No cannot be ensured,لم يتم العثور على BOM نشط للعنصر {0}. لا يمكن ضمان التسليم عن طريق الرقم التسلسلي,
No pending medication orders found for selected criteria,لم يتم العثور على طلبات الأدوية المعلقة للمعايير المحددة,
From Date cannot be after the current date.,لا يمكن أن يكون من تاريخ بعد التاريخ الحالي.,
To Date cannot be after the current date.,لا يمكن أن يكون &quot;To Date&quot; بعد التاريخ الحالي.,
From Time cannot be after the current time.,من وقت لا يمكن أن يكون بعد الوقت الحالي.,
To Time cannot be after the current time.,لا يمكن أن يكون الوقت بعد الوقت الحالي.,
Stock Entry {0} created and ,تم إنشاء إدخال المخزون {0} و,
Inpatient Medication Orders updated successfully,تم تحديث طلبات الأدوية للمرضى الداخليين بنجاح,
Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1},الصف {0}: لا يمكن إنشاء إدخال دواء للمرضى الداخليين مقابل طلب دواء للمرضى الداخليين تم إلغاؤه {1},
Row {0}: This Medication Order is already marked as completed,الصف {0}: تم بالفعل وضع علامة على طلب الدواء هذا على أنه مكتمل,
Quantity not available for {0} in warehouse {1},الكمية غير متوفرة لـ {0} في المستودع {1},
Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.,يرجى تمكين السماح بالمخزون السلبي في إعدادات المخزون أو إنشاء إدخال المخزون للمتابعة.,
No Inpatient Record found against patient {0},لم يتم العثور على سجل للمرضى الداخليين للمريض {0},
An Inpatient Medication Order {0} against Patient Encounter {1} already exists.,يوجد بالفعل طلب دواء للمرضى الداخليين {0} ضد مقابلة المريض {1}.,

Can't render this file because it is too large.

View File

@ -110,7 +110,6 @@ Actual qty in stock,Реално количество в наличност,
Actual type tax cannot be included in Item rate in row {0},Актуалния вид данък не може да бъде включен в цената на артикула от ред {0},
Add,Добави,
Add / Edit Prices,Добавяне / Редактиране на цените,
Add All Suppliers,Добавете всички доставчици,
Add Comment,Добави коментар,
Add Customers,Добавете клиенти,
Add Employees,Добави Служители,
@ -480,7 +479,6 @@ Cannot produce more Item {0} than Sales Order quantity {1},Не може да с
Cannot promote Employee with status Left,Не мога да популяризирам служител със състояние вляво,
Cannot refer row number greater than or equal to current row number for this Charge type,Не може да се отнесе поредни номера по-голям или равен на текущия брой ред за този тип Charge,
Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,Не можете да изберете тип заряд като &quot;На предишния ред Сума&quot; или &quot;На предишния ред Total&quot; за първи ред,
Cannot set a received RFQ to No Quote,Не може да се зададе получена RFQ в Без котировка,
Cannot set as Lost as Sales Order is made.,Не може да се определи като загубена тъй като поръчка за продажба е направена.,
Cannot set authorization on basis of Discount for {0},Не можете да зададете разрешение въз основа на Отстъпка за {0},
Cannot set multiple Item Defaults for a company.,Не може да се задават няколко елемента по подразбиране за компания.,
@ -934,7 +932,6 @@ Employee Referral,Служебни препоръки,
Employee Transfer cannot be submitted before Transfer Date ,Прехвърлянето на служители не може да бъде подадено преди датата на прехвърлянето,
Employee cannot report to himself.,Служител не може да докладва пред самия себе си.,
Employee relieved on {0} must be set as 'Left',Служител облекчение на {0} трябва да се зададе като &quot;Ляв&quot;,
Employee status cannot be set to 'Left' as following employees are currently reporting to this employee:&nbsp;,"Състоянието на служителя не може да бъде зададено на „Наляво“, тъй като в момента следните служители докладват на този служител:",
Employee {0} already submited an apllication {1} for the payroll period {2},Служител {0} вече подаде приложение {1} за периода на заплащане {2},
Employee {0} has already applied for {1} between {2} and {3} : ,Служител {0} вече кандидатства за {1} между {2} и {3}:,
Employee {0} has no maximum benefit amount,Служител {0} няма максимална сума на доходите,
@ -1456,7 +1453,6 @@ Leave application {0} already exists against the student {1},Оставете з
"Leave cannot be allocated before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","Отпуск не могат да бъдат разпределени преди {0}, като баланс отпуск вече е ръчен изпраща в записа на бъдещото разпределение отпуск {1}",
"Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","Остави, не може да се прилага / отмени преди {0}, като баланс отпуск вече е ръчен изпраща в записа на бъдещото разпределение отпуск {1}",
Leave of type {0} cannot be longer than {1},Разрешение за типа {0} не може да бъде по-дълъг от {1},
Leave the field empty to make purchase orders for all suppliers,"Оставете полето празно, за да направите поръчки за покупка за всички доставчици",
Leaves,Листа,
Leaves Allocated Successfully for {0},Листата Разпределен успешно в продължение на {0},
Leaves has been granted sucessfully,Листата е предоставена успешно,
@ -1699,7 +1695,6 @@ No Items to pack,Няма елементи за опаковане,
No Items with Bill of Materials to Manufacture,Не артикули с Бил на материали за производство на,
No Items with Bill of Materials.,Няма артикули с разчет на материали.,
No Permission,Няма разрешение,
No Quote,Без цитат,
No Remarks,Няма забележки,
No Result to submit,Няма отговор за изпращане,
No Salary Structure assigned for Employee {0} on given date {1},"Няма структура на заплатата, определена за служител {0} на дадена дата {1}",
@ -1856,7 +1851,6 @@ Overlap in scoring between {0} and {1},Припокриване на точку
Overlapping conditions found between:,Припокриване условия намерени между:,
Owner,Собственик,
PAN,PAN,
PO already created for all sales order items,PO вече е създадена за всички елементи от поръчките за продажба,
POS,POS,
POS Profile,POS профил,
POS Profile is required to use Point-of-Sale,Профилът на POS е необходим за използване на Point-of-Sale,
@ -2502,7 +2496,6 @@ Row {0}: Quality Inspection rejected for item {1},Ред {0}: Проверка
Row {0}: UOM Conversion Factor is mandatory,Row {0}: мерна единица реализациите Factor е задължително,
Row {0}: select the workstation against the operation {1},Ред {0}: изберете работната станция срещу операцията {1},
Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.,"Ред {0}: {1} Серийни номера, изисквани за елемент {2}. Предоставихте {3}.",
Row {0}: {1} is required to create the Opening {2} Invoices,Ред {0}: {1} е необходим за създаване на {2} Фактури за отваряне,
Row {0}: {1} must be greater than 0,Ред {0}: {1} трябва да е по-голям от 0,
Row {0}: {1} {2} does not match with {3},Ред {0}: {1} {2} не съвпада с {3},
Row {0}:Start Date must be before End Date,Row {0}: Началната дата трябва да е преди крайната дата,
@ -2642,7 +2635,6 @@ Selling Rate,Продажна цена,
Send Grant Review Email,Изпратете имейл за преглед на одобрението,
Send Now,Изпрати сега,
Send SMS,Изпратете SMS,
Send Supplier Emails,Изпрати Доставчик имейли,
Send mass SMS to your contacts,Изпратете маса SMS към вашите контакти,
Sensitivity,чувствителност,
Sent,Изпратено,
@ -3443,7 +3435,6 @@ on,На,
{0} variants created.,{0} вариантите са създадени.,
{0} {1} created,{0} {1} създаден,
{0} {1} does not exist,{0} {1} не съществува,
{0} {1} does not exist.,{0} {1} не съществува.,
{0} {1} has been modified. Please refresh.,"{0} {1} е променен. Моля, опреснете.",
{0} {1} has not been submitted so the action cannot be completed,"{0} {1} не е изпратена, така че действието не може да бъде завършено",
"{0} {1} is associated with {2}, but Party Account is {3}","{0} {1} е свързана с {2}, но профилът на компания е {3}",
@ -3480,6 +3471,7 @@ on,На,
{0}: {1} does not exists,{0}: {1} не съществува,
{0}: {1} not found in Invoice Details table,{0}: {1} не е намерен в Таблицата с Датайлите на Фактури,
{} of {},{} на {},
Assigned To,Възложените,
Chat,Чат,
Completed By,Завършено от,
Conditions,условия,
@ -3502,6 +3494,7 @@ Merge with existing,Обединяване със съществуващото,
Office,Офис,
Orientation,ориентация,
Passive,Пасивен,
Payment Failed,Неуспешно плащане,
Percent,Процент,
Permanent,постоянен,
Personal,Персонален,
@ -3566,6 +3559,8 @@ Naming Series,Поредни Номера,
No data to export,Няма данни за експорт,
Portrait,Портрет,
Print Heading,Print Heading,
Scheduler Inactive,Графикът е неактивен,
Scheduler is inactive. Cannot import data.,Графикът е неактивен. Данните не могат да се импортират.,
Show Document,Показване на документ,
Show Traceback,Показване на Traceback,
Video,Видео,
@ -3691,7 +3686,6 @@ Create Pick List,Създайте списък за избор,
Create Quality Inspection for Item {0},Създаване на проверка на качеството на артикул {0},
Creating Accounts...,Създаване на акаунти ...,
Creating bank entries...,Създаване на банкови записи ...,
Creating {0},Създаване на {0},
Credit limit is already defined for the Company {0},Кредитният лимит вече е определен за компанията {0},
Ctrl + Enter to submit,Ctrl + Enter за изпращане,
Ctrl+Enter to submit,Ctrl + Enter за изпращане,
@ -4524,31 +4518,22 @@ Closed Documents,Затворени документи,
Accounts Settings,Настройки на Сметки,
Settings for Accounts,Настройки за сметки,
Make Accounting Entry For Every Stock Movement,Направи счетоводен запис за всеки склад Movement,
"If enabled, the system will post accounting entries for inventory automatically.","Ако е активирана, системата ще публикуваме счетоводни записвания за инвентара автоматично.",
Accounts Frozen Upto,Замразени Сметки до,
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","Счетоводен запис, замразени до тази дата, никой не може да направи / промени записите с изключение на ролята посочена по-долу",
Role Allowed to Set Frozen Accounts & Edit Frozen Entries,Роля позволено да определят замразени сметки &amp; Редактиране на замразени влизания,
Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,Потребителите с тази роля е разрешено да задават замразени сметки и да се създаде / модифицира счетоводни записи срещу замразените сметки,
Determine Address Tax Category From,Определете категорията на адресния данък от,
Address used to determine Tax Category in transactions.,"Адрес, използван за определяне на данъчна категория при транзакции.",
Over Billing Allowance (%),Надбавка за таксуване (%),
Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.,"Процент, който ви позволява да таксувате повече спрямо поръчаната сума. Например: Ако стойността на поръчката е 100 долара за артикул и толерансът е зададен като 10%, тогава можете да таксувате за 110 долара.",
Credit Controller,Кредит контрольор,
Role that is allowed to submit transactions that exceed credit limits set.,"Роля, която е оставена да се представят сделки, които надвишават кредитни лимити, определени.",
Check Supplier Invoice Number Uniqueness,Провери за уникалност на фактура на доставчик,
Make Payment via Journal Entry,Направи Плащане чрез вестник Влизане,
Unlink Payment on Cancellation of Invoice,Прекратяване на връзката с плащане при анулиране на фактура,
Book Asset Depreciation Entry Automatically,Автоматично отписване на амортизацията на активи,
Automatically Add Taxes and Charges from Item Tax Template,Автоматично добавяне на данъци и такси от шаблона за данък върху стоки,
Automatically Fetch Payment Terms,Автоматично извличане на условията за плащане,
Show Inclusive Tax In Print,Показване на включения данък в печат,
Show Payment Schedule in Print,Показване на графика на плащанията в печат,
Currency Exchange Settings,Настройки за обмяна на валута,
Allow Stale Exchange Rates,Разрешаване на стационарни обменни курсове,
Stale Days,Старши дни,
Report Settings,Настройки на отчетите,
Use Custom Cash Flow Format,Използвайте персонализиран формат на паричен поток,
Only select if you have setup Cash Flow Mapper documents,Изберете само ако имате настройки за документиране на паричните потоци,
Allowed To Transact With,Позволени да извършват транзакции с,
SWIFT number,SWIFT номер,
Branch Code,Код на клона,
@ -5485,8 +5470,6 @@ Settings for Buying Module,Настройки на модул - Закупува
Supplier Naming By,"Доставчик наименуването им,",
Default Supplier Group,Група доставчици по подразбиране,
Default Buying Price List,Ценови лист за закупуване по подразбиране,
Maintain same rate throughout purchase cycle,Поддържане на същия процент в цялия цикъл на покупка,
Allow Item to be added multiple times in a transaction,Оставя т да бъдат добавени няколко пъти в една сделка,
Backflush Raw Materials of Subcontract Based On,Възстановяване на суровини от договори за подизпълнение,
Material Transferred for Subcontract,Прехвърлен материал за подизпълнение,
Over Transfer Allowance (%),Помощ за прехвърляне (%),
@ -5530,7 +5513,6 @@ Purchase Receipt Item Supplied,Покупка Квитанция приложе
Current Stock,Наличност,
PUR-RFQ-.YYYY.-,PUR-RFQ-.YYYY.-,
For individual supplier,За отделен доставчик,
Supplier Detail,Доставчик - детайли,
Link to Material Requests,Връзка към заявки за материали,
Message for Supplier,Съобщение за доставчика,
Request for Quotation Item,Запитване за оферта - позиция,
@ -6724,10 +6706,7 @@ HR Settings,Настройки на човешките ресурси (ЧР),
Employee Settings,Настройки на служители,
Retirement Age,пенсионна възраст,
Enter retirement age in years,Въведете пенсионна възраст в години,
Employee Records to be created by,Архивите на служителите да бъдат създадени от,
Employee record is created using selected field. ,Запис на служителите е създаден с помощта на избран област.,
Stop Birthday Reminders,Stop напомняне за рождени дни,
Don't send Employee Birthday Reminders,Не изпращайте на служителите напомняне за рождени дни,
Expense Approver Mandatory In Expense Claim,Задължителният разпоредител с разходи в декларацията за разходи,
Payroll Settings,Настройки ТРЗ,
Leave,Оставете,
@ -6749,7 +6728,6 @@ Role Allowed to Create Backdated Leave Application,Ролята е разреш
Leave Approver Mandatory In Leave Application,Оставете призванието задължително в отпуск,
Show Leaves Of All Department Members In Calendar,Показване на листата на всички членове на катедрата в календара,
Auto Leave Encashment,Автоматично оставяне Encashment,
Restrict Backdated Leave Application,Ограничете приложението за обратно изтегляне,
Hiring Settings,Настройки за наемане,
Check Vacancies On Job Offer Creation,Проверете свободни работни места при създаване на оферта за работа,
Identification Document Type,Идентификационен документ тип,
@ -7283,28 +7261,21 @@ Completed Qty,Изпълнено Количество,
Manufacturing Settings,Настройки производство,
Raw Materials Consumption,Консумация на суровини,
Allow Multiple Material Consumption,Позволявайте многократна консумация на материали,
Allow multiple Material Consumption against a Work Order,Позволете многократна консумация на материали срещу работна поръчка,
Backflush Raw Materials Based On,Изписване на суровини въз основа на,
Material Transferred for Manufacture,Материалът е прехвърлен за Производство,
Capacity Planning,Планиране на капацитета,
Disable Capacity Planning,Деактивиране на планирането на капацитета,
Allow Overtime,Разрешаване на Извънредно раб.време,
Plan time logs outside Workstation Working Hours.,Планирайте времето трупи извън Workstation работно време.,
Allow Production on Holidays,Разрешаване на производство на празници,
Capacity Planning For (Days),Планиране на капацитет за (дни),
Try planning operations for X days in advance.,Опитайте планира операции за Х дни предварително.,
Time Between Operations (in mins),Време между операциите (в минути),
Default 10 mins,По подразбиране 10 минути,
Default Warehouses for Production,Складове по подразбиране за производство,
Default Work In Progress Warehouse,Склад за незав.производство по подразбиране,
Default Finished Goods Warehouse,По подразбиране - Склад за готова продукция,
Default Scrap Warehouse,Склад за скрап по подразбиране,
Over Production for Sales and Work Order,Над производство за продажба и поръчка за работа,
Overproduction Percentage For Sales Order,Процент на свръхпроизводство за поръчка за продажба,
Overproduction Percentage For Work Order,Процент на свръхпроизводство за работна поръчка,
Other Settings,Други настройки,
Update BOM Cost Automatically,Актуализиране на цената на BOM автоматично,
"Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.","Актуализиране на BOM струва автоматично чрез Scheduler, въз основа на последната скорост на оценка / ценоразпис / последната сума на покупката на суровини.",
Material Request Plan Item,Елемент от плана за материали,
Material Request Type,Заявка за материал - тип,
Material Issue,Изписване на материал,
@ -7771,15 +7742,9 @@ Campaign Naming By,Задаване на име на кампания,
Default Customer Group,Клиентска група по подразбиране,
Default Territory,Територия по подразбиране,
Close Opportunity After Days,Затвори възможността след брой дни,
Auto close Opportunity after 15 days,Автоматично затваряне на възможността в 15-дневен срок,
Default Quotation Validity Days,Начални дни на валидност на котировката,
Sales Update Frequency,Честота на обновяване на продажбите,
How often should project and company be updated based on Sales Transactions.,Колко често трябва да се актуализира проектът и фирмата въз основа на продажбите.,
Each Transaction,Всяка транзакция,
Allow user to edit Price List Rate in transactions,Позволи на потребителя да редактира цените в Ценоразпис от транзакциите,
Allow multiple Sales Orders against a Customer's Purchase Order,Разрешаване на множество Поръчки за продажби срещу поръчка на клиента,
Validate Selling Price for Item against Purchase Rate or Valuation Rate,Валидиране на продажна цена за позиция срещу процент за закупуване или цена по оценка,
Hide Customer's Tax Id from Sales Transactions,Скриване на данъчния идентификационен номер на клиента от сделки за продажба,
SMS Center,SMS Center,
Send To,Изпрати на,
All Contact,Всички контакти,
@ -8388,24 +8353,14 @@ Default Item Group,Група елементи по подразбиране,
Default Stock UOM,Мерна единица за стоки по подразбиране,
Sample Retention Warehouse,Склад за съхраняване на проби,
Default Valuation Method,Метод на оценка по подразбиране,
Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.,Процент ви е позволено да получи или достави повече от поръчаното количество. Например: Ако сте поръчали 100 единици. и си Allowance е 10% след което се оставя да се получи 110 единици.,
Action if Quality inspection is not submitted,"Действие, ако не бъде представена проверка за качество",
Show Barcode Field,Покажи поле за баркод,
Convert Item Description to Clean HTML,Конвертиране на елемента Описание за почистване на HTML,
Auto insert Price List rate if missing,"Auto вложка Ценоразпис ставка, ако липсва",
Allow Negative Stock,Разрешаване на отрицателна наличност,
Automatically Set Serial Nos based on FIFO,Автоматично Определете серийни номера на базата на FIFO,
Set Qty in Transactions based on Serial No Input,Задайте количество в транзакции въз основа на сериен № вход,
Auto Material Request,Auto Материал Искане,
Raise Material Request when stock reaches re-order level,Повдигнете Материал Заявка когато фондова достигне ниво повторна поръчка,
Notify by Email on creation of automatic Material Request,Изпращайте по имейл за създаване на автоматично искане за материали,
Inter Warehouse Transfer Settings,Настройки за прехвърляне на Inter Warehouse,
Allow Material Transfer From Delivery Note and Sales Invoice,Разрешаване на прехвърляне на материали от бележка за доставка и фактура за продажба,
Allow Material Transfer From Purchase Receipt and Purchase Invoice,Разрешаване на трансфер на материали от разписка за покупка и фактура за покупка,
Freeze Stock Entries,Фиксиране на вписване в запасите,
Stock Frozen Upto,Фондова Frozen Upto,
Freeze Stocks Older Than [Days],Freeze Запаси по-стари от [Days],
Role Allowed to edit frozen stock,Роля за редактиране замразена,
Batch Identification,Идентификация на партидата,
Use Naming Series,Използвайте серията за наименуване,
Naming Series Prefix,Наименуване на серийния префикс,
@ -8731,11 +8686,9 @@ Published on,Публикувано на,
Service Received But Not Billed,"Услугата получена, но не е таксувана",
Deferred Accounting Settings,Настройки за отложено счетоводство,
Book Deferred Entries Based On,Резервирайте отложените записи въз основа на,
"If ""Months"" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.","Ако е избрано „Месеци“, тогава фиксираната сума ще бъде осчетоводена като отсрочени приходи или разходи за всеки месец, независимо от броя на дните в месеца. Ще бъде пропорционално, ако отложените приходи или разходи не бъдат записани за цял месец.",
Days,Дни,
Months,Месеци,
Book Deferred Entries Via Journal Entry,Резервирайте отложените записи чрез запис в дневника,
If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense,"Ако това не е отметнато, ще бъдат създадени директни записи за GL, за да се резервират отсрочени приходи / разходи",
Submit Journal Entries,Изпращане на записи в дневника,
If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,"Ако това не е отметнато, записите в дневника ще бъдат запазени в състояние на чернова и ще трябва да бъдат изпратени ръчно",
Enable Distributed Cost Center,Активиране на разпределен център за разходи,
@ -8880,8 +8833,6 @@ Source State,Източник,
Is Inter State,Е Inter State,
Purchase Details,Подробности за покупката,
Depreciation Posting Date,Дата на осчетоводяване на амортизация,
Purchase Order Required for Purchase Invoice & Receipt Creation,"Поръчка за покупка, необходима за създаване на фактура за покупка и получаване",
Purchase Receipt Required for Purchase Invoice Creation,"Разписка за покупка, необходима за създаване на фактура за покупка",
"By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ",По подразбиране името на доставчика е зададено според въведеното име на доставчика. Ако искате доставчиците да бъдат посочени от,
choose the 'Naming Series' option.,изберете опцията „Naming Series“.,
Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,"Конфигурирайте ценовата листа по подразбиране, когато създавате нова транзакция за покупка. Цените на артикулите ще бъдат извлечени от тази ценова листа.",
@ -9142,8 +9093,6 @@ Conditions and Formula variable and example,Условия и формула п
Feedback By,Обратна връзка от,
MTNG-.YYYY.-.MM.-.DD.-,MTNG-.YYYY .-. MM .-. DD.-,
Manufacturing Section,Производствена секция,
Sales Order Required for Sales Invoice & Delivery Note Creation,Поръчка за продажба е необходима за фактура за продажба и създаване на бележка за доставка,
Delivery Note Required for Sales Invoice Creation,Необходима бележка за доставка за създаване на фактура за продажба,
"By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ",По подразбиране Името на клиента се задава според въведеното Пълно име. Ако искате клиентите да бъдат именувани от,
Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,"Конфигурирайте ценовата листа по подразбиране, когато създавате нова транзакция за продажби. Цените на артикулите ще бъдат извлечени от тази ценова листа.",
"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.","Ако тази опция е конфигурирана „Да“, ERPNext ще ви попречи да създадете фактура за продажба или бележка за доставка, без първо да създавате поръчка за продажба. Тази конфигурация може да бъде заменена за конкретен клиент, като активирате квадратчето „Разрешаване на създаването на фактура за продажба без поръчка за продажба“ в клиентския мастер.",
@ -9367,8 +9316,6 @@ Courses updated,Курсовете са актуализирани,
{0} {1} has been added to all the selected topics successfully.,{0} {1} бе добавен успешно към всички избрани теми.,
Topics updated,Темите са актуализирани,
Academic Term and Program,Академичен срок и програма,
Last Stock Transaction for item {0} was on {1}.,Последната транзакция на склад за артикул {0} беше на {1}.,
Stock Transactions for Item {0} cannot be posted before this time.,Транзакции със запаси за артикул {0} не могат да бъдат публикувани преди това време.,
Please remove this item and try to submit again or update the posting time.,"Моля, премахнете този елемент и опитайте да изпратите отново или актуализирайте времето за публикуване.",
Failed to Authenticate the API key.,Неуспешно удостоверяване на API ключа.,
Invalid Credentials,Невалидни идентификационни данни,
@ -9615,7 +9562,6 @@ Remember to set {field_label}. It is required by {regulation}.,Не забрав
Enrollment Date cannot be before the Start Date of the Academic Year {0},Датата на записване не може да бъде преди началната дата на учебната година {0},
Enrollment Date cannot be after the End Date of the Academic Term {0},Датата на записване не може да бъде след Крайната дата на академичния срок {0},
Enrollment Date cannot be before the Start Date of the Academic Term {0},Дата на записване не може да бъде преди началната дата на академичния срок {0},
Posting future transactions are not allowed due to Immutable Ledger,Публикуването на бъдещи транзакции не е разрешено поради неизменяема книга,
Future Posting Not Allowed,Публикуването в бъдеще не е разрешено,
"To enable Capital Work in Progress Accounting, ","За да активирате счетоводното отчитане на текущата работа,",
you must select Capital Work in Progress Account in accounts table,трябва да изберете Сметка за текущ капитал в таблицата на сметките,
@ -9632,3 +9578,157 @@ Company Not Linked,Фирма не е свързана,
Import Chart of Accounts from CSV / Excel files,Импортиране на сметката от CSV / Excel файлове,
Completed Qty cannot be greater than 'Qty to Manufacture',Попълненото количество не може да бъде по-голямо от „Количество за производство“,
"Row {0}: For Supplier {1}, Email Address is Required to send an email",Ред {0}: За доставчика {1} е необходим имейл адрес за изпращане на имейл,
"If enabled, the system will post accounting entries for inventory automatically","Ако е активирана, системата автоматично ще публикува счетоводни записи за инвентара",
Accounts Frozen Till Date,"Сметки, замразени до датата",
Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,Счетоводните записи са замразени до тази дата. Никой не може да създава или променя записи освен потребители с посочената по-долу роля,
Role Allowed to Set Frozen Accounts and Edit Frozen Entries,Позволена роля за задаване на замразени акаунти и редактиране на замразени записи,
Address used to determine Tax Category in transactions,"Адрес, използван за определяне на данъчната категория при транзакции",
"The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ","Процентът, който имате право да таксувате повече срещу поръчаната сума. Например, ако стойността на поръчката е $ 100 за артикул и толерансът е зададен като 10%, тогава имате право да таксувате до $ 110",
This role is allowed to submit transactions that exceed credit limits,"Тази роля има право да подава транзакции, които надвишават кредитните лимити",
"If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month","Ако е избрано „Месеци“, фиксирана сума ще бъде осчетоводена като отсрочени приходи или разходи за всеки месец, независимо от броя на дните в месеца. Той ще бъде пропорционален, ако отложените приходи или разходи не бъдат записани за цял месец",
"If this is unchecked, direct GL entries will be created to book deferred revenue or expense","Ако това не е отметнато, ще бъдат създадени директни записи в GL, за да се отчетат отсрочени приходи или разходи",
Show Inclusive Tax in Print,Показване на включения данък в печат,
Only select this if you have set up the Cash Flow Mapper documents,Изберете това само ако сте настроили документите за картографиране на парични потоци,
Payment Channel,Канал за плащане,
Is Purchase Order Required for Purchase Invoice & Receipt Creation?,Изисква ли се поръчка за покупка за създаване на фактура за покупка и получаване?,
Is Purchase Receipt Required for Purchase Invoice Creation?,Изисква ли се разписка за покупка за създаване на фактура за покупка?,
Maintain Same Rate Throughout the Purchase Cycle,Поддържайте една и съща ставка през целия цикъл на покупка,
Allow Item To Be Added Multiple Times in a Transaction,Разрешаване на добавянето на елемент няколко пъти в транзакция,
Suppliers,Доставчици,
Send Emails to Suppliers,Изпращайте имейли до доставчиците,
Select a Supplier,Изберете доставчик,
Cannot mark attendance for future dates.,Не може да се отбележи присъствие за бъдещи дати.,
Do you want to update attendance? <br> Present: {0} <br> Absent: {1},Искате ли да актуализирате присъствието?<br> Присъства: {0}<br> Отсъства: {1},
Mpesa Settings,Настройки на Mpesa,
Initiator Name,Име на инициатора,
Till Number,До номер,
Sandbox,Пясъчник,
Online PassKey,Онлайн PassKey,
Security Credential,Удостоверения за сигурност,
Get Account Balance,Вземете салдо по акаунта,
Please set the initiator name and the security credential,"Моля, задайте името на инициатора и идентификационните данни за защита",
Inpatient Medication Entry,Вход за стационарни лекарства,
HLC-IME-.YYYY.-,HLC-IME-.YYYY.-,
Item Code (Drug),Код на артикула (наркотик),
Medication Orders,Поръчки за лекарства,
Get Pending Medication Orders,Вземете чакащи поръчки за лекарства,
Inpatient Medication Orders,Заповеди за стационарни медикаменти,
Medication Warehouse,Склад за лекарства,
Warehouse from where medication stock should be consumed,"Склад, откъдето трябва да се консумира запас от лекарства",
Fetching Pending Medication Orders,Извличане на чакащи поръчки за лекарства,
Inpatient Medication Entry Detail,Подробности за стационарното лекарство,
Medication Details,Подробности за лекарствата,
Drug Code,Код за наркотици,
Drug Name,Име на лекарството,
Against Inpatient Medication Order,Срещу заповед за стационарно лечение,
Against Inpatient Medication Order Entry,Срещу влизане на заповед за стационарно лечение,
Inpatient Medication Order,Заповед за стационарно лечение,
HLC-IMO-.YYYY.-,HLC-IMO-.YYYY.-,
Total Orders,Общо поръчки,
Completed Orders,Изпълнени поръчки,
Add Medication Orders,Добавете поръчки за лекарства,
Adding Order Entries,Добавяне на записи за поръчки,
{0} medication orders completed,{0} поръчки за лекарства завършени,
{0} medication order completed,{0} поръчка за лекарства завършена,
Inpatient Medication Order Entry,Вписване на заповед за стационарно лечение,
Is Order Completed,Изпълнена ли е поръчката,
Employee Records to Be Created By,"Записи на служителите, които ще бъдат създадени от",
Employee records are created using the selected field,Записите на служителите се създават с помощта на избраното поле,
Don't send employee birthday reminders,Не изпращайте напомняния за рождения ден на служителите,
Restrict Backdated Leave Applications,Ограничете приложенията за отпуск със задна дата,
Sequence ID,Идент. № на последователността,
Sequence Id,Идент. № на последователността,
Allow multiple material consumptions against a Work Order,Позволете многократни консумации на материали срещу работна поръчка,
Plan time logs outside Workstation working hours,Планирайте дневници за време извън работното време на работната станция,
Plan operations X days in advance,Планирайте операциите X дни предварително,
Time Between Operations (Mins),Време между операциите (минути),
Default: 10 mins,По подразбиране: 10 минути,
Overproduction for Sales and Work Order,Свръхпроизводство за продажби и работна поръчка,
"Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials","Актуализирайте BOM разходите автоматично чрез планиращ механизъм, въз основа на най-новия процент на оценка / Ценова листа / Степен на последно закупуване на суровини",
Purchase Order already created for all Sales Order items,Поръчка за покупка вече е създадена за всички елементи на Поръчка за продажба,
Select Items,Изберете елементи,
Against Default Supplier,Срещу доставчик по подразбиране,
Auto close Opportunity after the no. of days mentioned above,"Автоматично затваряне Възможност след не. от дните, споменати по-горе",
Is Sales Order Required for Sales Invoice & Delivery Note Creation?,Изисква ли се поръчка за продажба за създаване на фактура за продажба и бележка за доставка?,
Is Delivery Note Required for Sales Invoice Creation?,Необходима ли е бележка за доставка за създаване на фактура за продажба?,
How often should Project and Company be updated based on Sales Transactions?,Колко често проектът и компанията трябва да се актуализират въз основа на транзакции за продажба?,
Allow User to Edit Price List Rate in Transactions,Позволете на потребителя да редактира ценовата листа в транзакциите,
Allow Item to Be Added Multiple Times in a Transaction,Разрешаване на добавянето на елемент няколко пъти в транзакция,
Allow Multiple Sales Orders Against a Customer's Purchase Order,Разрешаване на множество поръчки за продажба срещу поръчка на клиента,
Validate Selling Price for Item Against Purchase Rate or Valuation Rate,Проверете продажната цена за артикул спрямо процента на покупка или степента на оценка,
Hide Customer's Tax ID from Sales Transactions,Скриване на данъчния номер на клиента от продажби,
"The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.","Процентът, който имате право да получавате или доставяте повече спрямо поръчаното количество. Например, ако сте поръчали 100 единици и вашата надбавка е 10%, тогава имате право да получите 110 единици.",
Action If Quality Inspection Is Not Submitted,"Действие, ако не е представена проверка на качеството",
Auto Insert Price List Rate If Missing,"Автоматично въвеждане на ценоразпис, ако липсва",
Automatically Set Serial Nos Based on FIFO,Автоматично задаване на серийни номера въз основа на FIFO,
Set Qty in Transactions Based on Serial No Input,Задайте количество в транзакции въз основа на сериен вход,
Raise Material Request When Stock Reaches Re-order Level,"Повишете заявката за материал, когато запасите достигнат ниво на повторна поръчка",
Notify by Email on Creation of Automatic Material Request,Уведомете по имейл за създаването на автоматична заявка за материал,
Allow Material Transfer from Delivery Note to Sales Invoice,Разрешаване на прехвърляне на материал от бележка за доставка до фактура за продажба,
Allow Material Transfer from Purchase Receipt to Purchase Invoice,Разрешаване на прехвърляне на материал от разписка за покупка към фактура за покупка,
Freeze Stocks Older Than (Days),Замразете запасите по-стари от (дни),
Role Allowed to Edit Frozen Stock,"Роля, разрешена за редактиране на замразени запаси",
The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,Неразпределената сума на запис за плащане {0} е по-голяма от неразпределената сума на банковата транзакция,
Payment Received,Получено плащане,
Attendance cannot be marked outside of Academic Year {0},Присъствието не може да бъде маркирано извън академичната година {0},
Student is already enrolled via Course Enrollment {0},Студентът вече е записан чрез записване на курс {0},
Attendance cannot be marked for future dates.,Присъствието не може да бъде маркирано за бъдещи дати.,
Please add programs to enable admission application.,"Моля, добавете програми, за да разрешите кандидатстване.",
The following employees are currently still reporting to {0}:,Понастоящем следните служители все още се отчитат пред {0}:,
Please make sure the employees above report to another Active employee.,"Моля, уверете се, че служителите по-горе се отчитат пред друг активен служител.",
Cannot Relieve Employee,Не може да облекчи служителя,
Please enter {0},"Моля, въведете {0}",
Please select another payment method. Mpesa does not support transactions in currency '{0}',"Моля, изберете друг начин на плащане. Mpesa не поддържа транзакции във валута „{0}“",
Transaction Error,Грешка в транзакцията,
Mpesa Express Transaction Error,Грешка при транзакцията на Mpesa Express,
"Issue detected with Mpesa configuration, check the error logs for more details","Открит е проблем с конфигурацията на Mpesa, проверете регистрационните файлове за грешки за повече подробности",
Mpesa Express Error,Грешка в Mpesa Express,
Account Balance Processing Error,Грешка при обработката на салдото по акаунта,
Please check your configuration and try again,"Моля, проверете вашата конфигурация и опитайте отново",
Mpesa Account Balance Processing Error,Грешка при обработката на салдото в Mpesa акаунт,
Balance Details,Подробности за баланса,
Current Balance,Текущ баланс,
Available Balance,Наличен баланс,
Reserved Balance,Запазен баланс,
Uncleared Balance,Неизчистен баланс,
Payment related to {0} is not completed,"Плащането, свързано с {0}, не е завършено",
Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.,"Ред № {}: Сериен номер {}. {} вече е транзактиран в друга POS фактура. Моля, изберете валиден сериен номер.",
Row #{}: Item Code: {} is not available under warehouse {}.,Ред № {}: Код на артикула: {} не е наличен в склада {}.,
Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.,Ред № {}: Количеството на склад не е достатъчно за Код на артикула: {} под склад {}. Налично количество {}.,
Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.,"Ред № {}: Моля, изберете сериен номер и партида срещу елемент: {} или го премахнете, за да завършите транзакцията.",
Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.,"Ред № {}: Не е избран сериен номер за елемент: {}. Моля, изберете един или го премахнете, за да завършите транзакцията.",
Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.,"Ред № {}: Не е избрана партида срещу елемент: {}. Моля, изберете партида или я премахнете, за да завършите транзакцията.",
Payment amount cannot be less than or equal to 0,Сумата на плащането не може да бъде по-малка или равна на 0,
Please enter the phone number first,"Моля, въведете първо телефонния номер",
Row #{}: {} {} does not exist.,Ред № {}: {} {} не съществува.,
Row #{0}: {1} is required to create the Opening {2} Invoices,Ред № {0}: {1} е необходим за създаване на отварящите се {2} фактури,
You had {} errors while creating opening invoices. Check {} for more details,Имахте {} грешки при създаването на фактури за отваряне. Проверете {} за повече подробности,
Error Occured,Възникна грешка,
Opening Invoice Creation In Progress,Отваряне на фактура в процес на създаване,
Creating {} out of {} {},Създава се {} от {} {},
(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,"(Сериен номер: {0}) не може да бъде консумиран, тъй като е резервиран за пълно изпълнение на поръчка за продажба {1}.",
Item {0} {1},Елемент {0} {1},
Last Stock Transaction for item {0} under warehouse {1} was on {2}.,Последната транзакция на склад за артикул {0} под склад {1} беше на {2}.,
Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,Транзакции със запаси за артикул {0} под склад {1} не могат да бъдат публикувани преди това време.,
Posting future stock transactions are not allowed due to Immutable Ledger,Публикуването на бъдещи сделки с акции не е разрешено поради неизменяема книга,
A BOM with name {0} already exists for item {1}.,Спецификация със име {0} вече съществува за елемент {1}.,
{0}{1} Did you rename the item? Please contact Administrator / Tech support,"{0} {1} Преименувахте ли елемента? Моля, свържете се с администратор / техническа поддръжка",
At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},На ред № {0}: идентификаторът на последователността {1} не може да бъде по-малък от идентификатора на последователността на предишния ред {2},
The {0} ({1}) must be equal to {2} ({3}),{0} ({1}) трябва да е равно на {2} ({3}),
"{0}, complete the operation {1} before the operation {2}.","{0}, завършете операцията {1} преди операцията {2}.",
Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No.,"Не може да се гарантира доставка чрез сериен номер, тъй като елемент {0} е добавен със и без Осигурете доставка чрез сериен номер",
Item {0} has no Serial No. Only serilialized items can have delivery based on Serial No,Елемент {0} няма сериен номер. Само сериализираните артикули могат да имат доставка въз основа на сериен номер,
No active BOM found for item {0}. Delivery by Serial No cannot be ensured,Не е намерена активна спецификация за елемент {0}. Доставката по сериен номер не може да бъде осигурена,
No pending medication orders found for selected criteria,Не са намерени чакащи поръчки за лекарства за избрани критерии,
From Date cannot be after the current date.,От дата не може да бъде след текущата дата.,
To Date cannot be after the current date.,До дата не може да бъде след текущата дата.,
From Time cannot be after the current time.,От Time не може да бъде след текущото време.,
To Time cannot be after the current time.,To Time не може да бъде след текущото време.,
Stock Entry {0} created and ,Запис на запас {0} създаден и,
Inpatient Medication Orders updated successfully,Поръчките за стационарни лекарства се актуализират успешно,
Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1},Ред {0}: Не може да се създаде запис за стационарно лекарство срещу отменена заповед за стационарно лечение {1},
Row {0}: This Medication Order is already marked as completed,Ред {0}: Тази поръчка за лекарства вече е отбелязана като изпълнена,
Quantity not available for {0} in warehouse {1},Количеството не е налично за {0} в склада {1},
Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.,"Моля, активирайте Разрешаване на отрицателни запаси в настройките на запасите или създайте запис на запаси, за да продължите.",
No Inpatient Record found against patient {0},Не е открит стационарен запис срещу пациент {0},
An Inpatient Medication Order {0} against Patient Encounter {1} already exists.,Вече съществува заповед за стационарно лечение {0} срещу среща с пациент {1}.,

Can't render this file because it is too large.

View File

@ -110,7 +110,6 @@ Actual qty in stock,স্টক মধ্যে প্রকৃত Qty এ,
Actual type tax cannot be included in Item rate in row {0},প্রকৃত টাইপ ট্যাক্স সারিতে আইটেম রেট অন্তর্ভুক্ত করা যাবে না {0},
Add,যোগ,
Add / Edit Prices,/ সম্পাদনা বর্ণনা করো,
Add All Suppliers,সমস্ত সরবরাহকারী যোগ করুন,
Add Comment,মন্তব্য যোগ করুন,
Add Customers,গ্রাহকরা যোগ করুন,
Add Employees,এমপ্লয়িজ যোগ,
@ -480,7 +479,6 @@ Cannot produce more Item {0} than Sales Order quantity {1},সেলস আদ
Cannot promote Employee with status Left,কর্মচারী উন্নয়নে স্থিরতা বজায় রাখতে পারে না,
Cannot refer row number greater than or equal to current row number for this Charge type,এই চার্জ ধরণ জন্য বর্তমান সারির সংখ্যা এর চেয়ে বড় বা সমান সারির সংখ্যা পড়ুন করতে পারবেন না,
Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row,প্রথম সারির &#39;পূর্ববর্তী সারি মোট&#39; &#39;পূর্ববর্তী সারি পরিমাণ&#39; হিসেবে অভিযোগ টাইপ নির্বাচন করা বা না করা,
Cannot set a received RFQ to No Quote,কোন উদ্ধৃত কোন প্রাপ্ত RFQ সেট করতে পারবেন না,
Cannot set as Lost as Sales Order is made.,বিক্রয় আদেশ তৈরি করা হয় যেমন বিচ্ছিন্ন সেট করা যায় না.,
Cannot set authorization on basis of Discount for {0},জন্য ছাড়ের ভিত্তিতে অনুমোদন সেট করা যায় না {0},
Cannot set multiple Item Defaults for a company.,একটি কোম্পানির জন্য একাধিক আইটেম ডিফল্ট সেট করতে পারবেন না।,
@ -934,7 +932,6 @@ Employee Referral,কর্মচারী রেফারেল,
Employee Transfer cannot be submitted before Transfer Date ,স্থানান্তর তারিখ আগে কর্মচারী স্থানান্তর জমা দেওয়া যাবে না,
Employee cannot report to himself.,কর্মচারী নিজেকে প্রতিবেদন করতে পারবে না.,
Employee relieved on {0} must be set as 'Left',{0} নির্ধারণ করা আবশ্যক উপর অব্যাহতিপ্রাপ্ত কর্মচারী &#39;বাম&#39; হিসাবে,
Employee status cannot be set to 'Left' as following employees are currently reporting to this employee:&nbsp;,নিম্নোক্ত কর্মীরা বর্তমানে এই কর্মচারীর প্রতিবেদন করছেন বলে কর্মচারীর অবস্থা &#39;বামে&#39; সেট করা যাবে না:,
Employee {0} already submited an apllication {1} for the payroll period {2},কর্মচারী {0} ইতিমধ্যে payroll সময়ের {2} জন্য একটি anpllication {1} জমা দিয়েছে,
Employee {0} has already applied for {1} between {2} and {3} : ,কর্মচারী {0} ইতিমধ্যে {1} এবং {3} এর মধ্যে {1} জন্য প্রয়োগ করেছেন:,
Employee {0} has no maximum benefit amount,কর্মচারী {0} এর সর্বাধিক বেনিফিট পরিমাণ নেই,
@ -1456,7 +1453,6 @@ Leave application {0} already exists against the student {1},অ্যাপ্
"Leave cannot be allocated before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","আগে বরাদ্দ করা না যাবে ছেড়ে {0}, ছুটি ভারসাম্য ইতিমধ্যে হ্যান্ড ফরওয়ার্ড ভবিষ্যতে ছুটি বরাদ্দ রেকর্ড হয়েছে হিসাবে {1}",
"Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}","ছুটি ভারসাম্য ইতিমধ্যে হ্যান্ড ফরওয়ার্ড ভবিষ্যতে ছুটি বরাদ্দ রেকর্ড হয়েছে হিসাবে, আগে {0} বাতিল / প্রয়োগ করা যাবে না ছেড়ে {1}",
Leave of type {0} cannot be longer than {1},ধরনের ছুটি {0} চেয়ে বেশি হতে পারেনা {1},
Leave the field empty to make purchase orders for all suppliers,সব সরবরাহকারীদের জন্য ক্রয় আদেশ করতে ফাঁকা ক্ষেত্র ত্যাগ করুন,
Leaves,পত্রাদি,
Leaves Allocated Successfully for {0},সাফল্যের বরাদ্দ পাতার {0},
Leaves has been granted sucessfully,পাতাগুলি সফলভাবে দেওয়া হয়েছে,
@ -1699,7 +1695,6 @@ No Items to pack,কোনও আইটেম প্যাক,
No Items with Bill of Materials to Manufacture,সামগ্রী বিল দিয়ে কোন সামগ্রী উত্পাদনপ্রণালী,
No Items with Bill of Materials.,বিল আইটেমস সহ কোনও আইটেম নেই।,
No Permission,অনুমতি নেই,
No Quote,কোন উদ্ধৃতি নেই,
No Remarks,কোন মন্তব্য,
No Result to submit,কোন ফলাফল জমা নেই,
No Salary Structure assigned for Employee {0} on given date {1},প্রদত্ত তারিখের {0} কর্মচারীর জন্য নির্ধারিত কোন বেতন কাঠামো {1},
@ -1856,7 +1851,6 @@ Overlap in scoring between {0} and {1},{0} এবং {1} এর মধ্যে
Overlapping conditions found between:,মধ্যে পাওয়া ওভারল্যাপিং শর্ত:,
Owner,মালিক,
PAN,প্যান,
PO already created for all sales order items,PO ইতিমধ্যে সমস্ত বিক্রয় আদেশ আইটেম জন্য তৈরি,
POS,পিওএস,
POS Profile,পিওএস প্রোফাইল,
POS Profile is required to use Point-of-Sale,পয়েন্ট-অফ-সেল ব্যবহার করার জন্য পিওএস প্রোফাইল প্রয়োজন,
@ -2502,7 +2496,6 @@ Row {0}: Quality Inspection rejected for item {1},সারি {0}: আইটে
Row {0}: UOM Conversion Factor is mandatory,সারি {0}: UOM রূপান্তর ফ্যাক্টর বাধ্যতামূলক,
Row {0}: select the workstation against the operation {1},সারি {0}: অপারেশন {1} বিরুদ্ধে ওয়ার্কস্টেশন নির্বাচন করুন,
Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.,সারি {0}: {1} আইটেমের জন্য প্রয়োজনীয় সিরিয়াল নম্বর {2}। আপনি {3} প্রদান করেছেন।,
Row {0}: {1} is required to create the Opening {2} Invoices,সারি {0}: {1} ওপেনিং {2} চালান তৈরি করতে হবে,
Row {0}: {1} must be greater than 0,সারি {0}: {1} 0 এর থেকে বড় হতে হবে,
Row {0}: {1} {2} does not match with {3},সারি {0}: {1} {2} সঙ্গে মেলে না {3},
Row {0}:Start Date must be before End Date,সারি {0}: আরম্ভের তারিখ শেষ তারিখের আগে হওয়া আবশ্যক,
@ -2642,7 +2635,6 @@ Selling Rate,বিক্রি হার,
Send Grant Review Email,গ্রান্ট রিভিউ ইমেল পাঠান,
Send Now,এখন পাঠান,
Send SMS,এসএমএস পাঠান,
Send Supplier Emails,সরবরাহকারী ইমেইল পাঠান,
Send mass SMS to your contacts,ভর এসএমএস আপনার পরিচিতি পাঠান,
Sensitivity,সংবেদনশীলতা,
Sent,প্রেরিত,
@ -3443,7 +3435,6 @@ on,উপর,
{0} variants created.,{0} বৈকল্পিক তৈরি করা হয়েছে।,
{0} {1} created,{0} {1} সৃষ্টি,
{0} {1} does not exist,{0} {1} অস্তিত্ব নেই,
{0} {1} does not exist.,{0} {1} বিদ্যমান নেই,
{0} {1} has been modified. Please refresh.,{0} {1} নথীটি পরিবর্তিত হয়েছে. রিফ্রেশ করুন.,
{0} {1} has not been submitted so the action cannot be completed,{0} {1} জমা দেওয়া হয়েছে করেননি তাই কর্ম সম্পন্ন করা যাবে না,
"{0} {1} is associated with {2}, but Party Account is {3}","{0} {1} {2} সাথে যুক্ত, কিন্তু পার্টি অ্যাকাউন্ট {3}",
@ -3480,6 +3471,7 @@ on,উপর,
{0}: {1} does not exists,{0}: {1} বিদ্যমান নয়,
{0}: {1} not found in Invoice Details table,{0}: {1} চালান বিবরণ টেবিল মধ্যে পাওয়া যায়নি,
{} of {},{} এর {},
Assigned To,নিযুক্ত করা,
Chat,চ্যাট,
Completed By,দ্বারা সম্পন্ন,
Conditions,পরিবেশ,
@ -3502,6 +3494,7 @@ Merge with existing,বিদ্যমান সাথে একত্রীক
Office,অফিস,
Orientation,ঝোঁক,
Passive,নিষ্ক্রিয়,
Payment Failed,পেমেন্ট ব্যর্থ হয়েছে,
Percent,শতাংশ,
Permanent,স্থায়ী,
Personal,ব্যক্তিগত,
@ -3566,6 +3559,8 @@ Naming Series,নামকরণ সিরিজ,
No data to export,রফতানির জন্য কোনও ডেটা নেই,
Portrait,প্রতিকৃতি,
Print Heading,প্রিন্ট শীর্ষক,
Scheduler Inactive,সময়সূচী নিষ্ক্রিয়,
Scheduler is inactive. Cannot import data.,সময়সূচী নিষ্ক্রিয়। ডেটা আমদানি করা যায় না।,
Show Document,দস্তাবেজ দেখান,
Show Traceback,ট্রেসব্যাক প্রদর্শন করুন,
Video,ভিডিও,
@ -3691,7 +3686,6 @@ Create Pick List,বাছাই তালিকা তৈরি করুন,
Create Quality Inspection for Item {0},আইটেমের জন্য গুণগত পরিদর্শন তৈরি করুন {0},
Creating Accounts...,অ্যাকাউন্ট তৈরি করা হচ্ছে ...,
Creating bank entries...,ব্যাঙ্ক এন্ট্রি তৈরি করা হচ্ছে ...,
Creating {0},{0} তৈরি করা হচ্ছে,
Credit limit is already defined for the Company {0},ক্রেডিট সীমা ইতিমধ্যে সংস্থার জন্য নির্ধারিত হয়েছে {0},
Ctrl + Enter to submit,জমা দিতে Ctrl + Enter,
Ctrl+Enter to submit,জমা দিতে Ctrl + লিখুন,
@ -4524,31 +4518,22 @@ Closed Documents,বন্ধ ডকুমেন্টস,
Accounts Settings,সেটিংস অ্যাকাউন্ট,
Settings for Accounts,অ্যাকাউন্ট এর জন্য সেটিং,
Make Accounting Entry For Every Stock Movement,প্রতি স্টক আন্দোলনের জন্য অ্যাকাউন্টিং এন্ট্রি করতে,
"If enabled, the system will post accounting entries for inventory automatically.","সক্রিয় করা হলে, সিস্টেম স্বয়ংক্রিয়ভাবে পরিসংখ্যা জন্য অ্যাকাউন্টিং এন্ট্রি পোস্ট করতে হবে.",
Accounts Frozen Upto,হিমায়িত পর্যন্ত অ্যাকাউন্ট,
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","এই ডেট নিথর অ্যাকাউন্টিং এন্ট্রি, কেউ / না নিম্নোল্লিখিত শর্ত ভূমিকা ছাড়া এন্ট্রি পরিবর্তন করতে পারেন.",
Role Allowed to Set Frozen Accounts & Edit Frozen Entries,ভূমিকা হিমায়িত একাউন্টস ও সম্পাদনা হিমায়িত সাজপোশাকটি সেট করার মঞ্জুরি,
Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,এই ব্যবহারকারীরা হিমায়িত অ্যাকাউন্ট বিরুদ্ধে হিসাব থেকে হিমায়িত অ্যাকাউন্ট সেট এবং তৈরি / পরিবর্তন করার অনুমতি দেওয়া হয়,
Determine Address Tax Category From,এড্রেস ট্যাক্স বিভাগ থেকে নির্ধারণ করুন,
Address used to determine Tax Category in transactions.,লেনদেনে ট্যাক্স বিভাগ নির্ধারণ করতে ব্যবহৃত ঠিকানা Address,
Over Billing Allowance (%),ওভার বিলিং ভাতা (%),
Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.,অর্ডারের পরিমাণের তুলনায় আপনাকে আরও বেশি বিল দেওয়ার অনুমতি দেওয়া হচ্ছে শতাংশ। উদাহরণস্বরূপ: যদি কোনও আইটেমের জন্য অর্ডার মান $ 100 এবং সহনশীলতা 10% হিসাবে সেট করা থাকে তবে আপনাকে 110 ডলারে বিল দেওয়ার অনুমতি দেওয়া হবে।,
Credit Controller,ক্রেডিট কন্ট্রোলার,
Role that is allowed to submit transactions that exceed credit limits set.,সেট ক্রেডিট সীমা অতিক্রম লেনদেন জমা করার অনুমতি দেওয়া হয় যে ভূমিকা.,
Check Supplier Invoice Number Uniqueness,চেক সরবরাহকারী চালান নম্বর স্বতন্ত্রতা,
Make Payment via Journal Entry,জার্নাল এন্ট্রি মাধ্যমে টাকা প্রাপ্তির,
Unlink Payment on Cancellation of Invoice,চালান বাতিলের পেমেন্ট লিঙ্কমুক্ত,
Book Asset Depreciation Entry Automatically,বইয়ের অ্যাসেট অবচয় এণ্ট্রি স্বয়ংক্রিয়ভাবে,
Automatically Add Taxes and Charges from Item Tax Template,আইটেম ট্যাক্স টেম্পলেট থেকে স্বয়ংক্রিয়ভাবে কর এবং চার্জ যুক্ত করুন,
Automatically Fetch Payment Terms,স্বয়ংক্রিয়ভাবে প্রদানের শর্তাদি আনুন,
Show Inclusive Tax In Print,প্রিন্ট ইন ইনজেকশন ট্যাক্স দেখান,
Show Payment Schedule in Print,প্রিন্ট ইন পেমেন্ট শেল্ড দেখান,
Currency Exchange Settings,মুদ্রা বিনিময় সেটিংস,
Allow Stale Exchange Rates,স্টেলা এক্সচেঞ্জের হার মঞ্জুর করুন,
Stale Days,স্টাইল দিন,
Report Settings,রিপোর্ট সেটিংস,
Use Custom Cash Flow Format,কাস্টম ক্যাশ ফ্লো বিন্যাস ব্যবহার করুন,
Only select if you have setup Cash Flow Mapper documents,যদি আপনি সেটআপ ক্যাশ ফ্লো ম্যাপার ডকুমেন্টগুলি নির্বাচন করেন তবে কেবল নির্বাচন করুন,
Allowed To Transact With,সঙ্গে লেনদেন অনুমোদিত,
SWIFT number,দ্রুতগতি সংখ্যা,
Branch Code,শাখা কোড,
@ -5485,8 +5470,6 @@ Settings for Buying Module,মডিউল কেনা জন্য সেট
Supplier Naming By,দ্বারা সরবরাহকারী নেমিং,
Default Supplier Group,ডিফল্ট সরবরাহকারী গ্রুপ,
Default Buying Price List,ডিফল্ট ক্রয় মূল্য তালিকা,
Maintain same rate throughout purchase cycle,কেনার চক্র সারা একই হার বজায় রাখা,
Allow Item to be added multiple times in a transaction,আইটেম একটি লেনদেনের মধ্যে একাধিক বার যুক্ত করা সম্ভব,
Backflush Raw Materials of Subcontract Based On,উপর ভিত্তি করে Subcontract এর কাঁচামাল Backflush,
Material Transferred for Subcontract,উপসম্পাদকীয় জন্য উপাদান হস্তান্তর,
Over Transfer Allowance (%),ওভার ট্রান্সফার ভাতা (%),
@ -5530,7 +5513,6 @@ Purchase Receipt Item Supplied,কেনার রসিদ আইটেম স
Current Stock,বর্তমান তহবিল,
PUR-RFQ-.YYYY.-,PUR-RFQ-.YYYY.-,
For individual supplier,পৃথক সরবরাহকারী জন্য,
Supplier Detail,সরবরাহকারী বিস্তারিত,
Link to Material Requests,উপাদান অনুরোধ লিঙ্ক,
Message for Supplier,সরবরাহকারী জন্য বার্তা,
Request for Quotation Item,উদ্ধৃতি আইটেম জন্য অনুরোধ,
@ -6724,10 +6706,7 @@ HR Settings,এইচআর সেটিংস,
Employee Settings,কর্মচারী সেটিংস,
Retirement Age,কর্ম - ত্যাগ বয়ম,
Enter retirement age in years,বছরে অবসরের বয়স লিখুন,
Employee Records to be created by,কর্মচারী রেকর্ড করে তৈরি করা,
Employee record is created using selected field. ,কর্মচারী রেকর্ড নির্বাচিত ক্ষেত্র ব্যবহার করে নির্মিত হয়.,
Stop Birthday Reminders,বন্ধ করুন জন্মদিনের রিমাইন্ডার,
Don't send Employee Birthday Reminders,কর্মচারী জন্মদিনের রিমাইন্ডার পাঠাবেন না,
Expense Approver Mandatory In Expense Claim,ব্যয় দাবি মধ্যে ব্যয়বহুল ব্যয়বহুল,
Payroll Settings,বেতনের সেটিংস,
Leave,ছেড়ে দিন,
@ -6749,7 +6728,6 @@ Role Allowed to Create Backdated Leave Application,ব্যাকটেড ল
Leave Approver Mandatory In Leave Application,আবেদন ত্যাগ করুন,
Show Leaves Of All Department Members In Calendar,ক্যালেন্ডারে সকল বিভাগের সদস্যদের তালিকা দেখান,
Auto Leave Encashment,অটো ছেড়ে দিন এনক্যাশমেন্ট,
Restrict Backdated Leave Application,ব্যাকটেড ছুটির আবেদন সীমাবদ্ধ করুন,
Hiring Settings,নিয়োগের সেটিংস,
Check Vacancies On Job Offer Creation,কাজের অফার তৈরিতে শূন্যপদগুলি পরীক্ষা করুন,
Identification Document Type,সনাক্তকরণ নথি প্রকার,
@ -7283,28 +7261,21 @@ Completed Qty,সমাপ্ত Qty,
Manufacturing Settings,উৎপাদন সেটিংস,
Raw Materials Consumption,কাঁচামাল ব্যবহার,
Allow Multiple Material Consumption,একাধিক উপাদান ব্যবহার অনুমোদন,
Allow multiple Material Consumption against a Work Order,একটি ওয়ার্ক অর্ডার বিরুদ্ধে একাধিক উপাদান ব্যবহার অনুমোদন,
Backflush Raw Materials Based On,Backflush কাঁচামালের ভিত্তিতে,
Material Transferred for Manufacture,উপাদান প্রস্তুত জন্য বদলিকৃত,
Capacity Planning,ক্ষমতা পরিকল্পনা,
Disable Capacity Planning,সক্ষমতা পরিকল্পনা অক্ষম করুন,
Allow Overtime,ওভারটাইম মঞ্জুরি,
Plan time logs outside Workstation Working Hours.,ওয়ার্কস্টেশন ওয়ার্কিং সময়ের বাইরে সময় লগ পরিকল্পনা করুন.,
Allow Production on Holidays,ছুটির উৎপাদন মঞ্জুরি,
Capacity Planning For (Days),(দিন) জন্য ক্ষমতা পরিকল্পনা,
Try planning operations for X days in advance.,অগ্রিম এক্স দিনের জন্য অপারেশন পরিকল্পনা চেষ্টা করুন.,
Time Between Operations (in mins),(মিনিট) অপারেশনস মধ্যে সময়,
Default 10 mins,10 মিনিট ডিফল্ট,
Default Warehouses for Production,উত্পাদনের জন্য ডিফল্ট গুদাম,
Default Work In Progress Warehouse,প্রগতি গুদাম ডিফল্ট কাজ,
Default Finished Goods Warehouse,ডিফল্ট তৈরি পণ্য গুদাম,
Default Scrap Warehouse,ডিফল্ট স্ক্র্যাপ গুদাম,
Over Production for Sales and Work Order,বিক্রয় ও কাজের আদেশের জন্য ওভার প্রোডাকশন,
Overproduction Percentage For Sales Order,বিক্রয় আদেশের জন্য প্রযোজক শতাংশ,
Overproduction Percentage For Work Order,কাজের আদেশের জন্য প্রযোজক শতাংশ,
Other Settings,অন্যান্য সেটিংস্,
Update BOM Cost Automatically,স্বয়ংক্রিয়ভাবে BOM খরচ আপডেট করুন,
"Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.",সর্বশেষ মূল্যনির্ধারণ হার / মূল্য তালিকা হার / কাঁচামালের সর্বশেষ ক্রয়ের হারের ভিত্তিতে স্বয়ংক্রিয়ভাবে নির্ধারিত BOM- এর মূল্য নির্ধারনের মাধ্যমে।,
Material Request Plan Item,উপাদান অনুরোধের পরিকল্পনা আইটেম,
Material Request Type,উপাদান অনুরোধ টাইপ,
Material Issue,উপাদান ইস্যু,
@ -7771,15 +7742,9 @@ Campaign Naming By,প্রচারে নেমিং,
Default Customer Group,ডিফল্ট গ্রাহক গ্রুপ,
Default Territory,ডিফল্ট টেরিটরি,
Close Opportunity After Days,বন্ধ সুযোগ দিন পরে,
Auto close Opportunity after 15 days,15 দিন পর অটো বন্ধ সুযোগ,
Default Quotation Validity Days,ডিফল্ট কোটেশন বৈধতা দিন,
Sales Update Frequency,বিক্রয় আপডেট ফ্রিকোয়েন্সি,
How often should project and company be updated based on Sales Transactions.,সেলস লেনদেনের উপর ভিত্তি করে কতগুলি প্রকল্প এবং কোম্পানিকে আপডেট করা উচিত।,
Each Transaction,প্রতিটি লেনদেন,
Allow user to edit Price List Rate in transactions,ব্যবহারকারী লেনদেনের মূল্য তালিকা হার সম্পাদন করার অনুমতি প্রদান,
Allow multiple Sales Orders against a Customer's Purchase Order,একটি গ্রাহকের ক্রয় আদেশের বিরুদ্ধে একাধিক বিক্রয় আদেশ মঞ্জুরি,
Validate Selling Price for Item against Purchase Rate or Valuation Rate,যাচাই করে নিন বিক্রয় মূল্য ক্রয় হার বা মূল্যনির্ধারণ হার বিরুদ্ধে আইটেম জন্য,
Hide Customer's Tax Id from Sales Transactions,সেলস লেনদেন থেকে গ্রাহকের ট্যাক্স আইডি লুকান,
SMS Center,এসএমএস কেন্দ্র,
Send To,পাঠানো,
All Contact,সমস্ত যোগাযোগ,
@ -8388,24 +8353,14 @@ Default Item Group,ডিফল্ট আইটেম গ্রুপ,
Default Stock UOM,ডিফল্ট শেয়ার UOM,
Sample Retention Warehouse,নমুনা ধারণ গুদাম,
Default Valuation Method,ডিফল্ট মূল্যনির্ধারণ পদ্ধতি,
Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.,শতকরা আপনি পাবেন বা আদেশ পরিমাণ বিরুদ্ধে আরো বিলি করার অনুমতি দেওয়া হয়. উদাহরণস্বরূপ: আপনি 100 ইউনিট আদেশ আছে. এবং আপনার ভাতা তারপর আপনি 110 ইউনিট গ্রহণ করার অনুমতি দেওয়া হয় 10% হয়.,
Action if Quality inspection is not submitted,মান পরিদর্শন জমা না দেওয়া হলে পদক্ষেপ,
Show Barcode Field,দেখান বারকোড ফিল্ড,
Convert Item Description to Clean HTML,পরিষ্কার এইচটিএমএল আইটেম বর্ণনা রূপান্তর,
Auto insert Price List rate if missing,অটো সন্নিবেশ মূল্য তালিকা হার অনুপস্থিত যদি,
Allow Negative Stock,নেতিবাচক শেয়ার মঞ্জুরি,
Automatically Set Serial Nos based on FIFO,স্বয়ংক্রিয়ভাবে FIFO উপর ভিত্তি করে আমরা সিরিয়াল সেট,
Set Qty in Transactions based on Serial No Input,সিরিয়াল কোন ইনপুটের উপর ভিত্তি করে লেনদেনের পরিমাণ নির্ধারণ করুন,
Auto Material Request,অটো উপাদানের জন্য অনুরোধ,
Raise Material Request when stock reaches re-order level,শেয়ার পুনরায় আদেশ পর্যায়ে পৌঁছে যখন উপাদান অনুরোধ বাড়াতে,
Notify by Email on creation of automatic Material Request,স্বয়ংক্রিয় উপাদান অনুরোধ নির্মাণের ইমেইল দ্বারা সূচিত,
Inter Warehouse Transfer Settings,আন্তঃ গুদাম স্থানান্তর সেটিংস,
Allow Material Transfer From Delivery Note and Sales Invoice,বিতরণ নোট এবং বিক্রয় চালান থেকে উপাদান স্থানান্তরের অনুমতি দিন,
Allow Material Transfer From Purchase Receipt and Purchase Invoice,ক্রয় রশিদ এবং ক্রয় চালান থেকে উপাদান স্থানান্তরকে অনুমতি দিন,
Freeze Stock Entries,ফ্রিজ শেয়ার সাজপোশাকটি,
Stock Frozen Upto,শেয়ার হিমায়িত পর্যন্ত,
Freeze Stocks Older Than [Days],ফ্রিজ স্টক চেয়ে পুরোনো [দিন],
Role Allowed to edit frozen stock,ভূমিকা হিমায়িত শেয়ার সম্পাদনা করতে পারবেন,
Batch Identification,ব্যাচ সনাক্তকরণ,
Use Naming Series,নামকরণ সিরিজ ব্যবহার করুন,
Naming Series Prefix,নামকরণ সিরিজ উপসর্গ,
@ -8731,11 +8686,9 @@ Published on,প্রকাশিত,
Service Received But Not Billed,পরিষেবা প্রাপ্ত হয়েছে তবে বিল দেওয়া হয়নি,
Deferred Accounting Settings,স্থগিত অ্যাকাউন্টিং সেটিংস,
Book Deferred Entries Based On,বুক ডিফার্ড এন্ট্রি উপর ভিত্তি করে,
"If ""Months"" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",যদি &quot;মাসস&quot; বাছাই করা হয় তবে নির্দিষ্ট মাসে এক মাসের দিন নির্বিশেষে প্রতিটি মাসের জন্য পিছিয়ে যাওয়া আয় বা ব্যয় হিসাবে বুক করা হবে। স্থগিত রাজস্ব বা ব্যয় পুরো এক মাসের জন্য বুকিং না দেওয়া থাকলে তা প্রমাণিত হবে।,
Days,দিনগুলি,
Months,মাস,
Book Deferred Entries Via Journal Entry,জার্নাল এন্ট্রি মাধ্যমে বুক ডিফার্ড এন্ট্রি,
If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense,এটি যদি চেক না করা হয় তবে সরাসরি জিএল এন্ট্রিগুলি ডিফার্ড রাজস্ব / ব্যয় বুকিংয়ের জন্য তৈরি করা হবে,
Submit Journal Entries,জার্নাল এন্ট্রি জমা দিন,
If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,এটি যদি চেক না করা হয় তবে জার্নাল এন্ট্রিগুলি একটি খসড়া অবস্থায় সংরক্ষণ করা হবে এবং ম্যানুয়ালি জমা দিতে হবে,
Enable Distributed Cost Center,বিতরণ ব্যয় কেন্দ্র সক্ষম করুন,
@ -8880,8 +8833,6 @@ Source State,উত্স রাজ্য,
Is Inter State,ইন্টার স্টেট,
Purchase Details,ক্রয়ের বিশদ,
Depreciation Posting Date,অবচয় পোস্টের তারিখ,
Purchase Order Required for Purchase Invoice & Receipt Creation,ক্রয় চালান এবং প্রাপ্তি তৈরির জন্য ক্রয়ের অর্ডার প্রয়োজনীয়,
Purchase Receipt Required for Purchase Invoice Creation,ইনভয়েস তৈরির জন্য ক্রয়ের রশিদ প্রয়োজনীয়,
"By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ","ডিফল্টরূপে, সরবরাহকারী নাম প্রবেশ করানো সরবরাহকারীর নাম অনুসারে সেট করা হয়। আপনি যদি সরবরাহকারীদের দ্বারা একটি দ্বারা নামকরণ করতে চান",
choose the 'Naming Series' option.,&#39;নামকরণ সিরিজ&#39; বিকল্পটি চয়ন করুন।,
Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.,নতুন ক্রয় লেনদেন তৈরি করার সময় ডিফল্ট মূল্য তালিকাকে কনফিগার করুন। এই মূল্য তালিকা থেকে আইটেমের দামগুলি আনা হবে।,
@ -9142,8 +9093,6 @@ Conditions and Formula variable and example,শর্ত এবং সূত্
Feedback By,প্রতিক্রিয়া দ্বারা,
MTNG-.YYYY.-.MM.-.DD.-,এমটিএনজি -হায়িওয়াই .- এমএম .-। ডিডি.-,
Manufacturing Section,উত্পাদন বিভাগ,
Sales Order Required for Sales Invoice & Delivery Note Creation,বিক্রয় চালান এবং বিতরণ নোট তৈরির জন্য প্রয়োজনীয় বিক্রয় অর্ডার,
Delivery Note Required for Sales Invoice Creation,বিক্রয় চালান তৈরির জন্য বিতরণ নোট প্রয়োজনীয় Requ,
"By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ","ডিফল্টরূপে, গ্রাহকের নাম প্রবেশ সম্পূর্ণ নাম অনুসারে সেট করা হয়। আপনি যদি চান গ্রাহকদের একটি দ্বারা নামকরণ করা",
Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.,নতুন বিক্রয় লেনদেন তৈরি করার সময় ডিফল্ট মূল্য তালিকাকে কনফিগার করুন। এই মূল্য তালিকা থেকে আইটেমের দামগুলি আনা হবে।,
"If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.",যদি এই বিকল্পটি &#39;হ্যাঁ&#39; কনফিগার করা থাকে তবে ERPNext আপনাকে প্রথমে বিক্রয় আদেশ তৈরি না করে বিক্রয় চালান বা বিতরণ নোট তৈরি করা থেকে বিরত রাখবে। এই কনফিগারেশনটি কোনও নির্দিষ্ট গ্রাহকের জন্য &#39;বিক্রয় অর্ডার ব্যতীত বিক্রয় চালানের ক্রয়কে অনুমতি দিন&#39; চেকবক্সটি সক্ষম করে ওভাররাইড করা যেতে পারে।,
@ -9367,8 +9316,6 @@ Courses updated,কোর্স আপডেট করা হয়েছে,
{0} {1} has been added to all the selected topics successfully.,Selected 0} {1 successfully সফলভাবে নির্বাচিত সমস্ত বিষয়ের সাথে যুক্ত করা হয়েছে।,
Topics updated,বিষয় আপডেট হয়েছে,
Academic Term and Program,একাডেমিক টার্ম এবং প্রোগ্রাম,
Last Stock Transaction for item {0} was on {1}.,আইটেম Last 0} এর জন্য সর্বশেষ স্টক লেনদেন {1} এ ছিল},
Stock Transactions for Item {0} cannot be posted before this time.,আইটেম for 0 for এর জন্য স্টক লেনদেন এই সময়ের আগে পোস্ট করা যাবে না।,
Please remove this item and try to submit again or update the posting time.,দয়া করে এই আইটেমটি সরান এবং আবার জমা দেওয়ার চেষ্টা করুন বা পোস্টিং সময় আপডেট করুন।,
Failed to Authenticate the API key.,API কীটি প্রমাণীকরণে ব্যর্থ।,
Invalid Credentials,অবৈধ প্রশংসাপত্র,
@ -9615,7 +9562,6 @@ Remember to set {field_label}. It is required by {regulation}.,{ক্ষেত
Enrollment Date cannot be before the Start Date of the Academic Year {0},তালিকাভুক্তির তারিখ একাডেমিক বছরের শুরুর তারিখের আগে হতে পারে না {0},
Enrollment Date cannot be after the End Date of the Academic Term {0},তালিকাভুক্তির তারিখ একাডেমিক মেয়াদ শেষের তারিখের পরে হতে পারে না {0},
Enrollment Date cannot be before the Start Date of the Academic Term {0},তালিকাভুক্তির তারিখ একাডেমিক টার্মের শুরুর তারিখের আগে হতে পারে না {0},
Posting future transactions are not allowed due to Immutable Ledger,অপরিবর্তনীয় লেজারের কারণে ভবিষ্যতে লেনদেনগুলি অনুমোদিত নয়,
Future Posting Not Allowed,ভবিষ্যতের পোস্টিং অনুমোদিত নয়,
"To enable Capital Work in Progress Accounting, ","অগ্রগতি অ্যাকাউন্টিংয়ে মূলধন কাজ সক্ষম করতে,",
you must select Capital Work in Progress Account in accounts table,আপনার অবশ্যই অ্যাকাউন্টের সারণীতে প্রগতি অ্যাকাউন্টে মূলধন কাজ নির্বাচন করতে হবে,
@ -9632,3 +9578,157 @@ Company Not Linked,সংযুক্ত নয় সংস্থা,
Import Chart of Accounts from CSV / Excel files,সিএসভি / এক্সেল ফাইলগুলি থেকে অ্যাকাউন্টগুলির চার্ট আমদানি করুন,
Completed Qty cannot be greater than 'Qty to Manufacture',সম্পূর্ণ পরিমাণটি &#39;কোটির থেকে উত্পাদন&#39; এর চেয়ে বড় হতে পারে না,
"Row {0}: For Supplier {1}, Email Address is Required to send an email",সারি {0}: সরবরাহকারী {1} এর জন্য ইমেল প্রেরণের জন্য ইমেল ঠিকানা প্রয়োজন,
"If enabled, the system will post accounting entries for inventory automatically","সক্ষম করা থাকলে, সিস্টেম স্বয়ংক্রিয়ভাবে ইনভেন্টরির জন্য অ্যাকাউন্টিং এন্ট্রি পোস্ট করবে",
Accounts Frozen Till Date,অ্যাকাউন্টগুলি হিমশীতল তারিখ পর্যন্ত,
Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,অ্যাকাউন্টিং এন্ট্রি এই তারিখ পর্যন্ত হিমশীতল। নীচে উল্লিখিত ভূমিকাযুক্ত ব্যবহারকারী ব্যতীত কেউ এন্ট্রি তৈরি বা সংশোধন করতে পারবেন না,
Role Allowed to Set Frozen Accounts and Edit Frozen Entries,হিমায়িত অ্যাকাউন্টগুলি সেট করতে এবং হিমায়িত এন্ট্রি সম্পাদনা করার জন্য ভূমিকা অনুমোদিত,
Address used to determine Tax Category in transactions,লেনদেনে ট্যাক্স বিভাগ নির্ধারণ করতে ব্যবহৃত ঠিকানা Address,
"The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ","অর্ডারের পরিমাণের তুলনায় আপনাকে যে পরিমাণ শতাংশ বেশি বিল দেওয়ার অনুমতি দেওয়া হচ্ছে। উদাহরণস্বরূপ, যদি কোনও আইটেমের জন্য অর্ডার মান $ 100 এবং সহনশীলতা 10% হিসাবে সেট করা থাকে তবে আপনাকে 110 ডলার পর্যন্ত বিল দেওয়ার অনুমতি দেওয়া হবে",
This role is allowed to submit transactions that exceed credit limits,এই ভূমিকাটি transactionsণের সীমা অতিক্রম করে এমন লেনদেন জমা দেওয়ার অনুমতিপ্রাপ্ত,
"If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month",যদি &quot;মাস&quot; নির্বাচিত হয় তবে এক মাসের কতগুলি দিন নির্বিশেষে প্রতিটি মাসের জন্য একটি নির্দিষ্ট পরিমাণ স্থগিত রাজস্ব বা ব্যয় হিসাবে বুক করা হবে। স্থগিত রাজস্ব বা ব্যয় পুরো এক মাসের জন্য বুকিং না দেওয়া থাকলে এটি প্রমাণিত হবে,
"If this is unchecked, direct GL entries will be created to book deferred revenue or expense",এটি যদি চেক না করা থাকে তবে মুলতুবি রাজস্ব বা ব্যয় বুক করার জন্য সরাসরি জিএল এন্ট্রি তৈরি করা হবে,
Show Inclusive Tax in Print,প্রিন্টে অন্তর্ভুক্ত কর প্রদর্শন করুন,
Only select this if you have set up the Cash Flow Mapper documents,আপনি যদি নগদ ফ্লো ম্যাপার নথিগুলি সেট আপ করেন তবেই এটি নির্বাচন করুন,
Payment Channel,পেমেন্ট চ্যানেল,
Is Purchase Order Required for Purchase Invoice & Receipt Creation?,ক্রয় চালান এবং প্রাপ্তি তৈরির জন্য কি ক্রয়ের অর্ডার প্রয়োজনীয়?,
Is Purchase Receipt Required for Purchase Invoice Creation?,ক্রয় চালান তৈরির জন্য কি ক্রয়ের রশিদ প্রয়োজন?,
Maintain Same Rate Throughout the Purchase Cycle,ক্রয় চক্র জুড়ে একই হার বজায় রাখুন,
Allow Item To Be Added Multiple Times in a Transaction,কোনও লেনদেনে আইটেমটি একাধিকবার যুক্ত হওয়ার অনুমতি দিন,
Suppliers,সরবরাহকারীদের,
Send Emails to Suppliers,সরবরাহকারীদের ইমেল প্রেরণ করুন,
Select a Supplier,সরবরাহকারী নির্বাচন করুন,
Cannot mark attendance for future dates.,ভবিষ্যতের তারিখগুলির জন্য উপস্থিতি চিহ্নিত করতে পারে না।,
Do you want to update attendance? <br> Present: {0} <br> Absent: {1},আপনি কি উপস্থিতি আপডেট করতে চান?<br> বর্তমান: {0}<br> অনুপস্থিত: {1},
Mpesa Settings,ম্যাপিসা সেটিংস,
Initiator Name,শুরুর নাম,
Till Number,সংখ্যা পর্যন্ত,
Sandbox,স্যান্ডবক্স,
Online PassKey,অনলাইন পাসকি,
Security Credential,সুরক্ষা শংসাপত্র,
Get Account Balance,অ্যাকাউন্ট ব্যালেন্স পান,
Please set the initiator name and the security credential,দয়া করে প্রারম্ভিকের নাম এবং সুরক্ষা শংসাপত্র সেট করুন,
Inpatient Medication Entry,ইনপ্যাশেন্ট মেডিকেশন এন্ট্রি,
HLC-IME-.YYYY.-,এইচএলসি-আইএমই -YYYY.-,
Item Code (Drug),আইটেম কোড (ড্রাগ),
Medication Orders,ওষুধের আদেশ,
Get Pending Medication Orders,মুলতুবি ওষুধের আদেশ পান,
Inpatient Medication Orders,রোগী ওষুধের আদেশ,
Medication Warehouse,Icationষধ গুদাম,
Warehouse from where medication stock should be consumed,গুদাম যেখান থেকে ওষুধের স্টক খাওয়া উচিত,
Fetching Pending Medication Orders,মুলতুবি ওষুধের আদেশগুলি আনা হচ্ছে,
Inpatient Medication Entry Detail,ইনপ্যাশেন্ট ওষুধ এন্ট্রি বিশদ,
Medication Details,ওষুধের বিশদ,
Drug Code,ড্রাগ কোড,
Drug Name,ড্রাগ নাম,
Against Inpatient Medication Order,ইনপ্যাশেন্ট ওষুধের আদেশের বিরুদ্ধে,
Against Inpatient Medication Order Entry,ইনপ্যাশেন্ট ওষুধের আদেশ প্রবেশের বিরুদ্ধে,
Inpatient Medication Order,ইনপ্যাশেন্ট মেডিকেশন অর্ডার,
HLC-IMO-.YYYY.-,এইচএলসি-আইএমও-.YYYY.-,
Total Orders,মোট আদেশ,
Completed Orders,সম্পূর্ণ আদেশ,
Add Medication Orders,ওষুধের আদেশ যুক্ত করুন,
Adding Order Entries,অর্ডার এন্ট্রি যুক্ত করা হচ্ছে,
{0} medication orders completed,{0} ওষুধের অর্ডার সম্পূর্ণ হয়েছে,
{0} medication order completed,{0} ওষুধের অর্ডার সম্পূর্ণ হয়েছে,
Inpatient Medication Order Entry,ইনপ্যাশেন্ট মেডিকেশন অর্ডার এন্ট্রি,
Is Order Completed,অর্ডার সম্পূর্ণ হয়েছে,
Employee Records to Be Created By,দ্বারা তৈরি করা হবে কর্মচারী রেকর্ডস,
Employee records are created using the selected field,কর্মচারী রেকর্ডগুলি নির্বাচিত ক্ষেত্রটি ব্যবহার করে তৈরি করা হয়,
Don't send employee birthday reminders,কর্মচারীর জন্মদিনের অনুস্মারকগুলি প্রেরণ করবেন না,
Restrict Backdated Leave Applications,ব্যাকটেড ছুটি অ্যাপ্লিকেশনগুলি সীমাবদ্ধ করুন,
Sequence ID,সিকোয়েন্স আইডি,
Sequence Id,সিকোয়েন্স আইডি,
Allow multiple material consumptions against a Work Order,ওয়ার্ক অর্ডারের বিপরীতে একাধিক উপাদানের কনসপোশনগুলিকে মঞ্জুরি দিন,
Plan time logs outside Workstation working hours,ওয়ার্কস্টেশন কাজের সময় বাইরে লগ পরিকল্পনা করুন,
Plan operations X days in advance,এক্স ক্রিয়াকলাপের এক্স দিন আগেই,
Time Between Operations (Mins),অপারেশনগুলির মধ্যে সময় (মিনিট),
Default: 10 mins,ডিফল্ট: 10 মিনিট,
Overproduction for Sales and Work Order,বিক্রয় ও কাজের আদেশের জন্য অতিরিক্ত উত্পাদন,
"Update BOM cost automatically via scheduler, based on the latest Valuation Rate/Price List Rate/Last Purchase Rate of raw materials",সর্বশেষ মূল্যমানের হার / মূল্য তালিকার হার / কাঁচামালের সর্বশেষ ক্রয়ের হারের উপর ভিত্তি করে শিডিউলের মাধ্যমে বিওএমের দাম স্বয়ংক্রিয়ভাবে আপডেট করুন,
Purchase Order already created for all Sales Order items,ক্রয়ের আদেশ ইতিমধ্যে সমস্ত বিক্রয় আদেশ আইটেমগুলির জন্য তৈরি করা হয়েছে,
Select Items,আইটেম নির্বাচন করুন,
Against Default Supplier,ডিফল্ট সরবরাহকারী বিরুদ্ধে,
Auto close Opportunity after the no. of days mentioned above,নোটের পরে অটো বন্ধ করার সুযোগ। উপরে উল্লিখিত দিনের,
Is Sales Order Required for Sales Invoice & Delivery Note Creation?,বিক্রয় চালান এবং বিতরণ নোট তৈরির জন্য কি বিক্রয় আদেশের প্রয়োজনীয়?,
Is Delivery Note Required for Sales Invoice Creation?,ডেলিভারি নোটটি কি বিক্রয় চালান তৈরির জন্য প্রয়োজনীয়?,
How often should Project and Company be updated based on Sales Transactions?,বিক্রয় লেনদেনের উপর ভিত্তি করে কতবার প্রকল্প এবং সংস্থাকে আপডেট করা উচিত?,
Allow User to Edit Price List Rate in Transactions,লেনদেনগুলিতে ব্যবহারকারীকে মূল্য তালিকার হার সম্পাদনা করার অনুমতি দিন,
Allow Item to Be Added Multiple Times in a Transaction,কোনও লেনদেনে আইটেমটিকে একাধিকবার যুক্ত হওয়ার অনুমতি দিন,
Allow Multiple Sales Orders Against a Customer's Purchase Order,গ্রাহকের ক্রয়ের আদেশের বিরুদ্ধে একাধিক বিক্রয় অর্ডার মঞ্জুরি দিন,
Validate Selling Price for Item Against Purchase Rate or Valuation Rate,ক্রয় হার বা মূল্য হারের বিপরীতে আইটেমের জন্য বিক্রয় মূল্য বৈধ করুন,
Hide Customer's Tax ID from Sales Transactions,বিক্রয় লেনদেন থেকে গ্রাহকের করের আইডি লুকান,
"The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.","অর্ডারের পরিমাণের তুলনায় আপনাকে যে পরিমাণ শতাংশ পাওয়ার বা আরও সরবরাহ করার অনুমতি দেওয়া হয়। উদাহরণস্বরূপ, আপনি যদি 100 ইউনিট অর্ডার করে থাকেন এবং আপনার ভাতা 10% হয় তবে আপনাকে 110 টি ইউনিট পাওয়ার অনুমতি দেওয়া হবে।",
Action If Quality Inspection Is Not Submitted,মান পরিদর্শন জমা না দেওয়া হলে অ্যাকশন,
Auto Insert Price List Rate If Missing,অনুপস্থিত থাকলে অটো সন্নিবেশ মূল্য তালিকার হার,
Automatically Set Serial Nos Based on FIFO,ফিফোর উপর ভিত্তি করে স্বয়ংক্রিয়ভাবে সিরিয়াল নম্বর সেট করুন,
Set Qty in Transactions Based on Serial No Input,সিরিয়াল কোনও ইনপুট ভিত্তিক লেনদেনের পরিমাণ নির্ধারণ করুন,
Raise Material Request When Stock Reaches Re-order Level,স্টক পুনঃ-অর্ডার স্তরে পৌঁছালে উপাদানের অনুরোধ উত্থাপন করুন,
Notify by Email on Creation of Automatic Material Request,স্বয়ংক্রিয় পদার্থের অনুরোধ তৈরির বিষয়ে ইমেল দ্বারা অবহিত করুন,
Allow Material Transfer from Delivery Note to Sales Invoice,বিতরণ নোট থেকে বিক্রয় ইনভয়েসে উপাদান স্থানান্তরের অনুমতি দিন,
Allow Material Transfer from Purchase Receipt to Purchase Invoice,ক্রয় রশিদ থেকে ক্রয় চালানের কাছে পদার্থ স্থানান্তরকে অনুমতি দিন,
Freeze Stocks Older Than (Days),পুরানো স্টকগুলি (দিনগুলি) থেকে পুরানো,
Role Allowed to Edit Frozen Stock,ফ্রোজেন স্টক সম্পাদনা করার জন্য ভূমিকা অনুমোদিত,
The unallocated amount of Payment Entry {0} is greater than the Bank Transaction's unallocated amount,পেমেন্ট এন্ট্রি un 0 The এর অবিকৃত পরিমাণটি ব্যাংকের লেনদেনের অযাচিত পরিমাণের চেয়ে বেশি,
Payment Received,পেমেন্ট পেয়েছি,
Attendance cannot be marked outside of Academic Year {0},উপস্থিতি একাডেমিক বছর marked 0 outside এর বাইরে চিহ্নিত করা যায় না,
Student is already enrolled via Course Enrollment {0},শিক্ষার্থী ইতিমধ্যে কোর্স তালিকাভুক্তি {0 via এর মাধ্যমে তালিকাভুক্ত হয়েছে,
Attendance cannot be marked for future dates.,উপস্থিতি ভবিষ্যতের তারিখগুলির জন্য চিহ্নিত করা যায় না।,
Please add programs to enable admission application.,ভর্তির আবেদন সক্ষম করতে প্রোগ্রাম যুক্ত করুন।,
The following employees are currently still reporting to {0}:,নিম্নলিখিত কর্মচারী বর্তমানে {0} প্রতিবেদন করছেন:,
Please make sure the employees above report to another Active employee.,উপরের কর্মীরা অন্য সক্রিয় কর্মচারীকে রিপোর্ট করেছেন তা নিশ্চিত করুন।,
Cannot Relieve Employee,কর্মচারীকে মুক্তি দিতে পারে না,
Please enter {0},দয়া করে {0 enter লিখুন,
Please select another payment method. Mpesa does not support transactions in currency '{0}',দয়া করে অন্য অর্থ প্রদানের পদ্ধতিটি নির্বাচন করুন। এমপিসা মুদ্রা &#39;{0}&#39; এর লেনদেনকে সমর্থন করে না,
Transaction Error,লেনদেনের ত্রুটি,
Mpesa Express Transaction Error,ম্যাপ্সা এক্সপ্রেস লেনদেন ত্রুটি,
"Issue detected with Mpesa configuration, check the error logs for more details","এমপেসা কনফিগারেশন সহ সমস্যা সনাক্ত হয়েছে, আরও তথ্যের জন্য ত্রুটিযুক্ত লগগুলি পরীক্ষা করুন",
Mpesa Express Error,ম্যাপিসা এক্সপ্রেস ত্রুটি,
Account Balance Processing Error,অ্যাকাউন্ট ব্যালেন্স প্রক্রিয়াকরণ ত্রুটি,
Please check your configuration and try again,আপনার কনফিগারেশন পরীক্ষা করে দেখুন এবং আবার চেষ্টা করুন,
Mpesa Account Balance Processing Error,মাইপা অ্যাকাউন্টে ব্যালেন্স প্রক্রিয়াকরণ ত্রুটি,
Balance Details,ব্যালেন্স বিশদ,
Current Balance,বর্তমান হিসাব,
Available Balance,পর্যাপ্ত টাকা,
Reserved Balance,সংরক্ষিত ভারসাম্য,
Uncleared Balance,অপরিচ্ছন্ন ব্যালেন্স,
Payment related to {0} is not completed,{0} সম্পর্কিত অর্থ প্রদান সম্পূর্ণ হয়নি,
Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. Please select valid serial no.,সারি # {}: ক্রমিক নং {}} {already ইতিমধ্যে অন্য একটি পস ইনভয়েসে লেনদেন হয়েছে। দয়া করে বৈধ সিরিয়াল নম্বর নির্বাচন করুন।,
Row #{}: Item Code: {} is not available under warehouse {}.,সারি # {}: আইটেম কোড: {w গুদাম under} এর অধীন উপলব্ধ},
Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}.,সারি # {}: স্টক পরিমাণ আইটেম কোডের জন্য পর্যাপ্ত নয়: are w গুদাম}} এর অধীনে} উপলব্ধ পরিমাণ {}.,
Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.,সারি # {}: দয়া করে একটি সিরিয়াল নং এবং আইটেমের বিরুদ্ধে ব্যাচ নির্বাচন করুন::} বা লেনদেন সম্পূর্ণ করতে এটি সরান।,
Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.,সারি # {}: আইটেমের বিরুদ্ধে কোনও ক্রমিক সংখ্যা নির্বাচন করা হয়নি:}}। লেনদেন সম্পূর্ণ করতে দয়া করে একটি নির্বাচন করুন বা এটি সরান।,
Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.,সারি # {}: আইটেমের বিরুদ্ধে কোনও ব্যাচ নির্বাচন করা হয়নি:}}। লেনদেন সম্পূর্ণ করতে দয়া করে একটি ব্যাচ নির্বাচন করুন বা এটি সরান।,
Payment amount cannot be less than or equal to 0,প্রদানের পরিমাণ 0 এর চেয়ে কম বা সমান হতে পারে না,
Please enter the phone number first,প্রথমে ফোন নম্বরটি প্রবেশ করান,
Row #{}: {} {} does not exist.,সারি # {}: {} {} বিদ্যমান নেই।,
Row #{0}: {1} is required to create the Opening {2} Invoices,সারি # {0}: উদ্বোধনী} 2} চালানগুলি তৈরি করতে {1 required প্রয়োজন,
You had {} errors while creating opening invoices. Check {} for more details,খোলার চালান তৈরি করার সময় আপনার}} ত্রুটি হয়েছিল। আরও তথ্যের জন্য Check Check পরীক্ষা করুন,
Error Occured,ত্রুটি ঘটেছে,
Opening Invoice Creation In Progress,চালানের চালনা প্রগতিতে চলছে,
Creating {} out of {} {},{} {Of এর বাইরে Creat} তৈরি করা হচ্ছে,
(Serial No: {0}) cannot be consumed as it's reserverd to fullfill Sales Order {1}.,(ক্রমিক নং: {0}) সেবন পুরোপুরি বিক্রয় আদেশ {1 to এ সংরক্ষিত থাকায় সেবন করা যায় না},
Item {0} {1},আইটেম {0} {1},
Last Stock Transaction for item {0} under warehouse {1} was on {2}.,গুদাম {1} এর অধীনে আইটেম {0} এর জন্য সর্বশেষ স্টক লেনদেন {2 on এ ছিল},
Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.,গুদাম {1} এর অধীনে আইটেম {0। এর জন্য স্টক লেনদেন এই সময়ের আগে পোস্ট করা যাবে না।,
Posting future stock transactions are not allowed due to Immutable Ledger,অপরিবর্তনীয় লেজারের কারণে ভবিষ্যতে স্টক লেনদেনের অনুমতি দেওয়া হয় না,
A BOM with name {0} already exists for item {1}.,আইটেম {1} এর জন্য B 0 name নামের একটি বিওএম ইতিমধ্যে বিদ্যমান},
{0}{1} Did you rename the item? Please contact Administrator / Tech support,{0} {1 you আপনি কি আইটেমটির নাম পরিবর্তন করেছেন? প্রশাসক / প্রযুক্তি সহায়তার সাথে যোগাযোগ করুন,
At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2},সারিতে # {0}: সিকোয়েন্স আইডি {1 previous পূর্ববর্তী সারির সিকোয়েন্স আইডি {2 than এর চেয়ে কম হতে পারে না,
The {0} ({1}) must be equal to {2} ({3}),{0} ({1}) অবশ্যই {2} ({3}) এর সমান হতে হবে,
"{0}, complete the operation {1} before the operation {2}.","{0}, অপারেশন} 2} এর আগে অপারেশনটি complete 1 {সম্পূর্ণ করুন}",
Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No.,সিরিয়াল নং দ্বারা সরবরাহ নিশ্চিত করা যায় না যেমন আইটেম {0 Ser ক্রমিক নং দ্বারা সরবরাহ নিশ্চিতকরণ ছাড়া এবং যোগ করা হয়,
Item {0} has no Serial No. Only serilialized items can have delivery based on Serial No,আইটেম {0 no এর কোনও ক্রমিক নং নেই কেবল সিরিলাইজ করা আইটেমগুলির ক্রমিক নংয়ের ভিত্তিতে ডেলিভারি থাকতে পারে,
No active BOM found for item {0}. Delivery by Serial No cannot be ensured,আইটেম {0} এর জন্য কোনও সক্রিয় বিওএম পাওয়া যায় নি} ক্রমিক নং দ্বারা সরবরাহ নিশ্চিত করা যায় না,
No pending medication orders found for selected criteria,নির্বাচিত মানদণ্ডের জন্য কোনও মুলতুবি medicationষধের অর্ডার পাওয়া যায় নি,
From Date cannot be after the current date.,তারিখ থেকে বর্তমান তারিখের পরে হতে পারে না।,
To Date cannot be after the current date.,তারিখের তারিখ বর্তমান তারিখের পরে হতে পারে না।,
From Time cannot be after the current time.,সময় থেকে বর্তমান সময়ের পরে আর হতে পারে না।,
To Time cannot be after the current time.,টু টাইম বর্তমান সময়ের পরে হতে পারে না।,
Stock Entry {0} created and ,স্টক এন্ট্রি {0} তৈরি এবং,
Inpatient Medication Orders updated successfully,ইনপ্যাশেন্ট মেডিকেশন অর্ডারগুলি সফলভাবে আপডেট হয়েছে updated,
Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1},সারি {0}: বাতিল রোগীদের Medষধ আদেশের বিরুদ্ধে ইনপিশেন্ট entষধ প্রবেশ তৈরি করতে পারে না {1},
Row {0}: This Medication Order is already marked as completed,সারি {0}: এই icationষধ আদেশটি ইতিমধ্যে সম্পূর্ণ হিসাবে চিহ্নিত হয়েছে,
Quantity not available for {0} in warehouse {1},গুদামে {0} এর জন্য পরিমাণ পাওয়া যায় না {1},
Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.,স্টক সেটিংসে নেতিবাচক স্টককে মঞ্জুরি দিন বা এগিয়ে যাওয়ার জন্য স্টক এন্ট্রি তৈরি করুন।,
No Inpatient Record found against patient {0},রোগীর বিরুদ্ধে কোনও ইনপিশেন্ট রেকর্ড পাওয়া যায় নি {0},
An Inpatient Medication Order {0} against Patient Encounter {1} already exists.,রোগী এনকাউন্টার} 1} এর বিপরীতে একটি ইনপিশেন্ট icationষধ আদেশ {0} ইতিমধ্যে বিদ্যমান।,

Can't render this file because it is too large.

Some files were not shown because too many files have changed in this diff Show More