Merge branch 'develop' into shopping-cart

This commit is contained in:
Marica 2021-02-16 20:55:00 +05:30 committed by GitHub
commit 4441cebbb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 126 additions and 28 deletions

View File

@ -82,7 +82,7 @@ def get_fiscal_years(transaction_date=None, fiscal_year=None, label="Date", verb
error_msg = _("""{0} {1} is not in any active Fiscal Year""").format(label, formatdate(transaction_date))
if company:
error_msg = _("""{0} for {1}""").format(error_msg, frappe.bold(company))
if verbose==1: frappe.msgprint(error_msg)
raise FiscalYearError(error_msg)
@ -888,17 +888,22 @@ def get_coa(doctype, parent, is_root, chart=None):
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
warehouse_account=None, company=None):
stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items, company)
repost_gle_for_stock_vouchers(stock_vouchers, posting_date, company, warehouse_account)
def repost_gle_for_stock_vouchers(stock_vouchers, posting_date, company=None, warehouse_account=None):
def _delete_gl_entries(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
if not warehouse_account:
warehouse_account = get_warehouse_account_map(company)
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
gle = get_voucherwise_gl_entries(stock_vouchers, posting_date)
for voucher_type, voucher_no in future_stock_vouchers:
for voucher_type, voucher_no in stock_vouchers:
existing_gle = gle.get((voucher_type, voucher_no), [])
voucher_obj = frappe.get_doc(voucher_type, voucher_no)
expected_gle = voucher_obj.get_gl_entries(warehouse_account)
@ -909,7 +914,7 @@ def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for
else:
_delete_gl_entries(voucher_type, voucher_no)
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None, company=None):
future_stock_vouchers = []
values = []
@ -922,6 +927,10 @@ def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, f
condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
values += for_warehouses
if company:
condition += " and company = %s"
values.append(company)
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
from `tabStock Ledger Entry` sle
where
@ -982,7 +991,7 @@ def check_if_stock_and_account_balance_synced(posting_date, company, voucher_typ
error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses as on {3}.").format(
stock_bal, account_bal, frappe.bold(account), posting_date)
error_resolution = _("Please create an adjustment Journal Entry for amount {0} on {1}")\
.format(frappe.bold(diff), frappe.bold(posting_date))
.format(frappe.bold(diff), frappe.bold(posting_date))
frappe.msgprint(
msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),

View File

@ -488,13 +488,12 @@ class StockController(AccountsController):
"voucher_no": self.name,
"company": self.company
})
if check_if_future_sle_exists(args):
create_repost_item_valuation_entry(args)
elif not is_reposting_pending():
check_if_stock_and_account_balance_synced(self.posting_date,
self.company, self.doctype, self.name)
def is_reposting_pending():
return frappe.db.exists("Repost Item Valuation",
{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})

View File

@ -20,7 +20,7 @@ class PlaidConnector():
client_id=self.settings.plaid_client_id,
secret=self.settings.get_password("plaid_secret"),
environment=self.settings.plaid_env,
api_version="2019-05-29"
api_version="2020-09-14"
)
def get_access_token(self, public_token):
@ -29,7 +29,7 @@ class PlaidConnector():
response = self.client.Item.public_token.exchange(public_token)
access_token = response["access_token"]
return access_token
def get_token_request(self, update_mode=False):
country_codes = ["US", "CA", "FR", "IE", "NL", "ES", "GB"] if self.settings.enable_european_access else ["US", "CA"]
args = {

View File

@ -121,6 +121,7 @@ class ClinicalProcedure(Document):
stock_entry.stock_entry_type = 'Material Receipt'
stock_entry.to_warehouse = self.warehouse
stock_entry.company = self.company
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
for item in self.items:
if item.qty > item.actual_qty:

View File

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
# Copyright (c) 2017, ESS LLP and Contributors
# See license.txt
from __future__ import unicode_literals
@ -60,6 +60,7 @@ def create_procedure(procedure_template, patient, practitioner):
procedure.practitioner = practitioner
procedure.consume_stock = procedure_template.allow_stock_consumption
procedure.items = procedure_template.items
procedure.warehouse = frappe.db.get_single_value('Stock Settings', 'default_warehouse')
procedure.company = "_Test Company"
procedure.warehouse = "_Test Warehouse - _TC"
procedure.submit()
return procedure

View File

@ -752,3 +752,5 @@ erpnext.patches.v13_0.set_company_in_leave_ledger_entry
erpnext.patches.v13_0.convert_qi_parameter_to_link_field
erpnext.patches.v13_0.setup_patient_history_settings_for_standard_doctypes
erpnext.patches.v13_0.add_naming_series_to_old_projects # 1-02-2021
erpnext.patches.v12_0.add_state_code_for_ladakh
erpnext.patches.v13_0.item_reposting_for_incorrect_sl_and_gl

View File

@ -0,0 +1,16 @@
import frappe
from erpnext.regional.india import states
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
custom_fields = ['Address-gst_state', 'Tax Category-gst_state']
# Update options in gst_state custom fields
for field in custom_fields:
gst_state_field = frappe.get_doc('Custom Field', field)
gst_state_field.options = '\n'.join(states)
gst_state_field.save()

View File

@ -0,0 +1,27 @@
import frappe
from frappe import _
from erpnext.stock.stock_ledger import update_entries_after
from erpnext.accounts.utils import update_gl_entries_after
def execute():
data = frappe.db.sql(''' SELECT name, item_code, warehouse, voucher_type, voucher_no, posting_date, posting_time
from `tabStock Ledger Entry` where creation > '2020-12-26 12:58:55.903836' and is_cancelled = 0
order by timestamp(posting_date, posting_time) asc, creation asc''', as_dict=1)
for index, d in enumerate(data):
update_entries_after({
"item_code": d.item_code,
"warehouse": d.warehouse,
"posting_date": d.posting_date,
"posting_time": d.posting_time,
"voucher_type": d.voucher_type,
"voucher_no": d.voucher_no,
"sle_id": d.name
}, allow_negative_stock=True)
frappe.db.auto_commit_on_many_writes = 1
for row in frappe.get_all('Company', filters= {'enable_perpetual_inventory': 1}):
update_gl_entries_after('2020-12-25', '01:58:55', company=row.name)
frappe.db.auto_commit_on_many_writes = 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -140,6 +140,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
() => me.update_batch_serial_no_items(),
() => {
refresh_field("items");
refresh_field("packed_items");
if (me.callback) {
return me.callback(me.item);
}
@ -154,7 +155,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
if (this.item.serial_no) {
this.dialog.fields_dict.serial_no.set_value(this.item.serial_no);
}
if (this.has_batch && !this.has_serial_no && d.batch_no) {
this.frm.doc.items.forEach(data => {
if(data.item_code == d.item_code) {
@ -231,7 +232,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
this.map_row_values(row, batch, 'batch_no',
'selected_qty', this.values.warehouse);
});
}
}
},
update_serial_no_item() {
@ -250,7 +251,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
filters: { 'name': ["in", selected_serial_nos]},
fields: ["batch_no", "name"]
}).then((data) => {
// data = [{batch_no: 'batch-1', name: "SR-001"},
// data = [{batch_no: 'batch-1', name: "SR-001"},
// {batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}]
const batch_serial_map = data.reduce((acc, d) => {
if (!acc[d['batch_no']]) acc[d['batch_no']] = [];
@ -298,6 +299,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
} else {
row.warehouse = values.warehouse || warehouse;
}
this.frm.dirty();
},
update_total_qty: function() {

View File

@ -32,7 +32,12 @@ body[data-route*="marketplace"] {
}
.hub-image-loading, .hub-image-broken {
.img-background();
content: " ";
position: absolute;
left: 0;
height: 100%;
width: 100%;
background-color: var(--bg-light-gray);
display: flex;
align-items: center;
justify-content: center;

View File

@ -5,12 +5,16 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import getdate
from frappe.utils import getdate, get_link_to_form
from frappe.model.document import Document
from erpnext.accounts.utils import get_fiscal_year
class LowerDeductionCertificate(Document):
def validate(self):
self.validate_dates()
self.validate_supplier_against_section_code()
def validate_dates(self):
if getdate(self.valid_upto) < getdate(self.valid_from):
frappe.throw(_("Valid Upto date cannot be before Valid From date"))
@ -24,3 +28,20 @@ class LowerDeductionCertificate(Document):
<= fiscal_year.year_end_date):
frappe.throw(_("Valid Upto date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
def validate_supplier_against_section_code(self):
duplicate_certificate = frappe.db.get_value('Lower Deduction Certificate', {'supplier': self.supplier, 'section_code': self.section_code}, ['name', 'valid_from', 'valid_upto'], as_dict=True)
if duplicate_certificate and self.are_dates_overlapping(duplicate_certificate):
certificate_link = get_link_to_form('Lower Deduction Certificate', duplicate_certificate.name)
frappe.throw(_("There is already a valid Lower Deduction Certificate {0} for Supplier {1} against Section Code {2} for this time period.")
.format(certificate_link, frappe.bold(self.supplier), frappe.bold(self.section_code)))
def are_dates_overlapping(self,duplicate_certificate):
valid_from = duplicate_certificate.valid_from
valid_upto = duplicate_certificate.valid_upto
if valid_from <= getdate(self.valid_from) <= valid_upto:
return True
elif valid_from <= getdate(self.valid_upto) <= valid_upto:
return True
elif getdate(self.valid_from) <= valid_from and valid_upto <= getdate(self.valid_upto):
return True
return False

View File

@ -20,6 +20,7 @@ states = [
'Jharkhand',
'Karnataka',
'Kerala',
'Ladakh',
'Lakshadweep Islands',
'Madhya Pradesh',
'Maharashtra',
@ -59,6 +60,7 @@ state_numbers = {
"Jharkhand": "20",
"Karnataka": "29",
"Kerala": "32",
"Ladakh": "38",
"Lakshadweep Islands": "31",
"Madhya Pradesh": "23",
"Maharashtra": "27",
@ -80,4 +82,4 @@ state_numbers = {
"West Bengal": "19",
}
number_state_mapping = {v: k for k, v in iteritems(state_numbers)}
number_state_mapping = {v: k for k, v in iteritems(state_numbers)}

View File

@ -168,5 +168,10 @@
"state_number": "37",
"state_code": "AD",
"state_name": "Andhra Pradesh (New)"
},
{
"state_number": "38",
"state_code": "LA",
"state_name": "Ladakh"
}
]

View File

@ -514,7 +514,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
make_delivery_note: function() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
frm: me.frm
frm: this.frm
})
},

View File

@ -64,7 +64,7 @@ def get_warehouse_account(warehouse, warehouse_account=None):
if not account and warehouse.company:
account = get_company_default_inventory_account(warehouse.company)
if not account and warehouse.company:
if not account and warehouse.company and not warehouse.is_group:
frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}")
.format(warehouse.name, warehouse.company))
return account

View File

@ -298,9 +298,9 @@ class TestBatch(unittest.TestCase):
self.assertEqual(details.get('price_list_rate'), 400)
def create_batch(item_code, rate, create_item_price_for_batch):
pi = make_purchase_invoice(company="_Test Company with perpetual inventory",
warehouse= "Stores - TCP1", cost_center = "Main - TCP1", update_stock=1,
expense_account ="_Test Account Cost for Goods Sold - TCP1", item_code=item_code)
pi = make_purchase_invoice(company="_Test Company",
warehouse= "Stores - _TC", cost_center = "Main - _TC", update_stock=1,
expense_account ="_Test Account Cost for Goods Sold - _TC", item_code=item_code)
batch = frappe.db.get_value('Batch', {'item': item_code, 'reference_name': pi.name})

View File

@ -148,7 +148,6 @@ class TestLandedCostVoucher(unittest.TestCase):
def test_landed_cost_voucher_for_odd_numbers (self):
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):
@ -208,6 +207,10 @@ class TestLandedCostVoucher(unittest.TestCase):
self.assertEqual(pr.items[1].landed_cost_voucher_amount, 100)
def test_multi_currency_lcv(self):
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records
save_new_records(test_records)
## Create USD Shipping charges_account
usd_shipping = create_account(account_name="Shipping Charges USD",
parent_account="Duties and Taxes - TCP1", company="_Test Company with perpetual inventory",

View File

@ -64,7 +64,7 @@ def repost(doc):
message += "<br>" + "Traceback: <br>" + traceback
frappe.db.set_value(doc.doctype, doc.name, 'error_log', message)
notify_error_to_stock_managers(doc)
notify_error_to_stock_managers(doc, message)
doc.set_status('Failed')
raise
finally:

View File

@ -190,6 +190,7 @@ def create_shipment_company(company_name, abbr):
company.abbr = abbr
company.default_currency = 'EUR'
company.country = 'Germany'
company.enable_perpetual_inventory = 0
company.insert()
return company

View File

@ -194,6 +194,8 @@ class update_entries_after(object):
self.process_sle(sle)
def get_sle_against_current_voucher(self):
self.args['time_format'] = '%H:%i:%s'
return frappe.db.sql("""
select
*, timestamp(posting_date, posting_time) as "timestamp"
@ -202,7 +204,8 @@ class update_entries_after(object):
where
item_code = %(item_code)s
and warehouse = %(warehouse)s
and timestamp(posting_date, time_format(posting_time, '%H:%i:%s')) = timestamp(%(posting_date)s, time_format(%(posting_time)s, '%H:%i:%s'))
and voucher_type = %(voucher_type)s
and voucher_no = %(voucher_no)s
order by
creation ASC
for update

View File

@ -3,7 +3,7 @@ frappe
gocardless-pro==1.11.0
googlemaps==3.1.1
pandas>=1.0.5
plaid-python==6.0.0
plaid-python>=7.0.0
pycountry==19.8.18
PyGithub==1.44.1
python-stdnum==1.12
@ -12,4 +12,4 @@ taxjar==1.9.0
tweepy==3.8.0
Unidecode==1.1.1
WooCommerce==2.1.1
pycryptodome==3.9.8
pycryptodome==3.9.8