f7780cdb58
1. 'Party type' and 'Party' filters have been added 2. checkbox to include Amount in Acccount Currency 3. Grouping vouchers on Party 4. Replaced Company with Posting Date
231 lines
5.8 KiB
Python
231 lines
5.8 KiB
Python
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
|
# For license information, please see license.txt
|
|
|
|
from collections import OrderedDict
|
|
|
|
import frappe
|
|
from frappe import _, qb
|
|
from frappe.query_builder import Criterion
|
|
|
|
|
|
class PaymentLedger(object):
|
|
def __init__(self, filters=None):
|
|
self.filters = filters
|
|
self.columns, self.data = [], []
|
|
self.voucher_dict = OrderedDict()
|
|
self.voucher_amount = []
|
|
self.ple = qb.DocType("Payment Ledger Entry")
|
|
|
|
def init_voucher_dict(self):
|
|
if self.voucher_amount:
|
|
# for each ple, using group_by_key to create a key and assign it to +/- list
|
|
for ple in self.voucher_amount:
|
|
group_by_key = None
|
|
if not self.filters.group_party:
|
|
group_by_key = (ple.against_voucher_type, ple.against_voucher_no, ple.party)
|
|
else:
|
|
group_by_key = (ple.party_type, ple.party)
|
|
|
|
target = None
|
|
if ple.amount > 0:
|
|
target = self.voucher_dict.setdefault(group_by_key, {}).setdefault("increase", [])
|
|
else:
|
|
target = self.voucher_dict.setdefault(group_by_key, {}).setdefault("decrease", [])
|
|
|
|
# this if condition will lose unassigned ple entries(against_voucher doc doesn't have ple)
|
|
# need to somehow include the stray entries as well.
|
|
if target is not None:
|
|
entry = frappe._dict(
|
|
posting_date=ple.posting_date,
|
|
account=ple.account,
|
|
party_type=ple.party_type,
|
|
party=ple.party,
|
|
voucher_type=ple.voucher_type,
|
|
voucher_no=ple.voucher_no,
|
|
against_voucher_type=ple.against_voucher_type,
|
|
against_voucher_no=ple.against_voucher_no,
|
|
amount=ple.amount,
|
|
currency=ple.account_currency,
|
|
)
|
|
|
|
if self.filters.include_account_currency:
|
|
entry["amount_in_account_currency"] = ple.amount_in_account_currency
|
|
|
|
target.append(entry)
|
|
|
|
def build_data(self):
|
|
self.data.clear()
|
|
|
|
for value in self.voucher_dict.values():
|
|
voucher_data = []
|
|
if value.get("increase"):
|
|
voucher_data.extend(value.get("increase"))
|
|
if value.get("decrease"):
|
|
voucher_data.extend(value.get("decrease"))
|
|
|
|
if voucher_data:
|
|
# balance row
|
|
total = 0
|
|
total_in_account_currency = 0
|
|
|
|
for x in voucher_data:
|
|
total += x.amount
|
|
if self.filters.include_account_currency:
|
|
total_in_account_currency += x.amount_in_account_currency
|
|
|
|
entry = frappe._dict(
|
|
against_voucher_no="Outstanding:",
|
|
amount=total,
|
|
currency=voucher_data[0].currency,
|
|
)
|
|
|
|
if self.filters.include_account_currency:
|
|
entry["amount_in_account_currency"] = total_in_account_currency
|
|
|
|
voucher_data.append(entry)
|
|
|
|
# empty row
|
|
voucher_data.append(frappe._dict())
|
|
self.data.extend(voucher_data)
|
|
|
|
def build_conditions(self):
|
|
self.conditions = []
|
|
|
|
if self.filters.company:
|
|
self.conditions.append(self.ple.company == self.filters.company)
|
|
|
|
if self.filters.account:
|
|
self.conditions.append(self.ple.account.isin(self.filters.account))
|
|
|
|
if self.filters.period_start_date:
|
|
self.conditions.append(self.ple.posting_date.gte(self.filters.period_start_date))
|
|
|
|
if self.filters.period_end_date:
|
|
self.conditions.append(self.ple.posting_date.lte(self.filters.period_end_date))
|
|
|
|
if self.filters.voucher_no:
|
|
self.conditions.append(self.ple.voucher_no == self.filters.voucher_no)
|
|
|
|
if self.filters.against_voucher_no:
|
|
self.conditions.append(self.ple.against_voucher_no == self.filters.against_voucher_no)
|
|
|
|
if self.filters.party_type:
|
|
self.conditions.append(self.ple.party_type == self.filters.party_type)
|
|
|
|
if self.filters.party:
|
|
self.conditions.append(self.ple.party.isin(self.filters.party))
|
|
|
|
def get_data(self):
|
|
ple = self.ple
|
|
|
|
self.build_conditions()
|
|
|
|
# fetch data from table
|
|
self.voucher_amount = (
|
|
qb.from_(ple)
|
|
.select(ple.star)
|
|
.where(ple.delinked == 0)
|
|
.where(Criterion.all(self.conditions))
|
|
.run(as_dict=True)
|
|
)
|
|
|
|
def get_columns(self):
|
|
options = None
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Posting Date"),
|
|
fieldname="posting_date",
|
|
fieldtype="Date",
|
|
options=options,
|
|
width="100",
|
|
)
|
|
)
|
|
|
|
self.columns.append(
|
|
dict(label=_("Account"), fieldname="account", fieldtype="data", options=options, width="100")
|
|
)
|
|
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Party Type"), fieldname="party_type", fieldtype="data", options=options, width="100"
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(label=_("Party"), fieldname="party", fieldtype="data", options=options, width="100")
|
|
)
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Voucher Type"),
|
|
fieldname="voucher_type",
|
|
fieldtype="data",
|
|
options=options,
|
|
width="100",
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Voucher No"),
|
|
fieldname="voucher_no",
|
|
fieldtype="Dynamic Link",
|
|
options="voucher_type",
|
|
width="100",
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Against Voucher Type"),
|
|
fieldname="against_voucher_type",
|
|
fieldtype="data",
|
|
options=options,
|
|
width="100",
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Against Voucher No"),
|
|
fieldname="against_voucher_no",
|
|
fieldtype="Dynamic Link",
|
|
options="against_voucher_type",
|
|
width="100",
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Amount"),
|
|
fieldname="amount",
|
|
fieldtype="Currency",
|
|
options="Company:company:default_currency",
|
|
width="100",
|
|
)
|
|
)
|
|
|
|
if self.filters.include_account_currency:
|
|
self.columns.append(
|
|
dict(
|
|
label=_("Amount in Account Currency"),
|
|
fieldname="amount_in_account_currency",
|
|
fieldtype="Currency",
|
|
options="currency",
|
|
width="100",
|
|
)
|
|
)
|
|
self.columns.append(
|
|
dict(label=_("Currency"), fieldname="currency", fieldtype="Currency", hidden=True)
|
|
)
|
|
|
|
def run(self):
|
|
self.get_columns()
|
|
self.get_data()
|
|
|
|
# initialize dictionary and group using key
|
|
self.init_voucher_dict()
|
|
|
|
# convert dictionary to list and add balance rows
|
|
self.build_data()
|
|
|
|
return self.columns, self.data
|
|
|
|
|
|
def execute(filters=None):
|
|
return PaymentLedger(filters).run()
|