Skip to content

Commit

Permalink
Merge pull request #1503 from CompassionCH/devel
Browse files Browse the repository at this point in the history
Accounting update
  • Loading branch information
ecino authored Mar 17, 2022
2 parents 6100155 + f972cfc commit a9bd4be
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 5 deletions.
7 changes: 6 additions & 1 deletion account_reconcile_compassion/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# pylint: disable=C8101
{
"name": "Bank Statement Reconcile for Compassion CH",
"version": "12.0.1.0.0",
"version": "12.0.1.1.0",
"author": "Compassion CH",
"license": "AGPL-3",
"category": "Finance",
Expand All @@ -40,7 +40,11 @@
"sponsorship_switzerland", # compassion-switzerland,
"mobile_app_connector", # compassion-modules
"account_bank_statement_import_camt_details", # OCA/bank-statement-import
"payment_postfinance_flex" # paid-addons
],
"external_dependencies": {"python": [
"postfinancecheckout"
]},
"data": [
"data/statement_operation.xml",
"views/account_reconcile_compassion.xml",
Expand All @@ -53,6 +57,7 @@
"views/statement_view.xml",
"views/statement_operation_view.xml",
"views/view_bank_statement_form.xml",
"views/reconcile_1015_wizard_view.xml",
],
"qweb": ["static/src/xml/account_move_reconciliation.xml"],
"auto_install": False,
Expand Down
30 changes: 30 additions & 0 deletions account_reconcile_compassion/views/reconcile_1015_wizard_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_reconcile_1015_form" model="ir.ui.view">
<field name="name">reconcile.1015.wizard.form</field>
<field name="model">reconcile.1015.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="account_id"/>
</group>
</sheet>
<footer>
<button name="reconcile_1015" type="object" string="Reconcile" class="oe_highlight"/>
</footer>
</form>
</field>
</record>

<!-- Action opening the tree view -->
<record id="action_open_reconcile_1015" model="ir.actions.act_window">
<field name="name">Reconcile 1015</field>
<field name="res_model">reconcile.1015.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>

<menuitem id="menu_open_reconcile_1015" parent="account.menu_finance_entries_actions" action="action_open_reconcile_1015" name="Reconcile 1015"/>
</odoo>
1 change: 1 addition & 0 deletions account_reconcile_compassion/wizards/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
from . import reconcile_fund_wizard
from . import reconcile_split_payment_wizard
from . import change_attribution_wizard
from . import reconcile_1015_wizard
207 changes: 207 additions & 0 deletions account_reconcile_compassion/wizards/reconcile_1015_wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
##############################################################################
#
# Copyright (C) 2022 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Emanuel Cino <[email protected]>
#
# The licence is in the file __manifest__.py
#
##############################################################################
from datetime import datetime, timedelta
from enum import Enum
from postfinancecheckout import Configuration
from postfinancecheckout.api.transaction_service_api import TransactionServiceApi

from odoo import api, models, fields, _
from odoo.tools import ormcache


class Provider(Enum):
WORLDLINE = "WORLDLINE SCHWEIZ AG"
PF_CARD = "POSTFINANCE CARD"
TWINT = "TWINT"
E_FINANCE = "POSTFINANCE E-FINANCE"


PF_MAPPING = {
Provider.WORLDLINE: "SIX Acquiring",
Provider.PF_CARD: "PostFinance Acquiring - PostFinance Card",
Provider.E_FINANCE: "PostFinance Acquiring - PostFinance E-Finance",
Provider.TWINT: "TWINT - TWINT Connector"
}


class ReconcileFundWizard(models.TransientModel):

_name = "reconcile.1015.wizard"
_description = "Wizard reconcile 1015 account"

account_id = fields.Many2one(
"account.account", "Reconcile account",
default=lambda s: s.env["account.account"].search([
("code", "=", "1015")], limit=1)
)
full_reconcile_line_ids = fields.Many2many(
"account.move.line", "reconcile_1015_reconciled", string="Reconciled lines",
readonly=True
)
partial_reconcile_line_ids = fields.Many2many(
"account.move.line", "reconcile_1015_partial_reconciled",
string="Partial reconciled lines", readonly=True
)
missing_donation_line_ids = fields.Many2many(
"account.move.line", "reconcile_1015_missing_invoice",
string="Leftover donations",
readonly=True
)

def reconcile_1015(self):
mvl_obj = self.env["account.move.line"]
credit_lines = mvl_obj.search([
("account_id", "=", self.account_id.id),
("full_reconcile_id", "=", False),
("credit", ">", 0),
("date", ">=", "2022-02-09") # Date of activation of pf_checkout
])
for cl in credit_lines:
self.reconcile_using_pf_checkout(cl)

# Compute results
if self.partial_reconcile_line_ids:
oldest_credit = min(self.partial_reconcile_line_ids.mapped("date"))
self.missing_donation_line_ids = mvl_obj.search([
("account_id", "=", self.account_id.id),
("full_reconcile_id", "=", False),
("debit", ">", 0),
("date", "<=", fields.Date.to_string(oldest_credit)),
("date", ">=", "2022-02-09") # Date of activation of pf_checkout
]).filtered(lambda m: not m.matched_credit_ids)
if self.full_reconcile_line_ids:
self.env.user.notify_success(
message=_("Successfully reconciled %s entries")
% len(self.full_reconcile_line_ids),
sticky=True
)
else:
if not credit_lines:
self.env.user.notify_success(
message=_("Every credit entry is reconciled"))
else:
self.env.user.notify_warning(
message=_("0 credit entry could be fully reconciled"))
return {
"type": "ir.actions.act_window",
"view_mode": "tree,form",
"view_type": "form",
"res_model": "account.move.line",
"target": "current",
"context": self.env.context,
"domain": [("id", "in", (self.partial_reconcile_line_ids +
self.missing_donation_line_ids).ids)]
}

@api.multi
def reconcile_using_pf_checkout(self, move_line):
# Transactions are grouped by dates
date_position = -1
date_length = 8
search_days_delta = 0
if Provider.WORLDLINE.value in move_line.name:
date_position = self._search_in_credit_string(move_line, "REFERENCES: ")
search_days_delta = -9
provider = Provider.WORLDLINE
elif Provider.TWINT.value in move_line.name:
date_position = self._search_in_credit_string(move_line, "Payout ")
search_days_delta = -1
provider = Provider.TWINT
elif Provider.PF_CARD.value in move_line.name:
date_position = self._search_in_credit_string(move_line, " TRAITEMENT DU ")
date_length = 10
provider = Provider.PF_CARD
elif Provider.E_FINANCE.value in move_line.name:
date_position = self._search_in_credit_string(move_line, " TRAITEMENT DU ")
date_length = 10
provider = Provider.E_FINANCE
if date_position == -1:
self.missing_line_ids += move_line
return False
date_transactions = datetime.strptime(
move_line.name[date_position:date_position + date_length],
"%Y%m%d" if date_length == 8 else "%d.%m.%Y"
) + timedelta(days=search_days_delta)
pf_service, space_id = self.get_pf_service()
debit_match = self.env["account.move.line"]
pf_filter = self.get_pf_filter(date_transactions, provider)
for transaction in pf_service.search(space_id, pf_filter):
# Some references have this TEMPTR- prefix that should be ignored
ref = transaction.merchant_reference.replace("TEMPTR-", "").split("-")[0]
debit_match += self.env["account.move.line"].search([
("ref", "like", ref),
("debit", ">", 0),
("full_reconcile_id", "=", False),
("account_id", "=", self.account_id.id)
]).filtered(lambda m: not m.matched_credit_ids)
# Perform a partial or full reconcile
(move_line + debit_match).reconcile()
if sum(debit_match.mapped("debit")) == move_line.credit:
self.full_reconcile_line_ids += move_line
else:
self.partial_reconcile_line_ids += move_line
return True

@api.model
def _search_in_credit_string(self, move_line, search_string):
string_position = move_line.name.find(search_string)
if string_position > -1:
string_position += len(search_string)
return string_position

@ormcache()
def get_pf_service(self):
pf_acquirer = self.env.ref(
"payment_postfinance_flex.payment_acquirer_postfinance")
config = Configuration(
user_id=pf_acquirer.postfinance_api_userid,
api_secret=pf_acquirer.postfinance_api_application_key)
return TransactionServiceApi(configuration=config),\
pf_acquirer.postfinance_api_spaceid

@api.model
def get_pf_filter(self, date_search=None, provider=None, state="FULFILL"):
if date_search is None:
date_search = datetime.today()
stop = date_search.replace(hour=23, minute=0, second=0, microsecond=0)
start = stop + timedelta(days=-1)
domain = {
"filter": {
"children": [
{
"fieldName": "createdOn",
"operator": "GREATER_THAN",
"type": "LEAF",
"value": start.isoformat(),
},
{
"fieldName": "createdOn",
"operator": "LESS_THAN_OR_EQUAL",
"type": "LEAF",
"value": stop.isoformat(),
},
{
"fieldName": "state",
"operator": "EQUALS",
"type": "LEAF",
"value": state,
}
],
"type": "AND",
}
}
if provider is not None:
domain["filter"]["children"].append({
"fieldName": "paymentConnectorConfiguration.name",
"operator": "CONTAINS",
"type": "LEAF",
"value": PF_MAPPING.get(provider),
})
return domain
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ZoomAttendee(models.Model):
("attended", "Attended"),
("missing", "Didn't show up"),
("declined", "Declined")
], default="invited", group_expand="_expand_states")
], default="invited", group_expand="_expand_states", track_visibility="onchange")
optional_message = fields.Text()
color = fields.Integer(compute="_compute_color")

Expand Down
7 changes: 7 additions & 0 deletions report_compassion/models/res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,16 @@ def get_receipt(self, year):
("last_payment", "<=", end_date),
("state", "=", "paid"),
("product_id.requires_thankyou", "=", True),
# invoice from either the partner, the company or the employee
# to obtain the same results when tax receipt is computed from companies or employees
"|",
# invoice from the partner (when self is either an company or an employee)
("partner_id", "=", self.id),
"|",
# invoice from the company (when self is an employee)
("partner_id.parent_id", "=", self.id),
# invoice from the employees (when self is a company)
("partner_id.child_ids", "=", self.id),
]
)
return sum(invoice_lines.mapped("price_subtotal"))
Expand Down
5 changes: 2 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ bs4
firebase_admin
geojson
jwt
matplotlib
mysqlclient
odoo-sphinx-autodoc
git+git://github.com/OCA/openupgradelib
git+https://github.com/OCA/openupgradelib
git+https://github.com/pfpayments/python-sdk
opencv-python
opencv-contrib-python
pandas
Expand Down Expand Up @@ -36,5 +36,4 @@ timezonefinder
unidecode
wand
PyMuPDF
boxdetect
fintech

0 comments on commit a9bd4be

Please sign in to comment.