Compare commits
11 Commits
handle-mul
...
v15.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0925cb28c7 | ||
|
|
9863ba5fd8 | ||
|
|
889f84bcb7 | ||
|
|
b9e4719045 | ||
|
|
5cca001a58 | ||
|
|
e76860fae1 | ||
|
|
844e6f47df | ||
|
|
62d9de4848 | ||
|
|
fa5c75fd0a | ||
|
|
777c1dd1ea | ||
|
|
fca812448e |
60
.github/helper/translation.py
vendored
60
.github/helper/translation.py
vendored
@@ -1,60 +0,0 @@
|
|||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
errors_encounter = 0
|
|
||||||
pattern = re.compile(r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)")
|
|
||||||
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
|
|
||||||
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
|
|
||||||
f_string_pattern = re.compile(r"_\(f[\"']")
|
|
||||||
starts_with_f_pattern = re.compile(r"_\(f")
|
|
||||||
|
|
||||||
# skip first argument
|
|
||||||
files = sys.argv[1:]
|
|
||||||
files_to_scan = [_file for _file in files if _file.endswith(('.py', '.js'))]
|
|
||||||
|
|
||||||
for _file in files_to_scan:
|
|
||||||
with open(_file, 'r') as f:
|
|
||||||
print(f'Checking: {_file}')
|
|
||||||
file_lines = f.readlines()
|
|
||||||
for line_number, line in enumerate(file_lines, 1):
|
|
||||||
if 'frappe-lint: disable-translate' in line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
start_matches = start_pattern.search(line)
|
|
||||||
if start_matches:
|
|
||||||
starts_with_f = starts_with_f_pattern.search(line)
|
|
||||||
|
|
||||||
if starts_with_f:
|
|
||||||
has_f_string = f_string_pattern.search(line)
|
|
||||||
if has_f_string:
|
|
||||||
errors_encounter += 1
|
|
||||||
print(f'\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}')
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
|
|
||||||
match = pattern.search(line)
|
|
||||||
error_found = False
|
|
||||||
|
|
||||||
if not match and line.endswith((',\n', '[\n')):
|
|
||||||
# concat remaining text to validate multiline pattern
|
|
||||||
line = "".join(file_lines[line_number - 1:])
|
|
||||||
line = line[start_matches.start() + 1:]
|
|
||||||
match = pattern.match(line)
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
error_found = True
|
|
||||||
print(f'\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}')
|
|
||||||
|
|
||||||
if not error_found and not words_pattern.search(line):
|
|
||||||
error_found = True
|
|
||||||
print(f'\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}')
|
|
||||||
|
|
||||||
if error_found:
|
|
||||||
errors_encounter += 1
|
|
||||||
|
|
||||||
if errors_encounter > 0:
|
|
||||||
print('\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.')
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
print('\nGood To Go!')
|
|
||||||
26
.github/workflows/backport.yml
vendored
26
.github/workflows/backport.yml
vendored
@@ -1,26 +0,0 @@
|
|||||||
name: Backport
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
- labeled
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
main:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 60
|
|
||||||
steps:
|
|
||||||
- name: Checkout Actions
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
repository: "frappe/backport"
|
|
||||||
path: ./actions
|
|
||||||
ref: develop
|
|
||||||
- name: Install Actions
|
|
||||||
run: npm install --production --prefix ./actions
|
|
||||||
- name: Run backport
|
|
||||||
uses: ./actions/backport
|
|
||||||
with:
|
|
||||||
token: ${{secrets.BACKPORT_BOT_TOKEN}}
|
|
||||||
labelsToAdd: "backport"
|
|
||||||
title: "{{originalTitle}}"
|
|
||||||
32
.github/workflows/initiate_release.yml
vendored
32
.github/workflows/initiate_release.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
# This workflow is agnostic to branches. Only maintain on develop branch.
|
|
||||||
# To add/remove versions just modify the matrix.
|
|
||||||
|
|
||||||
name: Create weekly release pull requests
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# 9:30 UTC => 3 PM IST Tuesday
|
|
||||||
- cron: "30 9 * * 2"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stable-release:
|
|
||||||
name: Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
version: ["13", "14"]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: octokit/request-action@v2.x
|
|
||||||
with:
|
|
||||||
route: POST /repos/{owner}/{repo}/pulls
|
|
||||||
owner: frappe
|
|
||||||
repo: erpnext
|
|
||||||
title: |-
|
|
||||||
"chore: release v${{ matrix.version }}"
|
|
||||||
body: "Automated weekly release."
|
|
||||||
base: version-${{ matrix.version }}
|
|
||||||
head: version-${{ matrix.version }}-hotfix
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -2,21 +2,23 @@ name: Generate Semantic Release
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- version-13
|
- version-15
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Entire Repository
|
- name: Checkout Entire Repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||||
|
|||||||
26
.github/workflows/server-tests-mariadb.yml
vendored
26
.github/workflows/server-tests-mariadb.yml
vendored
@@ -117,7 +117,7 @@ jobs:
|
|||||||
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --with-coverage --total-builds 4 --build-number ${{ matrix.container }}'
|
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds 4 --build-number ${{ matrix.container }}'
|
||||||
env:
|
env:
|
||||||
TYPE: server
|
TYPE: server
|
||||||
CI_BUILD_ID: ${{ github.run_id }}
|
CI_BUILD_ID: ${{ github.run_id }}
|
||||||
@@ -126,27 +126,3 @@ jobs:
|
|||||||
- name: Show bench output
|
- name: Show bench output
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
run: cat ~/frappe-bench/bench_start.log || true
|
run: cat ~/frappe-bench/bench_start.log || true
|
||||||
|
|
||||||
- name: Upload coverage data
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: coverage-${{ matrix.container }}
|
|
||||||
path: /home/runner/frappe-bench/sites/coverage.xml
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
name: Coverage Wrap Up
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Clone
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Download artifacts
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
|
|
||||||
- name: Upload coverage data
|
|
||||||
uses: codecov/codecov-action@v2
|
|
||||||
with:
|
|
||||||
name: MariaDB
|
|
||||||
fail_ci_if_error: true
|
|
||||||
verbose: true
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"branches": ["version-13"],
|
"branches": ["version-14"],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@semantic-release/commit-analyzer", {
|
"@semantic-release/commit-analyzer", {
|
||||||
"preset": "angular",
|
"preset": "angular",
|
||||||
@@ -21,4 +21,4 @@
|
|||||||
],
|
],
|
||||||
"@semantic-release/github"
|
"@semantic-release/github"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import inspect
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
__version__ = "15.0.0-dev"
|
__version__ = "15.0.0"
|
||||||
|
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ def create_merge_logs(invoice_by_customer, closing_entry=None):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
message_log = frappe.message_log.pop() if frappe.message_log else str(e)
|
message_log = frappe.message_log.pop() if frappe.message_log else str(e)
|
||||||
error_message = safe_load_json(message_log)
|
error_message = get_error_message(message_log)
|
||||||
|
|
||||||
if closing_entry:
|
if closing_entry:
|
||||||
closing_entry.set_status(update=True, status="Failed")
|
closing_entry.set_status(update=True, status="Failed")
|
||||||
@@ -483,7 +483,7 @@ def cancel_merge_logs(merge_logs, closing_entry=None):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
message_log = frappe.message_log.pop() if frappe.message_log else str(e)
|
message_log = frappe.message_log.pop() if frappe.message_log else str(e)
|
||||||
error_message = safe_load_json(message_log)
|
error_message = get_error_message(message_log)
|
||||||
|
|
||||||
if closing_entry:
|
if closing_entry:
|
||||||
closing_entry.set_status(update=True, status="Submitted")
|
closing_entry.set_status(update=True, status="Submitted")
|
||||||
@@ -525,10 +525,8 @@ def check_scheduler_status():
|
|||||||
frappe.throw(_("Scheduler is inactive. Cannot enqueue job."), title=_("Scheduler Inactive"))
|
frappe.throw(_("Scheduler is inactive. Cannot enqueue job."), title=_("Scheduler Inactive"))
|
||||||
|
|
||||||
|
|
||||||
def safe_load_json(message):
|
def get_error_message(message) -> str:
|
||||||
try:
|
try:
|
||||||
json_message = json.loads(message).get("message")
|
return message["message"]
|
||||||
except Exception:
|
except Exception:
|
||||||
json_message = message
|
return str(message)
|
||||||
|
|
||||||
return json_message
|
|
||||||
|
|||||||
@@ -1066,7 +1066,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"debit_in_account_currency": (
|
"debit_in_account_currency": (
|
||||||
base_asset_amount if cwip_account_currency == self.company_currency else asset_amount
|
base_asset_amount if cwip_account_currency == self.company_currency else asset_amount
|
||||||
),
|
),
|
||||||
"cost_center": self.cost_center,
|
"cost_center": item.cost_center or self.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
},
|
},
|
||||||
item=item,
|
item=item,
|
||||||
|
|||||||
@@ -1949,6 +1949,30 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
|
|||||||
self.assertEqual(po.docstatus, 1)
|
self.assertEqual(po.docstatus, 1)
|
||||||
self.assertEqual(pi.docstatus, 1)
|
self.assertEqual(pi.docstatus, 1)
|
||||||
|
|
||||||
|
def test_default_cost_center_for_purchase(self):
|
||||||
|
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||||
|
|
||||||
|
for c_center in ["_Test Cost Center Selling", "_Test Cost Center Buying"]:
|
||||||
|
create_cost_center(cost_center_name=c_center)
|
||||||
|
|
||||||
|
item = create_item(
|
||||||
|
"_Test Cost Center Item For Purchase",
|
||||||
|
is_stock_item=1,
|
||||||
|
buying_cost_center="_Test Cost Center Buying - _TC",
|
||||||
|
selling_cost_center="_Test Cost Center Selling - _TC",
|
||||||
|
)
|
||||||
|
|
||||||
|
pi = make_purchase_invoice(
|
||||||
|
item=item.name, qty=1, rate=1000, update_stock=True, do_not_submit=True, cost_center=""
|
||||||
|
)
|
||||||
|
|
||||||
|
pi.items[0].cost_center = ""
|
||||||
|
pi.set_missing_values()
|
||||||
|
pi.calculate_taxes_and_totals()
|
||||||
|
pi.save()
|
||||||
|
|
||||||
|
self.assertEqual(pi.items[0].cost_center, "_Test Cost Center Buying - _TC")
|
||||||
|
|
||||||
|
|
||||||
def set_advance_flag(company, flag, default_account):
|
def set_advance_flag(company, flag, default_account):
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class StockController(AccountsController):
|
|||||||
elif self.doctype in ["Purchase Receipt", "Purchase Invoice"] and self.docstatus == 1:
|
elif self.doctype in ["Purchase Receipt", "Purchase Invoice"] and self.docstatus == 1:
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
gl_entries = self.get_asset_gl_entry(gl_entries)
|
gl_entries = self.get_asset_gl_entry(gl_entries)
|
||||||
|
update_regional_gl_entries(gl_entries, self)
|
||||||
make_gl_entries(gl_entries, from_repost=from_repost)
|
make_gl_entries(gl_entries, from_repost=from_repost)
|
||||||
|
|
||||||
def validate_serialized_batch(self):
|
def validate_serialized_batch(self):
|
||||||
@@ -855,8 +856,9 @@ class StockController(AccountsController):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def show_accounting_ledger_preview(company, doctype, docname):
|
def show_accounting_ledger_preview(company, doctype, docname):
|
||||||
filters = {"company": company, "include_dimensions": 1}
|
filters = frappe._dict(company=company, include_dimensions=1)
|
||||||
doc = frappe.get_doc(doctype, docname)
|
doc = frappe.get_doc(doctype, docname)
|
||||||
|
doc.run_method("before_gl_preview")
|
||||||
|
|
||||||
gl_columns, gl_data = get_accounting_ledger_preview(doc, filters)
|
gl_columns, gl_data = get_accounting_ledger_preview(doc, filters)
|
||||||
|
|
||||||
@@ -867,8 +869,9 @@ def show_accounting_ledger_preview(company, doctype, docname):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def show_stock_ledger_preview(company, doctype, docname):
|
def show_stock_ledger_preview(company, doctype, docname):
|
||||||
filters = {"company": company}
|
filters = frappe._dict(company=company)
|
||||||
doc = frappe.get_doc(doctype, docname)
|
doc = frappe.get_doc(doctype, docname)
|
||||||
|
doc.run_method("before_sl_preview")
|
||||||
|
|
||||||
sl_columns, sl_data = get_stock_ledger_preview(doc, filters)
|
sl_columns, sl_data = get_stock_ledger_preview(doc, filters)
|
||||||
|
|
||||||
@@ -1216,3 +1219,8 @@ def create_item_wise_repost_entries(voucher_type, voucher_no, allow_zero_rate=Fa
|
|||||||
repost_entries.append(repost_entry)
|
repost_entries.append(repost_entry)
|
||||||
|
|
||||||
return repost_entries
|
return repost_entries
|
||||||
|
|
||||||
|
|
||||||
|
@erpnext.allow_regional
|
||||||
|
def update_regional_gl_entries(gl_list, doc):
|
||||||
|
return
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0 12C0 5.37258 5.37258 0 12 0H88C94.6274 0 100 5.37258 100 12V88C100 94.6274 94.6274 100 88 100H12C5.37258 100 0 94.6274 0 88V12Z" fill="#0089FF"/>
|
<path d="M0 12C0 5.37258 5.37258 0 12 0H88C94.6274 0 100 5.37258 100 12V88C100 94.6274 94.6274 100 88 100H12C5.37258 100 0 94.6274 0 88V12Z" fill="#171717"/>
|
||||||
<path d="M65.7097 32.9462H67.3871V24H33V32.9462H43.9032H65.7097Z" fill="white"/>
|
<path d="M65.7097 32.9462H67.3871V24H33V32.9462H43.9032H65.7097Z" fill="white"/>
|
||||||
<path d="M43.9032 66.2151V53.914H65.7097V44.9677H43.9032H33V75.1613H67.6667V66.2151H43.9032Z" fill="white"/>
|
<path d="M43.9032 66.2151V53.914H65.7097V44.9677H43.9032H33V75.1613H67.6667V66.2151H43.9032Z" fill="white"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0 12C0 5.37258 5.37258 0 12 0H88C94.6274 0 100 5.37258 100 12V88C100 94.6274 94.6274 100 88 100H12C5.37258 100 0 94.6274 0 88V12Z" fill="#0089FF"/>
|
<path d="M0 12C0 5.37258 5.37258 0 12 0H88C94.6274 0 100 5.37258 100 12V88C100 94.6274 94.6274 100 88 100H12C5.37258 100 0 94.6274 0 88V12Z" fill="#171717"/>
|
||||||
<path d="M65.7097 32.9462H67.3871V24H33V32.9462H43.9032H65.7097Z" fill="white"/>
|
<path d="M65.7097 32.9462H67.3871V24H33V32.9462H43.9032H65.7097Z" fill="white"/>
|
||||||
<path d="M43.9032 66.2151V53.914H65.7097V44.9677H43.9032H33V75.1613H67.6667V66.2151H43.9032Z" fill="white"/>
|
<path d="M43.9032 66.2151V53.914H65.7097V44.9677H43.9032H33V75.1613H67.6667V66.2151H43.9032Z" fill="white"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
@@ -62,7 +62,7 @@ frappe.ui.form.on('Delivery Trip', {
|
|||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, __("Get customers from"));
|
}, __("Get stops from"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -907,6 +907,8 @@ def create_item(
|
|||||||
opening_stock=0,
|
opening_stock=0,
|
||||||
is_fixed_asset=0,
|
is_fixed_asset=0,
|
||||||
asset_category=None,
|
asset_category=None,
|
||||||
|
buying_cost_center=None,
|
||||||
|
selling_cost_center=None,
|
||||||
company="_Test Company",
|
company="_Test Company",
|
||||||
):
|
):
|
||||||
if not frappe.db.exists("Item", item_code):
|
if not frappe.db.exists("Item", item_code):
|
||||||
@@ -924,7 +926,15 @@ def create_item(
|
|||||||
item.is_purchase_item = is_purchase_item
|
item.is_purchase_item = is_purchase_item
|
||||||
item.is_customer_provided_item = is_customer_provided_item
|
item.is_customer_provided_item = is_customer_provided_item
|
||||||
item.customer = customer or ""
|
item.customer = customer or ""
|
||||||
item.append("item_defaults", {"default_warehouse": warehouse, "company": company})
|
item.append(
|
||||||
|
"item_defaults",
|
||||||
|
{
|
||||||
|
"default_warehouse": warehouse,
|
||||||
|
"company": company,
|
||||||
|
"selling_cost_center": selling_cost_center,
|
||||||
|
"buying_cost_center": buying_cost_center,
|
||||||
|
},
|
||||||
|
)
|
||||||
item.save()
|
item.save()
|
||||||
else:
|
else:
|
||||||
item = frappe.get_doc("Item", item_code)
|
item = frappe.get_doc("Item", item_code)
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account)
|
self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account)
|
||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
self.get_asset_gl_entry(gl_entries)
|
self.get_asset_gl_entry(gl_entries)
|
||||||
|
update_regional_gl_entries(gl_entries, self)
|
||||||
|
|
||||||
return process_gl_map(gl_entries)
|
return process_gl_map(gl_entries)
|
||||||
|
|
||||||
@@ -821,16 +822,14 @@ class PurchaseReceipt(BuyingController):
|
|||||||
po_details.append(d.purchase_order_item)
|
po_details.append(d.purchase_order_item)
|
||||||
|
|
||||||
if po_details:
|
if po_details:
|
||||||
updated_pr += update_billed_amount_based_on_po(po_details, update_modified)
|
updated_pr += update_billed_amount_based_on_po(po_details, update_modified, self)
|
||||||
|
|
||||||
for pr in set(updated_pr):
|
for pr in set(updated_pr):
|
||||||
pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
|
pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
|
||||||
update_billing_percentage(pr_doc, update_modified=update_modified)
|
update_billing_percentage(pr_doc, update_modified=update_modified)
|
||||||
|
|
||||||
self.load_from_db()
|
|
||||||
|
|
||||||
|
def update_billed_amount_based_on_po(po_details, update_modified=True, pr_doc=None):
|
||||||
def update_billed_amount_based_on_po(po_details, update_modified=True):
|
|
||||||
po_billed_amt_details = get_billed_amount_against_po(po_details)
|
po_billed_amt_details = get_billed_amount_against_po(po_details)
|
||||||
|
|
||||||
# Get all Purchase Receipt Item rows against the Purchase Order Items
|
# Get all Purchase Receipt Item rows against the Purchase Order Items
|
||||||
@@ -859,13 +858,19 @@ def update_billed_amount_based_on_po(po_details, update_modified=True):
|
|||||||
po_billed_amt_details[pr_item.purchase_order_item] = billed_against_po
|
po_billed_amt_details[pr_item.purchase_order_item] = billed_against_po
|
||||||
|
|
||||||
if pr_item.billed_amt != billed_amt_agianst_pr:
|
if pr_item.billed_amt != billed_amt_agianst_pr:
|
||||||
frappe.db.set_value(
|
# update existing doc if possible
|
||||||
"Purchase Receipt Item",
|
if pr_doc and pr_item.parent == pr_doc.name:
|
||||||
pr_item.name,
|
pr_item = next((item for item in pr_doc.items if item.name == pr_item.name), None)
|
||||||
"billed_amt",
|
pr_item.db_set("billed_amt", billed_amt_agianst_pr, update_modified=update_modified)
|
||||||
billed_amt_agianst_pr,
|
|
||||||
update_modified=update_modified,
|
else:
|
||||||
)
|
frappe.db.set_value(
|
||||||
|
"Purchase Receipt Item",
|
||||||
|
pr_item.name,
|
||||||
|
"billed_amt",
|
||||||
|
billed_amt_agianst_pr,
|
||||||
|
update_modified=update_modified,
|
||||||
|
)
|
||||||
|
|
||||||
updated_pr.append(pr_item.parent)
|
updated_pr.append(pr_item.parent)
|
||||||
|
|
||||||
@@ -941,9 +946,6 @@ def get_billed_amount_against_po(po_items):
|
|||||||
|
|
||||||
|
|
||||||
def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate=False):
|
def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate=False):
|
||||||
# Reload as billed amount was set in db directly
|
|
||||||
pr_doc.load_from_db()
|
|
||||||
|
|
||||||
# Update Billing % based on pending accepted qty
|
# Update Billing % based on pending accepted qty
|
||||||
total_amount, total_billed_amount = 0, 0
|
total_amount, total_billed_amount = 0, 0
|
||||||
item_wise_returned_qty = get_item_wise_returned_qty(pr_doc)
|
item_wise_returned_qty = get_item_wise_returned_qty(pr_doc)
|
||||||
@@ -969,7 +971,6 @@ def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate
|
|||||||
|
|
||||||
percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6)
|
percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6)
|
||||||
pr_doc.db_set("per_billed", percent_billed)
|
pr_doc.db_set("per_billed", percent_billed)
|
||||||
pr_doc.load_from_db()
|
|
||||||
|
|
||||||
if update_modified:
|
if update_modified:
|
||||||
pr_doc.set_status(update=True)
|
pr_doc.set_status(update=True)
|
||||||
@@ -1255,3 +1256,8 @@ def get_item_account_wise_additional_cost(purchase_document):
|
|||||||
|
|
||||||
def on_doctype_update():
|
def on_doctype_update():
|
||||||
frappe.db.add_index("Purchase Receipt", ["supplier", "is_return", "return_against"])
|
frappe.db.add_index("Purchase Receipt", ["supplier", "is_return", "return_against"])
|
||||||
|
|
||||||
|
|
||||||
|
@erpnext.allow_regional
|
||||||
|
def update_regional_gl_entries(gl_list, doc):
|
||||||
|
return
|
||||||
|
|||||||
@@ -737,6 +737,12 @@ def get_default_cost_center(args, item=None, item_group=None, brand=None, compan
|
|||||||
data = frappe.get_attr(path)(args.get("item_code"), company)
|
data = frappe.get_attr(path)(args.get("item_code"), company)
|
||||||
|
|
||||||
if data and (data.selling_cost_center or data.buying_cost_center):
|
if data and (data.selling_cost_center or data.buying_cost_center):
|
||||||
|
if args.get("customer") and data.selling_cost_center:
|
||||||
|
return data.selling_cost_center
|
||||||
|
|
||||||
|
elif args.get("supplier") and data.buying_cost_center:
|
||||||
|
return data.buying_cost_center
|
||||||
|
|
||||||
return data.selling_cost_center or data.buying_cost_center
|
return data.selling_cost_center or data.buying_cost_center
|
||||||
|
|
||||||
if not cost_center and args.get("cost_center"):
|
if not cost_center and args.get("cost_center"):
|
||||||
|
|||||||
Reference in New Issue
Block a user