Merge branch 'develop' into scheduling-ui-rewrite

This commit is contained in:
Pranav Nachnekar 2019-11-04 04:38:59 +00:00 committed by GitHub
commit af18b2cdc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
148 changed files with 1130 additions and 777 deletions

47
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,47 @@
---
name: Bug report
about: Report a bug encountered while using ERPNext
labels: bug
---
<!--
Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
- For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
- For documentation issues, refer to https://github.com/frappe/erpnext_com
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
the original discussion.
3. When making a bug report, make sure you provide all required information. The easier it is for
maintainers to reproduce, the faster it'll be fixed.
4. If you think you know what the reason for the bug is, share it with us. Maybe put in a PR 😉
-->
## Description of the issue
## Context information (for bug reports)
**Output of `bench version`**
```
(paste here)
```
## Steps to reproduce the issue
1.
2.
3.
### Observed result
### Expected result
### Stacktrace / full error message
```
(paste here)
```
## Additional information
OS version / distribution, `ERPNext` install method, etc.

View File

@ -0,0 +1,28 @@
---
name: Feature request
about: Suggest an idea to improve ERPNext
labels: feature-request
---
<!--
Welcome to ERPNext issue tracker! Before creating an issue, please heed the following:
1. This tracker should only be used to report bugs and request features / enhancements to ERPNext
- For questions and general support, checkout the manual https://erpnext.com/docs/user/manual/en or use https://discuss.erpnext.com
- For documentation issues, refer to https://github.com/frappe/erpnext_com
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
the original discussion.
3. When making a feature request, make sure to be as verbose as possible. The better you convey your message, the greater the drive to make it happen.
-->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,17 @@
---
name: Question about using ERPNext
about: This is not the appropriate channel
labels: invalid
---
Please post on our forums:
for questions about using `ERPNext`: https://discuss.erpnext.com
for questions about using the `Frappe Framework`: https://discuss.frappe.io
for questions about using `bench`, probably the best place to start is the [bench repo](https://github.com/frappe/bench)
For documentation issues, use the [ERPNext Documentation](https://erpnext.com/docs/) or [Frappe Framework Documentation](https://frappe.io/docs/user/en) or the [developer cheetsheet](https://github.com/frappe/frappe/wiki/Developer-Cheatsheet)
> **Posts that are not bug reports or feature requests will not be addressed on this issue tracker.**

View File

@ -1,2 +1,33 @@
Please read the pull request checklist to make sure your changes are merged: https://github.com/frappe/erpnext/wiki/Pull-Request-Checklist
<!--
Some key notes before you open a PR:
1. Select which branch should this PR be merged in?
2. PR name follows [convention](http://karma-runner.github.io/4.0/dev/git-commit-msg.html)
3. All tests pass locally, UI and Unit tests
4. All business logic and validations must be on the server-side
5. Update necessary Documentation
6. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes
Also, if you're new here
- Documentation Guidelines => https://github.com/frappe/erpnext/wiki/Updating-Documentation
- Contribution Guide => https://github.com/frappe/erpnext/blob/develop/.github/CONTRIBUTING.md
- Pull Request Checklist => https://github.com/frappe/erpnext/wiki/Pull-Request-Checklist
-->
> Please provide enough information so that others can review your pull request:
<!-- You can skip this if you're fixing a typo or updating existing documentation -->
> Explain the **details** for making this change. What existing problem does the pull request solve?
<!-- Example: When "Adding a function to do X", explain why it is necessary to have a way to do X. -->
> Screenshots/GIFs
<!-- Add images/recordings to better visualize the change: expected/current behviour -->

7
SECURITY.md Normal file
View File

@ -0,0 +1,7 @@
# Security Policy
The ERPNext team and community take security issues seriously. To report a security issue, fill out the form at [https://erpnext.com/security/report](https://erpnext.com/security/report).
You can help us make ERPNext and all it's users more secure by following the [Reporting guidelines](https://erpnext.com/security).
We appreciate your efforts to responsibly disclose your findings. We'll endeavor to respond quickly, and will keep you updated throughout the process.

View File

@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '12.1.6'
__version__ = '12.1.8'
def get_default_company(user=None):
'''Get default company for user'''

View File

@ -3,6 +3,7 @@
from __future__ import unicode_literals
import frappe, json
from frappe import _
from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate
from erpnext.accounts.report.general_ledger.general_ledger import execute
from frappe.core.page.dashboard.dashboard import cache_source, get_from_date_from_timespan
@ -24,6 +25,9 @@ def get(chart_name = None, chart = None, no_cache = None, from_date = None, to_d
account = filters.get("account")
company = filters.get("company")
if not account and chart:
frappe.throw(_("Account is not set for the dashboard chart {0}").format(chart))
if not to_date:
to_date = nowdate()
if not from_date:

View File

@ -117,7 +117,7 @@ class Account(NestedSet):
if not parent_acc_name_map: return
self.create_account_for_child_company(parent_acc_name_map, descendants)
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_group_or_ledger(self):
if self.get("__islocal"):
@ -159,7 +159,7 @@ class Account(NestedSet):
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
def create_account_for_child_company(self, parent_acc_name_map, descendants):
def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name):
for company in descendants:
if not parent_acc_name_map.get(company):
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")

View File

@ -160,7 +160,7 @@ def _make_test_records(verbose):
["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"]
]
for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"]]:
for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"], ["_Test Company with perpetual inventory", "TCP1"]]:
test_objects = make_test_objects("Account", [{
"doctype": "Account",
"account_name": account_name,

View File

@ -2,6 +2,15 @@
// For license information, please see license.txt
frappe.ui.form.on('Coupon Code', {
setup: function(frm) {
frm.set_query("pricing_rule", function() {
return {
filters: [
["Pricing Rule","coupon_code_based", "=", "1"]
]
};
});
},
coupon_name:function(frm){
if (frm.doc.__islocal===1) {
frm.trigger("make_coupon_code");

View File

@ -24,6 +24,7 @@
],
"fields": [
{
"description": "e.g. \"Summer Holiday 2019 Offer 20\"",
"fieldname": "coupon_name",
"fieldtype": "Data",
"label": "Coupon Name",
@ -50,7 +51,7 @@
"fieldtype": "Column Break"
},
{
"description": "To be used to get discount",
"description": "unique e.g. SAVE20 To be used to get discount",
"fieldname": "coupon_code",
"fieldtype": "Data",
"label": "Coupon Code",
@ -62,12 +63,13 @@
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule",
"options": "Pricing Rule"
"options": "Pricing Rule",
"reqd": 1
},
{
"fieldname": "uses",
"fieldtype": "Section Break",
"label": "Uses"
"label": "Validity and Usage"
},
{
"fieldname": "valid_from",
@ -113,7 +115,7 @@
"read_only": 1
}
],
"modified": "2019-10-15 14:12:22.686986",
"modified": "2019-10-19 14:48:14.602481",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Coupon Code",

View File

@ -8,10 +8,12 @@ import unittest
from frappe.utils import today, cint, flt, getdate
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
from erpnext.accounts.party import get_dashboard_info
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestLoyaltyProgram(unittest.TestCase):
@classmethod
def setUpClass(self):
set_perpetual_inventory(0)
# create relevant item, customer, loyalty program, etc
create_records()

View File

@ -308,7 +308,7 @@ frappe.ui.form.on('Payment Entry', {
() => {
frm.set_party_account_based_on_party = false;
if (r.message.bank_account) {
frm.set_value("bank_account", r.message.bank_account);
frm.set_value("party_bank_account", r.message.bank_account);
}
}
]);

View File

@ -10,7 +10,7 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_ent
from frappe.utils import cint, flt, today, nowdate, add_days
import frappe.defaults
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
test_records as pr_test_records
test_records as pr_test_records, make_purchase_receipt, get_taxes
from erpnext.controllers.accounts_controller import get_payment_terms
from erpnext.exceptions import InvalidCurrency
from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
@ -57,16 +57,11 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account))
def test_gl_entries_with_perpetual_inventory(self):
pi = frappe.copy_doc(test_records[1])
set_perpetual_inventory(1, pi.company)
pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10)
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pi.company)), 1)
pi.insert()
pi.submit()
self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0, pi.company)
def test_terms_added_after_save(self):
pi = frappe.copy_doc(test_records[1])
pi.insert()
@ -196,21 +191,21 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(pi.on_hold, 0)
def test_gl_entries_with_perpetual_inventory_against_pr(self):
pr = frappe.copy_doc(pr_test_records[0])
set_perpetual_inventory(1, pr.company)
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pr.submit()
pi = frappe.copy_doc(test_records[1])
for d in pi.get("items"):
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", get_taxes_and_charges=True,)
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10,do_not_save= "True")
for d in pi.items:
d.purchase_receipt = pr.name
pi.insert()
pi.submit()
self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0, pr.company)
def check_gle_for_pi(self, pi):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
@ -218,10 +213,10 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertTrue(gl_entries)
expected_values = dict((d[0], d) for d in [
["_Test Payable - _TC", 0, 720],
["Stock Received But Not Billed - _TC", 500.0, 0],
["_Test Account Shipping Charges - _TC", 100.0, 0],
["_Test Account VAT - _TC", 120.0, 0],
["Creditors - TCP1", 0, 720],
["Stock Received But Not Billed - TCP1", 500.0, 0],
["_Test Account Shipping Charges - TCP1", 100.0, 0],
["_Test Account VAT - TCP1", 120.0, 0],
])
for i, gle in enumerate(gl_entries):
@ -524,10 +519,9 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertFalse(gle)
def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime())
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
@ -548,9 +542,9 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(expected_gl_entries[gle.account][2], gle.credit)
def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - _TC", is_paid=1)
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", is_paid=1, company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit,
sum(credit) as credit, debit_in_account_currency, credit_in_account_currency
@ -563,7 +557,7 @@ class TestPurchaseInvoice(unittest.TestCase):
expected_gl_entries = dict((d[0], d) for d in [
[pi.credit_to, 250.0, 250.0],
[stock_in_hand_account, 250.0, 0.0],
["Cash - _TC", 0.0, 250.0]
["Cash - TCP1", 0.0, 250.0]
])
for i, gle in enumerate(gl_entries):
@ -630,6 +624,7 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
def test_rejected_serial_no(self):
set_perpetual_inventory(0)
pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
rejected_qty=1, rate=500, update_stock=1,
rejected_warehouse = "_Test Rejected Warehouse - _TC")
@ -881,7 +876,7 @@ def make_purchase_invoice(**args):
pi.is_return = args.is_return
pi.return_against = args.return_against
pi.is_subcontracted = args.is_subcontracted or "No"
pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
pi.append("items", {
"item_code": args.item or args.item_code or "_Test Item",
@ -890,14 +885,21 @@ def make_purchase_invoice(**args):
"received_qty": args.received_qty or 0,
"rejected_qty": args.rejected_qty or 0,
"rate": args.rate or 50,
'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC',
"conversion_factor": 1.0,
"serial_no": args.serial_no,
"stock_uom": "_Test UOM",
"cost_center": "_Test Cost Center - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
"rejected_serial_no": args.rejected_serial_no or ""
})
if args.get_taxes_and_charges:
taxes = get_taxes()
for tax in taxes:
pi.append("taxes", tax)
if not args.do_not_save:
pi.insert()
if not args.do_not_submit:

View File

@ -402,14 +402,21 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
for docs in doc_list:
for name, doc in iteritems(docs):
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
validate_records(doc)
si_doc = frappe.new_doc('Sales Invoice')
si_doc.offline_pos_name = name
si_doc.update(doc)
si_doc.set_posting_time = 1
si_doc.customer = get_customer_id(doc)
si_doc.due_date = doc.get('posting_date')
name_list = submit_invoice(si_doc, name, doc, name_list)
if isinstance(doc, dict):
validate_records(doc)
si_doc = frappe.new_doc('Sales Invoice')
si_doc.offline_pos_name = name
si_doc.update(doc)
si_doc.set_posting_time = 1
si_doc.customer = get_customer_id(doc)
si_doc.due_date = doc.get('posting_date')
name_list = submit_invoice(si_doc, name, doc, name_list)
else:
doc.due_date = doc.get('posting_date')
doc.customer = get_customer_id(doc)
doc.set_posting_time = 1
doc.offline_pos_name = name
name_list = submit_invoice(doc, name, doc, name_list)
else:
name_list.append(name)

View File

@ -686,7 +686,6 @@ class SalesInvoice(SellingController):
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
if not gl_entries:
gl_entries = self.get_gl_entries()

View File

@ -68,8 +68,6 @@
"selling_price_list": "_Test Price List",
"territory": "_Test Territory"
},
{
"company": "_Test Company",
"conversion_rate": 1.0,
@ -276,7 +274,6 @@
"uom": "_Test UOM 1",
"conversion_factor": 1,
"stock_uom": "_Test UOM 1"
},
{
"cost_center": "_Test Cost Center - _TC",

View File

@ -20,6 +20,9 @@ from erpnext.stock.doctype.item.test_item import create_item
from six import iteritems
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
from erpnext.regional.india.utils import get_ewb_data
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
class TestSalesInvoice(unittest.TestCase):
def make(self):
@ -550,7 +553,6 @@ class TestSalesInvoice(unittest.TestCase):
si.get("taxes")[6].tax_amount = 2
si.insert()
print(si.name)
expected_values = [
{
@ -679,56 +681,67 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
def test_pos_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
pos["is_pos"] = 1
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300}]
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
pos.is_pos = 1
pos.update_stock = 1
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50})
taxes = get_taxes_and_charges()
pos.taxes = []
for tax in taxes:
pos.append("taxes", tax)
si = frappe.copy_doc(pos)
si.insert()
si.submit()
self.assertEqual(si.paid_amount, 100.0)
self.assertEqual(si.paid_amount, 600.0)
self.pos_gl_entry(si, pos, 300)
self.pos_gl_entry(si, pos, 50)
def test_pos_change_amount(self):
set_perpetual_inventory()
make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
pos["is_pos"] = 1
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 340}]
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
si = frappe.copy_doc(pos)
si.change_amount = 5.0
si.insert()
si.submit()
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
self.assertEqual(si.grand_total, 630.0)
self.assertEqual(si.write_off_amount, -5)
pos.is_pos = 1
pos.update_stock = 1
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 60})
pos.change_amount = 5.0
pos.insert()
pos.submit()
self.assertEqual(pos.grand_total, 100.0)
self.assertEqual(pos.write_off_amount, -5)
def test_make_pos_invoice(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
set_perpetual_inventory()
make_pos_profile()
self._insert_purchase_receipt()
pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
pos = copy.deepcopy(test_records[1])
pos["is_pos"] = 1
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
pos.is_pos = 1
pos.update_stock = 1
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50})
taxes = get_taxes_and_charges()
pos.taxes = []
for tax in taxes:
pos.append("taxes", tax)
invoice_data = [{'09052016142': pos}]
si = make_invoice(invoice_data).get('invoice')
@ -736,16 +749,15 @@ class TestSalesInvoice(unittest.TestCase):
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
si = frappe.get_doc('Sales Invoice', sales_invoice[0].name)
self.assertEqual(si.grand_total, 630.0)
self.pos_gl_entry(si, pos, 330)
self.assertEqual(si.grand_total, 100)
self.pos_gl_entry(si, pos, 50)
def test_make_pos_invoice_in_draft(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
from erpnext.stock.doctype.item.test_item import make_item
set_perpetual_inventory()
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
@ -789,7 +801,7 @@ class TestSalesInvoice(unittest.TestCase):
si.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEqual([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse - _TC", -1.0])
['_Test FG Item', 'Stores - TCP1', -1.0])
# check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit
@ -797,19 +809,19 @@ class TestSalesInvoice(unittest.TestCase):
order by account asc, debit asc, credit asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
stock_in_hand = get_inventory_account('_Test Company')
stock_in_hand = get_inventory_account('_Test Company with perpetual inventory')
expected_gl_entries = sorted([
[si.debit_to, 630.0, 0.0],
[pos["items"][0]["income_account"], 0.0, 500.0],
[pos["taxes"][0]["account_head"], 0.0, 80.0],
[pos["taxes"][1]["account_head"], 0.0, 50.0],
[si.debit_to, 100.0, 0.0],
[pos.items[0].income_account, 0.0, 89.09],
['Round Off - TCP1', 0.0, 0.01],
[pos.taxes[0].account_head, 0.0, 10.69],
[pos.taxes[1].account_head, 0.0, 0.21],
[stock_in_hand, 0.0, abs(sle.stock_value_difference)],
[pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0],
[si.debit_to, 0.0, 300.0],
[pos.items[0].expense_account, abs(sle.stock_value_difference), 0.0],
[si.debit_to, 0.0, 50.0],
[si.debit_to, 0.0, cash_amount],
["_Test Bank - _TC", 300.0, 0.0],
["Cash - _TC", cash_amount, 0.0]
["_Test Bank - TCP1", 50, 0.0],
["Cash - TCP1", cash_amount, 0.0]
])
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
@ -823,9 +835,9 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
set_perpetual_inventory(0)
frappe.db.sql("delete from `tabPOS Profile`")
si.delete()
def test_pos_si_without_payment(self):
set_perpetual_inventory()
@ -1008,7 +1020,6 @@ class TestSalesInvoice(unittest.TestCase):
"""
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
se = make_serialized_item()
@ -1023,14 +1034,17 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(si.get("items")[0].serial_no, dn.get("items")[0].serial_no)
def test_return_sales_invoice(self):
set_perpetual_inventory()
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100)
actual_qty_0 = get_qty_after_transaction()
actual_qty_0 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
si = create_sales_invoice(qty=5, rate=500, update_stock=1)
si = create_sales_invoice(qty = 5, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1")
actual_qty_1 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
frappe.db.commit()
actual_qty_1 = get_qty_after_transaction()
self.assertEqual(actual_qty_0 - 5, actual_qty_1)
# outgoing_rate
@ -1038,10 +1052,9 @@ class TestSalesInvoice(unittest.TestCase):
"voucher_no": si.name}, "stock_value_difference") / 5
# return entry
si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1)
actual_qty_2 = get_qty_after_transaction()
si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1")
actual_qty_2 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
self.assertEqual(actual_qty_1 + 2, actual_qty_2)
incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
@ -1049,7 +1062,7 @@ class TestSalesInvoice(unittest.TestCase):
["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', si1.items[0].warehouse)
stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory', si1.items[0].warehouse)
# Check gl entry
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
@ -1058,7 +1071,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, stock_value_difference)
party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
"voucher_no": si1.name, "account": "Debtors - _TC", "party": "_Test Customer"}, "credit")
"voucher_no": si1.name, "account": "Debtors - TCP1", "party": "_Test Customer"}, "credit")
self.assertEqual(party_credited, 1000)
@ -1066,7 +1079,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(si1.outstanding_amount)
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
set_perpetual_inventory(0)
def test_discount_on_net_total(self):
si = frappe.copy_doc(test_records[2])
@ -1524,6 +1536,8 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(si.total_taxes_and_charges, 577.05)
self.assertEqual(si.grand_total, 1827.05)
def test_create_invoice_without_terms(self):
si = create_sales_invoice(do_not_save=1)
self.assertFalse(si.get('payment_schedule'))
@ -1930,4 +1944,29 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party
if against_voucher_type == 'Purchase Invoice':
bal = bal * -1
return bal
return bal
def get_taxes_and_charges():
return [{
"account_head": "_Test Account Excise Duty - TCP1",
"charge_type": "On Net Total",
"cost_center": "Main - TCP1",
"description": "Excise Duty",
"doctype": "Sales Taxes and Charges",
"idx": 1,
"included_in_print_rate": 1,
"parentfield": "taxes",
"rate": 12
},
{
"account_head": "_Test Account Education Cess - TCP1",
"charge_type": "On Previous Row Amount",
"cost_center": "Main - TCP1",
"description": "Education Cess",
"doctype": "Sales Taxes and Charges",
"idx": 2,
"included_in_print_rate": 1,
"parentfield": "taxes",
"rate": 2,
"row_id": 1
}]

View File

@ -14,13 +14,13 @@ class TestShippingRule(unittest.TestCase):
shipping_rule.name = test_records[0].get('name')
shipping_rule.get("conditions")[0].from_value = 101
self.assertRaises(FromGreaterThanToError, shipping_rule.insert)
def test_many_zero_to_values(self):
shipping_rule = frappe.copy_doc(test_records[0])
shipping_rule.name = test_records[0].get('name')
shipping_rule.get("conditions")[0].to_value = 0
self.assertRaises(ManyBlankToValuesError, shipping_rule.insert)
def test_overlapping_conditions(self):
for range_a, range_b in [
((50, 150), (0, 100)),
@ -38,6 +38,10 @@ class TestShippingRule(unittest.TestCase):
self.assertRaises(OverlappingConditionError, shipping_rule.insert)
def create_shipping_rule(shipping_rule_type, shipping_rule_name):
if frappe.db.exists("Shipping Rule", shipping_rule_name):
return frappe.get_doc("Shipping Rule", shipping_rule_name)
sr = frappe.new_doc("Shipping Rule")
sr.account = "_Test Account Shipping Charges - _TC"
sr.calculate_based_on = "Net Total"
@ -70,4 +74,4 @@ def create_shipping_rule(shipping_rule_type, shipping_rule_name):
})
sr.insert(ignore_permissions=True)
sr.submit()
return sr
return sr

View File

@ -3,8 +3,9 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe.utils import flt, cstr, cint
from frappe.utils import flt, cstr, cint, comma_and
from frappe import _
from erpnext.accounts.utils import get_stock_and_account_balance
from frappe.model.meta import get_field_precision
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@ -12,6 +13,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import g
class ClosedAccountingPeriod(frappe.ValidationError): pass
class StockAccountInvalidTransaction(frappe.ValidationError): pass
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False):
if gl_map:
@ -115,11 +117,9 @@ def check_if_in_list(gle, gl_map, dimensions=None):
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost:
validate_account_for_perpetual_inventory(gl_map)
validate_cwip_accounts(gl_map)
round_off_debit_credit(gl_map)
for entry in gl_map:
make_entry(entry, adv_adj, update_outstanding, from_repost)
@ -127,6 +127,10 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost:
validate_expense_against_budget(entry)
if not from_repost:
validate_account_for_perpetual_inventory(gl_map)
def make_entry(args, adv_adj, update_outstanding, from_repost=False):
args.update({"doctype": "GL Entry"})
gle = frappe.get_doc(args)
@ -137,15 +141,31 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
gle.submit()
def validate_account_for_perpetual_inventory(gl_map):
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)) \
and gl_map[0].voucher_type=="Journal Entry":
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
where account_type = 'Stock' and is_group=0""")]
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
account_list = [gl_entries.account for gl_entries in gl_map]
for entry in gl_map:
if entry.account in aii_accounts:
aii_accounts = [d.name for d in frappe.get_all("Account",
filters={'account_type': 'Stock', 'is_group': 0, 'company': gl_map[0].company})]
for account in account_list:
if account not in aii_accounts:
continue
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
gl_map[0].posting_date, gl_map[0].company)
if gl_map[0].voucher_type=="Journal Entry":
# In case of Journal Entry, there are no corresponding SL entries,
# hence deducting currency amount
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
if account_bal == stock_bal:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction)
.format(account), StockAccountInvalidTransaction)
elif account_bal != stock_bal:
frappe.throw(_("Account Balance ({0}) and Stock Value ({1}) is out of sync for account {2} and linked warehouse ({3}). Please create adjustment Journal Entry for amount {4}.")
.format(account_bal, stock_bal, account, comma_and(warehouse_list), stock_bal - account_bal),
StockValueAndAccountBalanceOutOfSync)
def validate_cwip_accounts(gl_map):
if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \

View File

@ -69,7 +69,7 @@ def get_columns(filters):
for year in fiscal_year:
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
if filters["period"] == "Yearly":
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Variance ") + " " + str(year[0])]
for label in labels:
columns.append(label+":Float:150")
else:

View File

@ -13,6 +13,10 @@ from six import iteritems
# imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
class FiscalYearError(frappe.ValidationError): pass
@frappe.whitelist()
@ -560,23 +564,23 @@ def fix_total_debit_credit():
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no))
def get_stock_and_account_difference(account_list=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
def get_stock_and_account_balance(account=None, posting_date=None, company=None):
if not posting_date: posting_date = nowdate()
difference = {}
warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account):
if account_data.get('account') in account_list:
account_balance = get_balance_on(account_data.get('account'), posting_date, in_account_currency=False)
stock_value = get_stock_value_on(warehouse, posting_date)
if abs(flt(stock_value) - flt(account_balance)) > 0.005:
difference.setdefault(account_data.get('account'), flt(stock_value) - flt(account_balance))
account_balance = get_balance_on(account, posting_date, in_account_currency=False)
return difference
related_warehouses = [wh for wh, wh_details in warehouse_account.items()
if wh_details.account == account and not wh_details.is_group]
total_stock_value = 0.0
for warehouse in related_warehouses:
value = get_stock_value_on(warehouse, posting_date)
total_stock_value += value
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
return flt(account_balance, precision), flt(total_stock_value, precision), related_warehouses
def get_currency_precision():
precision = cint(frappe.db.get_default("currency_precision"))

View File

@ -1,13 +1,13 @@
{
"add_total_row": 0,
"creation": "2019-09-23 16:35:02.836134",
"disable_prepared_report": 0,
"disable_prepared_report": 1,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-09-23 16:35:02.836134",
"modified": "2019-10-22 13:00:31.539726",
"modified_by": "Administrator",
"module": "Assets",
"name": "Fixed Asset Register",

View File

@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cstr
def execute(filters=None):
filters = frappe._dict(filters or {})
@ -149,12 +150,12 @@ def get_finance_book_value_map(finance_book=''):
FROM `tabAsset Finance Book`
WHERE
parentfield='finance_books'
AND finance_book=%s''', (finance_book)))
AND ifnull(finance_book, '')=%s''', cstr(finance_book)))
def get_purchase_receipt_supplier_map():
return frappe._dict(frappe.db.sql(''' Select
pr.name, pr.supplier
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri
WHERE
pri.parent = pr.name
AND pri.is_fixed_asset=1
@ -164,7 +165,7 @@ def get_purchase_receipt_supplier_map():
def get_purchase_invoice_supplier_map():
return frappe._dict(frappe.db.sql(''' Select
pi.name, pi.supplier
FROM `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pii
FROM `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pii
WHERE
pii.parent = pi.name
AND pii.is_fixed_asset=1

View File

@ -18,7 +18,7 @@ def get_data():
"onboard_present": 1
},
{
"module_name": "Accounting",
"module_name": "Accounts",
"category": "Modules",
"label": _("Accounting"),
"color": "#3498db",

View File

@ -127,7 +127,11 @@ def get_data():
"name": "Shipping Rule",
"description": _("Rules for adding shipping costs."),
},
{
"type": "doctype",
"name": "Coupon Code",
"description": _("Define coupon codes."),
}
]
},
{

View File

@ -1172,6 +1172,7 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
data = json.loads(trans_items)
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
for d in data:
@ -1204,18 +1205,22 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
# if rate is greater than price_list_rate, set margin
# or set discount
child_item.discount_percentage = 0
child_item.margin_type = "Amount"
child_item.margin_rate_or_amount = flt(child_item.rate - child_item.price_list_rate,
child_item.precision("margin_rate_or_amount"))
child_item.rate_with_margin = child_item.rate
if parent_doctype in sales_doctypes:
child_item.margin_type = "Amount"
child_item.margin_rate_or_amount = flt(child_item.rate - child_item.price_list_rate,
child_item.precision("margin_rate_or_amount"))
child_item.rate_with_margin = child_item.rate
else:
child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0,
child_item.precision("discount_percentage"))
child_item.discount_amount = flt(
child_item.price_list_rate) - flt(child_item.rate)
child_item.margin_type = ""
child_item.margin_rate_or_amount = 0
child_item.rate_with_margin = 0
if parent_doctype in sales_doctypes:
child_item.margin_type = ""
child_item.margin_rate_or_amount = 0
child_item.rate_with_margin = 0
child_item.flags.ignore_validate_update_after_submit = True
if new_child_flag:

View File

@ -152,6 +152,20 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
#Get searchfields from meta and use in Item Link field query
meta = frappe.get_meta("Item", cached=True)
searchfields = meta.get_search_fields()
if "description" in searchfields:
searchfields.remove("description")
columns = [field for field in searchfields if not field in ["name", "item_group", "description"]]
columns = ", ".join(columns)
searchfields = searchfields + [field for field in[searchfield or "name", "item_code", "item_group", "item_name"]
if not field in searchfields]
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
description_cond = ''
if frappe.db.count('Item', cache=True) < 50000:
# scan description only if items are less than 50000
@ -162,17 +176,14 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
tabItem.item_group,
if(length(tabItem.description) > 40, \
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
concat(substr(tabItem.description, 1, 40), "..."), description) as description,
{columns}
from tabItem
where tabItem.docstatus < 2
and tabItem.has_variants=0
and tabItem.disabled=0
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
and (tabItem.`{key}` LIKE %(txt)s
or tabItem.item_code LIKE %(txt)s
or tabItem.item_group LIKE %(txt)s
or tabItem.item_name LIKE %(txt)s
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
{description_cond})
{fcond} {mcond}
order by
@ -182,6 +193,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
name, item_name
limit %(start)s, %(page_len)s """.format(
key=searchfield,
columns=columns,
scond=searchfields,
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
mcond=get_match_cond(doctype).replace('%', '%%'),
description_cond = description_cond),
@ -280,22 +293,31 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
"page_len": page_len
}
having_clause = "having sum(sle.actual_qty) > 0"
if filters.get("is_return"):
having_clause = ""
if args.get('warehouse'):
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
from `tabStock Ledger Entry` sle
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
where
batch.disabled = 0
and sle.item_code = %(item_code)s
and sle.warehouse = %(warehouse)s
and (sle.batch_no like %(txt)s
or batch.manufacturing_date like %(txt)s)
and batch.docstatus < 2
{0}
{match_conditions}
group by batch_no having sum(sle.actual_qty) > 0
order by batch.expiry_date, sle.batch_no desc
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
from `tabStock Ledger Entry` sle
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
where
batch.disabled = 0
and sle.item_code = %(item_code)s
and sle.warehouse = %(warehouse)s
and (sle.batch_no like %(txt)s
or batch.manufacturing_date like %(txt)s)
and batch.docstatus < 2
{cond}
{match_conditions}
group by batch_no {having_clause}
order by batch.expiry_date, sle.batch_no desc
limit %(start)s, %(page_len)s""".format(
cond=cond,
match_conditions=get_match_cond(doctype),
having_clause = having_clause
), args)
return batch_nos
else:

View File

@ -207,41 +207,6 @@ class StockController(AccountsController):
reference_doctype=self.doctype,
reference_name=self.name)).insert().name
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]
acc_diff = get_stock_and_account_difference(account_list,
expected_gle[0].posting_date, self.company)
cost_center = self.get_company_default("cost_center")
stock_adjustment_account = self.get_company_default("stock_adjustment_account")
gl_entries = []
for account, diff in acc_diff.items():
if diff:
gl_entries.append([
# stock in hand account
voucher_obj.get_gl_dict({
"account": account,
"against": stock_adjustment_account,
"debit": diff,
"remarks": "Adjustment Accounting Entry for Stock",
}),
# account against stock in hand
voucher_obj.get_gl_dict({
"account": stock_adjustment_account,
"against": account,
"credit": diff,
"cost_center": cost_center or None,
"remarks": "Adjustment Accounting Entry for Stock",
}),
])
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
def check_expense_account(self, item):
if not item.get("expense_account"):
frappe.throw(_("Expense or Difference account is mandatory for Item {0} as it impacts overall stock value").format(item.item_code))

View File

@ -10,13 +10,14 @@ from erpnext.demo.domains import data
from frappe import _
def setup(domain):
frappe.flags.in_demo = 1
complete_setup(domain)
setup_demo_page()
setup_fiscal_year()
setup_holiday_list()
setup_user()
setup_employee()
setup_user_roles()
setup_user_roles(domain)
setup_role_permissions()
setup_custom_field_for_domain()
@ -183,13 +184,19 @@ def setup_salary_structure(employees, salary_slip_based_on_timesheet=0):
return ss
def setup_user_roles():
def setup_user_roles(domain):
user = frappe.get_doc('User', 'demo@erpnext.com')
user.add_roles('HR User', 'HR Manager', 'Accounts User', 'Accounts Manager',
'Stock User', 'Stock Manager', 'Sales User', 'Sales Manager', 'Purchase User',
'Purchase Manager', 'Projects User', 'Manufacturing User', 'Manufacturing Manager',
'Support Team', 'Academics User', 'Physician', 'Healthcare Administrator', 'Laboratory User',
'Nursing User', 'Patient')
'Support Team')
if domain == "Healthcare":
user.add_roles('Physician', 'Healthcare Administrator', 'Laboratory User',
'Nursing User', 'Patient')
if domain == "Education":
user.add_roles('Academics User')
if not frappe.db.get_global('demo_hr_user'):
user = frappe.get_doc('User', 'CaitlinSnow@example.com')
@ -219,7 +226,7 @@ def setup_user_roles():
if not frappe.db.get_global('demo_manufacturing_user'):
user = frappe.get_doc('User', 'NeptuniaAquaria@example.com')
user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
user.add_roles('Manufacturing User', 'Stock Manager', 'Stock User', 'Purchase User', 'Accounts User')
update_employee_department(user.name, 'Production')
frappe.db.set_global('demo_manufacturing_user', user.name)
@ -241,11 +248,12 @@ def setup_user_roles():
update_employee_department(user.name, 'Management')
frappe.db.set_global('demo_projects_user', user.name)
if not frappe.db.get_global('demo_education_user'):
user = frappe.get_doc('User', 'ArthurCurry@example.com')
user.add_roles('Academics User')
update_employee_department(user.name, 'Management')
frappe.db.set_global('demo_education_user', user.name)
if domain == "Education":
if not frappe.db.get_global('demo_education_user'):
user = frappe.get_doc('User', 'ArthurCurry@example.com')
user.add_roles('Academics User')
update_employee_department(user.name, 'Management')
frappe.db.set_global('demo_education_user', user.name)
#Add Expense Approver
user = frappe.get_doc('User', 'ClarkKent@example.com')

View File

@ -73,14 +73,16 @@ def work():
make_pos_invoice()
def make_payment_entries(ref_doctype, report):
outstanding_invoices = list(set([r[3] for r in query_report.run(report, {
"report_date": frappe.flags.current_date,
"company": erpnext.get_default_company()
})["result"] if r[2]==ref_doctype]))
outstanding_invoices = frappe.get_all(ref_doctype, fields=["name"],
filters={
"company": erpnext.get_default_company(),
"outstanding_amount": (">", 0.0)
})
# make Payment Entry
for inv in outstanding_invoices[:random.randint(1, 2)]:
pe = get_payment_entry(ref_doctype, inv)
pe = get_payment_entry(ref_doctype, inv.name)
pe.posting_date = frappe.flags.current_date
pe.reference_no = random_string(6)
pe.reference_date = frappe.flags.current_date
@ -91,7 +93,7 @@ def make_payment_entries(ref_doctype, report):
# make payment via JV
for inv in outstanding_invoices[:1]:
jv = frappe.get_doc(get_payment_entry_against_invoice(ref_doctype, inv))
jv = frappe.get_doc(get_payment_entry_against_invoice(ref_doctype, inv.name))
jv.posting_date = frappe.flags.current_date
jv.cheque_no = random_string(6)
jv.cheque_date = frappe.flags.current_date

View File

@ -39,61 +39,4 @@ def make_project(current_date):
"doctype": "Project",
"project_name": "New Product Development " + current_date.strftime("%Y-%m-%d"),
})
project.set("tasks", [
{
"title": "Review Requirements",
"start_date": frappe.utils.add_days(current_date, 10),
"end_date": frappe.utils.add_days(current_date, 11)
},
{
"title": "Design Options",
"start_date": frappe.utils.add_days(current_date, 11),
"end_date": frappe.utils.add_days(current_date, 20)
},
{
"title": "Make Prototypes",
"start_date": frappe.utils.add_days(current_date, 20),
"end_date": frappe.utils.add_days(current_date, 30)
},
{
"title": "Customer Feedback on Prototypes",
"start_date": frappe.utils.add_days(current_date, 30),
"end_date": frappe.utils.add_days(current_date, 40)
},
{
"title": "Freeze Feature Set",
"start_date": frappe.utils.add_days(current_date, 40),
"end_date": frappe.utils.add_days(current_date, 45)
},
{
"title": "Testing",
"start_date": frappe.utils.add_days(current_date, 45),
"end_date": frappe.utils.add_days(current_date, 60)
},
{
"title": "Product Engineering",
"start_date": frappe.utils.add_days(current_date, 45),
"end_date": frappe.utils.add_days(current_date, 55)
},
{
"title": "Supplier Contracts",
"start_date": frappe.utils.add_days(current_date, 55),
"end_date": frappe.utils.add_days(current_date, 70)
},
{
"title": "Design and Build Fixtures",
"start_date": frappe.utils.add_days(current_date, 45),
"end_date": frappe.utils.add_days(current_date, 65)
},
{
"title": "Test Run",
"start_date": frappe.utils.add_days(current_date, 70),
"end_date": frappe.utils.add_days(current_date, 80)
},
{
"title": "Launch",
"start_date": frappe.utils.add_days(current_date, 80),
"end_date": frappe.utils.add_days(current_date, 90)
},
])
project.insert()

View File

@ -66,7 +66,7 @@ def make_opportunity(domain):
b = frappe.get_doc({
"doctype": "Opportunity",
"opportunity_from": "Customer",
"customer": get_random("Customer"),
"party_name": frappe.get_value("Customer", get_random("Customer"), 'name'),
"opportunity_type": "Sales",
"with_items": 1,
"transaction_date": frappe.flags.current_date,

View File

@ -27,3 +27,16 @@ frappe.ui.form.on('Student', {
}
}
});
frappe.ui.form.on('Student Guardian', {
guardians_add: function(frm){
frm.fields_dict['guardians'].grid.get_field('guardian').get_query = function(doc){
var guardian_list = [];
if(!doc.__islocal) guardian_list.push(doc.guardian);
$.each(doc.guardians, function(idx, val){
if (val.guardian) guardian_list.push(val.guardian);
});
return { filters: [['Guardian', 'name', 'not in', guardian_list]] };
};
}
});

View File

@ -29,7 +29,8 @@ def sync_sales_order(order, request_id=None):
validate_item(order, shopify_settings)
create_order(order, shopify_settings)
except Exception as e:
make_shopify_log(status="Error", message=e.message, exception=False)
make_shopify_log(status="Error", exception=e)
else:
make_shopify_log(status="Success")
@ -42,9 +43,9 @@ def prepare_sales_invoice(order, request_id=None):
sales_order = get_sales_order(cstr(order['id']))
if sales_order:
create_sales_invoice(order, shopify_settings, sales_order)
make_shopify_log(status="Success")
except Exception:
make_shopify_log(status="Error", exception=True)
make_shopify_log(status="Success")
except Exception as e:
make_shopify_log(status="Error", exception=e, rollback=True)
def prepare_delivery_note(order, request_id=None):
frappe.set_user('Administrator')
@ -56,8 +57,8 @@ def prepare_delivery_note(order, request_id=None):
if sales_order:
create_delivery_note(order, shopify_settings, sales_order)
make_shopify_log(status="Success")
except Exception:
make_shopify_log(status="Error", exception=True)
except Exception as e:
make_shopify_log(status="Error", exception=e, rollback=True)
def get_sales_order(shopify_order_id):
sales_order = frappe.db.get_value("Sales Order", filters={"shopify_order_id": shopify_order_id})
@ -97,7 +98,7 @@ def create_sales_order(shopify_order, shopify_settings, company=None):
message = 'Following items are exists in order but relevant record not found in Product master'
message += "\n" + ", ".join(product_not_exists)
make_shopify_log(status="Error", message=message, exception=True)
make_shopify_log(status="Error", exception=e, rollback=True)
return ''

View File

@ -12,23 +12,38 @@ class ShopifyLog(Document):
pass
def make_shopify_log(status="Queued", message=None, exception=False):
def make_shopify_log(status="Queued", exception=None, rollback=False):
# if name not provided by log calling method then fetch existing queued state log
make_new = False
if not frappe.flags.request_id:
return
make_new = True
log = frappe.get_doc("Shopify Log", frappe.flags.request_id)
if exception:
if rollback:
frappe.db.rollback()
log = frappe.get_doc({"doctype":"Shopify Log"}).insert(ignore_permissions=True)
log.message = message if message else ''
if make_new:
log = frappe.get_doc({"doctype":"Shopify Log"}).insert(ignore_permissions=True)
else:
log = log = frappe.get_doc("Shopify Log", frappe.flags.request_id)
log.message = get_message(exception)
log.traceback = frappe.get_traceback()
log.status = status
log.save(ignore_permissions=True)
frappe.db.commit()
def get_message(exception):
message = None
if hasattr(exception, 'message'):
message = exception.message
elif hasattr(exception, '__str__'):
message = exception.__str__()
else:
message = "Something went wrong while syncing"
return message
def dump_request_data(data, event="create/order"):
event_mapper = {
"orders/create": get_webhook_address(connector_name='shopify_connection', method="sync_sales_order", exclude_uri=True),
@ -43,11 +58,11 @@ def dump_request_data(data, event="create/order"):
}).insert(ignore_permissions=True)
frappe.db.commit()
frappe.enqueue(method=event_mapper[event], queue='short', timeout=300, is_async=True,
frappe.enqueue(method=event_mapper[event], queue='short', timeout=300, is_async=True,
**{"order": data, "request_id": log.name})
@frappe.whitelist()
def resync(method, name, request_data):
frappe.db.set_value("Shopify Log", name, "status", "Queued", update_modified=False)
frappe.enqueue(method=method, queue='short', timeout=300, is_async=True,
frappe.enqueue(method=method, queue='short', timeout=300, is_async=True,
**{"order": json.loads(request_data), "request_id": name})

View File

@ -30,13 +30,9 @@ class ShopifySettings(Document):
# url = get_shopify_url('admin/webhooks.json', self)
created_webhooks = [d.method for d in self.webhooks]
url = get_shopify_url('admin/api/2019-04/webhooks.json', self)
print('url', url)
for method in webhooks:
print('method', method)
session = get_request_session()
print('session', session)
try:
print(get_header(self))
d = session.post(url, data=json.dumps({
"webhook": {
"topic": method,
@ -44,11 +40,10 @@ class ShopifySettings(Document):
"format": "json"
}
}), headers=get_header(self))
print('d', d.json())
d.raise_for_status()
self.update_webhook_table(method, d.json())
except Exception as e:
make_shopify_log(status="Warning", message=e, exception=False)
make_shopify_log(status="Warning", exception=e, rollback=True)
def unregister_webhooks(self):
session = get_request_session()
@ -67,7 +62,6 @@ class ShopifySettings(Document):
self.remove(d)
def update_webhook_table(self, method, res):
print('update')
self.append("webhooks", {
"webhook_id": res['webhook']['id'],
"method": method
@ -75,7 +69,6 @@ class ShopifySettings(Document):
def get_shopify_url(path, settings):
if settings.app_type == "Private":
print(settings.api_key, settings.get_password('password'), settings.shopify_url, path)
return 'https://{}:{}@{}/{}'.format(settings.api_key, settings.get_password('password'), settings.shopify_url, path)
else:
return 'https://{}/{}'.format(settings.shopify_url, path)

View File

@ -283,7 +283,6 @@ scheduler_events = {
],
"daily": [
"erpnext.stock.reorder_item.reorder_item",
"erpnext.setup.doctype.email_digest.email_digest.send",
"erpnext.support.doctype.issue.issue.auto_close_tickets",
"erpnext.crm.doctype.opportunity.opportunity.auto_close_opportunity",
"erpnext.controllers.accounts_controller.update_invoice_status",
@ -306,6 +305,7 @@ scheduler_events = {
"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status"
],
"daily_long": [
"erpnext.setup.doctype.email_digest.email_digest.send",
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
"erpnext.hr.utils.generate_leave_encashment"

View File

@ -2,11 +2,11 @@ frappe.listview_settings['Expense Claim'] = {
add_fields: ["total_claimed_amount", "docstatus"],
get_indicator: function(doc) {
if(doc.status == "Paid") {
return [__("Paid"), "green", "status,=,'Paid'"];
return [__("Paid"), "green", "status,=,Paid"];
}else if(doc.status == "Unpaid") {
return [__("Unpaid"), "orange"];
return [__("Unpaid"), "orange", "status,=,Unpaid"];
} else if(doc.status == "Rejected") {
return [__("Rejected"), "grey"];
return [__("Rejected"), "grey", "status,=,Rejected"];
}
}
};

View File

@ -125,7 +125,7 @@ class LeaveApplication(Document):
status = "Half Day" if date == self.half_day_date else "On Leave"
attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee,
attenance_date = date, docstatus = ('!=', 2)))
attendance_date = date, docstatus = ('!=', 2)))
if attendance_name:
# update existing attendance, change absent to on leave
@ -503,14 +503,17 @@ def get_leave_allocation_records(employee, date, leave_type=None):
def get_pending_leaves_for_period(employee, leave_type, from_date, to_date):
''' Returns leaves that are pending approval '''
return frappe.db.get_value("Leave Application",
leaves = frappe.get_all("Leave Application",
filters={
"employee": employee,
"leave_type": leave_type,
"from_date": ("<=", from_date),
"to_date": (">=", to_date),
"status": "Open"
}, fieldname=['SUM(total_leave_days)']) or flt(0)
},
or_filters={
"from_date": ["between", (from_date, to_date)],
"to_date": ["between", (from_date, to_date)]
}, fields=['SUM(total_leave_days) as leaves'])[0]
return leaves['leaves'] if leaves['leaves'] else 0.0
def get_remaining_leaves(allocation, leaves_taken, date, expiry):
''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''

View File

@ -5,6 +5,12 @@ from frappe import _
def get_data():
return {
'fieldname': 'leave_application',
'transactions': [
{
'items': ['Attendance']
}
],
'reports': [
{
'label': _('Reports'),

View File

@ -72,7 +72,7 @@ class TestLeaveApplication(unittest.TestCase):
application.to_date = "2013-01-05"
return application
def test_attendance_creation(self):
def test_overwrite_attendance(self):
'''check attendance is automatically created on leave approval'''
make_allocation_record()
application = self.get_application(_test_records[0])
@ -82,7 +82,8 @@ class TestLeaveApplication(unittest.TestCase):
application.insert()
application.submit()
attendance = frappe.get_all('Attendance', ['name', 'status', 'attendance_date'], dict(leave_application = application.name))
attendance = frappe.get_all('Attendance', ['name', 'status', 'attendance_date'],
dict(attendance_date=('between', ['2018-01-01', '2018-01-03']), docstatus=("!=", 2)))
# attendance created for all 3 days
self.assertEqual(len(attendance), 3)
@ -95,20 +96,6 @@ class TestLeaveApplication(unittest.TestCase):
for d in ('2018-01-01', '2018-01-02', '2018-01-03'):
self.assertTrue(getdate(d) in dates)
def test_overwrite_attendance(self):
# employee marked as absent
doc = frappe.new_doc("Attendance")
doc.employee = '_T-Employee-00001'
doc.attendance_date = '2018-01-01'
doc.company = '_Test Company'
doc.status = 'Absent'
doc.flags.ignore_validate = True
doc.insert(ignore_permissions=True)
doc.submit()
# now check if the status has been updated
self.test_attendance_creation()
def test_block_list(self):
self._clear_roles()

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe, erpnext
import datetime, math
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words
from frappe.model.naming import make_autoname
from frappe import msgprint, _

View File

@ -75,7 +75,7 @@ def get_data(filters):
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
if (leave_approvers and len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
or ("HR Manager" in frappe.get_roles(user)):
row = frappe._dict({
'employee': employee.name,
@ -111,10 +111,10 @@ def get_conditions(filters):
def get_department_leave_approver_map(department=None):
conditions=''
if department:
conditions='and department_name = %(department)s or parent_department = %(department)s'%{'department': department}
conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
# get current department and all its child
department_list = frappe.db.sql_list(''' SELECT name FROM `tabDepartment` WHERE disabled=0 {0}'''.format(conditions)) #nosec
department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
# retrieve approvers list from current department and from its subsequent child departments
approver_list = frappe.get_all('Department Approver', filters={

View File

@ -20,6 +20,12 @@ frappe.ui.form.on('Maintenance Schedule', {
frm.set_value({transaction_date: frappe.datetime.get_today()});
}
},
refresh: function(frm) {
setTimeout(() => {
frm.toggle_display('generate_schedule', !(frm.is_new()));
frm.toggle_display('schedule', !(frm.is_new()));
},10);
},
customer: function(frm) {
erpnext.utils.get_party_details(frm)
},

View File

@ -150,7 +150,7 @@ class MaintenanceSchedule(TransactionBase):
elif not d.no_of_visits:
throw(_("Please mention no of visits required"))
elif not d.sales_person:
throw(_("Please select Incharge Person's name"))
throw(_("Please select a Sales Person for item: {0}".format(d.item_name)))
if getdate(d.start_date) >= getdate(d.end_date):
throw(_("Start date should be less than end date for Item {0}").format(d.item_code))

View File

@ -12,6 +12,7 @@ frappe.ui.form.on('Blanket Order', {
},
refresh: function(frm) {
erpnext.hide_company();
if (frm.doc.customer && frm.doc.docstatus === 1) {
frm.add_custom_button(__('View Orders'), function() {
frappe.set_route('List', 'Sales Order', {blanket_order: frm.doc.name});
@ -51,11 +52,19 @@ frappe.ui.form.on('Blanket Order', {
set_tc_name_filter: function(frm) {
if (frm.doc.blanket_order_type === 'Selling') {
frm.set_df_property("customer","reqd", 1);
frm.set_df_property("supplier","reqd", 0);
frm.set_value("supplier", "");
frm.set_query("tc_name", function() {
return { filters: { selling: 1 } };
});
}
if (frm.doc.blanket_order_type === 'Purchasing') {
frm.set_df_property("supplier","reqd", 1);
frm.set_df_property("customer","reqd", 0);
frm.set_value("customer", "");
frm.set_query("tc_name", function() {
return { filters: { buying: 1 } };
});

View File

@ -88,7 +88,8 @@
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company"
"options": "Company",
"reqd": 1
},
{
"fieldname": "section_break_12",
@ -128,7 +129,7 @@
}
],
"is_submittable": 1,
"modified": "2019-06-19 11:59:09.279607",
"modified": "2019-10-16 13:38:32.302316",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Blanket Order",

View File

@ -4,13 +4,21 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import _
from frappe.utils import flt, getdate
from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
from erpnext.stock.doctype.item.item import get_item_defaults
class BlanketOrder(Document):
def validate(self):
self.validate_dates()
def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(_("From date cannot be greater than To date"))
def update_ordered_qty(self):
ref_doctype = "Sales Order" if self.blanket_order_type == "Selling" else "Purchase Order"
item_ordered_qty = frappe._dict(frappe.db.sql("""

View File

@ -35,12 +35,15 @@ class BOM(WebsiteGenerator):
# name can be BOM/ITEM/001, BOM/ITEM/001-1, BOM-ITEM-001, BOM-ITEM-001-1
# split by item
names = [name.split(self.item)[-1][1:] for name in names]
names = [name.split(self.item, 1) for name in names]
names = [d[-1][1:] for d in filter(lambda x: len(x) > 1 and x[-1], names)]
# split by (-) if cancelled
names = [cint(name.split('-')[-1]) for name in names]
idx = max(names) + 1
if names:
names = [cint(name.split('-')[-1]) for name in names]
idx = max(names) + 1
else:
idx = 1
else:
idx = 1
@ -289,7 +292,8 @@ class BOM(WebsiteGenerator):
return valuation_rate
def manage_default_bom(self):
""" Uncheck others if current one is selected as default,
""" Uncheck others if current one is selected as default or
check the current one as default if it the only bom for the selected item,
update default bom in item master
"""
if self.is_default and self.is_active:
@ -298,6 +302,9 @@ class BOM(WebsiteGenerator):
item = frappe.get_doc("Item", self.item)
if item.default_bom != self.name:
frappe.db.set_value('Item', self.item, 'default_bom', self.name)
elif not frappe.db.exists(dict(doctype='BOM', docstatus=1, item=self.item, is_default=1)) \
and self.is_active:
frappe.db.set(self, "is_default", 1)
else:
frappe.db.set(self, "is_default", 0)
item = frappe.get_doc("Item", self.item)

View File

@ -103,7 +103,7 @@ frappe.ui.form.on('Production Plan', {
${__('Reserved Qty for Production: Raw materials quantity to make manufacturing items.')}
</li>
<li>
${__('Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.')}
${__('Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.')}
</li>
</ul>
</div>

View File

@ -622,7 +622,7 @@ def get_items_for_material_requests(doc, ignore_existing_ordered_qty=None):
for data in po_items:
planned_qty = data.get('required_qty') or data.get('planned_qty')
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty') or ignore_existing_ordered_qty
warehouse = data.get("warehouse") or warehouse
warehouse = warehouse or data.get("warehouse")
item_details = {}
if data.get("bom") or data.get("bom_no"):

View File

@ -11,9 +11,11 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import get_sa
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestProductionPlan(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
for item in ['Test Production Item 1', 'Subassembly Item 1',
'Raw Material Item 1', 'Raw Material Item 2']:
create_item(item, valuation_rate=100)

View File

@ -17,11 +17,11 @@ from erpnext.manufacturing.doctype.production_plan.test_production_plan import m
class TestWorkOrder(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
self.warehouse = '_Test Warehouse 2 - _TC'
self.item = '_Test Item'
def check_planned_qty(self):
set_perpetual_inventory(0)
planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item",
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0

View File

@ -342,7 +342,7 @@ frappe.ui.form.on("Work Order", {
},
project: function(frm) {
if(!erpnext.in_production_item_onchange) {
if(!erpnext.in_production_item_onchange && !frm.doc.bom_no) {
frm.trigger("production_item");
}
},

View File

@ -640,3 +640,4 @@ erpnext.patches.v12_0.create_default_energy_point_rules
erpnext.patches.v12_0.set_produced_qty_field_in_sales_order_for_work_order
erpnext.patches.v12_0.generate_leave_ledger_entries
erpnext.patches.v12_0.set_default_shopify_app_type
erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings

View File

@ -4,7 +4,7 @@ from frappe.model.utils.rename_field import rename_field
def execute():
frappe.reload_doc('desk', 'doctype', 'auto_repeat')
frappe.reload_doc('automation', 'doctype', 'auto_repeat')
doctypes_to_rename = {
'accounts': ['Journal Entry', 'Payment Entry', 'Purchase Invoice', 'Sales Invoice'],
@ -41,4 +41,4 @@ def drop_columns_from_subscription():
if field in frappe.db.get_table_columns("Subscription"):
fields_to_drop['Subscription'].append(field)
frappe.model.delete_fields(fields_to_drop, delete=1)
frappe.model.delete_fields(fields_to_drop, delete=1)

View File

@ -0,0 +1,5 @@
import frappe
def execute():
frappe.db.sql("""UPDATE `tabUser` SET `home_settings` = REPLACE(`home_settings`, 'Accounting', 'Accounts')""")
frappe.cache().delete_key('home_settings')

View File

@ -11,6 +11,9 @@ frappe.ui.form.on("Project", {
// add a new row and set the project
let time_log = frappe.model.get_new_doc('Timesheet Detail');
time_log.project = frm.doc.name;
time_log.parent = new_doc.name;
time_log.parentfield = 'time_logs';
time_log.parenttype = 'Timesheet';
new_doc.time_logs = [time_log];
frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);

View File

@ -353,17 +353,35 @@ def get_events(start, end, filters=None):
def get_timesheets_list(doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified"):
user = frappe.session.user
# find customer name from contact.
customer = frappe.db.sql('''SELECT dl.link_name FROM `tabContact` AS c inner join \
`tabDynamic Link` AS dl ON c.first_name=dl.link_name WHERE c.email_id=%s''',user)
customer = ''
timesheets = []
contact = frappe.db.exists('Contact', {'user': user})
if contact:
# find customer
contact = frappe.get_doc('Contact', contact)
customer = contact.get_link_for('Customer')
if customer:
# find list of Sales Invoice for made for customer.
sales_invoice = frappe.db.sql('''SELECT name FROM `tabSales Invoice` WHERE customer = %s''',customer)
sales_invoices = [d.name for d in frappe.get_all('Sales Invoice', filters={'customer': customer})] or [None]
projects = [d.name for d in frappe.get_all('Project', filters={'customer': customer})]
# Return timesheet related data to web portal.
return frappe. db.sql('''SELECT ts.name, tsd.activity_type, ts.status, ts.total_billable_hours, \
tsd.sales_invoice, tsd.project FROM `tabTimesheet` AS ts inner join `tabTimesheet Detail` \
AS tsd ON tsd.parent = ts.name where tsd.sales_invoice IN %s order by\
end_date asc limit {0} , {1}'''.format(limit_start, limit_page_length), [sales_invoice], as_dict = True)
timesheets = frappe.db.sql('''
SELECT
ts.name, tsd.activity_type, ts.status, ts.total_billable_hours,
COALESCE(ts.sales_invoice, tsd.sales_invoice) AS sales_invoice, tsd.project
FROM `tabTimesheet` ts, `tabTimesheet Detail` tsd
WHERE tsd.parent = ts.name AND
(
ts.sales_invoice IN %(sales_invoices)s OR
tsd.sales_invoice IN %(sales_invoices)s OR
tsd.project IN %(projects)s
)
ORDER BY `end_date` ASC
LIMIT {0}, {1}
'''.format(limit_start, limit_page_length), dict(sales_invoices=sales_invoices, projects=projects), as_dict=True) #nosec
return timesheets
def get_list_context(context=None):
return {

View File

@ -1653,6 +1653,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
'item_code': item.item_code,
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate(),
}
if (doc.is_return) {
filters["is_return"] = 1;
}
if (item.warehouse) filters["warehouse"] = item.warehouse;
return {

View File

@ -31,8 +31,8 @@
"contact_phone",
"contact_mobile",
"contact_email",
"company_address_display",
"company_address",
"company_address_display",
"col_break46",
"shipping_address_name",
"shipping_address",
@ -342,12 +342,13 @@
{
"fieldname": "company_address_display",
"fieldtype": "Small Text",
"label": "Company Address",
"read_only": 1
},
{
"fieldname": "company_address",
"fieldtype": "Link",
"label": "Company Address",
"label": "Company Address Name",
"options": "Address"
},
{
@ -682,10 +683,10 @@
"label": "Additional Discount and Coupon Code"
},
{
"fieldname": "coupon_code",
"fieldtype": "Link",
"label": "Coupon Code",
"options": "Coupon Code"
"fieldname": "coupon_code",
"fieldtype": "Link",
"label": "Coupon Code",
"options": "Coupon Code"
},
{
"default": "Grand Total",
@ -1185,6 +1186,7 @@
"default": "0",
"fieldname": "skip_delivery_note",
"fieldtype": "Check",
"hidden": 1,
"label": "Skip Delivery Note",
"print_hide": 1
}
@ -1192,7 +1194,7 @@
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
"modified": "2019-10-14 08:46:07.540565",
"modified": "2019-10-23 14:26:42.767189",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
@ -1269,4 +1271,4 @@
"title_field": "title",
"track_changes": 1,
"track_seen": 1
}
}

View File

@ -205,7 +205,7 @@ class SalesOrder(SellingController):
if self.coupon_code:
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
update_coupon_code_count(self.coupon_code,'cancelled')
def update_project(self):
if frappe.db.get_single_value('Selling Settings', 'sales_update_frequency') != "Each Transaction":
return
@ -661,12 +661,15 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
if source_parent.project:
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
if not target.cost_center and target.item_code:
if target.item_code:
item = get_item_defaults(target.item_code, source_parent.company)
item_group = get_item_group_defaults(target.item_code, source_parent.company)
target.cost_center = item.get("selling_cost_center") \
cost_center = item.get("selling_cost_center") \
or item_group.get("selling_cost_center")
if cost_center:
target.cost_center = cost_center
doclist = get_mapped_doc("Sales Order", source_name, {
"Sales Order": {
"doctype": "Sales Invoice",

View File

@ -33,6 +33,10 @@ class Company(NestedSet):
return exists
def validate(self):
self.update_default_account = False
if self.is_new():
self.update_default_account = True
self.validate_abbr()
self.validate_default_accounts()
self.validate_currency()
@ -203,8 +207,8 @@ class Company(NestedSet):
"default_expense_account": "Cost of Goods Sold"
})
for default_account in default_accounts:
if self.is_new() or frappe.flags.in_test:
if self.update_default_account or frappe.flags.in_test:
for default_account in default_accounts:
self._set_default_account(default_account, default_accounts.get(default_account))
if not self.default_income_account:

View File

@ -22,7 +22,7 @@ class TestCompany(unittest.TestCase):
company.create_chart_of_accounts_based_on = "Existing Company"
company.existing_company = "_Test Company"
company.save()
expected_results = {
"Debtors - CFEC": {
"account_type": "Receivable",
@ -37,7 +37,7 @@ class TestCompany(unittest.TestCase):
"parent_account": "Cash In Hand - CFEC"
}
}
for account, acc_property in expected_results.items():
acc = frappe.get_doc("Account", account)
for prop, val in acc_property.items():
@ -50,14 +50,14 @@ class TestCompany(unittest.TestCase):
countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France",
"Guatemala", "Indonesia", "Italy", "Mexico", "Nicaragua", "Netherlands", "Singapore",
"Brazil", "Argentina", "Hungary", "Taiwan"]
for country in countries:
templates = get_charts_for_country(country)
if len(templates) != 1 and "Standard" in templates:
templates.remove("Standard")
self.assertTrue(templates)
for template in templates:
try:
company = frappe.new_doc("Company")
@ -67,11 +67,11 @@ class TestCompany(unittest.TestCase):
company.create_chart_of_accounts_based_on = "Standard Template"
company.chart_of_accounts = template
company.save()
account_types = ["Cost of Goods Sold", "Depreciation",
"Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable",
account_types = ["Cost of Goods Sold", "Depreciation",
"Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable",
"Stock Adjustment", "Stock Received But Not Billed", "Bank", "Cash", "Stock"]
for account_type in account_types:
filters = {
"company": template,

View File

@ -62,5 +62,16 @@
"domain": "Manufacturing",
"chart_of_accounts": "Standard",
"default_holiday_list": "_Test Holiday List"
},
{
"abbr": "TCP1",
"company_name": "_Test Company with perpetual inventory",
"country": "India",
"default_currency": "INR",
"doctype": "Company",
"domain": "Manufacturing",
"chart_of_accounts": "Standard",
"enable_perpetual_inventory": 1,
"default_holiday_list": "_Test Holiday List"
}
]

View File

@ -66,7 +66,7 @@ def place_order():
from erpnext.selling.doctype.quotation.quotation import _make_sales_order
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
if not cart_settings.allow_items_not_in_stock:
if not cint(cart_settings.allow_items_not_in_stock):
for item in sales_order.get("items"):
item.reserved_warehouse, is_stock_item = frappe.db.get_value("Item",
item.item_code, ["website_warehouse", "is_stock_item"])

View File

@ -21,7 +21,7 @@ def get_warehouse_account_map(company=None):
filters['company'] = company
for d in frappe.get_all('Warehouse',
fields = ["name", "account", "parent_warehouse", "company"],
fields = ["name", "account", "parent_warehouse", "company", "is_group"],
filters = filters,
order_by="lft, rgt"):
if not d.account:

View File

@ -8,10 +8,13 @@ import unittest
from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no
from frappe.utils import cint
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestBatch(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
def test_item_has_batch_enabled(self):
self.assertRaises(ValidationError, frappe.get_doc({
"doctype": "Batch",

View File

@ -6,9 +6,9 @@ frappe.listview_settings['Delivery Note'] = {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if (doc.status === "Closed") {
return [__("Closed"), "green", "status,=,Closed"];
} else if (doc.grand_total !== 0 && flt(doc.per_billed, 2) < 100) {
} else if (flt(doc.per_billed, 2) < 100) {
return [__("To Bill"), "orange", "per_billed,<,100"];
} else if (doc.grand_total === 0 || flt(doc.per_billed, 2) == 100) {
} else if (flt(doc.per_billed, 2) == 100) {
return [__("Completed"), "green", "per_billed,=,100"];
}
},

View File

@ -20,18 +20,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \
import create_stock_reconciliation, set_valuation_method
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
class TestDeliveryNote(unittest.TestCase):
def tearDown(self):
target_warehouse = "_Test Warehouse 1 - _TC"
company = "_Test Company"
if not frappe.db.exists("Account", target_warehouse):
parent_account = frappe.db.get_value('Account',
{'company': company, 'is_group':1, 'account_type': 'Stock'},'name')
account = create_account(account_name="_Test Warehouse 1", \
account_type="Stock", parent_account= parent_account, company=company)
frappe.db.set_value('Warehouse', target_warehouse, 'account', account)
def setUp(self):
set_perpetual_inventory(0)
def test_over_billing_against_dn(self):
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
@ -68,17 +61,16 @@ class TestDeliveryNote(unittest.TestCase):
self.assertFalse(get_gl_entries("Delivery Note", dn.name))
def test_delivery_note_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100)
make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
prev_bal = get_balance_on(stock_in_hand_account)
dn = create_delivery_note()
dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries)
@ -88,7 +80,7 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = {
stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [stock_value_difference, 0.0]
"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
@ -98,7 +90,7 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(bal, prev_bal - stock_value_difference)
# back dated incoming entry
make_stock_entry(posting_date=add_days(nowdate(), -2), target="_Test Warehouse - _TC",
make_stock_entry(posting_date=add_days(nowdate(), -2), target="Stores - TCP1",
qty=5, basic_rate=100)
gl_entries = get_gl_entries("Delivery Note", dn.name)
@ -109,27 +101,25 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = {
stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [stock_value_difference, 0.0]
"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.name))
set_perpetual_inventory(0, company)
def test_delivery_note_gl_entry_packing_item(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, basic_rate=100)
make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=10, basic_rate=100)
make_stock_entry(item_code="_Test Item Home Desktop 100",
target="_Test Warehouse - _TC", qty=10, basic_rate=100)
target="Stores - TCP1", qty=10, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
prev_bal = get_balance_on(stock_in_hand_account)
dn = create_delivery_note(item_code="_Test Product Bundle Item")
dn = create_delivery_note(item_code="_Test Product Bundle Item", company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"},
@ -146,7 +136,7 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = {
stock_in_hand_account: [0.0, stock_value_diff],
"Cost of Goods Sold - _TC": [stock_value_diff, 0.0]
"Cost of Goods Sold - TCP1": [stock_value_diff, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
@ -158,8 +148,6 @@ class TestDeliveryNote(unittest.TestCase):
dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.name))
set_perpetual_inventory(0, company)
def test_serialized(self):
se = make_serialized_item()
serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
@ -218,16 +206,16 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(cstr(serial_no.get(field)), value)
def test_sales_return_for_non_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100)
actual_qty_0 = get_qty_after_transaction()
actual_qty_0 = get_qty_after_transaction(warehouse="Stores - TCP1")
dn = create_delivery_note(qty=5, rate=500)
dn = create_delivery_note(qty=5, rate=500, warehouse="Stores - TCP1", company=company,
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
actual_qty_1 = get_qty_after_transaction()
actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_0 - 5, actual_qty_1)
# outgoing_rate
@ -235,9 +223,10 @@ class TestDeliveryNote(unittest.TestCase):
"voucher_no": dn.name}, "stock_value_difference") / 5
# return entry
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500)
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500,
company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
actual_qty_2 = get_qty_after_transaction()
actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_1 + 2, actual_qty_2)
@ -246,27 +235,29 @@ class TestDeliveryNote(unittest.TestCase):
["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse)
stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse)
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note",
"voucher_no": dn1.name, "account": stock_in_hand_account}, "debit")
self.assertEqual(gle_warehouse_amount, stock_value_difference)
set_perpetual_inventory(0, company)
def test_return_single_item_from_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100)
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
qty=50, rate=100)
create_stock_reconciliation(item_code="_Test Item",
warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500)
dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500,
company=company, warehouse="Stores - TCP1",
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# Qty after delivery
actual_qty_1 = get_qty_after_transaction()
actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_1, 25)
# outgoing_rate
@ -274,10 +265,12 @@ class TestDeliveryNote(unittest.TestCase):
"voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference") / 25
# return 'test item' from packed items
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500)
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500,
company=company, warehouse="Stores - TCP1",
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return
actual_qty_2 = get_qty_after_transaction()
actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_2, 35)
# Check incoming rate for return entry
@ -286,7 +279,7 @@ class TestDeliveryNote(unittest.TestCase):
["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse)
stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse)
# Check gl entry for warehouse
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note",
@ -294,33 +287,33 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, stock_value_difference)
set_perpetual_inventory(0, company)
def test_return_entire_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
create_stock_reconciliation(item_code="_Test Item",
target="_Test Warehouse - _TC", qty=50, rate=100)
warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
target="_Test Warehouse - _TC", qty=50, rate=100)
warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
actual_qty = get_qty_after_transaction()
actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 50)
dn = create_delivery_note(item_code="_Test Product Bundle Item",
qty=5, rate=500)
qty=5, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return
actual_qty = get_qty_after_transaction()
actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 25)
# return bundled item
dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1,
return_against=dn.name, qty=-2, rate=500)
return_against=dn.name, qty=-2, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return
actual_qty = get_qty_after_transaction()
actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 35)
# Check incoming rate for return entry
@ -337,8 +330,6 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, 1400)
set_perpetual_inventory(0, company)
def test_return_for_serialized_items(self):
se = make_serialized_item()
serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
@ -375,56 +366,44 @@ class TestDeliveryNote(unittest.TestCase):
})
def test_delivery_of_bundled_items_to_target_warehouse(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_valuation_method("_Test Item", "FIFO")
set_valuation_method("_Test Item Home Desktop 100", "FIFO")
for warehouse in ("_Test Warehouse - _TC", "_Test Warehouse 1 - _TC"):
create_stock_reconciliation(item_code="_Test Item", target=warehouse,
qty=100, rate=100)
create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
target=warehouse, qty=100, rate=100)
target_warehouse=get_warehouse(company=company, abbr="TCP1",
warehouse_name="_Test Customer Warehouse").name
for warehouse in ("Stores - TCP1", target_warehouse):
create_stock_reconciliation(item_code="_Test Item", warehouse=warehouse, company = company,
expense_account = "Stock Adjustment - TCP1", qty=500, rate=100)
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company,
expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100)
opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC")
dn = create_delivery_note(item_code="_Test Product Bundle Item",
qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC", do_not_submit=True)
company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1',
expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500,
warehouse="Stores - TCP1", target_warehouse=target_warehouse)
dn.submit()
# qty after delivery
actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse - _TC")
self.assertEqual(actual_qty, 75)
actual_qty_at_source = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_at_source, 475)
actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC")
self.assertEqual(actual_qty, opening_qty_test_warehouse_1 + 25)
actual_qty_at_target = get_qty_after_transaction(warehouse=target_warehouse)
self.assertEqual(actual_qty_at_target, 525)
# stock value diff for source warehouse
# for "_Test Item"
# stock value diff for source warehouse for "_Test Item"
stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
"item_code": "_Test Item", "warehouse": "Stores - TCP1"},
"stock_value_difference")
# stock value diff for target warehouse
stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC"},
"stock_value_difference")
self.assertEqual(abs(stock_value_difference), stock_value_difference1)
# for "_Test Item Home Desktop 100"
stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC"},
"stock_value_difference")
# stock value diff for target warehouse
stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC"},
"item_code": "_Test Item", "warehouse": target_warehouse},
"stock_value_difference")
self.assertEqual(abs(stock_value_difference), stock_value_difference1)
@ -435,21 +414,20 @@ class TestDeliveryNote(unittest.TestCase):
stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference)
from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s
and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0])
and warehouse='Stores - TCP1'""", dn.name)[0][0])
expected_values = {
"Stock In Hand - _TC": [0.0, stock_value_difference],
"_Test Warehouse 1 - _TC": [stock_value_difference, 0.0]
"Stock In Hand - TCP1": [0.0, stock_value_difference],
target_warehouse: [stock_value_difference, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
set_perpetual_inventory(0, company)
def test_closed_delivery_note(self):
from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status
dn = create_delivery_note(do_not_submit=True)
dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True)
dn.submit()
update_delivery_note_status(dn.name, "Closed")
@ -574,24 +552,23 @@ class TestDeliveryNote(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
cost_center = "_Test Cost Center for BS Account - TCP1"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100)
make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
dn = create_delivery_note(cost_center=cost_center)
stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', expense_account = "Cost of Goods Sold - TCP1", cost_center=cost_center)
gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries)
expected_values = {
"Cost of Goods Sold - _TC": {
"Cost of Goods Sold - TCP1": {
"cost_center": cost_center
},
stock_in_hand_account: {
@ -600,8 +577,6 @@ class TestDeliveryNote(unittest.TestCase):
}
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
@ -609,23 +584,22 @@ class TestDeliveryNote(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
cost_center = "_Test Cost Center - _TC"
cost_center = "Main - TCP1"
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100)
make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
dn = create_delivery_note()
stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries)
expected_values = {
"Cost of Goods Sold - _TC": {
"Cost of Goods Sold - TCP1": {
"cost_center": cost_center
},
stock_in_hand_account: {
@ -635,8 +609,6 @@ class TestDeliveryNote(unittest.TestCase):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
def test_make_sales_invoice_from_dn_for_returned_qty(self):
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
@ -702,7 +674,7 @@ def create_delivery_note(**args):
"rate": args.rate or 100,
"conversion_factor": 1.0,
"allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1,
"expense_account": "Cost of Goods Sold - _TC",
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no,
"target_warehouse": args.target_warehouse

View File

@ -12,9 +12,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_rm_stock_entry
import unittest
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestItemAlternative(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
make_items()
def test_alternative_item_for_subcontract_rm(self):

View File

@ -14,15 +14,15 @@ from erpnext.accounts.doctype.account.test_account import get_inventory_account
class TestLandedCostVoucher(unittest.TestCase):
def test_landed_cost_voucher(self):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
set_perpetual_inventory(1)
pr = frappe.copy_doc(pr_test_records[0])
pr.submit()
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
last_sle = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pr.doctype,
"voucher_no": pr.name,
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
"warehouse": "Stores - TCP1"
},
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -35,7 +35,7 @@ class TestLandedCostVoucher(unittest.TestCase):
"voucher_type": pr.doctype,
"voucher_no": pr.name,
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
"warehouse": "Stores - TCP1"
},
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -48,55 +48,56 @@ class TestLandedCostVoucher(unittest.TestCase):
self.assertTrue(gl_entries)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse)
if stock_in_hand_account == fixed_asset_account:
expected_values = {
stock_in_hand_account: [800.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 300.0]
"Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - TCP1": [0.0, 300.0]
}
else:
expected_values = {
stock_in_hand_account: [400.0, 0.0],
fixed_asset_account: [400.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 300.0]
"Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - TCP1": [0.0, 300.0]
}
for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_landed_cost_voucher_against_purchase_invoice(self):
set_perpetual_inventory(1)
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime())
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1",
company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1",
warehouse= "Stores - TCP1", cost_center = "Main - TCP1",
expense_account ="_Test Account Cost for Goods Sold - TCP1")
last_sle = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pi.doctype,
"voucher_no": pi.name,
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
"warehouse": "Stores - TCP1"
},
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
submit_landed_cost_voucher("Purchase Invoice", pi.name)
pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
"landed_cost_voucher_amount")
self.assertEqual(pi_lc_value, 50.0)
last_sle_after_landed_cost = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pi.doctype,
"voucher_no": pi.name,
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
"warehouse": "Stores - TCP1"
},
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -111,21 +112,21 @@ class TestLandedCostVoucher(unittest.TestCase):
expected_values = {
stock_in_hand_account: [300.0, 0.0],
"Creditors - _TC": [0.0, 250.0],
"Expenses Included In Valuation - _TC": [0.0, 50.0]
"Creditors - TCP1": [0.0, 250.0],
"Expenses Included In Valuation - TCP1": [0.0, 50.0]
}
for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_landed_cost_voucher_for_serialized_item(self):
set_perpetual_inventory(1)
frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')")
pr = frappe.copy_doc(pr_test_records[0])
def test_landed_cost_voucher_for_serialized_item(self):
frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')")
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True,
get_taxes_and_charges = True, do_not_submit = True)
pr.items[0].item_code = "_Test Serialized Item"
pr.items[0].serial_no = "SN001\nSN002\nSN003\nSN004\nSN005"
pr.submit()
@ -138,39 +139,36 @@ class TestLandedCostVoucher(unittest.TestCase):
["warehouse", "purchase_rate"], as_dict=1)
self.assertEqual(serial_no.purchase_rate - serial_no_rate, 5.0)
self.assertEqual(serial_no.warehouse, "_Test Warehouse - _TC")
self.assertEqual(serial_no.warehouse, "Stores - TCP1")
set_perpetual_inventory(0)
def test_landed_cost_voucher_for_odd_numbers (self):
set_perpetual_inventory(1)
pr = make_purchase_receipt(do_not_save=True)
pr.items[0].cost_center = "_Test Company - _TC"
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", do_not_save=True)
pr.items[0].cost_center = "Main - TCP1"
for x in range(2):
pr.append("items", {
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC",
"cost_center": "_Test Company - _TC",
"warehouse": "Stores - TCP1",
"cost_center": "Main - TCP1",
"qty": 5,
"rate": 50
})
pr.submit()
lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, 123.22)
self.assertEqual(lcv.items[0].applicable_charges, 41.07)
self.assertEqual(lcv.items[2].applicable_charges, 41.08)
set_perpetual_inventory(0)
self.assertEqual(lcv.items[2].applicable_charges, 41.08)
def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=50):
ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
lcv = frappe.new_doc("Landed Cost Voucher")
lcv.company = "_Test Company"
lcv.distribute_charges_based_on = 'Amount'
lcv.set("purchase_receipts", [{
"receipt_document_type": receipt_document_type,
"receipt_document": receipt_document,
@ -178,7 +176,7 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=
"posting_date": ref_doc.posting_date,
"grand_total": ref_doc.base_grand_total
}])
lcv.set("taxes", [{
"description": "Insurance Charges",
"account": "_Test Account Insurance Charges - _TC",
@ -186,13 +184,13 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=
}])
lcv.insert()
distribute_landed_cost_on_items(lcv)
lcv.submit()
return lcv
def distribute_landed_cost_on_items(lcv):
based_on = lcv.distribute_charges_based_on.lower()
total = sum([flt(d.get(based_on)) for d in lcv.get("items")])

View File

@ -14,6 +14,7 @@ from erpnext.stock.doctype.item.test_item import make_item
from six import iteritems
class TestPurchaseReceipt(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
def test_make_purchase_invoice(self):
@ -32,7 +33,6 @@ class TestPurchaseReceipt(unittest.TestCase):
def test_purchase_receipt_no_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(0, company)
existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "stock_value")
@ -52,33 +52,29 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
def test_purchase_receipt_gl_entry(self):
pr = frappe.copy_doc(test_records[0])
set_perpetual_inventory(1, pr.company)
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pr.insert()
pr.submit()
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse)
stock_in_hand_account = get_inventory_account(pr.company, pr.items[0].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.items[1].warehouse)
if stock_in_hand_account == fixed_asset_account:
expected_values = {
stock_in_hand_account: [750.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 250.0]
"Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - TCP1": [0.0, 250.0]
}
else:
expected_values = {
stock_in_hand_account: [375.0, 0.0],
fixed_asset_account: [375.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 250.0]
"Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - TCP1": [0.0, 250.0]
}
for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit)
@ -86,8 +82,6 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.cancel()
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
set_perpetual_inventory(0, pr.company)
def test_subcontracting(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@ -132,11 +126,10 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.get("items")[0].rejected_warehouse)
def test_purchase_return(self):
set_perpetual_inventory()
pr = make_purchase_receipt()
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-2)
return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-2)
# check sle
outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
@ -153,28 +146,28 @@ class TestPurchaseReceipt(unittest.TestCase):
expected_values = {
stock_in_hand_account: [0.0, 100.0],
"Stock Received But Not Billed - _TC": [100.0, 0.0],
"Stock Received But Not Billed - TCP1": [100.0, 0.0],
}
for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_purchase_return_for_rejected_qty(self):
set_perpetual_inventory()
from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
pr = make_purchase_receipt(received_qty=4, qty=2)
rejected_warehouse=get_warehouse(company = "_Test Company with perpetual inventory", abbr = " - TCP1", warehouse_name = "_Test Rejected Warehouse").name
print(rejected_warehouse)
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", received_qty=4, qty=2, rejected_warehouse=rejected_warehouse)
return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, received_qty = -4, qty=-2)
return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, received_qty = -4, qty=-2, rejected_warehouse=rejected_warehouse)
actual_qty = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
"voucher_no": return_pr.name, 'warehouse': return_pr.items[0].rejected_warehouse}, "actual_qty")
self.assertEqual(actual_qty, -2)
set_perpetual_inventory(0)
def test_purchase_return_for_serialized_items(self):
def _check_serial_no_values(serial_no, field_values):
@ -337,7 +330,6 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.cancel()
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
self.assertEquals(len(serial_nos), 0)
#frappe.db.sql("delete from `tabLocation")
frappe.db.sql("delete from `tabAsset`")
def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self):
@ -345,8 +337,8 @@ class TestPurchaseReceipt(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
cost_center = "_Test Cost Center for BS Account - TCP1"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({
@ -354,8 +346,7 @@ class TestPurchaseReceipt(unittest.TestCase):
'location_name': 'Test Location'
}).insert()
set_perpetual_inventory(1, "_Test Company")
pr = make_purchase_receipt(cost_center=cost_center)
pr = make_purchase_receipt(cost_center=cost_center, company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@ -363,7 +354,7 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertTrue(gl_entries)
expected_values = {
"Stock Received But Not Billed - _TC": {
"Stock Received But Not Billed - TCP1": {
"cost_center": cost_center
},
stock_in_hand_account: {
@ -373,7 +364,6 @@ class TestPurchaseReceipt(unittest.TestCase):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
@ -387,9 +377,7 @@ class TestPurchaseReceipt(unittest.TestCase):
'doctype': 'Location',
'location_name': 'Test Location'
}).insert()
set_perpetual_inventory(1, "_Test Company")
pr = make_purchase_receipt()
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@ -397,7 +385,7 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertTrue(gl_entries)
expected_values = {
"Stock Received But Not Billed - _TC": {
"Stock Received But Not Billed - TCP1": {
"cost_center": None
},
stock_in_hand_account: {
@ -407,8 +395,6 @@ class TestPurchaseReceipt(unittest.TestCase):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
def test_make_purchase_invoice_from_pr_for_returned_qty(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po
@ -452,6 +438,78 @@ def get_gl_entries(voucher_type, voucher_no):
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""", (voucher_type, voucher_no), as_dict=1)
def get_taxes(**args):
args = frappe._dict(args)
return [{'account_head': '_Test Account Shipping Charges - TCP1',
'add_deduct_tax': 'Add',
'category': 'Valuation and Total',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'Shipping Charges',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 100.0,
'tax_amount': 100.0},
{'account_head': '_Test Account VAT - TCP1',
'add_deduct_tax': 'Add',
'category': 'Total',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'VAT',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 120.0,
'tax_amount': 120.0},
{'account_head': '_Test Account Customs Duty - TCP1',
'add_deduct_tax': 'Add',
'category': 'Valuation',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'Customs Duty',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 150.0,
'tax_amount': 150.0}]
def get_items(**args):
args = frappe._dict(args)
return [{
"base_amount": 250.0,
"conversion_factor": 1.0,
"description": "_Test Item",
"doctype": "Purchase Receipt Item",
"item_code": "_Test Item",
"item_name": "_Test Item",
"parentfield": "items",
"qty": 5.0,
"rate": 50.0,
"received_qty": 5.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"cost_center": args.cost_center or "Main - _TC"
},
{
"base_amount": 250.0,
"conversion_factor": 1.0,
"description": "_Test Item Home Desktop 100",
"doctype": "Purchase Receipt Item",
"item_code": "_Test Item Home Desktop 100",
"item_name": "_Test Item Home Desktop 100",
"parentfield": "items",
"qty": 5.0,
"rate": 50.0,
"received_qty": 5.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": args.warehouse or "_Test Warehouse 1 - _TC",
"cost_center": args.cost_center or "Main - _TC"
}]
def make_purchase_receipt(**args):
if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({
@ -468,7 +526,7 @@ def make_purchase_receipt(**args):
pr.company = args.company or "_Test Company"
pr.supplier = args.supplier or "_Test Supplier"
pr.is_subcontracted = args.is_subcontracted or "No"
pr.supplier_warehouse = "_Test Warehouse 1 - _TC"
pr.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
pr.currency = args.currency or "INR"
pr.is_return = args.is_return
pr.return_against = args.return_against
@ -492,6 +550,16 @@ def make_purchase_receipt(**args):
"asset_location": args.location or "Test Location"
})
if args.get_multiple_items:
pr.items = []
for item in get_items(warehouse= args.warehouse, cost_center = args.cost_center or frappe.get_cached_value('Company', pr.company, 'cost_center')):
pr.append("items", item)
if args.get_taxes_and_charges:
for tax in get_taxes():
pr.append("taxes", tax)
if not args.do_not_save:
pr.insert()
if not args.do_not_submit:

View File

@ -83,39 +83,5 @@
}
],
"supplier": "_Test Supplier"
},
{
"buying_price_list": "_Test Price List",
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"doctype": "Purchase Receipt",
"base_grand_total": 5000.0,
"is_subcontracted": "Yes",
"base_net_total": 5000.0,
"posting_date": "2013-02-12",
"items": [
{
"base_amount": 5000.0,
"conversion_factor": 1.0,
"description": "_Test FG Item",
"doctype": "Purchase Receipt Item",
"item_code": "_Test FG Item",
"item_name": "_Test FG Item",
"parentfield": "items",
"qty": 10.0,
"rate": 500.0,
"received_qty": 10.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC"
}
],
"supplier": "_Test Supplier",
"supplier_warehouse": "_Test Warehouse - _TC"
}
]

View File

@ -0,0 +1,14 @@
frappe.listview_settings['Serial No'] = {
add_fields: ["is_cancelled", "item_code", "warehouse", "warranty_expiry_date", "delivery_document_type"],
get_indicator: (doc) => {
if (doc.is_cancelled) {
return [__("Cancelled"), "red", "is_cancelled,=,Yes"];
} else if (doc.delivery_document_type) {
return [__("Delivered"), "green", "delivery_document_type,is,set|is_cancelled,=,No"];
} else if (doc.warranty_expiry_date && frappe.datetime.get_diff(doc.warranty_expiry_date, frappe.datetime.nowdate()) <= 0) {
return [__("Expired"), "red", "warranty_expiry_date,not in,|warranty_expiry_date,<=,Today|delivery_document_type,is,not set|is_cancelled,=,No"];
} else {
return [__("Active"), "green", "delivery_document_type,is,not set|is_cancelled,=,No"];
}
}
};

View File

@ -12,6 +12,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
test_dependencies = ["Item"]
test_records = frappe.get_test_records('Serial No')
@ -37,6 +38,8 @@ class TestSerialNo(unittest.TestCase):
self.assertTrue(SerialNoCannotCannotChangeError, sr.save)
def test_inter_company_transfer(self):
set_perpetual_inventory(0, "_Test Company 1")
set_perpetual_inventory(0)
se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
serial_nos = get_serial_nos(se.get("items")[0].serial_no)

View File

@ -241,7 +241,9 @@ class StockEntry(StockController):
for d in self.get("items"):
if not d.expense_account:
frappe.throw(_("Please enter Difference Account"))
frappe.throw(_("Please enter <b>Difference Account</b> or set default <b>Stock Adjustment Account</b> for company {0}")
.format(frappe.bold(self.company)))
elif self.is_opening == "Yes" and frappe.db.get_value("Account", d.expense_account, "report_type") == "Profit and Loss":
frappe.throw(_("Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry"), OpeningEntryAccountError)
@ -329,8 +331,8 @@ class StockEntry(StockController):
if total_completed_qty > flt(completed_qty):
job_card = frappe.db.get_value('Job Card', {'operation_id': d.name}, 'name')
if not job_card:
frappe.throw(_("Work Order {0}: job card not found for the operation {1}")
.format(self.work_order, job_card))
frappe.throw(_("Work Order {0}: Job Card not found for the operation {1}")
.format(self.work_order, d.operation))
work_order_link = frappe.utils.get_link_to_form('Work Order', self.work_order)
job_card_link = frappe.utils.get_link_to_form('Job Card', job_card)

View File

@ -16,7 +16,6 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError
from six import iteritems
def get_sle(**args):
@ -132,20 +131,19 @@ class TestStockEntry(unittest.TestCase):
self.assertTrue(item_code in items)
def test_material_receipt_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC")
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
stock_in_hand_account = get_inventory_account(mr.company, mr.get("items")[0].t_warehouse)
self.check_stock_ledger_entries("Stock Entry", mr.name,
[["_Test Item", "_Test Warehouse - _TC", 50.0]])
[["_Test Item", "Stores - TCP1", 50.0]])
self.check_gl_entries("Stock Entry", mr.name,
sorted([
[stock_in_hand_account, 5000.0, 0.0],
["Stock Adjustment - _TC", 0.0, 5000.0]
["Stock Adjustment - TCP1", 0.0, 5000.0]
])
)
@ -158,29 +156,26 @@ class TestStockEntry(unittest.TestCase):
where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
def test_material_issue_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC")
mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
qty=40, expense_account="Stock Adjustment - _TC")
mi = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", company=company,
qty=40, expense_account="Stock Adjustment - TCP1")
self.check_stock_ledger_entries("Stock Entry", mi.name,
[["_Test Item", "_Test Warehouse - _TC", -40.0]])
[["_Test Item", "Stores - TCP1", -40.0]])
stock_in_hand_account = get_inventory_account(mi.company, "_Test Warehouse - _TC")
stock_in_hand_account = get_inventory_account(mi.company, "Stores - TCP1")
stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
"voucher_no": mi.name}, "stock_value_difference"))
self.check_gl_entries("Stock Entry", mi.name,
sorted([
[stock_in_hand_account, 0.0, stock_value_diff],
["Stock Adjustment - _TC", stock_value_diff, 0.0]
["Stock Adjustment - TCP1", stock_value_diff, 0.0]
])
)
mi.cancel()
self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry`
@ -190,16 +185,15 @@ class TestStockEntry(unittest.TestCase):
where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
def test_material_transfer_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
create_stock_reconciliation(qty=100, rate=100)
mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
target="_Test Warehouse 1 - _TC", qty=45)
mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1",
target="Finished Goods - TCP1", qty=45)
self.check_stock_ledger_entries("Stock Entry", mtn.name,
[["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]])
[["_Test Item", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]])
stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse)
@ -212,7 +206,7 @@ class TestStockEntry(unittest.TestCase):
else:
stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
"voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference"))
"voucher_no": mtn.name, "warehouse": "Stores - TCP1"}, "stock_value_difference"))
self.check_gl_entries("Stock Entry", mtn.name,
sorted([
@ -255,14 +249,21 @@ class TestStockEntry(unittest.TestCase):
set_perpetual_inventory(0, repack.company)
def test_repack_with_additional_costs(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
repack = frappe.copy_doc(test_records[3])
make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
repack = make_stock_entry(company = company, purpose="Repack", do_not_save=True)
repack.posting_date = nowdate()
repack.posting_time = nowtime()
items = get_multiple_items()
repack.items = []
for item in items:
repack.append("items", item)
repack.set("additional_costs", [
{
"description": "Actual Oerating Cost",
@ -292,13 +293,12 @@ class TestStockEntry(unittest.TestCase):
self.check_gl_entries("Stock Entry", repack.name,
sorted([
[stock_in_hand_account, 1200, 0.0],
["Expenses Included In Valuation - _TC", 0.0, 1200.0]
["Expenses Included In Valuation - TCP1", 0.0, 1200.0]
])
)
set_perpetual_inventory(0, repack.company)
def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
expected_sle.sort(key=lambda x: x[0])
expected_sle.sort(key=lambda x: x[1])
# check stock ledger entries
sle = frappe.db.sql("""select item_code, warehouse, actual_qty
@ -306,7 +306,7 @@ class TestStockEntry(unittest.TestCase):
and voucher_no = %s order by item_code, warehouse, actual_qty""",
(voucher_type, voucher_no), as_list=1)
self.assertTrue(sle)
sle.sort(key=lambda x: x[0])
sle.sort(key=lambda x: x[1])
for i, sle in enumerate(sle):
self.assertEqual(expected_sle[i][0], sle[0])
@ -773,14 +773,12 @@ class TestStockEntry(unittest.TestCase):
self.assertEqual(doc.per_transferred, 100)
def test_gle_for_opening_stock_entry(self):
set_perpetual_inventory(1)
mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC", is_opening="Yes", do_not_save=True)
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
self.assertRaises(OpeningEntryAccountError, mr.save)
mr.items[0].expense_account = "Temporary Opening - _TC"
mr.items[0].expense_account = "Temporary Opening - TCP1"
mr.save()
mr.submit()
@ -805,14 +803,42 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
def get_qty_after_transaction(**args):
args = frappe._dict(args)
last_sle = get_previous_sle({
"item_code": args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"posting_date": args.posting_date or nowdate(),
"posting_time": args.posting_time or nowtime()
})
return flt(last_sle.get("qty_after_transaction"))
def get_multiple_items():
return [
{
"conversion_factor": 1.0,
"cost_center": "Main - TCP1",
"doctype": "Stock Entry Detail",
"expense_account": "Stock Adjustment - TCP1",
"basic_rate": 100,
"item_code": "_Test Item",
"qty": 50.0,
"s_warehouse": "Stores - TCP1",
"stock_uom": "_Test UOM",
"transfer_qty": 50.0,
"uom": "_Test UOM"
},
{
"conversion_factor": 1.0,
"cost_center": "Main - TCP1",
"doctype": "Stock Entry Detail",
"expense_account": "Stock Adjustment - TCP1",
"basic_rate": 5000,
"item_code": "_Test Item Home Desktop 100",
"qty": 1,
"stock_uom": "_Test UOM",
"t_warehouse": "Stores - TCP1",
"transfer_qty": 1,
"uom": "_Test UOM"
}
]
test_records = frappe.get_test_records('Stock Entry')

View File

@ -7,7 +7,7 @@
from __future__ import unicode_literals
import frappe, unittest
from frappe.utils import flt, nowdate, nowtime
from erpnext.accounts.utils import get_stock_and_account_difference
from erpnext.accounts.utils import get_stock_and_account_balance
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items
@ -21,7 +21,6 @@ class TestStockReconciliation(unittest.TestCase):
def setUpClass(self):
create_batch_or_serial_no_items()
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
insert_existing_sle()
def test_reco_for_fifo(self):
self._test_reco_sle_gle("FIFO")
@ -30,7 +29,8 @@ class TestStockReconciliation(unittest.TestCase):
self._test_reco_sle_gle("Moving Average")
def _test_reco_sle_gle(self, valuation_method):
set_perpetual_inventory()
insert_existing_sle(warehouse='Stores - TCP1')
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
# [[qty, valuation_rate, posting_date,
# posting_time, expected_stock_value, bin_qty, bin_valuation]]
input_data = [
@ -46,14 +46,15 @@ class TestStockReconciliation(unittest.TestCase):
last_sle = get_previous_sle({
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC",
"warehouse": "Stores - TCP1",
"posting_date": d[2],
"posting_time": d[3]
})
# submit stock reconciliation
stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1],
posting_date=d[2], posting_time=d[3])
posting_date=d[2], posting_time=d[3], warehouse="Stores - TCP1",
company=company, expense_account = "Stock Adjustment - TCP1")
# check stock value
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
@ -73,17 +74,18 @@ class TestStockReconciliation(unittest.TestCase):
# no gl entries
self.assertTrue(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
stock_reco.cancel()
acc_bal, stock_bal, wh_list = get_stock_and_account_balance("Stock In Hand - TCP1",
stock_reco.posting_date, stock_reco.company)
self.assertEqual(acc_bal, stock_bal)
self.assertFalse(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
stock_reco.cancel()
self.assertFalse(frappe.db.get_value("GL Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
self.assertFalse(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
set_perpetual_inventory(0)
self.assertFalse(frappe.db.get_value("GL Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
def test_get_items(self):
create_warehouse("_Test Warehouse Group 1", {"is_group": 1})
@ -203,17 +205,17 @@ class TestStockReconciliation(unittest.TestCase):
stock_doc.cancel()
def insert_existing_sle():
def insert_existing_sle(warehouse):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
target="_Test Warehouse - _TC", qty=10, basic_rate=700)
target=warehouse, qty=10, basic_rate=700)
make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
source="_Test Warehouse - _TC", qty=15)
source=warehouse, qty=15)
make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
target="_Test Warehouse - _TC", qty=15, basic_rate=1200)
target=warehouse, qty=15, basic_rate=1200)
def create_batch_or_serial_no_items():
create_warehouse("_Test Warehouse for Stock Reco1",
@ -244,7 +246,10 @@ def create_stock_reconciliation(**args):
sr.company = args.company or "_Test Company"
sr.expense_account = args.expense_account or \
("Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC")
sr.cost_center = args.cost_center or "_Test Cost Center - _TC"
sr.cost_center = args.cost_center \
or frappe.get_cached_value("Company", sr.company, "cost_center") \
or "_Test Cost Center - _TC"
sr.append("items", {
"item_code": args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC",

View File

@ -1,42 +1,36 @@
[
{
"company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse",
"is_group": 0
},
{
"company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Scrap Warehouse",
"is_group": 0
},
{
"company": "_Test Company",
"create_account_under": "Fixed Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 1",
"is_group": 0
},
{
"company": "_Test Company",
"create_account_under": "Fixed Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 2",
"is_group": 0
},
{
"company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Rejected Warehouse",
"is_group": 0
},
{
"company": "_Test Company 1",
"create_account_under": "Stock Assets - _TC1",
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 2",
"is_group": 0

View File

@ -101,8 +101,7 @@ def create_warehouse(warehouse_name, properties=None, company=None):
w.warehouse_name = warehouse_name
w.parent_warehouse = "_Test Warehouse Group - _TC"
w.company = company
make_account_for_warehouse(warehouse_name, w)
w.account = warehouse_id
w.account = get_warehouse_account(warehouse_name, company)
if properties:
w.update(properties)
w.save()
@ -110,9 +109,40 @@ def create_warehouse(warehouse_name, properties=None, company=None):
else:
return warehouse_id
def make_account_for_warehouse(warehouse_name, warehouse_obj):
if not frappe.db.exists("Account", warehouse_name + " - _TC"):
parent_account = frappe.db.get_value('Account',
{'company': warehouse_obj.company, 'is_group':1, 'account_type': 'Stock'},'name')
account = create_account(account_name=warehouse_name, \
account_type="Stock", parent_account= parent_account, company=warehouse_obj.company)
def get_warehouse(**args):
args = frappe._dict(args)
if(frappe.db.exists("Warehouse", args.warehouse_name + " - " + args.abbr)):
return frappe.get_doc("Warehouse", args.warehouse_name + " - " + args.abbr)
else:
w = frappe.get_doc({
"company": args.company or "_Test Company",
"doctype": "Warehouse",
"warehouse_name": args.warehouse_name,
"is_group": 0,
"account": get_warehouse_account(args.warehouse_name, args.company, args.abbr)
})
w.insert()
return w
def get_warehouse_account(warehouse_name, company, company_abbr=None):
if not company_abbr:
company_abbr = frappe.get_cached_value("Company", company, 'abbr')
if not frappe.db.exists("Account", warehouse_name + " - " + company_abbr):
return create_account(
account_name=warehouse_name,
parent_account=get_group_stock_account(company, company_abbr),
account_type='Stock',
company=company)
else:
return warehouse_name + " - " + company_abbr
def get_group_stock_account(company, company_abbr=None):
group_stock_account = frappe.db.get_value("Account",
filters={'account_type': 'Stock', 'is_group': 1, 'company': company}, fieldname='name')
if not group_stock_account:
if not company_abbr:
company_abbr = frappe.get_cached_value("Company", company, 'abbr')
group_stock_account = "Current Assets - " + company_abbr
return group_stock_account

View File

@ -89,7 +89,7 @@ def get_item_price_qty_data(filters):
{conditions}"""
.format(conditions=conditions), filters, as_dict=1)
price_list_names = list(set([frappe.db.escape(item.price_list_name) for item in item_results]))
price_list_names = list(set([item.price_list_name for item in item_results]))
buying_price_map = get_price_map(price_list_names, buying=1)
selling_price_map = get_price_map(price_list_names, selling=1)
@ -129,17 +129,15 @@ def get_price_map(price_list_names, buying=0, selling=0):
rate_key = "Buying Rate" if buying else "Selling Rate"
price_list_key = "Buying Price List" if buying else "Selling Price List"
price_list_condition = " and buying=1" if buying else " and selling=1"
pricing_details = frappe.db.sql("""
select
name,price_list,price_list_rate
from
`tabItem Price`
where
name in ({price_list_names}) {price_list_condition}
""".format(price_list_names=', '.join(['%s']*len(price_list_names)),
price_list_condition=price_list_condition), price_list_names, as_dict=1)
filters = {"name": ("in", price_list_names)}
if buying:
filters["buying"] = 1
else:
filters["selling"] = 1
pricing_details = frappe.get_all("Item Price",
fields = ["name", "price_list", "price_list_rate"], filters=filters)
for d in pricing_details:
name = d["name"]

View File

@ -30,7 +30,7 @@ def get_total_stock(filters):
if filters.get("group_by") == "Warehouse":
if filters.get("company"):
conditions += " AND warehouse.company = '%s'" % frappe.db.escape(filters.get("company"), percent=False)
conditions += " AND warehouse.company = %s" % frappe.db.escape(filters.get("company"), percent=False)
conditions += " GROUP BY ledger.warehouse, item.item_code"
columns += "'' as company, ledger.warehouse"

View File

@ -22,7 +22,6 @@ class Issue(Document):
return "{0}: {1}".format(_(self.status), self.subject)
def validate(self):
self.flags.ignore_disabled = 1
if self.is_new() and self.via_customer_portal:
self.flags.create_communication = True

View File

@ -1,13 +1,14 @@
<div class="web-list-item">
<a href="/timesheets?name={{ doc.name | urlencode }}" class="no-decoration">
<div class="row">
<div class="col-xs-3">
<span class="indicator {{ "red" if doc.status=="Cancelled" else "green" if doc.status=="Billed" else "blue" if doc.status=="Submitted" else "darkgrey" }}">{{ doc.name }}</span>
</div>
<div class="col-xs-3"> Billable Hours: {{ doc.total_billable_hours}} </div>
<div class="col-xs-2"> {{ _(doc.sales_invoice) }} </div>
<div class="col-xs-2"> {{ _(doc.project) }} </div>
<div class="col-xs-2"> {{ _(doc.activity_type) }} </div>
<div class="web-list-item transaction-list-item">
<div class="row">
<div class="col-xs-3">
<span class='indicator {{ "red" if doc.status=="Cancelled" else "green" if doc.status=="Billed" else "blue" if doc.status=="Submitted" else "darkgrey" }} small'>
{{ doc.name }}
</span>
</div>
</a>
<div class="col-xs-2 small"> {{ doc.total_billable_hours }} </div>
<div class="col-xs-2 small"> {{ doc.project or '' }} </div>
<div class="col-xs-2 small"> {{ doc.sales_invoice or '' }} </div>
<div class="col-xs-2 small"> {{ _(doc.activity_type) }} </div>
</div>
<!-- <a href="/timesheets?name={{ doc.name | urlencode }}" class="transaction-item-link">Link</a> -->
</div>

View File

@ -1562,7 +1562,7 @@ DocType: Sales Invoice,Payment Due Date,Betaaldatum
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Voorbehou Aantal: Hoeveelheid te koop bestel, maar nie afgelewer nie."
DocType: Drug Prescription,Interval UOM,Interval UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Herstel, as die gekose adres geredigeer word na die stoor"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Voorbehou Aantal vir Onderkontrakte: Hoeveelheid grondstowwe om onderverpakte items te maak.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Voorbehou Aantal vir Onderkontrakte: Hoeveelheid grondstowwe om onderverpakte items te maak.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Item Variant {0} bestaan reeds met dieselfde eienskappe
DocType: Item,Hub Publishing Details,Hub Publishing Details
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&#39;Oopmaak&#39;

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

View File

@ -1560,7 +1560,7 @@ DocType: Sales Invoice,Payment Due Date,ክፍያ መጠናቀቅ ያለበት
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.",የተያዙ ጫፎች ብዛት ለሽያጭ የታዘዘ ፣ ግን አልደረሰም ፡፡
DocType: Drug Prescription,Interval UOM,የጊዜ ክፍተት UOM
DocType: Customer,"Reselect, if the chosen address is edited after save",የተመረጠው አድራሻ ከተቀመጠ በኋላ ማስተካከያ ከተደረገበት አይምረጡ
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,የተያዙ ዕቃዎች ለንዑስ-ኮንትራክተር-ንዑስ-ንዑስ ንጥል ነገሮችን ለመስራት ጥሬ ዕቃዎች ብዛት።
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,የተያዙ ዕቃዎች ለንዑስ-ኮንትራክተር-ንዑስ-ንዑስ ንጥል ነገሮችን ለመስራት ጥሬ ዕቃዎች ብዛት።
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,ንጥል ተለዋጭ {0} ቀድሞውኑ ተመሳሳይ ባሕርያት ጋር አለ
DocType: Item,Hub Publishing Details,ሃቢ የህትመት ዝርዝሮች
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&#39;በመክፈት ላይ&#39;

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

View File

@ -1581,7 +1581,7 @@ DocType: Sales Invoice,Payment Due Date,تاريخ استحقاق السداد
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.",الكمية المحجوزة : الكمية المطلوبة لل بيع، ولكن لم يتم تسليمها .
DocType: Drug Prescription,Interval UOM,الفاصل الزمني أوم
DocType: Customer,"Reselect, if the chosen address is edited after save",إعادة تحديد، إذا تم تحرير عنوان المختار بعد حفظ
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,الكمية المحجوزة للعقد من الباطن: كمية المواد الخام لصنع سلع من الباطن.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,الكمية المحجوزة للعقد من الباطن: كمية المواد الخام لصنع سلع من الباطن.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,متغير الصنف {0} موجود بالفعل مع نفس الخصائص
DocType: Item,Hub Publishing Details,هاب تفاصيل النشر
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening','افتتاحي'

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

View File

@ -1562,7 +1562,7 @@ DocType: Sales Invoice,Payment Due Date,Дължимото плащане Дат
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Количество, запазено: Количество, поръчано за продажба, но не е доставено."
DocType: Drug Prescription,Interval UOM,Интервал (мерна единица)
DocType: Customer,"Reselect, if the chosen address is edited after save","Преименувайте отново, ако избраният адрес се редактира след запазване"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,"Количество, запазено за подизпълнение: Количество суровини за изработване на извадени продукти."
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,"Количество, запазено за подизпълнение: Количество суровини за изработване на извадени продукти."
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Позиция Variant {0} вече съществува с едни и същи атрибути
DocType: Item,Hub Publishing Details,Подробна информация за издателя
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',"""Начален баланс"""

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

View File

@ -1544,7 +1544,7 @@ DocType: Sales Invoice,Payment Due Date,পরিশোধযোগ্য তা
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","সংরক্ষিত পরিমাণ: পরিমাণ বিক্রয়ের জন্য অর্ডার করা হয়েছে, তবে বিতরণ করা হয়নি।"
DocType: Drug Prescription,Interval UOM,অন্তর্বর্তী UOM
DocType: Customer,"Reselect, if the chosen address is edited after save",সংরক্ষণ করার পরে যদি নির্বাচিত ঠিকানাটি সম্পাদনা করা হয় তবে নির্বাচন বাতিল করুন
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,সাবকন্ট্রাক্টের জন্য সংরক্ষিত পরিমাণ: উপকোট্রাক্ট আইটেমগুলি তৈরি করতে কাঁচামাল পরিমাণ।
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,সাবকন্ট্রাক্টের জন্য সংরক্ষিত পরিমাণ: উপকোট্রাক্ট আইটেমগুলি তৈরি করতে কাঁচামাল পরিমাণ।
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,আইটেম ভেরিয়েন্ট {0} ইতিমধ্যে একই বৈশিষ্ট্যাবলী সঙ্গে বিদ্যমান
DocType: Item,Hub Publishing Details,হাব প্রকাশনা বিবরণ
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',' শুরু'

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

View File

@ -1581,7 +1581,7 @@ DocType: Sales Invoice,Payment Due Date,Plaćanje Due Date
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Rezervirano Količina : Količina naručiti za prodaju , ali nije dostavljena ."
DocType: Drug Prescription,Interval UOM,Interval UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Ponovo odaberite, ako je izabrana adresa uređena nakon čuvanja"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Količina rezervisanog za podugovor: Količina sirovina za izradu predmeta koji se oduzimaju.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Količina rezervisanog za podugovor: Količina sirovina za izradu predmeta koji se oduzimaju.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Stavka Variant {0} već postoji s istim atributima
DocType: Item,Hub Publishing Details,Detalji izdavanja stanice
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&#39;Otvaranje&#39;

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

View File

@ -1581,7 +1581,7 @@ DocType: Sales Invoice,Payment Due Date,Data de pagament
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Reservats Quantitat: Quantitat va ordenar a la venda, però no entregat."
DocType: Drug Prescription,Interval UOM,Interval UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Torneu a seleccionar, si l&#39;adreça escollida s&#39;edita després de desar-la"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Quantitat reservada per al subcontracte: quantitat de matèries primeres per fabricar articles subcontractats.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Quantitat reservada per al subcontracte: quantitat de matèries primeres per fabricar articles subcontractats.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Article Variant {0} ja existeix amb els mateixos atributs
DocType: Item,Hub Publishing Details,Detalls de publicació del Hub
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&#39;Obertura&#39;

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

View File

@ -1580,7 +1580,7 @@ DocType: Sales Invoice,Payment Due Date,Splatno dne
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Reserved Množství: Množství objednal k prodeji, ale není doručena."
DocType: Drug Prescription,Interval UOM,Interval UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Znovu vyberte, pokud je zvolená adresa po uložení upravena"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Vyhrazeno Množství pro subdodávky: Množství surovin pro výrobu subdodávek.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Vyhrazeno Množství pro subdodávky: Množství surovin pro výrobu subdodávek.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Bod Variant {0} již existuje se stejnými vlastnostmi
DocType: Item,Hub Publishing Details,Podrobnosti o publikování Hubu
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',"""Otevírací"""

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

View File

@ -1562,7 +1562,7 @@ DocType: Sales Invoice,Payment Due Date,Sidste betalingsdato
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Reserveret antal: Mængde bestilt til salg, men ikke leveret."
DocType: Drug Prescription,Interval UOM,Interval UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Vælg igen, hvis den valgte adresse redigeres efter gem"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Reserveret antal til underentreprise: Råvaremængde til fremstilling af underleverede genstande.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Reserveret antal til underentreprise: Råvaremængde til fremstilling af underleverede genstande.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Item Variant {0} findes allerede med samme attributter
DocType: Item,Hub Publishing Details,Hub Publishing Detaljer
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening','Åbner'

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

View File

@ -1581,7 +1581,7 @@ DocType: Sales Invoice,Payment Due Date,Zahlungsstichtag
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Reservierte Menge: Für den Verkauf bestellte Menge, aber noch nicht geliefert."
DocType: Drug Prescription,Interval UOM,Intervall UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Wählen Sie erneut, wenn die gewählte Adresse nach dem Speichern bearbeitet wird"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Reservierte Menge für Lohnbearbeiter: Rohstoffmenge für Lohnbearbeiter.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Reservierte Menge für Lohnbearbeiter: Rohstoffmenge für Lohnbearbeiter.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Artikelvariante {0} mit denselben Attributen existiert bereits
DocType: Item,Hub Publishing Details,Hub-Veröffentlichungsdetails
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',"""Eröffnung"""

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

View File

@ -1581,7 +1581,7 @@ DocType: Sales Invoice,Payment Due Date,Ημερομηνία λήξης προθ
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.",Δεσμευμένη ποσότητα : ποσότητα που παραγγέλθηκε για πώληση αλλά δεν παραδόθηκε.
DocType: Drug Prescription,Interval UOM,Διαστήματα UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Επαναφέρετε την επιλογή, εάν η επιλεγμένη διεύθυνση επεξεργαστεί μετά την αποθήκευση"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Προβλεπόμενη ποσότητα για υπεργολαβία: Ποσότητα πρώτων υλών για την πραγματοποίηση υποκλάδων.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Προβλεπόμενη ποσότητα για υπεργολαβία: Ποσότητα πρώτων υλών για την πραγματοποίηση υποκλάδων.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Θέση Παραλλαγή {0} υπάρχει ήδη με ίδια χαρακτηριστικά
DocType: Item,Hub Publishing Details,Στοιχεία δημοσίευσης Hub
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',«Άνοιγμα»

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

View File

@ -1562,7 +1562,7 @@ DocType: Sales Invoice,Payment Due Date,Fecha de pago
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Cantidad Reservada: Cantidad a pedir a la venta , pero no entregado."
DocType: Drug Prescription,Interval UOM,Intervalo UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Vuelva a seleccionar, si la dirección elegida se edita después de guardar"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Cantidad reservada para subcontrato: Cantidad de materias primas para hacer artículos subcotractados.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Cantidad reservada para subcontrato: Cantidad de materias primas para hacer artículos subcotractados.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Artículo Variant {0} ya existe con los mismos atributos
DocType: Item,Hub Publishing Details,Detalle de Publicación del Hub
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&#39;Apertura&#39;

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

View File

@ -1558,7 +1558,7 @@ DocType: Sales Invoice,Payment Due Date,Maksetähtpäevast
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"Reserved Qty: Quantity ordered for sale, but not delivered.","Reserveeritud kogus: Müügiks tellitud kogus, kuid tarnimata."
DocType: Drug Prescription,Interval UOM,Intervall UOM
DocType: Customer,"Reselect, if the chosen address is edited after save","Kui valite valitud aadressi pärast salvestamist, vali uuesti"
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcotracted items.,Allhankelepingu jaoks reserveeritud kogus: Tooraine kogus alamhangete jaoks.
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,Reserved Qty for Subcontract: Raw materials quantity to make subcontracted items.,Allhankelepingu jaoks reserveeritud kogus: Tooraine kogus alamhangete jaoks.
apps/erpnext/erpnext/stock/doctype/item/item.js,Item Variant {0} already exists with same attributes,Punkt Variant {0} on juba olemas sama atribuute
DocType: Item,Hub Publishing Details,Hubi avaldamise üksikasjad
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py,'Opening',&quot;Avamine&quot;

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