Merge pull request #34052 from frappe/version-13-hotfix

chore: release v13
This commit is contained in:
Deepesh Garg
2023-02-14 16:07:17 +05:30
committed by GitHub
18 changed files with 549 additions and 400 deletions

View File

@@ -1,38 +1,38 @@
{ {
"country_code": "de", "country_code": "de",
"name": "SKR03 mit Kontonummern", "name": "SKR03 mit Kontonummern",
"tree": { "tree": {
"Aktiva": { "Aktiva": {
"is_group": 1, "is_group": 1,
"root_type": "Asset", "root_type": "Asset",
"A - Anlagevermögen": { "A - Anlagevermögen": {
"is_group": 1, "is_group": 1,
"EDV-Software": { "EDV-Software": {
"account_number": "0027", "account_number": "0027",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Gesch\u00e4ftsausstattung": { "Geschäftsausstattung": {
"account_number": "0410", "account_number": "0410",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"B\u00fcroeinrichtung": { "Büroeinrichtung": {
"account_number": "0420", "account_number": "0420",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Darlehen": { "Darlehen": {
"account_number": "0565" "account_number": "0565"
}, },
"Maschinen": { "Maschinen": {
"account_number": "0210", "account_number": "0210",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Betriebsausstattung": { "Betriebsausstattung": {
"account_number": "0400", "account_number": "0400",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Ladeneinrichtung": { "Ladeneinrichtung": {
"account_number": "0430", "account_number": "0430",
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Accumulated Depreciation": { "Accumulated Depreciation": {
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
@@ -60,36 +60,46 @@
"Durchlaufende Posten": { "Durchlaufende Posten": {
"account_number": "1590" "account_number": "1590"
}, },
"Gewinnermittlung \u00a74/3 nicht Ergebniswirksam": { "Verrechnungskonto Gewinnermittlung § 4 Abs. 3 EStG, nicht ergebniswirksam": {
"account_number": "1371" "account_number": "1371"
}, },
"Abziehbare Vorsteuer": { "Abziehbare Vorsteuer": {
"account_type": "Tax",
"is_group": 1, "is_group": 1,
"Abziehbare Vorsteuer 7%": { "Abziehbare Vorsteuer 7 %": {
"account_number": "1571" "account_number": "1571",
"account_type": "Tax",
"tax_rate": 7.0
}, },
"Abziehbare Vorsteuer 19%": { "Abziehbare Vorsteuer 19 %": {
"account_number": "1576" "account_number": "1576",
"account_type": "Tax",
"tax_rate": 19.0
}, },
"Abziehbare Vorsteuer nach \u00a713b UStG 19%": { "Abziehbare Vorsteuer nach § 13b UStG 19 %": {
"account_number": "1577" "account_number": "1577",
}, "account_type": "Tax",
"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": { "tax_rate": 19.0
"account_number": "3120"
} }
} }
}, },
"III. Wertpapiere": { "III. Wertpapiere": {
"is_group": 1 "is_group": 1,
"Anteile an verbundenen Unternehmen (Umlaufvermögen)": {
"account_number": "1340"
},
"Anteile an herrschender oder mit Mehrheit beteiligter Gesellschaft": {
"account_number": "1344"
},
"Sonstige Wertpapiere": {
"account_number": "1348"
}
}, },
"IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks.": { "IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks.": {
"is_group": 1, "is_group": 1,
"Kasse": { "Kasse": {
"account_type": "Cash",
"is_group": 1, "is_group": 1,
"account_type": "Cash",
"Kasse": { "Kasse": {
"is_group": 1,
"account_number": "1000", "account_number": "1000",
"account_type": "Cash" "account_type": "Cash"
} }
@@ -111,21 +121,21 @@
"C - Rechnungsabgrenzungsposten": { "C - Rechnungsabgrenzungsposten": {
"is_group": 1, "is_group": 1,
"Aktive Rechnungsabgrenzung": { "Aktive Rechnungsabgrenzung": {
"account_number": "0980" "account_number": "0980"
} }
}, },
"D - Aktive latente Steuern": { "D - Aktive latente Steuern": {
"is_group": 1, "is_group": 1,
"Aktive latente Steuern": { "Aktive latente Steuern": {
"account_number": "0983" "account_number": "0983"
} }
}, },
"E - Aktiver Unterschiedsbetrag aus der Vermögensverrechnung": { "E - Aktiver Unterschiedsbetrag aus der Vermögensverrechnung": {
"is_group": 1 "is_group": 1
} }
}, },
"Passiva": { "Passiva": {
"is_group": 1, "is_group": 1,
"root_type": "Liability", "root_type": "Liability",
"A. Eigenkapital": { "A. Eigenkapital": {
"is_group": 1, "is_group": 1,
@@ -200,26 +210,32 @@
}, },
"Umsatzsteuer": { "Umsatzsteuer": {
"is_group": 1, "is_group": 1,
"account_type": "Tax", "Umsatzsteuer 7 %": {
"Umsatzsteuer 7%": { "account_number": "1771",
"account_number": "1771" "account_type": "Tax",
"tax_rate": 7.0
}, },
"Umsatzsteuer 19%": { "Umsatzsteuer 19 %": {
"account_number": "1776" "account_number": "1776",
"account_type": "Tax",
"tax_rate": 19.0
}, },
"Umsatzsteuer-Vorauszahlung": { "Umsatzsteuer-Vorauszahlung": {
"account_number": "1780" "account_number": "1780",
"account_type": "Tax"
}, },
"Umsatzsteuer-Vorauszahlung 1/11": { "Umsatzsteuer-Vorauszahlung 1/11": {
"account_number": "1781" "account_number": "1781"
}, },
"Umsatzsteuer \u00a7 13b UStG 19%": { "Umsatzsteuer nach § 13b UStG 19 %": {
"account_number": "1787" "account_number": "1787",
"account_type": "Tax",
"tax_rate": 19.0
}, },
"Umsatzsteuer Vorjahr": { "Umsatzsteuer Vorjahr": {
"account_number": "1790" "account_number": "1790"
}, },
"Umsatzsteuer fr\u00fchere Jahre": { "Umsatzsteuer frühere Jahre": {
"account_number": "1791" "account_number": "1791"
} }
} }
@@ -234,44 +250,56 @@
"E. Passive latente Steuern": { "E. Passive latente Steuern": {
"is_group": 1 "is_group": 1
} }
}, },
"Erl\u00f6se u. Ertr\u00e4ge 2/8": { "Erlöse u. Erträge 2/8": {
"is_group": 1, "is_group": 1,
"root_type": "Income", "root_type": "Income",
"Erl\u00f6skonten 8": { "Erlöskonten 8": {
"is_group": 1, "is_group": 1,
"Erl\u00f6se": { "Erlöse": {
"account_number": "8200", "account_number": "8200",
"account_type": "Income Account" "account_type": "Income Account"
}, },
"Erl\u00f6se USt. 19%": { "Erlöse USt. 19 %": {
"account_number": "8400", "account_number": "8400",
"account_type": "Income Account" "account_type": "Income Account"
}, },
"Erl\u00f6se USt. 7%": { "Erlöse USt. 7 %": {
"account_number": "8300", "account_number": "8300",
"account_type": "Income Account" "account_type": "Income Account"
} }
}, },
"Ertragskonten 2": { "Ertragskonten 2": {
"is_group": 1, "is_group": 1,
"sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": { "sonstige Zinsen und ähnliche Erträge": {
"account_number": "2650", "account_number": "2650",
"account_type": "Income Account" "account_type": "Income Account"
}, },
"Au\u00dferordentliche Ertr\u00e4ge": { "Außerordentliche Erträge": {
"account_number": "2500", "account_number": "2500",
"account_type": "Income Account" "account_type": "Income Account"
}, },
"Sonstige Ertr\u00e4ge": { "Sonstige Erträge": {
"account_number": "2700", "account_number": "2700",
"account_type": "Income Account" "account_type": "Income Account"
} }
} }
}, },
"Aufwendungen 2/4": { "Aufwendungen 2/4": {
"is_group": 1, "is_group": 1,
"root_type": "Expense", "root_type": "Expense",
"Fremdleistungen": {
"account_number": "3100",
"account_type": "Expense Account"
},
"Fremdleistungen ohne Vorsteuer": {
"account_number": "3109",
"account_type": "Expense Account"
},
"Bauleistungen eines im Inland ansässigen Unternehmers 19 % Vorsteuer und 19 % Umsatzsteuer": {
"account_number": "3120",
"account_type": "Expense Account"
},
"Wareneingang": { "Wareneingang": {
"account_number": "3200" "account_number": "3200"
}, },
@@ -298,234 +326,234 @@
"Gegenkonto 4996-4998": { "Gegenkonto 4996-4998": {
"account_number": "4999" "account_number": "4999"
}, },
"Abschreibungen": { "Abschreibungen": {
"is_group": 1, "is_group": 1,
"Abschreibungen auf Sachanlagen (ohne AfA auf Kfz und Gebäude)": { "Abschreibungen auf Sachanlagen (ohne AfA auf Kfz und Gebäude)": {
"account_number": "4830", "account_number": "4830",
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"Abschreibungen auf Gebäude": { "Abschreibungen auf Gebäude": {
"account_number": "4831", "account_number": "4831",
"account_type": "Depreciation" "account_type": "Depreciation"
}, },
"Abschreibungen auf Kfz": { "Abschreibungen auf Kfz": {
"account_number": "4832", "account_number": "4832",
"account_type": "Depreciation" "account_type": "Depreciation"
}, },
"Sofortabschreibung GWG": { "Sofortabschreibung GWG": {
"account_number": "4855", "account_number": "4855",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Kfz-Kosten": { "Kfz-Kosten": {
"is_group": 1, "is_group": 1,
"Kfz-Steuer": { "Kfz-Steuer": {
"account_number": "4510", "account_number": "4510",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Kfz-Versicherungen": { "Kfz-Versicherungen": {
"account_number": "4520", "account_number": "4520",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"laufende Kfz-Betriebskosten": { "laufende Kfz-Betriebskosten": {
"account_number": "4530", "account_number": "4530",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Kfz-Reparaturen": { "Kfz-Reparaturen": {
"account_number": "4540", "account_number": "4540",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Fremdfahrzeuge": { "Fremdfahrzeuge": {
"account_number": "4570", "account_number": "4570",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"sonstige Kfz-Kosten": { "sonstige Kfz-Kosten": {
"account_number": "4580", "account_number": "4580",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Personalkosten": { "Personalkosten": {
"is_group": 1, "is_group": 1,
"Geh\u00e4lter": { "Gehälter": {
"account_number": "4120", "account_number": "4120",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"gesetzliche soziale Aufwendungen": { "gesetzliche soziale Aufwendungen": {
"account_number": "4130", "account_number": "4130",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Aufwendungen f\u00fcr Altersvorsorge": { "Aufwendungen für Altersvorsorge": {
"account_number": "4165", "account_number": "4165",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Verm\u00f6genswirksame Leistungen": { "Vermögenswirksame Leistungen": {
"account_number": "4170", "account_number": "4170",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Aushilfsl\u00f6hne": { "Aushilfslöhne": {
"account_number": "4190", "account_number": "4190",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Raumkosten": { "Raumkosten": {
"is_group": 1, "is_group": 1,
"Miete und Nebenkosten": { "Miete und Nebenkosten": {
"account_number": "4210", "account_number": "4210",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Gas, Wasser, Strom (Verwaltung, Vertrieb)": { "Gas, Wasser, Strom (Verwaltung, Vertrieb)": {
"account_number": "4240", "account_number": "4240",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Reinigung": { "Reinigung": {
"account_number": "4250", "account_number": "4250",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Reparatur/Instandhaltung": { "Reparatur/Instandhaltung": {
"is_group": 1, "is_group": 1,
"Reparatur u. Instandh. von Anlagen/Maschinen u. Betriebs- u. Gesch\u00e4ftsausst.": { "Reparaturen und Instandhaltungen von anderen Anlagen und Betriebs- und Geschäftsausstattung": {
"account_number": "4805", "account_number": "4805",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Versicherungsbeitr\u00e4ge": { "Versicherungsbeiträge": {
"is_group": 1, "is_group": 1,
"Versicherungen": { "Versicherungen": {
"account_number": "4360", "account_number": "4360",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Beitr\u00e4ge": { "Beiträge": {
"account_number": "4380", "account_number": "4380",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"sonstige Ausgaben": { "sonstige Ausgaben": {
"account_number": "4390", "account_number": "4390",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": { "steuerlich abzugsfähige Verspätungszuschläge und Zwangsgelder": {
"account_number": "4396", "account_number": "4396",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Werbe-/Reisekosten": { "Werbe-/Reisekosten": {
"is_group": 1, "is_group": 1,
"Werbekosten": { "Werbekosten": {
"account_number": "4610", "account_number": "4610",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Aufmerksamkeiten": { "Aufmerksamkeiten": {
"account_number": "4653", "account_number": "4653",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"nicht abzugsf\u00e4hige Betriebsausg. aus Werbe-, Repr\u00e4s.- u. Reisekosten": { "nicht abzugsfähige Betriebsausg. aus Werbe-, Repräs.- u. Reisekosten": {
"account_number": "4665", "account_number": "4665",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Reisekosten Unternehmer": { "Reisekosten Unternehmer": {
"account_number": "4670", "account_number": "4670",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"verschiedene Kosten": { "verschiedene Kosten": {
"is_group": 1, "is_group": 1,
"Porto": { "Porto": {
"account_number": "4910", "account_number": "4910",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Telekom": { "Telekom": {
"account_number": "4920", "account_number": "4920",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Mobilfunk D2": { "Mobilfunk D2": {
"account_number": "4921", "account_number": "4921",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Internet": { "Internet": {
"account_number": "4922", "account_number": "4922",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"B\u00fcrobedarf": { "Bürobedarf": {
"account_number": "4930", "account_number": "4930",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Zeitschriften, B\u00fccher": { "Zeitschriften, Bücher": {
"account_number": "4940", "account_number": "4940",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Fortbildungskosten": { "Fortbildungskosten": {
"account_number": "4945", "account_number": "4945",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Buchf\u00fchrungskosten": { "Buchführungskosten": {
"account_number": "4955", "account_number": "4955",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Abschlu\u00df- u. Pr\u00fcfungskosten": { "Abschluß- u. Prüfungskosten": {
"account_number": "4957", "account_number": "4957",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Nebenkosten des Geldverkehrs": { "Nebenkosten des Geldverkehrs": {
"account_number": "4970", "account_number": "4970",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Werkzeuge und Kleinger\u00e4te": { "Werkzeuge und Kleingeräte": {
"account_number": "4985", "account_number": "4985",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
}, },
"Zinsaufwendungen": { "Zinsaufwendungen": {
"is_group": 1, "is_group": 1,
"Zinsaufwendungen f\u00fcr kurzfristige Verbindlichkeiten": { "Zinsaufwendungen für kurzfristige Verbindlichkeiten": {
"account_number": "2110", "account_number": "2110",
"account_type": "Expense Account" "account_type": "Expense Account"
}, },
"Zinsaufwendungen f\u00fcr KFZ Finanzierung": { "Zinsaufwendungen für KFZ Finanzierung": {
"account_number": "2121", "account_number": "2121",
"account_type": "Expense Account" "account_type": "Expense Account"
} }
} }
}, },
"Anfangsbestand 9": { "Anfangsbestand 9": {
"is_group": 1, "is_group": 1,
"root_type": "Equity", "root_type": "Equity",
"Saldenvortragskonten": { "Saldenvortragskonten": {
"is_group": 1, "is_group": 1,
"Saldenvortrag Sachkonten": { "Saldenvortrag Sachkonten": {
"account_number": "9000" "account_number": "9000"
}, },
"Saldenvortr\u00e4ge Debitoren": { "Saldenvorträge Debitoren": {
"account_number": "9008" "account_number": "9008"
}, },
"Saldenvortr\u00e4ge Kreditoren": { "Saldenvorträge Kreditoren": {
"account_number": "9009" "account_number": "9009"
} }
} }
}, },
"Privatkonten 1": { "Privatkonten 1": {
"is_group": 1, "is_group": 1,
"root_type": "Equity", "root_type": "Equity",
"Privatentnahmen/-einlagen": { "Privatentnahmen/-einlagen": {
"is_group": 1, "is_group": 1,
"Privatentnahme allgemein": { "Privatentnahme allgemein": {
"account_number": "1800" "account_number": "1800"
}, },
"Privatsteuern": { "Privatsteuern": {
"account_number": "1810" "account_number": "1810"
}, },
"Sonderausgaben beschr\u00e4nkt abzugsf\u00e4hig": { "Sonderausgaben beschränkt abzugsfähig": {
"account_number": "1820" "account_number": "1820"
}, },
"Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig": { "Sonderausgaben unbeschränkt abzugsfähig": {
"account_number": "1830" "account_number": "1830"
}, },
"Au\u00dfergew\u00f6hnliche Belastungen": { "Außergewöhnliche Belastungen": {
"account_number": "1850" "account_number": "1850"
}, },
"Privateinlagen": { "Privateinlagen": {
"account_number": "1890" "account_number": "1890"
} }
} }
} }
} }
} }

View File

@@ -598,7 +598,7 @@ class PurchaseInvoice(BuyingController):
def make_supplier_gl_entry(self, gl_entries): def make_supplier_gl_entry(self, gl_entries):
# Checked both rounding_adjustment and rounded_total # Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total # because rounded_total had value even before introduction of posting GLE based on rounded total
grand_total = ( grand_total = (
self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
) )
@@ -799,10 +799,7 @@ class PurchaseInvoice(BuyingController):
else item.deferred_expense_account else item.deferred_expense_account
) )
if not item.is_fixed_asset: dummy, amount = self.get_amount_and_base_amount(item, None)
dummy, amount = self.get_amount_and_base_amount(item, None)
else:
amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
if provisional_accounting_for_non_stock_items: if provisional_accounting_for_non_stock_items:
if item.purchase_receipt: if item.purchase_receipt:

View File

@@ -755,6 +755,8 @@ class BuyingController(StockController, Subcontracting):
asset.purchase_date = self.posting_date asset.purchase_date = self.posting_date
asset.supplier = self.supplier asset.supplier = self.supplier
elif self.docstatus == 2: elif self.docstatus == 2:
if asset.docstatus == 2:
continue
if asset.docstatus == 0: if asset.docstatus == 0:
asset.set(field, None) asset.set(field, None)
asset.supplier = None asset.supplier = None

View File

@@ -345,7 +345,8 @@
"image_field": "website_image", "image_field": "website_image",
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2022-06-28 17:10:30.613251", "make_attachments_public": 1,
"modified": "2022-09-13 04:05:11.614087",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "E-commerce", "module": "E-commerce",
"name": "Website Item", "name": "Website Item",

View File

@@ -1,7 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt # License: GNU General Public License v3. See license.txt
import datetime import datetime
import math import math
@@ -316,6 +315,8 @@ class SalarySlip(TransactionBase):
) )
working_days = date_diff(self.end_date, self.start_date) + 1 working_days = date_diff(self.end_date, self.start_date) + 1
working_days_list = [add_days(self.start_date, i) for i in range(working_days)]
if for_preview: if for_preview:
self.total_working_days = working_days self.total_working_days = working_days
self.payment_days = working_days self.payment_days = working_days
@@ -325,6 +326,8 @@ class SalarySlip(TransactionBase):
if not cint(include_holidays_in_total_working_days): if not cint(include_holidays_in_total_working_days):
working_days -= len(holidays) working_days -= len(holidays)
working_days_list = [cstr(day) for day in working_days_list if cstr(day) not in holidays]
if working_days < 0: if working_days < 0:
frappe.throw(_("There are more holidays than working days this month.")) frappe.throw(_("There are more holidays than working days this month."))
@@ -335,7 +338,7 @@ class SalarySlip(TransactionBase):
actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays) actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays)
self.absent_days = absent self.absent_days = absent
else: else:
actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days) actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days_list)
if not lwp: if not lwp:
lwp = actual_lwp lwp = actual_lwp
@@ -458,16 +461,15 @@ class SalarySlip(TransactionBase):
def get_holidays_for_employee(self, start_date, end_date): def get_holidays_for_employee(self, start_date, end_date):
return get_holiday_dates_for_employee(self.employee, start_date, end_date) return get_holiday_dates_for_employee(self.employee, start_date, end_date)
def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days): def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days_list):
lwp = 0 lwp = 0
holidays = "','".join(holidays)
daily_wages_fraction_for_half_day = ( daily_wages_fraction_for_half_day = (
flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5 flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
) )
for d in range(working_days): for d in working_days_list:
date = add_days(cstr(getdate(self.start_date)), d) leave = get_lwp_or_ppl_for_date(d, self.employee, holidays)
leave = get_lwp_or_ppl_for_date(date, self.employee, holidays)
if leave: if leave:
equivalent_lwp_count = 0 equivalent_lwp_count = 0

View File

@@ -84,11 +84,15 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
} }
if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) { if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) {
this.frm.add_custom_button( if (frappe.boot.sysdefaults.allow_sales_order_creation_for_expired_quotation
__("Sales Order"), || (!doc.valid_till)
this.frm.cscript["Make Sales Order"], || frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) >= 0) {
__("Create") this.frm.add_custom_button(
); __("Sales Order"),
this.frm.cscript["Make Sales Order"],
__("Create")
);
}
if(doc.status!=="Ordered") { if(doc.status!=="Ordered") {
this.frm.add_custom_button(__('Set as Lost'), () => { this.frm.add_custom_button(__('Set as Lost'), () => {

View File

@@ -192,6 +192,17 @@ def get_list_context(context=None):
@frappe.whitelist() @frappe.whitelist()
def make_sales_order(source_name: str, target_doc=None): def make_sales_order(source_name: str, target_doc=None):
if not frappe.db.get_singles_value(
"Selling Settings", "allow_sales_order_creation_for_expired_quotation"
):
quotation = frappe.db.get_value(
"Quotation", source_name, ["transaction_date", "valid_till"], as_dict=1
)
if quotation.valid_till and (
quotation.valid_till < quotation.transaction_date or quotation.valid_till < getdate(nowdate())
):
frappe.throw(_("Validity period of this quotation has ended."))
return _make_sales_order(source_name, target_doc) return _make_sales_order(source_name, target_doc)

View File

@@ -126,11 +126,21 @@ class TestQuotation(FrappeTestCase):
def test_so_from_expired_quotation(self): def test_so_from_expired_quotation(self):
from erpnext.selling.doctype.quotation.quotation import make_sales_order from erpnext.selling.doctype.quotation.quotation import make_sales_order
frappe.db.set_single_value(
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0
)
quotation = frappe.copy_doc(test_records[0]) quotation = frappe.copy_doc(test_records[0])
quotation.valid_till = add_days(nowdate(), -1) quotation.valid_till = add_days(nowdate(), -1)
quotation.insert() quotation.insert()
quotation.submit() quotation.submit()
self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name)
frappe.db.set_single_value(
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1
)
make_sales_order(quotation.name) make_sales_order(quotation.name)
def test_shopping_cart_without_website_item(self): def test_shopping_cart_without_website_item(self):

View File

@@ -32,7 +32,8 @@
"sales_update_frequency", "sales_update_frequency",
"allow_multiple_items", "allow_multiple_items",
"allow_against_multiple_purchase_orders", "allow_against_multiple_purchase_orders",
"hide_tax_id" "hide_tax_id",
"allow_sales_order_creation_for_expired_quotation"
], ],
"fields": [ "fields": [
{ {
@@ -199,6 +200,12 @@
"fieldtype": "Select", "fieldtype": "Select",
"label": "Contract Naming By", "label": "Contract Naming By",
"options": "Party Name\nNaming Series" "options": "Party Name\nNaming Series"
},
{
"default": "0",
"fieldname": "allow_sales_order_creation_for_expired_quotation",
"fieldtype": "Check",
"label": "Allow Sales Order Creation For Expired Quotation"
} }
], ],
"icon": "fa fa-cog", "icon": "fa fa-cog",
@@ -206,7 +213,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"issingle": 1, "issingle": 1,
"links": [], "links": [],
"modified": "2022-03-28 12:18:06.768403", "modified": "2023-02-04 12:37:53.380857",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Selling", "module": "Selling",
"name": "Selling Settings", "name": "Selling Settings",

View File

@@ -41,8 +41,20 @@ def get_columns(filters):
{"label": _("Description"), "fieldtype": "Data", "fieldname": "description", "width": 150}, {"label": _("Description"), "fieldtype": "Data", "fieldname": "description", "width": 150},
{"label": _("Quantity"), "fieldtype": "Float", "fieldname": "quantity", "width": 150}, {"label": _("Quantity"), "fieldtype": "Float", "fieldname": "quantity", "width": 150},
{"label": _("UOM"), "fieldtype": "Link", "fieldname": "uom", "options": "UOM", "width": 100}, {"label": _("UOM"), "fieldtype": "Link", "fieldname": "uom", "options": "UOM", "width": 100},
{"label": _("Rate"), "fieldname": "rate", "options": "Currency", "width": 120}, {
{"label": _("Amount"), "fieldname": "amount", "options": "Currency", "width": 120}, "label": _("Rate"),
"fieldname": "rate",
"fieldtype": "Currency",
"options": "currency",
"width": 120,
},
{
"label": _("Amount"),
"fieldname": "amount",
"fieldtype": "Currency",
"options": "currency",
"width": 120,
},
{ {
"label": _("Sales Order"), "label": _("Sales Order"),
"fieldtype": "Link", "fieldtype": "Link",
@@ -93,8 +105,9 @@ def get_columns(filters):
}, },
{ {
"label": _("Billed Amount"), "label": _("Billed Amount"),
"fieldtype": "currency", "fieldtype": "Currency",
"fieldname": "billed_amount", "fieldname": "billed_amount",
"options": "currency",
"width": 120, "width": 120,
}, },
{ {
@@ -104,6 +117,13 @@ def get_columns(filters):
"options": "Company", "options": "Company",
"width": 100, "width": 100,
}, },
{
"label": _("Currency"),
"fieldtype": "Link",
"fieldname": "currency",
"options": "Currency",
"hidden": 1,
},
] ]
@@ -141,31 +161,12 @@ def get_data(filters):
"billed_amount": flt(record.get("billed_amt")), "billed_amount": flt(record.get("billed_amt")),
"company": record.get("company"), "company": record.get("company"),
} }
row["currency"] = frappe.get_cached_value("Company", row["company"], "default_currency")
data.append(row) data.append(row)
return data return data
def get_conditions(filters):
conditions = ""
if filters.get("item_group"):
conditions += "AND so_item.item_group = %s" % frappe.db.escape(filters.item_group)
if filters.get("from_date"):
conditions += "AND so.transaction_date >= '%s'" % filters.from_date
if filters.get("to_date"):
conditions += "AND so.transaction_date <= '%s'" % filters.to_date
if filters.get("item_code"):
conditions += "AND so_item.item_code = %s" % frappe.db.escape(filters.item_code)
if filters.get("customer"):
conditions += "AND so.customer = %s" % frappe.db.escape(filters.customer)
return conditions
def get_customer_details(): def get_customer_details():
details = frappe.get_all("Customer", fields=["name", "customer_name", "customer_group"]) details = frappe.get_all("Customer", fields=["name", "customer_name", "customer_group"])
customer_details = {} customer_details = {}
@@ -187,29 +188,50 @@ def get_item_details():
def get_sales_order_details(company_list, filters): def get_sales_order_details(company_list, filters):
conditions = get_conditions(filters) db_so = frappe.qb.DocType("Sales Order")
db_so_item = frappe.qb.DocType("Sales Order Item")
return frappe.db.sql( query = (
""" frappe.qb.from_(db_so)
SELECT .inner_join(db_so_item)
so_item.item_code, so_item.description, so_item.qty, .on(db_so_item.parent == db_so.name)
so_item.uom, so_item.base_rate, so_item.base_amount, .select(
so.name, so.transaction_date, so.customer,so.territory, db_so.name,
so.project, so_item.delivered_qty, db_so.customer,
so_item.billed_amt, so.company db_so.transaction_date,
FROM db_so.territory,
`tabSales Order` so, `tabSales Order Item` so_item db_so.project,
WHERE db_so.company,
so.name = so_item.parent db_so_item.item_code,
AND so.company in ({0}) db_so_item.description,
AND so.docstatus = 1 {1} db_so_item.qty,
""".format( db_so_item.uom,
",".join(["%s"] * len(company_list)), conditions db_so_item.base_rate,
), db_so_item.base_amount,
tuple(company_list), db_so_item.delivered_qty,
as_dict=1, (db_so_item.billed_amt * db_so.conversion_rate).as_("billed_amt"),
)
.where(db_so.docstatus == 1)
.where(db_so.company.isin(tuple(company_list)))
) )
if filters.get("item_group"):
query = query.where(db_so_item.item_group == frappe.db.escape(filters.item_group))
if filters.get("from_date"):
query = query.where(db_so.transaction_date >= filters.from_date)
if filters.get("to_date"):
query = query.where(db_so.transaction_date <= filters.to_date)
if filters.get("item_code"):
query = query.where(db_so_item.item_group == frappe.db.escape(filters.item_code))
if filters.get("customer"):
query = query.where(db_so.customer == filters.customer)
return query.run(as_dict=1)
def get_chart_data(data): def get_chart_data(data):
item_wise_sales_map = {} item_wise_sales_map = {}

View File

@@ -26,6 +26,12 @@ def boot_session(bootinfo):
frappe.db.get_single_value("Selling Settings", "default_valid_till") frappe.db.get_single_value("Selling Settings", "default_valid_till")
) )
bootinfo.sysdefaults.allow_sales_order_creation_for_expired_quotation = cint(
frappe.db.get_single_value(
"Selling Settings", "allow_sales_order_creation_for_expired_quotation"
)
)
# if no company, show a dialog box to create a new company # if no company, show a dialog box to create a new company
bootinfo.customer_count = frappe.db.sql("""SELECT count(*) FROM `tabCustomer`""")[0][0] bootinfo.customer_count = frappe.db.sql("""SELECT count(*) FROM `tabCustomer`""")[0][0]

View File

@@ -42,7 +42,7 @@ erpnext.stock.ItemDashboard = Class.extend({
let warehouse = unescape(element.attr('data-warehouse')); let warehouse = unescape(element.attr('data-warehouse'));
let actual_qty = unescape(element.attr('data-actual_qty')); let actual_qty = unescape(element.attr('data-actual_qty'));
let disable_quick_entry = Number(unescape(element.attr('data-disable_quick_entry'))); let disable_quick_entry = Number(unescape(element.attr('data-disable_quick_entry')));
let entry_type = action === "Move" ? "Material Transfer" : null; let entry_type = action === "Move" ? "Material Transfer" : "Material Receipt";
if (disable_quick_entry) { if (disable_quick_entry) {
open_stock_entry(item, warehouse, entry_type); open_stock_entry(item, warehouse, entry_type);
@@ -63,11 +63,19 @@ erpnext.stock.ItemDashboard = Class.extend({
function open_stock_entry(item, warehouse, entry_type) { function open_stock_entry(item, warehouse, entry_type) {
frappe.model.with_doctype('Stock Entry', function () { frappe.model.with_doctype('Stock Entry', function () {
var doc = frappe.model.get_new_doc('Stock Entry'); var doc = frappe.model.get_new_doc('Stock Entry');
if (entry_type) doc.stock_entry_type = entry_type; if (entry_type) {
doc.stock_entry_type = entry_type;
}
var row = frappe.model.add_child(doc, 'items'); var row = frappe.model.add_child(doc, 'items');
row.item_code = item; row.item_code = item;
row.s_warehouse = warehouse;
if (entry_type === "Material Transfer") {
row.s_warehouse = warehouse;
}
else {
row.t_warehouse = warehouse;
}
frappe.set_route('Form', doc.doctype, doc.name); frappe.set_route('Form', doc.doctype, doc.name);
}); });

View File

@@ -955,7 +955,8 @@
"image_field": "image", "image_field": "image",
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2022-04-28 04:52:10.272256", "make_attachments_public": 1,
"modified": "2022-09-13 04:08:17.431731",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Item", "name": "Item",

View File

@@ -366,10 +366,11 @@ frappe.ui.form.on('Material Request', {
frappe.ui.form.on("Material Request Item", { frappe.ui.form.on("Material Request Item", {
qty: function (frm, doctype, name) { qty: function (frm, doctype, name) {
var d = locals[doctype][name]; const item = locals[doctype][name];
if (flt(d.qty) < flt(d.min_order_qty)) { if (flt(item.qty) < flt(item.min_order_qty)) {
frappe.msgprint(__("Warning: Material Requested Qty is less than Minimum Order Qty")); frappe.msgprint(__("Warning: Material Requested Qty is less than Minimum Order Qty"));
} }
frm.events.get_item_data(frm, item, false);
}, },
from_warehouse: function(frm, doctype, name) { from_warehouse: function(frm, doctype, name) {

View File

@@ -2440,7 +2440,7 @@ def get_uom_details(item_code, uom, qty):
if not conversion_factor: if not conversion_factor:
frappe.msgprint( frappe.msgprint(
_("UOM coversion factor required for UOM: {0} in Item: {1}").format(uom, item_code) _("UOM conversion factor required for UOM: {0} in Item: {1}").format(uom, item_code)
) )
ret = {"uom": ""} ret = {"uom": ""}
else: else:

View File

@@ -1571,6 +1571,48 @@ class TestStockEntry(FrappeTestCase):
self.assertRaises(BatchExpiredError, se.save) self.assertRaises(BatchExpiredError, se.save)
def test_negative_stock_reco(self):
from erpnext.controllers.stock_controller import BatchExpiredError
from erpnext.stock.doctype.batch.test_batch import make_new_batch
frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 0)
item_code = "Test Negative Item - 001"
item_doc = create_item(item_code=item_code, is_stock_item=1, valuation_rate=10)
make_stock_entry(
item_code=item_code,
posting_date=add_days(today(), -3),
posting_time="00:00:00",
purpose="Material Receipt",
qty=10,
to_warehouse="_Test Warehouse - _TC",
do_not_save=True,
)
make_stock_entry(
item_code=item_code,
posting_date=today(),
posting_time="00:00:00",
purpose="Material Receipt",
qty=8,
from_warehouse="_Test Warehouse - _TC",
do_not_save=True,
)
sr_doc = create_stock_reconciliation(
purpose="Stock Reconciliation",
posting_date=add_days(today(), -3),
posting_time="00:00:00",
item_code=item_code,
warehouse="_Test Warehouse - _TC",
valuation_rate=10,
qty=7,
do_not_submit=True,
)
self.assertRaises(frappe.ValidationError, sr_doc.submit)
def make_serialized_item(**args): def make_serialized_item(**args):
args = frappe._dict(args) args = frappe._dict(args)

View File

@@ -62,7 +62,7 @@ def execute(filters=None):
continue continue
total_stock_value = sum(item_value[(item, item_group)]) total_stock_value = sum(item_value[(item, item_group)])
row = [item, item_group, total_stock_value] row = [item, item_map[item]["item_name"], item_group, total_stock_value]
fifo_queue = item_ageing[item]["fifo_queue"] fifo_queue = item_ageing[item]["fifo_queue"]
average_age = 0.00 average_age = 0.00
@@ -89,10 +89,11 @@ def get_columns(filters):
"""return columns""" """return columns"""
columns = [ columns = [
_("Item") + ":Link/Item:180", _("Item") + ":Link/Item:150",
_("Item Group") + "::100", _("Item Name") + ":Link/Item:150",
_("Value") + ":Currency:100", _("Item Group") + "::120",
_("Age") + ":Float:60", _("Value") + ":Currency:120",
_("Age") + ":Float:120",
] ]
return columns return columns
@@ -132,7 +133,7 @@ def get_warehouse_list(filters):
def add_warehouse_column(columns, warehouse_list): def add_warehouse_column(columns, warehouse_list):
if len(warehouse_list) > 1: if len(warehouse_list) > 1:
columns += [_("Total Qty") + ":Int:50"] columns += [_("Total Qty") + ":Int:120"]
for wh in warehouse_list: for wh in warehouse_list:
columns += [_(wh.name) + ":Int:54"] columns += [_(wh.name) + ":Int:100"]

View File

@@ -1021,7 +1021,7 @@ class update_entries_after(object):
frappe.db.set_value("Bin", bin_name, updated_values) frappe.db.set_value("Bin", bin_name, updated_values)
def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False): def get_previous_sle_of_current_voucher(args, operator="<", exclude_current_voucher=False):
"""get stock ledger entries filtered by specific posting datetime conditions""" """get stock ledger entries filtered by specific posting datetime conditions"""
args["time_format"] = "%H:%i:%s" args["time_format"] = "%H:%i:%s"
@@ -1043,11 +1043,17 @@ def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False):
and warehouse = %(warehouse)s and warehouse = %(warehouse)s
and is_cancelled = 0 and is_cancelled = 0
{voucher_condition} {voucher_condition}
and timestamp(posting_date, time_format(posting_time, %(time_format)s)) < timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s)) and (
posting_date < %(posting_date)s or
(
posting_date = %(posting_date)s and
time_format(posting_time, %(time_format)s) {operator} time_format(%(posting_time)s, %(time_format)s)
)
)
order by timestamp(posting_date, posting_time) desc, creation desc order by timestamp(posting_date, posting_time) desc, creation desc
limit 1 limit 1
for update""".format( for update""".format(
voucher_condition=voucher_condition operator=operator, voucher_condition=voucher_condition
), ),
args, args,
as_dict=1, as_dict=1,
@@ -1285,7 +1291,7 @@ def get_stock_reco_qty_shift(args):
stock_reco_qty_shift = flt(args.actual_qty) stock_reco_qty_shift = flt(args.actual_qty)
else: else:
# reco is being submitted # reco is being submitted
last_balance = get_previous_sle_of_current_voucher(args, exclude_current_voucher=True).get( last_balance = get_previous_sle_of_current_voucher(args, "<=", exclude_current_voucher=True).get(
"qty_after_transaction" "qty_after_transaction"
) )