Merge lp:~therp-nl/banking-addons/ba7.0-RFR-split_off_payment_part into lp:banking-addons

Proposed by Stefan Rijnhart (Opener)
Status: Merged
Merged at revision: 169
Proposed branch: lp:~therp-nl/banking-addons/ba7.0-RFR-split_off_payment_part
Merge into: lp:banking-addons
Prerequisite: lp:~banking-addons-team/banking-addons/ba70-mig_account_iban_preserve_domestic
Diff against target: 2904 lines (+1420/-999)
31 files modified
account_banking/__openerp__.py (+4/-3)
account_banking/account_banking.py (+0/-475)
account_banking/account_banking_view.xml (+0/-87)
account_banking/banking_import_transaction.py (+38/-330)
account_banking/data/account_banking_data.xml (+0/-7)
account_banking/security/ir.model.access.csv (+0/-1)
account_banking/wizard/__init__.py (+0/-2)
account_banking/wizard/bank_import.py (+0/-3)
account_banking/wizard/banking_transaction_wizard.py (+0/-9)
account_banking/wizard/banking_transaction_wizard.xml (+0/-8)
account_banking_nl_clieop/__terp__.py (+1/-1)
account_banking_payment/__init__.py (+1/-0)
account_banking_payment/__openerp__.py (+57/-0)
account_banking_payment/data/payment_mode_type.xml (+14/-0)
account_banking_payment/model/__init__.py (+10/-0)
account_banking_payment/model/account_bank_statement_line.py (+40/-0)
account_banking_payment/model/account_payment.py (+240/-0)
account_banking_payment/model/bank_payment_manual.py (+32/-32)
account_banking_payment/model/banking_import_line.py (+45/-0)
account_banking_payment/model/banking_import_transaction.py (+381/-0)
account_banking_payment/model/banking_transaction_wizard.py (+45/-0)
account_banking_payment/model/payment_line.py (+218/-0)
account_banking_payment/model/payment_mode.py (+51/-0)
account_banking_payment/model/payment_mode_type.py (+62/-0)
account_banking_payment/model/payment_order_create.py (+27/-28)
account_banking_payment/security/ir.model.access.csv (+2/-0)
account_banking_payment/view/account_payment.xml (+45/-0)
account_banking_payment/view/bank_payment_manual.xml (+16/-0)
account_banking_payment/view/banking_transaction_wizard.xml (+36/-0)
account_banking_payment/view/payment_mode_type.xml (+47/-0)
account_banking_payment/workflow/account_payment.xml (+8/-13)
To merge this branch: bzr merge lp:~therp-nl/banking-addons/ba7.0-RFR-split_off_payment_part
Reviewer Review Type Date Requested Status
Holger Brunn (Therp) code review Approve
Guewen Baconnier @ Camptocamp code review, no test Approve
Alexandre Fayolle - camptocamp code review, no test Needs Fixing
Review via email: mp+153680@code.launchpad.net

Description of the change

This change is a conceptually simple refactoring: the account_banking module has always containted code for importing bank statements as well as exporting payment orders. I have now split off the latter part in a separate module.

Unfortunately, the implementation of this simple concept has lead to a horrendous diff of 3000 lines, stretching what can be possibly expected from a community based review structure. Most of this is just copied code. You might want to focus on the following, actual changes:

l.927 introduction of move_info2values replacing l.1005-1022, so that it can be overridden in the new module (in l.2136)
l.949,965-973,982,986 conditionally using functionality from account_payment (if it is installed)
l.1037-1064 Do not attempt to trigger workflow when *recognizing* a payment order line but after confirmation of the match (in l.1994-2003)
l.1688,1729 Replacing wizard interface object with transient model (and actually calling the workflow instead of overwriting the state field)
l.2157-2179 Akwardly updating a pre-existing function map with functions to deal with additional match types added by the split off module
l.2615-2619,2636,2639,2647-2652,2657-2662 Compare dates from database with UTC date
l.2869-2906 Preserve original module name in xml ids for migration purposes

Note that although the target branch is 7.0, the code is still only compatible with 6.1. The actual migration of the code will be presented in another MP. I do not want to jeopardize the mature 6.1 branch with such large changes. Because I needed to test the code in 6.1, I made sure not to introduce any incompatiblities with this release (meaning: the view type *will* eventually be removed from the xml view definitions).

To post a comment you must log in.
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

Some nitpicking and more in-depth comments

* account_banking_payment/model/account_payment.py:

  - there are several spaces missing in the help strings (e.g. l1507-1510 for date_prefered column
  - btw "prefered" is spelled "preferred" in English (with two 'r'). Maybe it's still time to fix this one
  - l. 1542: missing call to tools.translate._() for 'Payment Order Export' ?

* account_banking_payment/model/payment_order_create.py

  - I'm very suspicious of the value of _today : run this in Tokyo at 7:00 AM localtime, and _today will yield a date one day off. This definitely requires testing with ntpd off and a compyter configured in a widely off TZ (or maybe use http://pythonhosted.org/testfixtures/datetime.html for this, if there's nothing in the OpenERP test framework)
  - I find a bit difficult to read your use of the ternary operator (with the if clause split on 2 lines, and the else clause appended at the end of the second line). If you're concerned about line lenght, I recommend using 3 lines, keeping the 'if' clause on a single line and the else clause by itself.

review: Needs Fixing (code review, no test)
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Alexandre,

thanks for taking the effort of ploughing through this monstrous diff!

Your first point is very good, but there is nothing that I can do about that. The list of fields on the payment model is merely there to add an entry to their 'states' list. In order to do so, I need to duplicate the earlier definitions from the account_payment module. The errors that you point out in field names and help texts are in that module. I wish it was easier to change this field attribute (and it would be if the orm did not lump attrs from the 'states' list and the 'attrs' dictionary together with the implicit 'AND' operator, lp:941901).

Other changes agreed and processed.

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

LGTM

review: Approve (code review, no test)
177. By Stefan Rijnhart (Opener)

[RFR] Merged with target branch

Revision history for this message
Holger Brunn (Therp) (hbrunn) wrote :

2624: that should be openerp.tools or openerp.tools.misc, right?

Minor thing:

2169ff: I think you can avoid the awkwardness by using banking_import_transaction._confirm_payment_order (that is, the reference to the unbound method)

review: Needs Fixing
178. By Stefan Rijnhart (Opener)

[FIX] Faulty import
[IMP] Method references in confirm/cancel mappings

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks Holger, referring to the methods in that way works very well. Fixed the import as well.

Revision history for this message
Holger Brunn (Therp) (hbrunn) :
review: Approve (code review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'account_banking/__openerp__.py'
--- account_banking/__openerp__.py 2013-02-26 21:06:36 +0000
+++ account_banking/__openerp__.py 2013-05-24 09:03:33 +0000
@@ -35,15 +35,16 @@
35 'author': 'Banking addons community',35 'author': 'Banking addons community',
36 'website': 'https://launchpad.net/banking-addons',36 'website': 'https://launchpad.net/banking-addons',
37 'category': 'Banking addons',37 'category': 'Banking addons',
38 'depends': ['base', 'account', 'base_iban', 'account_payment',38 'depends': [
39 'account_iban_preserve_domestic'],39 'account_voucher',
40 'account_iban_preserve_domestic',
41 ],
40 'init_xml': [],42 'init_xml': [],
41 'update_xml': [43 'update_xml': [
42 'security/ir.model.access.csv',44 'security/ir.model.access.csv',
43 'data/account_banking_data.xml',45 'data/account_banking_data.xml',
44 'wizard/bank_import_view.xml',46 'wizard/bank_import_view.xml',
45 'account_banking_view.xml',47 'account_banking_view.xml',
46 'account_banking_workflow.xml',
47 'wizard/banking_transaction_wizard.xml',48 'wizard/banking_transaction_wizard.xml',
48 'workflow/account_invoice.xml',49 'workflow/account_invoice.xml',
49 ],50 ],
5051
=== modified file 'account_banking/account_banking.py'
--- account_banking/account_banking.py 2013-03-20 19:25:57 +0000
+++ account_banking/account_banking.py 2013-05-24 09:03:33 +0000
@@ -272,68 +272,6 @@
272 }272 }
273account_banking_imported_file()273account_banking_imported_file()
274274
275class payment_mode_type(osv.osv):
276 _name= 'payment.mode.type'
277 _description= 'Payment Mode Type'
278 _columns= {
279 'name': fields.char(
280 'Name', size=64, required=True,
281 help='Payment Type'
282 ),
283 'code': fields.char(
284 'Code', size=64, required=True,
285 help='Specify the Code for Payment Type'
286 ),
287 # Setting suitable_bank_types to required pending
288 # https://bugs.launchpad.net/openobject-addons/+bug/786845
289 'suitable_bank_types': fields.many2many(
290 'res.partner.bank.type',
291 'bank_type_payment_type_rel',
292 'pay_type_id','bank_type_id',
293 'Suitable bank types', required=True),
294 'ir_model_id': fields.many2one(
295 'ir.model', 'Payment wizard',
296 help=('Select the Payment Wizard for payments of this type. '
297 'Leave empty for manual processing'),
298 domain=[('osv_memory', '=', True)],
299 ),
300 'payment_order_type': fields.selection(
301 [('payment', 'Payment'),('debit', 'Direct debit')],
302 'Payment order type', required=True,
303 ),
304 }
305
306 _defaults = {
307 'payment_order_type': lambda *a: 'payment',
308 }
309
310payment_mode_type()
311
312class payment_mode(osv.osv):
313 ''' Restoring the payment type from version 5,
314 used to select the export wizard (if any) '''
315 _inherit = "payment.mode"
316
317 def suitable_bank_types(self, cr, uid, payment_mode_id=None, context=None):
318 """ Reinstates functional code for suitable bank type filtering.
319 Current code in account_payment is disfunctional.
320 """
321 res = []
322 payment_mode = self.browse(
323 cr, uid, payment_mode_id, context)
324 if (payment_mode and payment_mode.type and
325 payment_mode.type.suitable_bank_types):
326 res = [type.code for type in payment_mode.type.suitable_bank_types]
327 return res
328
329 _columns = {
330 'type': fields.many2one(
331 'payment.mode.type', 'Payment type',
332 help='Select the Payment Type for the Payment Mode.'
333 ),
334 }
335payment_mode()
336
337class account_bank_statement(osv.osv):275class account_bank_statement(osv.osv):
338 '''276 '''
339 Extensions from account_bank_statement:277 Extensions from account_bank_statement:
@@ -785,419 +723,6 @@
785723
786account_bank_statement_line()724account_bank_statement_line()
787725
788class payment_line(osv.osv):
789 '''
790 Add extra export_state and date_done fields; make destination bank account
791 mandatory, as it makes no sense to send payments into thin air.
792 Edit: Payments can be by cash too, which is prohibited by mandatory bank
793 accounts.
794 '''
795 _inherit = 'payment.line'
796 _columns = {
797 # New fields
798 'export_state': fields.selection([
799 ('draft', 'Draft'),
800 ('open','Confirmed'),
801 ('cancel','Cancelled'),
802 ('sent', 'Sent'),
803 ('rejected', 'Rejected'),
804 ('done','Done'),
805 ], 'State', select=True
806 ),
807 'msg': fields.char('Message', size=255, required=False, readonly=True),
808
809 # Redefined fields: added states
810 'date_done': fields.datetime('Date Confirmed', select=True,
811 readonly=True),
812 'name': fields.char(
813 'Your Reference', size=64, required=True,
814 states={
815 'sent': [('readonly', True)],
816 'rejected': [('readonly', True)],
817 'done': [('readonly', True)]
818 },
819 ),
820 'communication': fields.char(
821 'Communication', size=64, required=False,
822 help=("Used as the message between ordering customer and current "
823 "company. Depicts 'What do you want to say to the recipient"
824 " about this order ?'"
825 ),
826 states={
827 'sent': [('readonly', True)],
828 'rejected': [('readonly', True)],
829 'done': [('readonly', True)]
830 },
831 ),
832 'communication2': fields.char(
833 'Communication 2', size=128,
834 help='The successor message of Communication.',
835 states={
836 'sent': [('readonly', True)],
837 'rejected': [('readonly', True)],
838 'done': [('readonly', True)]
839 },
840 ),
841 'move_line_id': fields.many2one(
842 'account.move.line', 'Entry line',
843 domain=[('reconcile_id','=', False),
844 ('account_id.type', '=','payable')
845 ],
846 help=('This Entry Line will be referred for the information of '
847 'the ordering customer.'
848 ),
849 states={
850 'sent': [('readonly', True)],
851 'rejected': [('readonly', True)],
852 'done': [('readonly', True)]
853 },
854 ),
855 'amount_currency': fields.float(
856 'Amount in Partner Currency', digits=(16,2),
857 required=True,
858 help='Payment amount in the partner currency',
859 states={
860 'sent': [('readonly', True)],
861 'rejected': [('readonly', True)],
862 'done': [('readonly', True)]
863 },
864 ),
865 'currency': fields.many2one(
866 'res.currency', 'Partner Currency', required=True,
867 states={
868 'sent': [('readonly', True)],
869 'rejected': [('readonly', True)],
870 'done': [('readonly', True)]
871 },
872 ),
873 'bank_id': fields.many2one(
874 'res.partner.bank', 'Destination Bank account',
875 states={
876 'sent': [('readonly', True)],
877 'rejected': [('readonly', True)],
878 'done': [('readonly', True)]
879 },
880 ),
881 'order_id': fields.many2one(
882 'payment.order', 'Order', required=True,
883 ondelete='cascade', select=True,
884 states={
885 'sent': [('readonly', True)],
886 'rejected': [('readonly', True)],
887 'done': [('readonly', True)]
888 },
889 ),
890 'partner_id': fields.many2one(
891 'res.partner', string="Partner", required=True,
892 help='The Ordering Customer',
893 states={
894 'sent': [('readonly', True)],
895 'rejected': [('readonly', True)],
896 'done': [('readonly', True)]
897 },
898 ),
899 'date': fields.date(
900 'Payment Date',
901 help=("If no payment date is specified, the bank will treat this "
902 "payment line directly"
903 ),
904 states={
905 'sent': [('readonly', True)],
906 'rejected': [('readonly', True)],
907 'done': [('readonly', True)]
908 },
909 ),
910 'state': fields.selection([
911 ('normal','Free'),
912 ('structured','Structured')
913 ], 'Communication Type', required=True,
914 states={
915 'sent': [('readonly', True)],
916 'rejected': [('readonly', True)],
917 'done': [('readonly', True)]
918 },
919 ),
920 }
921 _defaults = {
922 'export_state': lambda *a: 'draft',
923 'date_done': lambda *a: False,
924 'msg': lambda *a: '',
925 }
926
927 def fields_get(self, cr, uid, fields=None, context=None):
928 res = super(payment_line, self).fields_get(cr, uid, fields, context)
929 if 'communication' in res:
930 res['communication'].setdefault('states', {})
931 res['communication']['states']['structured'] = [('required', True)]
932 if 'communication2' in res:
933 res['communication2'].setdefault('states', {})
934 res['communication2']['states']['structured'] = [('readonly', True)]
935 res['communication2']['states']['normal'] = [('readonly', False)]
936
937 return res
938
939 """
940 Hooks for processing direct debit orders, such as implemented in
941 account_direct_debit module.
942 """
943 def get_storno_account_id(self, cr, uid, payment_line_id, amount,
944 currency_id, context=None):
945 """
946 Hook for verifying a match of the payment line with the amount.
947 Return the account associated with the storno.
948 Used in account_banking interactive mode
949 :param payment_line_id: the single payment line id
950 :param amount: the (signed) amount debited from the bank account
951 :param currency: the bank account's currency *browse object*
952 :return: an account if there is a full match, False otherwise
953 :rtype: database id of an account.account resource.
954 """
955
956 return False
957
958 def debit_storno(self, cr, uid, payment_line_id, amount,
959 currency_id, storno_retry=True, context=None):
960 """
961 Hook for handling a canceled item of a direct debit order.
962 Presumably called from a bank statement import routine.
963
964 Decide on the direction that the invoice's workflow needs to take.
965 You may optionally return an incomplete reconcile for the caller
966 to reconcile the now void payment.
967
968 :param payment_line_id: the single payment line id
969 :param amount: the (negative) amount debited from the bank account
970 :param currency: the bank account's currency *browse object*
971 :param boolean storno_retry: whether the storno is considered fatal \
972 or not.
973 :return: an incomplete reconcile for the caller to fill
974 :rtype: database id of an account.move.reconcile resource.
975 """
976
977 return False
978
979payment_line()
980
981class payment_order(osv.osv):
982 '''
983 Enable extra states for payment exports
984 '''
985 _inherit = 'payment.order'
986
987 _columns = {
988 'date_scheduled': fields.date(
989 'Scheduled date if fixed',
990 states={
991 'sent': [('readonly', True)],
992 'rejected': [('readonly', True)],
993 'done': [('readonly', True)]
994 },
995 help='Select a date if you have chosen Preferred Date to be fixed.'
996 ),
997 'reference': fields.char(
998 'Reference', size=128, required=True,
999 states={
1000 'sent': [('readonly', True)],
1001 'rejected': [('readonly', True)],
1002 'done': [('readonly', True)]
1003 },
1004 ),
1005 'mode': fields.many2one(
1006 'payment.mode', 'Payment mode', select=True, required=True,
1007 states={
1008 'sent': [('readonly', True)],
1009 'rejected': [('readonly', True)],
1010 'done': [('readonly', True)]
1011 },
1012 help='Select the Payment Mode to be applied.',
1013 ),
1014 'state': fields.selection([
1015 ('draft', 'Draft'),
1016 ('open','Confirmed'),
1017 ('cancel','Cancelled'),
1018 ('sent', 'Sent'),
1019 ('rejected', 'Rejected'),
1020 ('done','Done'),
1021 ], 'State', select=True
1022 ),
1023 'line_ids': fields.one2many(
1024 'payment.line', 'order_id', 'Payment lines',
1025 states={
1026 'sent': [('readonly', True)],
1027 'rejected': [('readonly', True)],
1028 'done': [('readonly', True)]
1029 },
1030 ),
1031 'user_id': fields.many2one(
1032 'res.users','User', required=True,
1033 states={
1034 'sent': [('readonly', True)],
1035 'rejected': [('readonly', True)],
1036 'done': [('readonly', True)]
1037 },
1038 ),
1039 'date_prefered': fields.selection([
1040 ('now', 'Directly'),
1041 ('due', 'Due date'),
1042 ('fixed', 'Fixed date')
1043 ], "Preferred date", change_default=True, required=True,
1044 states={
1045 'sent': [('readonly', True)],
1046 'rejected': [('readonly', True)],
1047 'done': [('readonly', True)]
1048 },
1049 help=("Choose an option for the Payment Order:'Fixed' stands for a "
1050 "date specified by you.'Directly' stands for the direct "
1051 "execution.'Due date' stands for the scheduled date of "
1052 "execution."
1053 )
1054 ),
1055 'payment_order_type': fields.selection(
1056 [('payment', 'Payment'),('debit', 'Direct debit')],
1057 'Payment order type', required=True,
1058 ),
1059 'date_sent': fields.date('Send date', readonly=True),
1060 }
1061
1062 _defaults = {
1063 'payment_order_type': lambda *a: 'payment',
1064 }
1065
1066 def launch_wizard(self, cr, uid, ids, context=None):
1067 """
1068 Search for a wizard to launch according to the type.
1069 If type is manual. just confirm the order.
1070 Previously (pre-v6) in account_payment/wizard/wizard_pay.py
1071 """
1072 if context == None:
1073 context = {}
1074 result = {}
1075 orders = self.browse(cr, uid, ids, context)
1076 order = orders[0]
1077 # check if a wizard is defined for the first order
1078 if order.mode.type and order.mode.type.ir_model_id:
1079 context['active_ids'] = ids
1080 wizard_model = order.mode.type.ir_model_id.model
1081 wizard_obj = self.pool.get(wizard_model)
1082 wizard_id = wizard_obj.create(cr, uid, {}, context)
1083 result = {
1084 'name': wizard_obj._description or 'Payment Order Export',
1085 'view_type': 'form',
1086 'view_mode': 'form',
1087 'res_model': wizard_model,
1088 'domain': [],
1089 'context': context,
1090 'type': 'ir.actions.act_window',
1091 'target': 'new',
1092 'res_id': wizard_id,
1093 'nodestroy': True,
1094 }
1095 else:
1096 # should all be manual orders without type or wizard model
1097 for order in orders[1:]:
1098 if order.mode.type and order.mode.type.ir_model_id:
1099 raise osv.except_osv(
1100 _('Error'),
1101 _('You can only combine payment orders of the same type')
1102 )
1103 # process manual payments
1104 wf_service = netsvc.LocalService('workflow')
1105 for order_id in ids:
1106 wf_service.trg_validate(uid, 'payment.order', order_id, 'sent', cr)
1107 return result
1108
1109 def _write_payment_lines(self, cursor, uid, ids, **kwargs):
1110 '''
1111 ORM method for setting attributes of corresponding payment.line objects.
1112 Note that while this is ORM compliant, it is also very ineffecient due
1113 to the absence of filters on writes and hence the requirement to
1114 filter on the client(=OpenERP server) side.
1115 '''
1116 if not hasattr(ids, '__iter__'):
1117 ids = [ids]
1118 payment_line_obj = self.pool.get('payment.line')
1119 line_ids = payment_line_obj.search(
1120 cursor, uid, [
1121 ('order_id', 'in', ids)
1122 ])
1123 payment_line_obj.write(cursor, uid, line_ids, kwargs)
1124
1125 def set_to_draft(self, cursor, uid, ids, *args):
1126 '''
1127 Set both self and payment lines to state 'draft'.
1128 '''
1129 self._write_payment_lines(cursor, uid, ids, export_state='draft')
1130 return super(payment_order, self).set_to_draft(
1131 cursor, uid, ids, *args
1132 )
1133
1134 def action_sent(self, cursor, uid, ids, *args):
1135 '''
1136 Set both self and payment lines to state 'sent'.
1137 '''
1138 self._write_payment_lines(cursor, uid, ids, export_state='sent')
1139 self.write(cursor, uid, ids, {'state':'sent',
1140 'date_sent': time.strftime('%Y-%m-%d')})
1141 return True
1142
1143 def action_rejected(self, cursor, uid, ids, *args):
1144 '''
1145 Set both self and payment lines to state 'rejected'.
1146 '''
1147 self._write_payment_lines(cursor, uid, ids, export_state='rejected')
1148 wf_service = netsvc.LocalService('workflow')
1149 for id in ids:
1150 wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cursor)
1151 return True
1152
1153 def set_done(self, cursor, uid, ids, *args):
1154 '''
1155 Extend standard transition to update children as well.
1156 '''
1157 self._write_payment_lines(cursor, uid, ids,
1158 export_state='done',
1159 date_done=time.strftime('%Y-%m-%d')
1160 )
1161 return super(payment_order, self).set_done(
1162 cursor, uid, ids, *args
1163 )
1164
1165 def get_wizard(self, type):
1166 '''
1167 Intercept manual bank payments to include 'sent' state. Default
1168 'manual' payments are flagged 'done' immediately.
1169 '''
1170 if type == 'BANKMAN':
1171 # Note that self._module gets overwritten by inheriters, so make
1172 # the module name hard coded.
1173 return 'account_banking', 'wizard_account_banking_payment_manual'
1174 return super(payment_order, self).get_wizard(type)
1175
1176 """
1177 Hooks for processing direct debit orders, such as implemented in
1178 account_direct_debit module.
1179 """
1180 def debit_reconcile_transfer(
1181 self, cr, uid, payment_order_id, amount, currency, context=None):
1182 """
1183 Reconcile the payment order if the amount is correct. Return the
1184 id of the reconciliation.
1185 """
1186 raise osv.except_osv(
1187 _("Cannot reconcile"),
1188 _("Cannot reconcile debit order: "+
1189 "Not implemented."))
1190
1191 def debit_unreconcile_transfer(
1192 self, cr, uid, payment_order_id, reconcile_id, amount, currency,
1193 context=None):
1194 """ Unreconcile the payment_order if at all possible """
1195 raise osv.except_osv(
1196 _("Cannot unreconcile"),
1197 _("Cannot unreconcile debit order: "+
1198 "Not implemented."))
1199
1200payment_order()
1201726
1202class res_partner_bank(osv.osv):727class res_partner_bank(osv.osv):
1203 '''728 '''
1204729
=== modified file 'account_banking/account_banking_view.xml'
--- account_banking/account_banking_view.xml 2013-01-30 11:34:58 +0000
+++ account_banking/account_banking_view.xml 2013-05-24 09:03:33 +0000
@@ -330,45 +330,6 @@
330 </field>330 </field>
331 </record>331 </record>
332332
333 <!-- Make buttons on payment order sensitive for extra states,
334 restore wizard functionality when making payments
335 -->
336
337 <record id="view_banking_payment_order_form_1" model="ir.ui.view">
338 <field name="name">account.payment.order.form.banking-1</field>
339 <field name="inherit_id" ref="account_payment.view_payment_order_form" />
340 <field name="model">payment.order</field>
341 <field name="type">form</field>
342 <field name="arch" type="xml">
343 <data>
344 <xpath expr="/form/group/button[@string='Select Invoices to Pay']"
345 position="replace">
346 <button colspan="2" name="%(account_payment.action_create_payment_order)s"
347 string="Select Invoices to Pay" type="action"
348 attrs="{'invisible':[('state','!=','draft')]}"
349 icon="gtk-find"
350 />
351 </xpath>
352 <xpath expr="/form/group/button[@string='Make Payments']"
353 position="replace">
354 <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/>
355 <newline/>
356 </xpath>
357 </data>
358 </field>
359 </record>
360 <record id="view_banking_payment_order_tree_1" model="ir.ui.view">
361 <field name="name">account.payment.order.tree.banking-1</field>
362 <field name="inherit_id" ref="account_payment.view_payment_order_tree" />
363 <field name="model">payment.order</field>
364 <field name="type">tree</field>
365 <field name="arch" type="xml">
366 <button string="Make Payments" position="replace">
367 <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/>
368 </button>
369 </field>
370 </record>
371
372 <!-- Set trigger on IBAN and acc_number fields in res_partner_bank form -->333 <!-- Set trigger on IBAN and acc_number fields in res_partner_bank form -->
373 <!--record id="view_partner_bank_account_banking_form_1" model="ir.ui.view">334 <!--record id="view_partner_bank_account_banking_form_1" model="ir.ui.view">
374 <field name="name">res.partner.bank.form.banking-1</field>335 <field name="name">res.partner.bank.form.banking-1</field>
@@ -459,54 +420,6 @@
459 </field>420 </field>
460 </record>421 </record>
461422
462 <!-- Insert payment_mode.type -->
463 <record id="view_payment_mode_form_inherit" model="ir.ui.view">
464 <field name="name">payment.mode.form.inherit</field>
465 <field name="model">payment.mode</field>
466 <field name="inherit_id" ref="account_payment.view_payment_mode_form"/>
467 <field name="type">form</field>
468 <field name="arch" type="xml">
469 <field name="company_id" position="after">
470 <field name="type"/>
471 </field>
472 </field>
473 </record>
474 <record id="view_payment_mode_tree_inherit" model="ir.ui.view">
475 <field name="name">payment.mode.tree.inherit</field>
476 <field name="model">payment.mode</field>
477 <field name="inherit_id" ref="account_payment.view_payment_mode_tree"/>
478 <field name="type">tree</field>
479 <field name="arch" type="xml">
480 <field name="company_id" position="after">
481 <field name="type"/>
482 </field>
483 </field>
484 </record>
485
486 <!-- basic view for payment mode type -->
487 <record model="ir.ui.view" id="view_payment_mode_type_form">
488 <field name="name">view.payment.mode.type.form</field>
489 <field name="model">payment.mode.type</field>
490 <field name="type">form</field>
491 <field name="arch" type="xml">
492 <form>
493 <field name="name" />
494 <field name="code" />
495 <field name="suitable_bank_types"/>
496 <field name="payment_order_type"/>
497 <field name="ir_model_id"/>
498 </form>
499 </field>
500 </record>
501
502 <!-- fixes https://bugs.launchpad.net/openobject-addons/+bug/903156 for 6.0
503 Note that 6.1 does not suffer from the problem
504 -->
505 <record id="account_payment.action_create_payment_order" model="ir.actions.act_window">
506 <field name="view_id" ref="account_payment.view_create_payment_order"/>
507 </record>
508
509
510 <record model="ir.ui.view" id="view_bank_statement_line_tree">423 <record model="ir.ui.view" id="view_bank_statement_line_tree">
511 <field name="name">Bank statement line tree view</field>424 <field name="name">Bank statement line tree view</field>
512 <field name="model">account.bank.statement.line</field>425 <field name="model">account.bank.statement.line</field>
513426
=== modified file 'account_banking/banking_import_transaction.py'
--- account_banking/banking_import_transaction.py 2013-02-07 09:56:06 +0000
+++ account_banking/banking_import_transaction.py 2013-05-24 09:03:33 +0000
@@ -123,43 +123,6 @@
123 # return move_lines to mix with the rest123 # return move_lines to mix with the rest
124 return [x for x in invoice.move_id.line_id if x.account_id.reconcile]124 return [x for x in invoice.move_id.line_id if x.account_id.reconcile]
125125
126 def _match_debit_order(
127 self, cr, uid, trans, log, context=None):
128
129 def is_zero(total):
130 return self.pool.get('res.currency').is_zero(
131 cr, uid, trans.statement_id.currency, total)
132
133 payment_order_obj = self.pool.get('payment.order')
134 order_ids = payment_order_obj.search(
135 cr, uid, [('payment_order_type', '=', 'debit'),
136 ('state', '=', 'sent'),
137 ('date_sent', '<=', str2date(trans.execution_date,
138 '%Y-%m-%d'))
139 ],
140 limit=0, context=context)
141 orders = payment_order_obj.browse(cr, uid, order_ids, context)
142 candidates = [x for x in orders if
143 is_zero(x.total - trans.transferred_amount)]
144 if len(candidates) > 0:
145 # retrieve the common account_id, if any
146 account_id = False
147 for line in candidates[0].line_ids[0].debit_move_line_id.move_id.line_id:
148 if line.account_id.type == 'other':
149 account_id = line.account_id.id
150 break
151 return dict(
152 move_line_ids = False,
153 match_type = 'payment_order',
154 payment_order_ids = [x.id for x in candidates],
155 account_id = account_id,
156 partner_id = False,
157 partner_bank_id = False,
158 reference = False,
159 type='general',
160 )
161 return False
162
163 def _match_invoice(self, cr, uid, trans, move_lines,126 def _match_invoice(self, cr, uid, trans, move_lines,
164 partner_ids, bank_account_ids,127 partner_ids, bank_account_ids,
165 log, linked_invoices,128 log, linked_invoices,
@@ -542,101 +505,6 @@
542 {'voucher_id': voucher_id}, context=context)505 {'voucher_id': voucher_id}, context=context)
543 transaction.refresh()506 transaction.refresh()
544507
545 def _confirm_storno(
546 self, cr, uid, transaction_id, context=None):
547 """
548 Creation of the reconciliation has been delegated to
549 *a* direct debit module, to allow for various direct debit styles
550 """
551 payment_line_pool = self.pool.get('payment.line')
552 statement_line_pool = self.pool.get('account.bank.statement.line')
553 transaction = self.browse(cr, uid, transaction_id, context=context)
554 if not transaction.payment_line_id:
555 raise osv.except_osv(
556 _("Cannot link with storno"),
557 _("No direct debit order item"))
558 reconcile_id = payment_line_pool.debit_storno(
559 cr, uid,
560 transaction.payment_line_id.id,
561 transaction.statement_line_id.amount,
562 transaction.statement_line_id.currency,
563 transaction.storno_retry,
564 context=context)
565 statement_line_pool.write(
566 cr, uid, transaction.statement_line_id.id,
567 {'reconcile_id': reconcile_id}, context=context)
568 transaction.refresh()
569
570 def _confirm_payment_order(
571 self, cr, uid, transaction_id, context=None):
572 """
573 Creation of the reconciliation has been delegated to
574 *a* direct debit module, to allow for various direct debit styles
575 """
576 payment_order_obj = self.pool.get('payment.order')
577 statement_line_pool = self.pool.get('account.bank.statement.line')
578 transaction = self.browse(cr, uid, transaction_id, context=context)
579 if not transaction.payment_order_id:
580 raise osv.except_osv(
581 _("Cannot reconcile"),
582 _("Cannot reconcile: no direct debit order"))
583 if transaction.payment_order_id.payment_order_type != 'debit':
584 raise osv.except_osv(
585 _("Cannot reconcile"),
586 _("Reconcile payment order not implemented"))
587 reconcile_id = payment_order_obj.debit_reconcile_transfer(
588 cr, uid,
589 transaction.payment_order_id.id,
590 transaction.statement_line_id.amount,
591 transaction.statement_line_id.currency,
592 context=context)
593 statement_line_pool.write(
594 cr, uid, transaction.statement_line_id.id,
595 {'reconcile_id': reconcile_id}, context=context)
596
597 def _confirm_payment(
598 self, cr, uid, transaction_id, context=None):
599 """
600 Do some housekeeping on the payment line
601 then pass on to _reconcile_move
602 """
603 transaction = self.browse(cr, uid, transaction_id, context=context)
604 payment_line_obj = self.pool.get('payment.line')
605 payment_line_obj.write(
606 cr, uid, transaction.payment_line_id.id, {
607 'export_state': 'done',
608 'date_done': transaction.statement_line_id.date,
609 }
610 )
611 self._confirm_move(cr, uid, transaction_id, context=context)
612
613 def _cancel_payment(
614 self, cr, uid, transaction_id, context=None):
615 raise osv.except_osv(
616 _("Cannot unreconcile"),
617 _("Cannot unreconcile: this operation is not yet supported for "
618 "match type 'payment'"))
619
620 def _cancel_payment_order(
621 self, cr, uid, transaction_id, context=None):
622 """
623 """
624 payment_order_obj = self.pool.get('payment.order')
625 transaction = self.browse(cr, uid, transaction_id, context=context)
626 if not transaction.payment_order_id:
627 raise osv.except_osv(
628 _("Cannot unreconcile"),
629 _("Cannot unreconcile: no direct debit order"))
630 if transaction.payment_order_id.payment_order_type != 'debit':
631 raise osv.except_osv(
632 _("Cannot unreconcile"),
633 _("Unreconcile payment order not implemented"))
634 return payment_order_obj.debit_unreconcile_transfer(
635 cr, uid, transaction.payment_order_id.id,
636 transaction.statement_line_id.reconcile_id.id,
637 transaction.statement_line_id.amount,
638 transaction.statement_line_id.currency)
639
640 def _legacy_do_move_unreconcile(self, cr, uid, move_line_ids, currency, context=None):508 def _legacy_do_move_unreconcile(self, cr, uid, move_line_ids, currency, context=None):
641 """509 """
642 Legacy method. Allow for canceling bank statement lines that 510 Legacy method. Allow for canceling bank statement lines that
@@ -768,70 +636,10 @@
768636
769 return True637 return True
770638
771 def _cancel_storno(
772 self, cr, uid, transaction_id, context=None):
773 """
774 TODO: delegate unreconciliation to the direct debit module,
775 to allow for various direct debit styles
776 """
777 payment_line_obj = self.pool.get('payment.line')
778 reconcile_obj = self.pool.get('account.move.reconcile')
779 transaction = self.browse(cr, uid, transaction_id, context=context)
780
781 if not transaction.payment_line_id:
782 raise osv.except_osv(
783 _("Cannot cancel link with storno"),
784 _("No direct debit order item"))
785 if not transaction.payment_line_id.storno:
786 raise osv.except_osv(
787 _("Cannot cancel link with storno"),
788 _("The direct debit order item is not marked for storno"))
789
790 journal = transaction.statement_line_id.statement_id.journal_id
791 if transaction.statement_line_id.amount >= 0:
792 account_id = journal.default_credit_account_id.id
793 else:
794 account_id = journal.default_debit_account_id.id
795 cancel_line = False
796 move_lines = []
797 for move in transaction.statement_line_id.move_ids:
798 # There should usually be just one move, I think
799 move_lines += move.line_id
800 for line in move_lines:
801 if line.account_id.id != account_id:
802 cancel_line = line
803 break
804 if not cancel_line:
805 raise osv.except_osv(
806 _("Cannot cancel link with storno"),
807 _("Line id not found"))
808 reconcile = cancel_line.reconcile_id or cancel_line.reconcile_partial_id
809 lines_reconcile = reconcile.line_id or reconcile.line_partial_ids
810 if len(lines_reconcile) < 3:
811 # delete the full reconciliation
812 reconcile_obj.unlink(cr, uid, reconcile.id, context)
813 else:
814 # we are left with a partial reconciliation
815 reconcile_obj.write(
816 cr, uid, reconcile.id,
817 {'line_partial_ids':
818 [(6, 0, [x.id for x in lines_reconcile if x.id != cancel_line.id])],
819 'line_id': [(6, 0, [])],
820 }, context)
821 # redo the original payment line reconciliation with the invoice
822 payment_line_obj.write(
823 cr, uid, transaction.payment_line_id.id,
824 {'storno': False}, context)
825 payment_line_obj.debit_reconcile(
826 cr, uid, transaction.payment_line_id.id, context)
827
828 cancel_map = {639 cancel_map = {
829 'storno': _cancel_storno,
830 'invoice': _cancel_voucher,640 'invoice': _cancel_voucher,
831 'manual': _cancel_voucher,641 'manual': _cancel_voucher,
832 'move': _cancel_voucher,642 'move': _cancel_voucher,
833 'payment_order': _cancel_payment_order,
834 'payment': _cancel_payment,
835 }643 }
836644
837 def cancel(self, cr, uid, ids, context=None):645 def cancel(self, cr, uid, ids, context=None):
@@ -850,11 +658,8 @@
850 return True658 return True
851659
852 confirm_map = {660 confirm_map = {
853 'storno': _confirm_storno,
854 'invoice': _confirm_move,661 'invoice': _confirm_move,
855 'manual': _confirm_move,662 'manual': _confirm_move,
856 'payment_order': _confirm_payment_order,
857 'payment': _confirm_payment,
858 'move': _confirm_move,663 'move': _confirm_move,
859 }664 }
860665
@@ -892,66 +697,6 @@
892 """697 """
893 return True698 return True
894 699
895 def _match_storno(
896 self, cr, uid, trans, log, context=None):
897 payment_line_obj = self.pool.get('payment.line')
898 line_ids = payment_line_obj.search(
899 cr, uid, [
900 ('order_id.payment_order_type', '=', 'debit'),
901 ('order_id.state', 'in', ['sent', 'done']),
902 ('communication', '=', trans.reference)
903 ], context=context)
904 # stornos MUST have an exact match
905 if len(line_ids) == 1:
906 account_id = payment_line_obj.get_storno_account_id(
907 cr, uid, line_ids[0], trans.transferred_amount,
908 trans.statement_id.currency, context=None)
909 if account_id:
910 return dict(
911 account_id = account_id,
912 match_type = 'storno',
913 payment_line_id = line_ids[0],
914 move_line_ids=False,
915 partner_id=False,
916 partner_bank_id=False,
917 reference=False,
918 type='customer',
919 )
920 # TODO log the reason why there is no result for transfers marked
921 # as storno
922 return False
923
924 def _match_payment(self, cr, uid, trans, payment_lines,
925 partner_ids, bank_account_ids, log, linked_payments):
926 '''
927 Find the payment order belonging to this reference - if there is one
928 This is the easiest part: when sending payments, the returned bank info
929 should be identical to ours.
930 This also means that we do not allow for multiple candidates.
931 '''
932 # TODO: Not sure what side effects are created when payments are done
933 # for credited customer invoices, which will be matched later on too.
934 digits = dp.get_precision('Account')(cr)[1]
935 candidates = [x for x in payment_lines
936 if x.communication == trans.reference
937 and round(x.amount, digits) == -round(trans.transferred_amount, digits)
938 and trans.remote_account in (x.bank_id.acc_number,
939 x.bank_id.acc_number_domestic)
940 ]
941 if len(candidates) == 1:
942 candidate = candidates[0]
943 # Check cache to prevent multiple matching of a single payment
944 if candidate.id not in linked_payments:
945 linked_payments[candidate.id] = True
946 move_info = self._get_move_info(cr, uid, [candidate.move_line_id.id])
947 move_info.update({
948 'match_type': 'payment',
949 'payment_line_id': candidate.id,
950 })
951 return move_info
952
953 return False
954
955 signal_duplicate_keys = [700 signal_duplicate_keys = [
956 # does not include float values701 # does not include float values
957 # such as transferred_amount702 # such as transferred_amount
@@ -1059,6 +804,22 @@
1059 retval['invoice_ids'] = [x.invoice.id for x in move_lines]804 retval['invoice_ids'] = [x.invoice.id for x in move_lines]
1060 retval['type'] = type_map[move_lines[0].invoice.type]805 retval['type'] = type_map[move_lines[0].invoice.type]
1061 return retval806 return retval
807
808 def move_info2values(self, move_info):
809 vals = {}
810 vals['match_type'] = move_info['match_type']
811 vals['move_line_ids'] = [(6, 0, move_info.get('move_line_ids') or [])]
812 vals['invoice_ids'] = [(6, 0, move_info.get('invoice_ids') or [])]
813 vals['move_line_id'] = (move_info.get('move_line_ids', False) and
814 len(move_info['move_line_ids']) == 1 and
815 move_info['move_line_ids'][0]
816 )
817 if move_info['match_type'] == 'invoice':
818 vals['invoice_id'] = (move_info.get('invoice_ids', False) and
819 len(move_info['invoice_ids']) == 1 and
820 move_info['invoice_ids'][0]
821 )
822 return vals
1062 823
1063 def match(self, cr, uid, ids, results=None, context=None):824 def match(self, cr, uid, ids, results=None, context=None):
1064 if not ids:825 if not ids:
@@ -1069,6 +830,7 @@
1069 journal_obj = self.pool.get('account.journal')830 journal_obj = self.pool.get('account.journal')
1070 move_line_obj = self.pool.get('account.move.line')831 move_line_obj = self.pool.get('account.move.line')
1071 payment_line_obj = self.pool.get('payment.line')832 payment_line_obj = self.pool.get('payment.line')
833 has_payment = bool(payment_line_obj)
1072 statement_line_obj = self.pool.get('account.bank.statement.line')834 statement_line_obj = self.pool.get('account.bank.statement.line')
1073 statement_obj = self.pool.get('account.bank.statement')835 statement_obj = self.pool.get('account.bank.statement')
1074 payment_order_obj = self.pool.get('payment.order')836 payment_order_obj = self.pool.get('payment.order')
@@ -1098,14 +860,15 @@
1098 # communication. Most likely there are much less sent payments860 # communication. Most likely there are much less sent payments
1099 # than reconciled and open/draft payments.861 # than reconciled and open/draft payments.
1100 # Strangely, payment_orders still do not have company_id862 # Strangely, payment_orders still do not have company_id
1101 cr.execute("SELECT l.id FROM payment_order o, payment_line l "863 if has_payment:
1102 "WHERE l.order_id = o.id AND "864 payment_line_ids = payment_line_obj.search(
1103 "o.state = 'sent' AND "865 cr, uid, [
1104 "l.date_done IS NULL"866 ('order_id.state', '=', 'sent'),
1105 )867 ('date_done', '=', False)], context=context)
1106 payment_line_ids = [x[0] for x in cr.fetchall()]868 payment_lines = payment_line_obj.browse(
1107 if payment_line_ids:869 cr, uid, payment_line_ids)
1108 payment_lines = payment_line_obj.browse(cr, uid, payment_line_ids)870 else:
871 payment_lines = False
1109872
1110 # Start the loop over the transactions requested to match873 # Start the loop over the transactions requested to match
1111 transactions = self.browse(cr, uid, ids, context)874 transactions = self.browse(cr, uid, ids, context)
@@ -1270,10 +1033,10 @@
1270 # rebrowse the current record after writing1033 # rebrowse the current record after writing
1271 transaction = self.browse(cr, uid, transaction.id, context=context)1034 transaction = self.browse(cr, uid, transaction.id, context=context)
1272 # Match full direct debit orders1035 # Match full direct debit orders
1273 if transaction.type == bt.DIRECT_DEBIT:1036 if transaction.type == bt.DIRECT_DEBIT and has_payment:
1274 move_info = self._match_debit_order(1037 move_info = self._match_debit_order(
1275 cr, uid, transaction, results['log'], context)1038 cr, uid, transaction, results['log'], context)
1276 if transaction.type == bt.STORNO:1039 if transaction.type == bt.STORNO and has_payment:
1277 move_info = self._match_storno(1040 move_info = self._match_storno(
1278 cr, uid, transaction, results['log'], context)1041 cr, uid, transaction, results['log'], context)
1279 # Allow inclusion of generated bank invoices1042 # Allow inclusion of generated bank invoices
@@ -1340,6 +1103,10 @@
1340 if (not move_info1103 if (not move_info
1341 and transaction.transferred_amount < 0 and payment_lines):1104 and transaction.transferred_amount < 0 and payment_lines):
1342 # Link open payment - if any1105 # Link open payment - if any
1106 # Note that _match_payment is defined in the
1107 # account_banking_payment module which should be installed
1108 # automatically if account_payment is. And if account_payment
1109 # is not installed, then payment_lines will be empty.
1343 move_info = self._match_payment(1110 move_info = self._match_payment(
1344 cr, uid, transaction,1111 cr, uid, transaction,
1345 payment_lines, partner_ids,1112 payment_lines, partner_ids,
@@ -1385,28 +1152,12 @@
1385 self_values = {}1152 self_values = {}
1386 if move_info:1153 if move_info:
1387 results['trans_matched_cnt'] += 11154 results['trans_matched_cnt'] += 1
1388 self_values['match_type'] = move_info['match_type']1155 self_values.update(
1389 self_values['payment_line_id'] = move_info.get('payment_line_id', False)1156 self.move_info2values(move_info))
1390 self_values['move_line_ids'] = [(6, 0, move_info.get('move_line_ids') or [])]1157 # values['match_type'] = move_info['match_type']
1391 self_values['invoice_ids'] = [(6, 0, move_info.get('invoice_ids') or [])]
1392 self_values['payment_order_ids'] = [(6, 0, move_info.get('payment_order_ids') or [])]
1393 self_values['payment_order_id'] = (move_info.get('payment_order_ids', False) and
1394 len(move_info['payment_order_ids']) == 1 and
1395 move_info['payment_order_ids'][0]
1396 )
1397 self_values['move_line_id'] = (move_info.get('move_line_ids', False) and
1398 len(move_info['move_line_ids']) == 1 and
1399 move_info['move_line_ids'][0]
1400 )
1401 if move_info['match_type'] == 'invoice':
1402 self_values['invoice_id'] = (move_info.get('invoice_ids', False) and
1403 len(move_info['invoice_ids']) == 1 and
1404 move_info['invoice_ids'][0]
1405 )
1406 values['partner_id'] = move_info['partner_id']1158 values['partner_id'] = move_info['partner_id']
1407 values['partner_bank_id'] = move_info['partner_bank_id']1159 values['partner_bank_id'] = move_info['partner_bank_id']
1408 values['type'] = move_info['type']1160 values['type'] = move_info['type']
1409 # values['match_type'] = move_info['match_type']
1410 else:1161 else:
1411 values['partner_id'] = values['partner_bank_id'] = False1162 values['partner_id'] = values['partner_bank_id'] = False
1412 if not values['partner_id'] and partner_ids and len(partner_ids) == 1:1163 if not values['partner_id'] and partner_ids and len(partner_ids) == 1:
@@ -1446,34 +1197,6 @@
1446 statement_obj.button_dummy(1197 statement_obj.button_dummy(
1447 cr, uid, imported_statement_ids, context=context)1198 cr, uid, imported_statement_ids, context=context)
14481199
1449 if payment_lines:
1450 # As payments lines are treated as individual transactions, the
1451 # batch as a whole is only marked as 'done' when all payment lines
1452 # have been reconciled.
1453 cr.execute(
1454 "SELECT DISTINCT o.id "
1455 "FROM payment_order o, payment_line l "
1456 "WHERE o.state = 'sent' "
1457 "AND o.id = l.order_id "
1458 "AND o.id NOT IN ("
1459 "SELECT DISTINCT order_id AS id "
1460 "FROM payment_line "
1461 "WHERE date_done IS NULL "
1462 "AND id IN (%s)"
1463 ")" % (','.join([str(x) for x in payment_line_ids]))
1464 )
1465 order_ids = [x[0] for x in cr.fetchall()]
1466 if order_ids:
1467 # Use workflow logics for the orders. Recode logic from
1468 # account_payment, in order to increase efficiency.
1469 payment_order_obj.set_done(cr, uid, order_ids,
1470 {'state': 'done'}
1471 )
1472 wf_service = netsvc.LocalService('workflow')
1473 for id in order_ids:
1474 wf_service.trg_validate(
1475 uid, 'payment.order', id, 'done', cr)
1476
1477 def _get_residual(self, cr, uid, ids, name, args, context=None):1200 def _get_residual(self, cr, uid, ids, name, args, context=None):
1478 """1201 """
1479 Calculate the residual against the candidate reconciliation.1202 Calculate the residual against the candidate reconciliation.
@@ -1518,10 +1241,6 @@
1518 elif transaction.match_type == 'invoice':1241 elif transaction.match_type == 'invoice':
1519 if transaction.invoice_ids and not transaction.invoice_id:1242 if transaction.invoice_ids and not transaction.invoice_id:
1520 res[transaction.id] = True1243 res[transaction.id] = True
1521 elif transaction.match_type == 'payment_order':
1522 if (transaction.payment_order_ids and not
1523 transaction.payment_order_id):
1524 res[transaction.id] = True
1525 return res1244 return res
1526 1245
1527 def clear_and_write(self, cr, uid, ids, vals=None, context=None):1246 def clear_and_write(self, cr, uid, ids, vals=None, context=None):
@@ -1535,12 +1254,10 @@
1535 'invoice_id', 1254 'invoice_id',
1536 'manual_invoice_id', 1255 'manual_invoice_id',
1537 'manual_move_line_id',1256 'manual_move_line_id',
1538 'payment_line_id',
1539 ]] +1257 ]] +
1540 [(x, [(6, 0, [])]) for x in [1258 [(x, [(6, 0, [])]) for x in [
1541 'move_line_ids',1259 'move_line_ids',
1542 'invoice_ids',1260 'invoice_ids',
1543 'payment_order_ids',
1544 ]]))1261 ]]))
1545 write_vals.update(vals or {})1262 write_vals.update(vals or {})
1546 return self.write(cr, uid, ids, write_vals, context=context)1263 return self.write(cr, uid, ids, write_vals, context=context)
@@ -1645,23 +1362,15 @@
1645 # match fields1362 # match fields
1646 'match_type': fields.selection(1363 'match_type': fields.selection(
1647 [('manual', 'Manual'), ('move','Move'), ('invoice', 'Invoice'),1364 [('manual', 'Manual'), ('move','Move'), ('invoice', 'Invoice'),
1648 ('payment', 'Payment'), ('payment_order', 'Payment order'),1365 ], 'Match type'),
1649 ('storno', 'Storno')],
1650 'Match type'),
1651 'match_multi': fields.function(1366 'match_multi': fields.function(
1652 _get_match_multi, method=True, string='Multi match',1367 _get_match_multi, method=True, string='Multi match',
1653 type='boolean'),1368 type='boolean'),
1654 'payment_order_ids': fields.many2many(
1655 'payment.order', 'banking_transaction_payment_order_rel',
1656 'order_id', 'transaction_id', 'Payment orders'),
1657 'payment_order_id': fields.many2one(
1658 'payment.order', 'Payment order to reconcile'),
1659 'move_line_ids': fields.many2many(1369 'move_line_ids': fields.many2many(
1660 'account.move.line', 'banking_transaction_move_line_rel',1370 'account.move.line', 'banking_transaction_move_line_rel',
1661 'move_line_id', 'transaction_id', 'Matching entries'),1371 'move_line_id', 'transaction_id', 'Matching entries'),
1662 'move_line_id': fields.many2one(1372 'move_line_id': fields.many2one(
1663 'account.move.line', 'Entry to reconcile'),1373 'account.move.line', 'Entry to reconcile'),
1664 'payment_line_id': fields.many2one('payment.line', 'Payment line'),
1665 'invoice_ids': fields.many2many(1374 'invoice_ids': fields.many2many(
1666 'account.invoice', 'banking_transaction_invoice_rel',1375 'account.invoice', 'banking_transaction_invoice_rel',
1667 'invoice_id', 'transaction_id', 'Matching invoices'),1376 'invoice_id', 'transaction_id', 'Matching invoices'),
@@ -1722,9 +1431,8 @@
1722 'match_type': fields.related(1431 'match_type': fields.related(
1723 'import_transaction_id', 'match_type', type='selection',1432 'import_transaction_id', 'match_type', type='selection',
1724 selection=[('manual', 'Manual'), ('move','Move'),1433 selection=[('manual', 'Manual'), ('move','Move'),
1725 ('invoice', 'Invoice'), ('payment', 'Payment'),1434 ('invoice', 'Invoice'),
1726 ('payment_order', 'Payment order'),1435 ],
1727 ('storno', 'Storno')],
1728 string='Match type', readonly=True,),1436 string='Match type', readonly=True,),
1729 'state': fields.selection(1437 'state': fields.selection(
1730 [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State',1438 [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State',
17311439
=== modified file 'account_banking/data/account_banking_data.xml'
--- account_banking/data/account_banking_data.xml 2012-04-14 08:58:58 +0000
+++ account_banking/data/account_banking_data.xml 2013-05-24 09:03:33 +0000
@@ -20,12 +20,5 @@
20 <record id="base_iban.bank_swift_field" model="res.partner.bank.type.field">20 <record id="base_iban.bank_swift_field" model="res.partner.bank.type.field">
21 <field eval="False" name="required"/>21 <field eval="False" name="required"/>
22 </record>22 </record>
23 <!-- Add manual bank transfer as default payment option -->
24 <record model="payment.mode.type" id="account_banking.manual_bank_tranfer">
25 <field name="name">Manual Bank Transfer</field>
26 <field name="code">BANKMAN</field>
27 <field name="suitable_bank_types"
28 eval="[(6,0,[ref('base.bank_normal'),ref('base_iban.bank_iban'),])]" />
29 </record>
30 </data>23 </data>
31</openerp>24</openerp>
3225
=== modified file 'account_banking/security/ir.model.access.csv'
--- account_banking/security/ir.model.access.csv 2011-12-21 15:49:58 +0000
+++ account_banking/security/ir.model.access.csv 2013-05-24 09:03:33 +0000
@@ -2,6 +2,5 @@
2"access_account_banking_settings","account.banking.account.settings","model_account_banking_account_settings","account.group_account_manager",1,1,1,12"access_account_banking_settings","account.banking.account.settings","model_account_banking_account_settings","account.group_account_manager",1,1,1,1
3"access_account_banking_settings_user","account.banking.account.settings user","model_account_banking_account_settings","account.group_account_user",1,0,0,03"access_account_banking_settings_user","account.banking.account.settings user","model_account_banking_account_settings","account.group_account_user",1,0,0,0
4"access_account_banking_import","account.bankimport","model_account_banking_imported_file","account.group_account_user",1,1,1,14"access_account_banking_import","account.bankimport","model_account_banking_imported_file","account.group_account_user",1,1,1,1
5"access_payment_mode_type","payment.mode.type","model_payment_mode_type","account_payment.group_account_payment",1,1,1,1
6"access_banking_import_transaction","Banking addons - Bank import transaction","model_banking_import_transaction","account.group_account_user",1,1,1,15"access_banking_import_transaction","Banking addons - Bank import transaction","model_banking_import_transaction","account.group_account_user",1,1,1,1
7"access_banking_transaction_wizard","Banking addons - Transaction wizard","model_banking_transaction_wizard","account.group_account_user",1,1,1,16"access_banking_transaction_wizard","Banking addons - Transaction wizard","model_banking_transaction_wizard","account.group_account_user",1,1,1,1
87
=== modified file 'account_banking/wizard/__init__.py'
--- account_banking/wizard/__init__.py 2011-12-19 12:03:32 +0000
+++ account_banking/wizard/__init__.py 2013-05-24 09:03:33 +0000
@@ -19,8 +19,6 @@
19#19#
20##############################################################################20##############################################################################
21import bank_import21import bank_import
22import bank_payment_manual
23import account_payment_order
24import banking_transaction_wizard22import banking_transaction_wizard
2523
26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:24# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
2725
=== modified file 'account_banking/wizard/bank_import.py'
--- account_banking/wizard/bank_import.py 2012-07-11 10:37:31 +0000
+++ account_banking/wizard/bank_import.py 2013-05-24 09:03:33 +0000
@@ -85,13 +85,10 @@
85 'invoice_ids': fields.many2many(85 'invoice_ids': fields.many2many(
86 'account.invoice', 'banking_import_line_invoice_rel',86 'account.invoice', 'banking_import_line_invoice_rel',
87 'line_id', 'invoice_id'),87 'line_id', 'invoice_id'),
88 'payment_order_id': fields.many2one('payment.order', 'Payment order'),
89 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'),88 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'),
90 'transaction_type': fields.selection([89 'transaction_type': fields.selection([
91 # TODO: payment terminal etc...90 # TODO: payment terminal etc...
92 ('invoice', 'Invoice payment'),91 ('invoice', 'Invoice payment'),
93 ('payment_order_line', 'Payment from a payment order'),
94 ('payment_order', 'Aggregate payment order'),
95 ('storno', 'Canceled debit order'),92 ('storno', 'Canceled debit order'),
96 ('bank_costs', 'Bank costs'),93 ('bank_costs', 'Bank costs'),
97 ('unknown', 'Unknown'),94 ('unknown', 'Unknown'),
9895
=== modified file 'account_banking/wizard/banking_transaction_wizard.py'
--- account_banking/wizard/banking_transaction_wizard.py 2012-12-01 18:31:34 +0000
+++ account_banking/wizard/banking_transaction_wizard.py 2013-05-24 09:03:33 +0000
@@ -320,15 +320,6 @@
320 'import_transaction_id', 'writeoff_journal_id',320 'import_transaction_id', 'writeoff_journal_id',
321 type='many2one', relation='account.journal',321 type='many2one', relation='account.journal',
322 string='Write-off journal'),322 string='Write-off journal'),
323 'payment_line_id': fields.related(
324 'import_transaction_id', 'payment_line_id', string="Matching payment or storno",
325 type='many2one', relation='payment.line', readonly=True),
326 'payment_order_ids': fields.related(
327 'import_transaction_id', 'payment_order_ids', string="Matching payment orders",
328 type='many2many', relation='payment.order'),
329 'payment_order_id': fields.related(
330 'import_transaction_id', 'payment_order_id', string="Payment order to reconcile",
331 type='many2one', relation='payment.order'),
332 'invoice_ids': fields.related(323 'invoice_ids': fields.related(
333 'import_transaction_id', 'invoice_ids', string="Matching invoices", 324 'import_transaction_id', 'invoice_ids', string="Matching invoices",
334 type='many2many', relation='account.invoice'),325 type='many2many', relation='account.invoice'),
335326
=== modified file 'account_banking/wizard/banking_transaction_wizard.xml'
--- account_banking/wizard/banking_transaction_wizard.xml 2013-01-13 14:11:44 +0000
+++ account_banking/wizard/banking_transaction_wizard.xml 2013-05-24 09:03:33 +0000
@@ -8,7 +8,6 @@
8 <field name="arch" type="xml">8 <field name="arch" type="xml">
9 <form string="Match transaction">9 <form string="Match transaction">
10 <!-- fields used for form logic -->10 <!-- fields used for form logic -->
11 <field name="payment_order_ids" invisible="True"/>
12 <field name="invoice_ids" invisible="True"/>11 <field name="invoice_ids" invisible="True"/>
13 <field name="move_line_ids" invisible="True"/>12 <field name="move_line_ids" invisible="True"/>
14 <field name="match_multi" invisible="True"/>13 <field name="match_multi" invisible="True"/>
@@ -36,9 +35,6 @@
36 <separator string="Multiple matches" colspan="2"/>35 <separator string="Multiple matches" colspan="2"/>
37 <label colspan="2" string="Multiple matches were found for this bank transfer. You must pick one of the matches or select a match manually below." />36 <label colspan="2" string="Multiple matches were found for this bank transfer. You must pick one of the matches or select a match manually below." />
38 </group>37 </group>
39 <field name='payment_line_id'
40 attrs="{'invisible': [('match_type', '!=', 'storno'),('match_type', '!=', 'payment')]}"
41 />
42 <group attrs="{'readonly': [('match_multi', '!=', True)]}" col="8">38 <group attrs="{'readonly': [('match_multi', '!=', True)]}" col="8">
43 <!-- show if we have an invoice type match (but the user may need to select from multiple options)39 <!-- show if we have an invoice type match (but the user may need to select from multiple options)
44 or whenever there is an invoice_id (e.g. in case of a manual match) 40 or whenever there is an invoice_id (e.g. in case of a manual match)
@@ -53,10 +49,6 @@
53 attrs="{'readonly': [('match_multi', '=', False)], 'invisible': [('match_type', '!=', 'move'),('invoice_id', '=', False)]}"49 attrs="{'readonly': [('match_multi', '=', False)], 'invisible': [('match_type', '!=', 'move'),('invoice_id', '=', False)]}"
54 domain="[('id', 'in', move_line_ids[0][2])]"50 domain="[('id', 'in', move_line_ids[0][2])]"
55 />51 />
56 <field name='payment_order_id'
57 attrs="{'readonly': [('match_multi', '=', False)], 'invisible': [('match_type', '!=', 'payment_order')]}"
58 domain="[('id', 'in', payment_order_ids[0][2])]"
59 />
60 <field name='analytic_account_id' />52 <field name='analytic_account_id' />
61 </group>53 </group>
62 <button colspan="1"54 <button colspan="1"
6355
=== modified file 'account_banking_nl_clieop/__terp__.py'
--- account_banking_nl_clieop/__terp__.py 2011-12-27 12:00:52 +0000
+++ account_banking_nl_clieop/__terp__.py 2013-05-24 09:03:33 +0000
@@ -30,7 +30,7 @@
30 'author': 'EduSense BV',30 'author': 'EduSense BV',
31 'website': 'http://www.edusense.nl',31 'website': 'http://www.edusense.nl',
32 'category': 'Account Banking',32 'category': 'Account Banking',
33 'depends': ['account_banking'],33 'depends': ['account_banking_payment'],
34 'init_xml': [],34 'init_xml': [],
35 'update_xml': [35 'update_xml': [
36 'account_banking_nl_clieop.xml',36 'account_banking_nl_clieop.xml',
3737
=== added directory 'account_banking_payment'
=== added file 'account_banking_payment/__init__.py'
--- account_banking_payment/__init__.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/__init__.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,1 @@
1import model
02
=== added file 'account_banking_payment/__openerp__.py'
--- account_banking_payment/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/__openerp__.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,57 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26{
27 'name': 'Account Banking - Payments',
28 'version': '0.1.164',
29 'license': 'AGPL-3',
30 'author': 'Banking addons community',
31 'website': 'https://launchpad.net/banking-addons',
32 'category': 'Banking addons',
33 'depends': [
34 'account_banking',
35 'account_payment',
36 ],
37 'data': [
38 'view/account_payment.xml',
39 'view/banking_transaction_wizard.xml',
40 'view/payment_mode_type.xml',
41 'view/bank_payment_manual.xml',
42 'data/payment_mode_type.xml',
43 'workflow/account_payment.xml',
44 'security/ir.model.access.csv',
45 ],
46 'description': '''
47 This addon adds payment infrastructure to the Banking Addons.
48
49 * Extends payments for digital banking:
50 + Adapted workflow in payments to reflect banking operations
51 + Relies on account_payment mechanics to extend with export generators.
52 - ClieOp3 (NL) payment and direct debit orders files available as
53 account_banking_nl_clieop
54 ''',
55 'auto_install': True,
56 'installable': False,
57}
058
=== added directory 'account_banking_payment/data'
=== added file 'account_banking_payment/data/payment_mode_type.xml'
--- account_banking_payment/data/payment_mode_type.xml 1970-01-01 00:00:00 +0000
+++ account_banking_payment/data/payment_mode_type.xml 2013-05-24 09:03:33 +0000
@@ -0,0 +1,14 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <!-- Add manual bank transfer as default payment option -->
5 <record model="payment.mode.type" id="account_banking.manual_bank_tranfer">
6 <field name="name">Manual Bank Transfer</field>
7 <field name="code">BANKMAN</field>
8 <field name="suitable_bank_types"
9 eval="[(6,0,[ref('base.bank_normal'),ref('base_iban.bank_iban'),])]" />
10 <field name="ir_model_id"
11 ref="account_banking_payment.model_payment_manual"/>
12 </record>
13 </data>
14</openerp>
015
=== added directory 'account_banking_payment/model'
=== added file 'account_banking_payment/model/__init__.py'
--- account_banking_payment/model/__init__.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/__init__.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,10 @@
1import account_payment
2import payment_line
3import payment_mode
4import payment_mode_type
5import payment_order_create
6import banking_import_transaction
7import account_bank_statement_line
8import banking_transaction_wizard
9import bank_payment_manual
10import banking_import_line
011
=== added file 'account_banking_payment/model/account_bank_statement_line.py'
--- account_banking_payment/model/account_bank_statement_line.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/account_bank_statement_line.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,40 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class account_bank_statement_line(orm.Model):
30 _inherit = 'account.bank.statement.line'
31 _columns = {
32 'match_type': fields.related(
33 # Add payment and storno types
34 'import_transaction_id', 'match_type', type='selection',
35 selection=[('manual', 'Manual'), ('move','Move'),
36 ('invoice', 'Invoice'), ('payment', 'Payment'),
37 ('payment_order', 'Payment order'),
38 ('storno', 'Storno')],
39 string='Match type', readonly=True,),
40 }
041
=== added file 'account_banking_payment/model/account_payment.py'
--- account_banking_payment/model/account_payment.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/account_payment.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,240 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27from openerp.tools.translate import _
28from openerp import netsvc
29
30
31class payment_order(orm.Model):
32 '''
33 Enable extra states for payment exports
34 '''
35 _inherit = 'payment.order'
36
37 _columns = {
38 'date_scheduled': fields.date(
39 'Scheduled date if fixed',
40 states={
41 'sent': [('readonly', True)],
42 'rejected': [('readonly', True)],
43 'done': [('readonly', True)]
44 },
45 help='Select a date if you have chosen Preferred Date to be fixed.'
46 ),
47 'reference': fields.char(
48 'Reference', size=128, required=True,
49 states={
50 'sent': [('readonly', True)],
51 'rejected': [('readonly', True)],
52 'done': [('readonly', True)]
53 },
54 ),
55 'mode': fields.many2one(
56 'payment.mode', 'Payment mode', select=True, required=True,
57 states={
58 'sent': [('readonly', True)],
59 'rejected': [('readonly', True)],
60 'done': [('readonly', True)]
61 },
62 help='Select the Payment Mode to be applied.',
63 ),
64 'state': fields.selection([
65 ('draft', 'Draft'),
66 ('open','Confirmed'),
67 ('cancel','Cancelled'),
68 ('sent', 'Sent'),
69 ('rejected', 'Rejected'),
70 ('done','Done'),
71 ], 'State', select=True
72 ),
73 'line_ids': fields.one2many(
74 'payment.line', 'order_id', 'Payment lines',
75 states={
76 'sent': [('readonly', True)],
77 'rejected': [('readonly', True)],
78 'done': [('readonly', True)]
79 },
80 ),
81 'user_id': fields.many2one(
82 'res.users','User', required=True,
83 states={
84 'sent': [('readonly', True)],
85 'rejected': [('readonly', True)],
86 'done': [('readonly', True)]
87 },
88 ),
89 'date_prefered': fields.selection([
90 ('now', 'Directly'),
91 ('due', 'Due date'),
92 ('fixed', 'Fixed date')
93 ], "Preferred date", change_default=True, required=True,
94 states={
95 'sent': [('readonly', True)],
96 'rejected': [('readonly', True)],
97 'done': [('readonly', True)]
98 },
99 help=("Choose an option for the Payment Order:'Fixed' stands for a "
100 "date specified by you.'Directly' stands for the direct "
101 "execution.'Due date' stands for the scheduled date of "
102 "execution."
103 )
104 ),
105 'payment_order_type': fields.selection(
106 [('payment', 'Payment'),('debit', 'Direct debit')],
107 'Payment order type', required=True,
108 ),
109 'date_sent': fields.date('Send date', readonly=True),
110 }
111
112 _defaults = {
113 'payment_order_type': 'payment',
114 }
115
116 def launch_wizard(self, cr, uid, ids, context=None):
117 """
118 Search for a wizard to launch according to the type.
119 If type is manual. just confirm the order.
120 Previously (pre-v6) in account_payment/wizard/wizard_pay.py
121 """
122 if context == None:
123 context = {}
124 result = {}
125 orders = self.browse(cr, uid, ids, context)
126 order = orders[0]
127 # check if a wizard is defined for the first order
128 if order.mode.type and order.mode.type.ir_model_id:
129 context['active_ids'] = ids
130 wizard_model = order.mode.type.ir_model_id.model
131 wizard_obj = self.pool.get(wizard_model)
132 wizard_id = wizard_obj.create(cr, uid, {}, context)
133 result = {
134 'name': wizard_obj._description or _('Payment Order Export'),
135 'view_type': 'form',
136 'view_mode': 'form',
137 'res_model': wizard_model,
138 'domain': [],
139 'context': context,
140 'type': 'ir.actions.act_window',
141 'target': 'new',
142 'res_id': wizard_id,
143 'nodestroy': True,
144 }
145 else:
146 # should all be manual orders without type or wizard model
147 for order in orders[1:]:
148 if order.mode.type and order.mode.type.ir_model_id:
149 raise orm.except_orm(
150 _('Error'),
151 _('You can only combine payment orders of the same type')
152 )
153 # process manual payments
154 wf_service = netsvc.LocalService('workflow')
155 for order_id in ids:
156 wf_service.trg_validate(uid, 'payment.order', order_id, 'sent', cr)
157 return result
158
159 def _write_payment_lines(self, cr, uid, ids, **kwargs):
160 '''
161 ORM method for setting attributes of corresponding payment.line objects.
162 Note that while this is ORM compliant, it is also very ineffecient due
163 to the absence of filters on writes and hence the requirement to
164 filter on the client(=OpenERP server) side.
165 '''
166 if not hasattr(ids, '__iter__'):
167 ids = [ids]
168 payment_line_obj = self.pool.get('payment.line')
169 line_ids = payment_line_obj.search(
170 cr, uid, [
171 ('order_id', 'in', ids)
172 ])
173 payment_line_obj.write(cr, uid, line_ids, kwargs)
174
175 def set_to_draft(self, cr, uid, ids, *args):
176 '''
177 Set both self and payment lines to state 'draft'.
178 '''
179 self._write_payment_lines(cr, uid, ids, export_state='draft')
180 return super(payment_order, self).set_to_draft(
181 cr, uid, ids, *args
182 )
183
184 def action_sent(self, cr, uid, ids, context=None):
185 '''
186 Set both self and payment lines to state 'sent'.
187 '''
188 self._write_payment_lines(cr, uid, ids, export_state='sent')
189 self.write(cr, uid, ids, {
190 'state': 'sent',
191 'date_sent': fields.date.context_today(
192 self, cr, uid, context=context),
193 }, context=context)
194 return True
195
196 def action_rejected(self, cr, uid, ids, *args):
197 '''
198 Set both self and payment lines to state 'rejected'.
199 '''
200 self._write_payment_lines(cr, uid, ids, export_state='rejected')
201 wf_service = netsvc.LocalService('workflow')
202 for id in ids:
203 wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cr)
204 return True
205
206 def set_done(self, cr, uid, ids, *args):
207 '''
208 Extend standard transition to update children as well.
209 '''
210 self._write_payment_lines(
211 cr, uid, ids,
212 export_state='done',
213 date_done=fields.date.context_today(self, cr, uid))
214 return super(payment_order, self).set_done(
215 cr, uid, ids, *args
216 )
217
218 """
219 Hooks for processing direct debit orders, such as implemented in
220 account_direct_debit module.
221 """
222 def debit_reconcile_transfer(
223 self, cr, uid, payment_order_id, amount, currency, context=None):
224 """
225 Reconcile the payment order if the amount is correct. Return the
226 id of the reconciliation.
227 """
228 raise orm.except_orm(
229 _("Cannot reconcile"),
230 _("Cannot reconcile debit order: "+
231 "Not implemented."))
232
233 def debit_unreconcile_transfer(
234 self, cr, uid, payment_order_id, reconcile_id, amount, currency,
235 context=None):
236 """ Unreconcile the payment_order if at all possible """
237 raise orm.except_orm(
238 _("Cannot unreconcile"),
239 _("Cannot unreconcile debit order: "+
240 "Not implemented."))
0241
=== renamed file 'account_banking/wizard/bank_payment_manual.py' => 'account_banking_payment/model/bank_payment_manual.py'
--- account_banking/wizard/bank_payment_manual.py 2010-12-20 10:58:51 +0000
+++ account_banking_payment/model/bank_payment_manual.py 2013-05-24 09:03:33 +0000
@@ -1,20 +1,24 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2##############################################################################2##############################################################################
3#3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
5# All Rights Reserved9# All Rights Reserved
6#10#
7# This program is free software: you can redistribute it and/or modify11# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by12# it under the terms of the GNU Affero General Public License as
9# the Free Software Foundation, either version 3 of the License, or13# published by the Free Software Foundation, either version 3 of the
10# (at your option) any later version.14# License, or (at your option) any later version.
11#15#
12# This program is distributed in the hope that it will be useful,16# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of17# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.19# GNU Affero General Public License for more details.
16#20#
17# You should have received a copy of the GNU General Public License21# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.22# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#23#
20##############################################################################24##############################################################################
@@ -24,30 +28,26 @@
24bank transfers.28bank transfers.
25'''29'''
2630
27import wizard31from openerp.osv import orm, fields
28import pooler32from openerp import netsvc
2933
30class payment_manual(wizard.interface):34
31 def _action_set_state_sent(self, cursor, uid, data, context):35class payment_manual(orm.TransientModel):
32 '''36 _name = 'payment.manual'
33 Set the payment order in state 'sent' to reflect money in transfer.37 _description = 'Set payment orders to \'sent\' manually'
34 '''38
35 payment_order_obj = pooler.get_pool(cursor.dbname)\39 def default_get(self, cr, uid, fields_list, context=None):
36 .get('payment.order')40 if context and context.get('active_ids'):
37 payment_order_obj.action_sent(cursor, uid, [data['id']], context)41 payment_order_obj = self.pool.get('payment.order')
38 return {}42 wf_service = netsvc.LocalService('workflow')
39 43 for order_id in context['active_ids']:
40 states= {44 wf_service.trg_validate(
41 'init' : {45 uid, 'payment.order', order_id, 'sent', cr)
42 'actions': [],46 return super(payment_manual, self).default_get(
43 'result': {47 cr, uid, fields_list, context=None)
44 'type':'action',48
45 'action': _action_set_state_sent,49 _columns = {
46 'state': 'end'50 # dummy field, to trigger a call to default_get
47 }51 'name': fields.char('Name', size=1),
48 }52 }
49 }53
50
51payment_manual('account_banking.payment_manual')
52
53# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
5454
=== added file 'account_banking_payment/model/banking_import_line.py'
--- account_banking_payment/model/banking_import_line.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/banking_import_line.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,45 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class banking_import_line(orm.TransientModel):
30 _inherit = 'banking.import.line'
31 _columns = {
32 'payment_order_id': fields.many2one(
33 'payment.order', 'Payment order'),
34 'transaction_type': fields.selection([
35 # Add payment order related transaction types
36 ('invoice', 'Invoice payment'),
37 ('payment_order_line', 'Payment from a payment order'),
38 ('payment_order', 'Aggregate payment order'),
39 ('storno', 'Canceled debit order'),
40 ('bank_costs', 'Bank costs'),
41 ('unknown', 'Unknown'),
42 ], 'Transaction type'),
43 }
44
45
046
=== added file 'account_banking_payment/model/banking_import_transaction.py'
--- account_banking_payment/model/banking_import_transaction.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/banking_import_transaction.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,381 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27from openerp import netsvc
28from openerp.tools.translate import _
29from openerp.addons.decimal_precision import decimal_precision as dp
30
31
32class banking_import_transaction(orm.Model):
33 _inherit = 'banking.import.transaction'
34
35 def _match_debit_order(
36 self, cr, uid, trans, log, context=None):
37
38 def is_zero(total):
39 return self.pool.get('res.currency').is_zero(
40 cr, uid, trans.statement_id.currency, total)
41
42 payment_order_obj = self.pool.get('payment.order')
43
44 order_ids = payment_order_obj.search(
45 cr, uid, [('payment_order_type', '=', 'debit'),
46 ('state', '=', 'sent'),
47 ('date_sent', '<=', trans.execution_date),
48 ],
49 limit=0, context=context)
50 orders = payment_order_obj.browse(cr, uid, order_ids, context)
51 candidates = [x for x in orders if
52 is_zero(x.total - trans.transferred_amount)]
53 if len(candidates) > 0:
54 # retrieve the common account_id, if any
55 account_id = False
56 for line in candidates[0].line_ids[0].debit_move_line_id.move_id.line_id:
57 if line.account_id.type == 'other':
58 account_id = line.account_id.id
59 break
60 return dict(
61 move_line_ids = False,
62 match_type = 'payment_order',
63 payment_order_ids = [x.id for x in candidates],
64 account_id = account_id,
65 partner_id = False,
66 partner_bank_id = False,
67 reference = False,
68 type='general',
69 )
70 return False
71
72 def _match_storno(
73 self, cr, uid, trans, log, context=None):
74 payment_line_obj = self.pool.get('payment.line')
75 line_ids = payment_line_obj.search(
76 cr, uid, [
77 ('order_id.payment_order_type', '=', 'debit'),
78 ('order_id.state', 'in', ['sent', 'done']),
79 ('communication', '=', trans.reference)
80 ], context=context)
81 # stornos MUST have an exact match
82 if len(line_ids) == 1:
83 account_id = payment_line_obj.get_storno_account_id(
84 cr, uid, line_ids[0], trans.transferred_amount,
85 trans.statement_id.currency, context=None)
86 if account_id:
87 return dict(
88 account_id = account_id,
89 match_type = 'storno',
90 payment_line_id = line_ids[0],
91 move_line_ids=False,
92 partner_id=False,
93 partner_bank_id=False,
94 reference=False,
95 type='customer',
96 )
97 # TODO log the reason why there is no result for transfers marked
98 # as storno
99 return False
100
101 def _match_payment(self, cr, uid, trans, payment_lines,
102 partner_ids, bank_account_ids, log, linked_payments):
103 '''
104 Find the payment order belonging to this reference - if there is one
105 This is the easiest part: when sending payments, the returned bank info
106 should be identical to ours.
107 This also means that we do not allow for multiple candidates.
108 '''
109 # TODO: Not sure what side effects are created when payments are done
110 # for credited customer invoices, which will be matched later on too.
111 digits = dp.get_precision('Account')(cr)[1]
112 candidates = [
113 x for x in payment_lines
114 if x.communication == trans.reference
115 and round(x.amount, digits) == -round(
116 trans.transferred_amount, digits)
117 and trans.remote_account in (x.bank_id.acc_number,
118 x.bank_id.acc_number_domestic)
119 ]
120 if len(candidates) == 1:
121 candidate = candidates[0]
122 # Check cache to prevent multiple matching of a single payment
123 if candidate.id not in linked_payments:
124 linked_payments[candidate.id] = True
125 move_info = self._get_move_info(
126 cr, uid, [candidate.move_line_id.id])
127 move_info.update({
128 'match_type': 'payment',
129 'payment_line_id': candidate.id,
130 })
131 return move_info
132
133 return False
134
135 def _confirm_storno(
136 self, cr, uid, transaction_id, context=None):
137 """
138 Creation of the reconciliation has been delegated to
139 *a* direct debit module, to allow for various direct debit styles
140 """
141 payment_line_pool = self.pool.get('payment.line')
142 statement_line_pool = self.pool.get('account.bank.statement.line')
143 transaction = self.browse(cr, uid, transaction_id, context=context)
144 if not transaction.payment_line_id:
145 raise orm.except_orm(
146 _("Cannot link with storno"),
147 _("No direct debit order item"))
148 reconcile_id = payment_line_pool.debit_storno(
149 cr, uid,
150 transaction.payment_line_id.id,
151 transaction.statement_line_id.amount,
152 transaction.statement_line_id.currency,
153 transaction.storno_retry,
154 context=context)
155 statement_line_pool.write(
156 cr, uid, transaction.statement_line_id.id,
157 {'reconcile_id': reconcile_id}, context=context)
158 transaction.refresh()
159
160 def _confirm_payment_order(
161 self, cr, uid, transaction_id, context=None):
162 """
163 Creation of the reconciliation has been delegated to
164 *a* direct debit module, to allow for various direct debit styles
165 """
166 payment_order_obj = self.pool.get('payment.order')
167 statement_line_pool = self.pool.get('account.bank.statement.line')
168 transaction = self.browse(cr, uid, transaction_id, context=context)
169 if not transaction.payment_order_id:
170 raise orm.except_orm(
171 _("Cannot reconcile"),
172 _("Cannot reconcile: no direct debit order"))
173 if transaction.payment_order_id.payment_order_type != 'debit':
174 raise orm.except_orm(
175 _("Cannot reconcile"),
176 _("Reconcile payment order not implemented"))
177 reconcile_id = payment_order_obj.debit_reconcile_transfer(
178 cr, uid,
179 transaction.payment_order_id.id,
180 transaction.statement_line_id.amount,
181 transaction.statement_line_id.currency,
182 context=context)
183 statement_line_pool.write(
184 cr, uid, transaction.statement_line_id.id,
185 {'reconcile_id': reconcile_id}, context=context)
186
187 def _confirm_payment(
188 self, cr, uid, transaction_id, context=None):
189 """
190 Do some housekeeping on the payment line
191 then pass on to _reconcile_move
192 """
193 transaction = self.browse(cr, uid, transaction_id, context=context)
194 payment_line_obj = self.pool.get('payment.line')
195 payment_line_obj.write(
196 cr, uid, transaction.payment_line_id.id, {
197 'export_state': 'done',
198 'date_done': transaction.statement_line_id.date,
199 }
200 )
201 self._confirm_move(cr, uid, transaction_id, context=context)
202 # Check if the payment order is 'done'
203 order_id = transaction.payment_line_id.order_id.id
204 other_lines = payment_line_obj.search(
205 cr, uid, [
206 ('order_id', '=', order_id),
207 ('date_done', '=', False),
208 ], context=context)
209 if not other_lines:
210 wf_service = netsvc.LocalService('workflow')
211 wf_service.trg_validate(
212 uid, 'payment.order', order_id, 'done', cr)
213
214 def _cancel_payment(
215 self, cr, uid, transaction_id, context=None):
216 """
217 Do not support cancelling individual lines yet, because the workflow
218 of the payment order does not support reopening.
219 """
220 raise orm.except_orm(
221 _("Cannot unreconcile"),
222 _("Cannot unreconcile: this operation is not yet supported for "
223 "match type 'payment'"))
224
225 def _cancel_payment_order(
226 self, cr, uid, transaction_id, context=None):
227 """
228 """
229 payment_order_obj = self.pool.get('payment.order')
230 transaction = self.browse(cr, uid, transaction_id, context=context)
231 if not transaction.payment_order_id:
232 raise orm.except_orm(
233 _("Cannot unreconcile"),
234 _("Cannot unreconcile: no direct debit order"))
235 if transaction.payment_order_id.payment_order_type != 'debit':
236 raise orm.except_orm(
237 _("Cannot unreconcile"),
238 _("Unreconcile payment order not implemented"))
239 return payment_order_obj.debit_unreconcile_transfer(
240 cr, uid, transaction.payment_order_id.id,
241 transaction.statement_line_id.reconcile_id.id,
242 transaction.statement_line_id.amount,
243 transaction.statement_line_id.currency)
244
245 def _cancel_storno(
246 self, cr, uid, transaction_id, context=None):
247 """
248 TODO: delegate unreconciliation to the direct debit module,
249 to allow for various direct debit styles
250 """
251 payment_line_obj = self.pool.get('payment.line')
252 reconcile_obj = self.pool.get('account.move.reconcile')
253 transaction = self.browse(cr, uid, transaction_id, context=context)
254
255 if not transaction.payment_line_id:
256 raise orm.except_orm(
257 _("Cannot cancel link with storno"),
258 _("No direct debit order item"))
259 if not transaction.payment_line_id.storno:
260 raise orm.except_orm(
261 _("Cannot cancel link with storno"),
262 _("The direct debit order item is not marked for storno"))
263
264 journal = transaction.statement_line_id.statement_id.journal_id
265 if transaction.statement_line_id.amount >= 0:
266 account_id = journal.default_credit_account_id.id
267 else:
268 account_id = journal.default_debit_account_id.id
269 cancel_line = False
270 move_lines = []
271 for move in transaction.statement_line_id.move_ids:
272 # There should usually be just one move, I think
273 move_lines += move.line_id
274 for line in move_lines:
275 if line.account_id.id != account_id:
276 cancel_line = line
277 break
278 if not cancel_line:
279 raise orm.except_orm(
280 _("Cannot cancel link with storno"),
281 _("Line id not found"))
282 reconcile = cancel_line.reconcile_id or cancel_line.reconcile_partial_id
283 lines_reconcile = reconcile.line_id or reconcile.line_partial_ids
284 if len(lines_reconcile) < 3:
285 # delete the full reconciliation
286 reconcile_obj.unlink(cr, uid, reconcile.id, context)
287 else:
288 # we are left with a partial reconciliation
289 reconcile_obj.write(
290 cr, uid, reconcile.id,
291 {'line_partial_ids':
292 [(6, 0, [x.id for x in lines_reconcile
293 if x.id != cancel_line.id])],
294 'line_id': [(6, 0, [])],
295 }, context)
296 # redo the original payment line reconciliation with the invoice
297 payment_line_obj.write(
298 cr, uid, transaction.payment_line_id.id,
299 {'storno': False}, context)
300 payment_line_obj.debit_reconcile(
301 cr, uid, transaction.payment_line_id.id, context)
302
303 _columns = {
304 'match_type': fields.selection(
305 # Add payment and storno types
306 [
307 ('manual', 'Manual'),
308 ('move','Move'),
309 ('invoice', 'Invoice'),
310 ('payment', 'Payment'),
311 ('payment_order', 'Payment order'),
312 ('storno', 'Storno'),
313 ],
314 'Match type'),
315 'payment_order_ids': fields.many2many(
316 'payment.order', 'banking_transaction_payment_order_rel',
317 'order_id', 'transaction_id', 'Payment orders'),
318 'payment_order_id': fields.many2one(
319 'payment.order', 'Payment order to reconcile'),
320 'payment_line_id': fields.many2one('payment.line', 'Payment line'),
321 }
322
323 def _get_match_multi(self, cr, uid, ids, name, args, context=None):
324 if not ids:
325 return {}
326 res = super(banking_import_transaction, self)._get_match_multi(
327 cr, uid, ids, name, args, context=context)
328 for transaction in self.browse(cr, uid, ids, context):
329 if transaction.match_type == 'payment_order':
330 if (transaction.payment_order_ids and not
331 transaction.payment_order_id):
332 res[transaction.id] = True
333 return res
334
335 def clear_and_write(self, cr, uid, ids, vals=None, context=None):
336 super(banking_import_transaction, self).clear_and_write(
337 cr, uid, ids, vals=vals, context=context)
338 return self.write(
339 cr, uid, ids, {
340 'payment_line_id': False,
341 'payment_order_ids': [(6, 0, [])],
342 },
343 context=context)
344
345 def move_info2values(self, move_info):
346 vals = super(banking_import_transaction, self).move_info2values(
347 move_info)
348 vals['payment_line_id'] = move_info.get('payment_line_id', False)
349 vals['payment_order_ids'] = [
350 (6, 0, move_info.get('payment_order_ids') or [])]
351 vals['payment_order_id'] = (
352 move_info.get('payment_order_ids', False) and
353 len(move_info['payment_order_ids']) == 1 and
354 move_info['payment_order_ids'][0]
355 )
356 return vals
357
358 def match(self, cr, uid, ids, results=None, context=None):
359 res = super(banking_import_transaction, self).match(
360 cr, uid, ids, results=results, context=context)
361
362 return res
363
364 def __init__(self, pool, cr):
365 """
366 Updating the function maps to handle the match types that this
367 module adds.
368 """
369 super(banking_import_transaction, self).__init__(pool, cr)
370
371 banking_import_transaction.confirm_map.update({
372 'storno': banking_import_transaction._confirm_storno,
373 'payment_order': banking_import_transaction._confirm_payment_order,
374 'payment': banking_import_transaction._confirm_payment,
375 })
376
377 banking_import_transaction.cancel_map.update({
378 'storno': banking_import_transaction._cancel_storno,
379 'payment_order': banking_import_transaction._cancel_payment_order,
380 'payment': banking_import_transaction._cancel_payment,
381 })
0382
=== added file 'account_banking_payment/model/banking_transaction_wizard.py'
--- account_banking_payment/model/banking_transaction_wizard.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/banking_transaction_wizard.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,45 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class banking_transaction_wizard(orm.TransientModel):
30 _inherit = 'banking.transaction.wizard'
31 _columns = {
32 'payment_line_id': fields.related(
33 'import_transaction_id', 'payment_line_id',
34 string="Matching payment or storno",
35 type='many2one', relation='payment.line',
36 readonly=True),
37 'payment_order_ids': fields.related(
38 'import_transaction_id', 'payment_order_ids',
39 string="Matching payment orders",
40 type='many2many', relation='payment.order'),
41 'payment_order_id': fields.related(
42 'import_transaction_id', 'payment_order_id',
43 string="Payment order to reconcile",
44 type='many2one', relation='payment.order'),
45 }
046
=== added file 'account_banking_payment/model/payment_line.py'
--- account_banking_payment/model/payment_line.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/payment_line.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,218 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class payment_line(orm.Model):
30 '''
31 Add extra export_state and date_done fields; make destination bank account
32 mandatory, as it makes no sense to send payments into thin air.
33 Edit: Payments can be by cash too, which is prohibited by mandatory bank
34 accounts.
35 '''
36 _inherit = 'payment.line'
37 _columns = {
38 # New fields
39 'export_state': fields.selection([
40 ('draft', 'Draft'),
41 ('open','Confirmed'),
42 ('cancel','Cancelled'),
43 ('sent', 'Sent'),
44 ('rejected', 'Rejected'),
45 ('done','Done'),
46 ], 'State', select=True
47 ),
48 'msg': fields.char('Message', size=255, required=False, readonly=True),
49
50 # Redefined fields: added states
51 'date_done': fields.datetime('Date Confirmed', select=True,
52 readonly=True),
53 'name': fields.char(
54 'Your Reference', size=64, required=True,
55 states={
56 'sent': [('readonly', True)],
57 'rejected': [('readonly', True)],
58 'done': [('readonly', True)]
59 },
60 ),
61 'communication': fields.char(
62 'Communication', size=64, required=False,
63 help=("Used as the message between ordering customer and current "
64 "company. Depicts 'What do you want to say to the recipient"
65 " about this order ?'"
66 ),
67 states={
68 'sent': [('readonly', True)],
69 'rejected': [('readonly', True)],
70 'done': [('readonly', True)]
71 },
72 ),
73 'communication2': fields.char(
74 'Communication 2', size=128,
75 help='The successor message of Communication.',
76 states={
77 'sent': [('readonly', True)],
78 'rejected': [('readonly', True)],
79 'done': [('readonly', True)]
80 },
81 ),
82 'move_line_id': fields.many2one(
83 'account.move.line', 'Entry line',
84 domain=[('reconcile_id','=', False),
85 ('account_id.type', '=','payable')
86 ],
87 help=('This Entry Line will be referred for the information of '
88 'the ordering customer.'
89 ),
90 states={
91 'sent': [('readonly', True)],
92 'rejected': [('readonly', True)],
93 'done': [('readonly', True)]
94 },
95 ),
96 'amount_currency': fields.float(
97 'Amount in Partner Currency', digits=(16,2),
98 required=True,
99 help='Payment amount in the partner currency',
100 states={
101 'sent': [('readonly', True)],
102 'rejected': [('readonly', True)],
103 'done': [('readonly', True)]
104 },
105 ),
106 'currency': fields.many2one(
107 'res.currency', 'Partner Currency', required=True,
108 states={
109 'sent': [('readonly', True)],
110 'rejected': [('readonly', True)],
111 'done': [('readonly', True)]
112 },
113 ),
114 'bank_id': fields.many2one(
115 'res.partner.bank', 'Destination Bank account',
116 states={
117 'sent': [('readonly', True)],
118 'rejected': [('readonly', True)],
119 'done': [('readonly', True)]
120 },
121 ),
122 'order_id': fields.many2one(
123 'payment.order', 'Order', required=True,
124 ondelete='cascade', select=True,
125 states={
126 'sent': [('readonly', True)],
127 'rejected': [('readonly', True)],
128 'done': [('readonly', True)]
129 },
130 ),
131 'partner_id': fields.many2one(
132 'res.partner', string="Partner", required=True,
133 help='The Ordering Customer',
134 states={
135 'sent': [('readonly', True)],
136 'rejected': [('readonly', True)],
137 'done': [('readonly', True)]
138 },
139 ),
140 'date': fields.date(
141 'Payment Date',
142 help=("If no payment date is specified, the bank will treat this "
143 "payment line directly"
144 ),
145 states={
146 'sent': [('readonly', True)],
147 'rejected': [('readonly', True)],
148 'done': [('readonly', True)]
149 },
150 ),
151 'state': fields.selection([
152 ('normal','Free'),
153 ('structured','Structured')
154 ], 'Communication Type', required=True,
155 states={
156 'sent': [('readonly', True)],
157 'rejected': [('readonly', True)],
158 'done': [('readonly', True)]
159 },
160 ),
161 }
162 _defaults = {
163 'export_state': 'draft',
164 'date_done': False,
165 'msg': '',
166 }
167
168 def fields_get(self, cr, uid, fields=None, context=None):
169 res = super(payment_line, self).fields_get(cr, uid, fields, context)
170 if 'communication' in res:
171 res['communication'].setdefault('states', {})
172 res['communication']['states']['structured'] = [('required', True)]
173 if 'communication2' in res:
174 res['communication2'].setdefault('states', {})
175 res['communication2']['states']['structured'] = [('readonly', True)]
176 res['communication2']['states']['normal'] = [('readonly', False)]
177
178 return res
179
180 """
181 Hooks for processing direct debit orders, such as implemented in
182 account_direct_debit module.
183 """
184 def get_storno_account_id(self, cr, uid, payment_line_id, amount,
185 currency_id, context=None):
186 """
187 Hook for verifying a match of the payment line with the amount.
188 Return the account associated with the storno.
189 Used in account_banking interactive mode
190 :param payment_line_id: the single payment line id
191 :param amount: the (signed) amount debited from the bank account
192 :param currency: the bank account's currency *browse object*
193 :return: an account if there is a full match, False otherwise
194 :rtype: database id of an account.account resource.
195 """
196
197 return False
198
199 def debit_storno(self, cr, uid, payment_line_id, amount,
200 currency_id, storno_retry=True, context=None):
201 """
202 Hook for handling a canceled item of a direct debit order.
203 Presumably called from a bank statement import routine.
204
205 Decide on the direction that the invoice's workflow needs to take.
206 You may optionally return an incomplete reconcile for the caller
207 to reconcile the now void payment.
208
209 :param payment_line_id: the single payment line id
210 :param amount: the (negative) amount debited from the bank account
211 :param currency: the bank account's currency *browse object*
212 :param boolean storno_retry: whether the storno is considered fatal \
213 or not.
214 :return: an incomplete reconcile for the caller to fill
215 :rtype: database id of an account.move.reconcile resource.
216 """
217
218 return False
0219
=== added file 'account_banking_payment/model/payment_mode.py'
--- account_banking_payment/model/payment_mode.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/payment_mode.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,51 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class payment_mode(orm.Model):
30 ''' Restoring the payment type from version 5,
31 used to select the export wizard (if any) '''
32 _inherit = "payment.mode"
33
34 def suitable_bank_types(self, cr, uid, payment_mode_id=None, context=None):
35 """ Reinstates functional code for suitable bank type filtering.
36 Current code in account_payment is disfunctional.
37 """
38 res = []
39 payment_mode = self.browse(
40 cr, uid, payment_mode_id, context)
41 if (payment_mode and payment_mode.type and
42 payment_mode.type.suitable_bank_types):
43 res = [type.code for type in payment_mode.type.suitable_bank_types]
44 return res
45
46 _columns = {
47 'type': fields.many2one(
48 'payment.mode.type', 'Payment type',
49 help='Select the Payment Type for the Payment Mode.'
50 ),
51 }
052
=== added file 'account_banking_payment/model/payment_mode_type.py'
--- account_banking_payment/model/payment_mode_type.py 1970-01-01 00:00:00 +0000
+++ account_banking_payment/model/payment_mode_type.py 2013-05-24 09:03:33 +0000
@@ -0,0 +1,62 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
9# All Rights Reserved
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU Affero General Public License as
13# published by the Free Software Foundation, either version 3 of the
14# License, or (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU Affero General Public License for more details.
20#
21# You should have received a copy of the GNU Affero General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24##############################################################################
25
26from openerp.osv import orm, fields
27
28
29class payment_mode_type(orm.Model):
30 _name = 'payment.mode.type'
31 _description = 'Payment Mode Type'
32 _columns = {
33 'name': fields.char(
34 'Name', size=64, required=True,
35 help='Payment Type'
36 ),
37 'code': fields.char(
38 'Code', size=64, required=True,
39 help='Specify the Code for Payment Type'
40 ),
41 # Setting suitable_bank_types to required pending
42 # https://bugs.launchpad.net/openobject-addons/+bug/786845
43 'suitable_bank_types': fields.many2many(
44 'res.partner.bank.type',
45 'bank_type_payment_type_rel',
46 'pay_type_id','bank_type_id',
47 'Suitable bank types', required=True),
48 'ir_model_id': fields.many2one(
49 'ir.model', 'Payment wizard',
50 help=('Select the Payment Wizard for payments of this type. '
51 'Leave empty for manual processing'),
52 domain=[('osv_memory', '=', True)],
53 ),
54 'payment_order_type': fields.selection(
55 [('payment', 'Payment'),('debit', 'Direct debit')],
56 'Payment order type', required=True,
57 ),
58 }
59
60 _defaults = {
61 'payment_order_type': 'payment',
62 }
063
=== renamed file 'account_banking/wizard/account_payment_order.py' => 'account_banking_payment/model/payment_order_create.py'
--- account_banking/wizard/account_payment_order.py 2013-01-21 20:25:00 +0000
+++ account_banking_payment/model/payment_order_create.py 2013-05-24 09:03:33 +0000
@@ -2,35 +2,33 @@
2##############################################################################2##############################################################################
3#3#
4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).4# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
5# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
6#
7# All other contributions are (C) by their respective contributors
8#
5# All Rights Reserved9# All Rights Reserved
6#10#
7# This program is free software: you can redistribute it and/or modify11# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by12# it under the terms of the GNU Affero General Public License as
9# the Free Software Foundation, either version 3 of the License, or13# published by the Free Software Foundation, either version 3 of the
10# (at your option) any later version.14# License, or (at your option) any later version.
11#15#
12# This program is distributed in the hope that it will be useful,16# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of17# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.19# GNU Affero General Public License for more details.
16#20#
17# You should have received a copy of the GNU General Public License21# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.22# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#23#
20##############################################################################24##############################################################################
2125
22import datetime26from datetime import datetime
23from osv import osv27from openerp.osv import orm, fields
24from account_banking.struct import struct28from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
25from account_banking.parsers import convert29
2630
27today = datetime.date.today31class payment_order_create(orm.TransientModel):
28
29def str2date(str):
30 dt = convert.str2date(str, '%Y-%m-%d')
31 return datetime.date(dt.year, dt.month, dt.day)
32
33class payment_order_create(osv.osv_memory):
34 _inherit = 'payment.order.create'32 _inherit = 'payment.order.create'
3533
36 def create_payment(self, cr, uid, ids, context=None):34 def create_payment(self, cr, uid, ids, context=None):
@@ -57,8 +55,9 @@
57 ### account banking55 ### account banking
58 # t = None56 # t = None
59 # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context)57 # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context)
60 line2bank = line_obj.line2bank(cr, uid, line_ids, payment.mode.id, context)58 line2bank = line_obj.line2bank(
61 _today = today()59 cr, uid, line_ids, payment.mode.id, context)
60 _today = fields.date.context_today(self, cr, uid, context=context)
62 ### end account banking61 ### end account banking
6362
64 ## Finally populate the current payment with new lines:63 ## Finally populate the current payment with new lines:
@@ -69,16 +68,18 @@
69 elif payment.date_prefered == 'due':68 elif payment.date_prefered == 'due':
70 ### account_banking69 ### account_banking
71 # date_to_pay = line.date_maturity70 # date_to_pay = line.date_maturity
72 date_to_pay = line.date_maturity and \71 date_to_pay = (
73 str2date(line.date_maturity) > _today\72 line.date_maturity
74 and line.date_maturity or False73 if line.date_maturity and line.date_maturity > _today
74 else False)
75 ### end account banking75 ### end account banking
76 elif payment.date_prefered == 'fixed':76 elif payment.date_prefered == 'fixed':
77 ### account_banking77 ### account_banking
78 # date_to_pay = payment.date_planned78 # date_to_pay = payment.date_planned
79 date_to_pay = payment.date_planned and \79 date_to_pay = (
80 str2date(payment.date_planned) > _today\80 payment.date_planned
81 and payment.date_planned or False81 if payment.date_planned and payment.date_planned > _today
82 else False)
82 ### end account banking83 ### end account banking
8384
84 ### account_banking85 ### account_banking
@@ -107,7 +108,7 @@
107 amount_currency = line.amount_to_pay108 amount_currency = line.amount_to_pay
108 ### end account_banking109 ### end account_banking
109110
110 payment_obj.create(cr, uid,{111 payment_obj.create(cr, uid, {
111 'move_line_id': line.id,112 'move_line_id': line.id,
112 'amount_currency': amount_currency,113 'amount_currency': amount_currency,
113 'bank_id': line2bank.get(line.id),114 'bank_id': line2bank.get(line.id),
@@ -123,5 +124,3 @@
123 'currency': line.invoice and line.invoice.currency_id.id or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id,124 'currency': line.invoice and line.invoice.currency_id.id or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id,
124 }, context=context)125 }, context=context)
125 return {'type': 'ir.actions.act_window_close'}126 return {'type': 'ir.actions.act_window_close'}
126
127payment_order_create()
128127
=== added directory 'account_banking_payment/security'
=== added file 'account_banking_payment/security/ir.model.access.csv'
--- account_banking_payment/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ account_banking_payment/security/ir.model.access.csv 2013-05-24 09:03:33 +0000
@@ -0,0 +1,2 @@
1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2"access_payment_mode_type","payment.mode.type","model_payment_mode_type","account_payment.group_account_payment",1,1,1,1
03
=== added directory 'account_banking_payment/view'
=== added file 'account_banking_payment/view/account_payment.xml'
--- account_banking_payment/view/account_payment.xml 1970-01-01 00:00:00 +0000
+++ account_banking_payment/view/account_payment.xml 2013-05-24 09:03:33 +0000
@@ -0,0 +1,45 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <!-- Make buttons on payment order sensitive for extra states,
5 restore wizard functionality when making payments
6 -->
7
8 <record id="view_banking_payment_order_form_1" model="ir.ui.view">
9 <field name="name">account.payment.order.form.banking-1</field>
10 <field name="inherit_id" ref="account_payment.view_payment_order_form" />
11 <field name="model">payment.order</field>
12 <field name="type">form</field>
13 <field name="arch" type="xml">
14 <data>
15 <xpath expr="/form/group/button[@string='Select Invoices to Pay']"
16 position="replace">
17 <button colspan="2" name="%(account_payment.action_create_payment_order)s"
18 string="Select Invoices to Pay" type="action"
19 attrs="{'invisible':[('state','!=','draft')]}"
20 icon="gtk-find"
21 />
22 </xpath>
23 <xpath expr="/form/group/button[@string='Make Payments']"
24 position="replace">
25 <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/>
26 <newline/>
27 </xpath>
28 </data>
29 </field>
30 </record>
31
32 <record id="view_banking_payment_order_tree_1" model="ir.ui.view">
33 <field name="name">account.payment.order.tree.banking-1</field>
34 <field name="inherit_id" ref="account_payment.view_payment_order_tree" />
35 <field name="model">payment.order</field>
36 <field name="type">tree</field>
37 <field name="arch" type="xml">
38 <button string="Make Payments" position="replace">
39 <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/>
40 </button>
41 </field>
42 </record>
43
44 </data>
45</openerp>
046
=== added file 'account_banking_payment/view/bank_payment_manual.xml'
--- account_banking_payment/view/bank_payment_manual.xml 1970-01-01 00:00:00 +0000
+++ account_banking_payment/view/bank_payment_manual.xml 2013-05-24 09:03:33 +0000
@@ -0,0 +1,16 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <record id="view_payment_manual_form" model="ir.ui.view">
5 <field name="name">Form for manual payment wizard</field>
6 <field name="model">payment.manual</field>
7 <field name="type">form</field>
8 <field name="arch" type="xml">
9 <form>
10 <label string="Payment order(s) have been set to 'sent'"/>
11 <button special="cancel" icon="gtk-ok" string="OK"/>
12 </form>
13 </field>
14 </record>
15 </data>
16</openerp>
017
=== added file 'account_banking_payment/view/banking_transaction_wizard.xml'
--- account_banking_payment/view/banking_transaction_wizard.xml 1970-01-01 00:00:00 +0000
+++ account_banking_payment/view/banking_transaction_wizard.xml 2013-05-24 09:03:33 +0000
@@ -0,0 +1,36 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <record model="ir.ui.view" id="transaction_wizard">
5 <field name="name">transaction.wizard</field>
6 <field name="model">banking.transaction.wizard</field>
7 <field name="inherit_id"
8 ref="account_banking.transaction_wizard_first" />
9 <field name="type">form</field>
10 <field name="arch" type="xml">
11 <field name="invoice_ids" position="before">
12 <field name="payment_order_ids" invisible="True"/>
13 </field>
14 <xpath expr="//group/separator[@string='Multiple matches']/.."
15 position="after">
16 <field name='payment_line_id'
17 attrs="{'invisible': [
18 ('match_type', '!=', 'storno'),
19 ('match_type', '!=', 'payment')]
20 }" />
21 </xpath>
22 <field name="move_line_id" position="after">
23 <field name='payment_order_id'
24 attrs="{'readonly': [
25 ('match_multi', '=', False)],
26 'invisible': [
27 ('match_type', '!=', 'payment_order')]}"
28 domain="[('id', 'in', payment_order_ids[0][2])]"
29 />
30 </field>
31 </field>
32 </record>
33 </data>
34</openerp>
35
36
037
=== added file 'account_banking_payment/view/payment_mode_type.xml'
--- account_banking_payment/view/payment_mode_type.xml 1970-01-01 00:00:00 +0000
+++ account_banking_payment/view/payment_mode_type.xml 2013-05-24 09:03:33 +0000
@@ -0,0 +1,47 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4
5 <!-- Add the payment mode type to the payment mode views -->
6 <record id="view_payment_mode_form_inherit" model="ir.ui.view">
7 <field name="name">payment.mode.form.inherit</field>
8 <field name="model">payment.mode</field>
9 <field name="inherit_id" ref="account_payment.view_payment_mode_form"/>
10 <field name="type">form</field>
11 <field name="arch" type="xml">
12 <field name="company_id" position="after">
13 <field name="type"/>
14 </field>
15 </field>
16 </record>
17
18 <record id="view_payment_mode_tree_inherit" model="ir.ui.view">
19 <field name="name">payment.mode.tree.inherit</field>
20 <field name="model">payment.mode</field>
21 <field name="inherit_id" ref="account_payment.view_payment_mode_tree"/>
22 <field name="type">tree</field>
23 <field name="arch" type="xml">
24 <field name="company_id" position="after">
25 <field name="type"/>
26 </field>
27 </field>
28 </record>
29
30 <!-- basic view for payment mode type -->
31 <record model="ir.ui.view" id="view_payment_mode_type_form">
32 <field name="name">view.payment.mode.type.form</field>
33 <field name="model">payment.mode.type</field>
34 <field name="type">form</field>
35 <field name="arch" type="xml">
36 <form>
37 <field name="name" />
38 <field name="code" />
39 <field name="suitable_bank_types"/>
40 <field name="payment_order_type"/>
41 <field name="ir_model_id"/>
42 </form>
43 </field>
44 </record>
45
46 </data>
47</openerp>
048
=== added directory 'account_banking_payment/workflow'
=== renamed file 'account_banking/account_banking_workflow.xml' => 'account_banking_payment/workflow/account_payment.xml'
--- account_banking/account_banking_workflow.xml 2011-12-12 15:00:03 +0000
+++ account_banking_payment/workflow/account_payment.xml 2013-05-24 09:03:33 +0000
@@ -1,20 +1,15 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<!--
3 Copyright (C) EduSense BV <http://www.edusense.nl>
4 All rights reserved.
5 The licence is in the file __terp__.py
6-->
7<openerp>2<openerp>
8 <data>3 <data>
9 <!-- New activity for workflow payment order: sent -->4 <!-- New activity for workflow payment order: sent -->
10 <record id="act_sent" model="workflow.activity">5 <record id="account_banking.act_sent" model="workflow.activity">
11 <field name="name">sent</field>6 <field name="name">sent</field>
12 <field name="wkf_id" ref="account_payment.wkf_payment_order"/>7 <field name="wkf_id" ref="account_payment.wkf_payment_order"/>
13 <field name="action">action_sent()</field>8 <field name="action">action_sent()</field>
14 <field name="kind">function</field>9 <field name="kind">function</field>
15 </record>10 </record>
16 <!-- New activity for workflow payment order: rejected -->11 <!-- New activity for workflow payment order: rejected -->
17 <record id="act_rejected" model="workflow.activity">12 <record id="account_banking.act_rejected" model="workflow.activity">
18 <field name="name">rejected</field>13 <field name="name">rejected</field>
19 <field name="wkf_id" ref="account_payment.wkf_payment_order"/>14 <field name="wkf_id" ref="account_payment.wkf_payment_order"/>
20 <field name="action">action_rejected()15 <field name="action">action_rejected()
@@ -22,21 +17,21 @@
22 <field name="kind">function</field>17 <field name="kind">function</field>
23 </record>18 </record>
24 <!-- Add new transition sent -> done -->19 <!-- Add new transition sent -> done -->
25 <record id="trans_sent_done" model="workflow.transition">20 <record id="account_banking.trans_sent_done" model="workflow.transition">
26 <field name="act_from" ref="act_sent"/>21 <field name="act_from" ref="account_banking.act_sent"/>
27 <field name="act_to" ref="account_payment.act_done"/>22 <field name="act_to" ref="account_payment.act_done"/>
28 <field name="signal">done</field>23 <field name="signal">done</field>
29 </record>24 </record>
30 <!-- Add new transition sent -> rejected -->25 <!-- Add new transition sent -> rejected -->
31 <record id="trans_sent_rejected" model="workflow.transition">26 <record id="account_banking.trans_sent_rejected" model="workflow.transition">
32 <field name="act_from" ref="act_sent"/>27 <field name="act_from" ref="account_banking.act_sent"/>
33 <field name="act_to" ref="act_rejected"/>28 <field name="act_to" ref="account_banking.act_rejected"/>
34 <field name="signal">rejected</field>29 <field name="signal">rejected</field>
35 </record>30 </record>
36 <!-- Rewrite existing open -> done transition to include 'sent' -->31 <!-- Rewrite existing open -> done transition to include 'sent' -->
37 <record id="account_payment.trans_open_done" model="workflow.transition">32 <record id="account_payment.trans_open_done" model="workflow.transition">
38 <field name="act_from" ref="account_payment.act_open"/>33 <field name="act_from" ref="account_payment.act_open"/>
39 <field name="act_to" ref="act_sent"/>34 <field name="act_to" ref="account_banking.act_sent"/>
40 <field name="signal">sent</field>35 <field name="signal">sent</field>
41 </record>36 </record>
42 </data>37 </data>

Subscribers

People subscribed via source and target branches

to status/vote changes: