(51) magento集成增加到款通知

这篇主要讲述如何二开增加自己的功能,我没有继承方式二开,习惯是不好的,直接改了原来的模块。

clip_image002

clip_image004

达到效果就这样,当在网站支付成功,会同步到ERP系统中。下面来讲述实现过程

建立文件 payment_notice.py

clip_image006

# -*- coding: utf-8 -*-


import
logging
import
xmlrpclib
from datetime import
datetime, timedelta
import openerp.addons.decimal_precision as
dp
from openerp import
models, fields, api, _
from openerp.addons.connector.connector import
ConnectorUnit
from openerp.addons.connector.exception import
(NothingToDoJob,
                                                FailedJobError,
                                                IDMissingInBackend)
from openerp.addons.connector.queue.job import
job

from openerp.addons.connector.unit.mapper import
(mapping,
                                                  ImportMapper
                                                  )

from .unit.backend_adapter import
(GenericAdapter,
                                   MAGENTO_DATETIME_FORMAT,
                                   )
from .unit.import_synchronizer import
(DelayedBatchImporter,
                                       MagentoImporter,
                                       )
from .unit.mapper import
normalize_datetime
from .backend import
magento
from .connector import
get_environment
from openerp.tools.float_utils import
float_round

_logger = logging.getLogger(__name__)



class
MagentoPaymentNotice(models.Model):
    _name =
'magento.payment.notice'
   
_inherit =
'magento.binding'
   
_description =
'Magento Payment Notice'
   
_inherits = {'payment.notice': 'openerp_id'
}

    openerp_id = fields.Many2one(
comodel_name='payment.notice'
,
                                
string='Payment Notice'
,
                                
required=True
,
                                
ondelete='cascade'
)
    total_amount = fields.Float(
       
string='Total amount'
,
       
digits_compute=dp.get_precision('Account'
)
    )
    total_amount_tax = fields.Float(
       
string='Total amount w. tax'
,
       
digits_compute=dp.get_precision('Account'
)
    )
    magento_order_id = fields.Integer(
string='Magento Order ID'
,
                                     
help="'order_id' field in Magento"
)
   
# when a sale order is modified, Magento creates a new one, cancels
    # the parent order and link the new one to the canceled parent
   
magento_parent_id = fields.Many2one(comodel_name='magento.sale.order'
,
                                       
string='Parent Magento Order'
)
    storeview_id = fields.Many2one(
comodel_name='magento.storeview'
,
                                  
string='Magento Storeview'
)
    store_id = fields.Many2one(
related='storeview_id.store_id'
,
                              
string='Storeview'
,
                              
readonly=True
)


class
PaymentNotice(models.Model):
    _inherit =
'payment.notice'

   
magento_bind_ids = fields.One2many(
       
comodel_name='magento.payment.notice'
,
       
inverse_name='openerp_id'
,
       
string="Magento Bindings"
,
    )


@
magento
class
PaymentNoticeAdapter(GenericAdapter):
    _model_name =
'magento.payment.notice'
   
_magento_model =
'sales_order'
   
_admin_path =
'{model}/view/order_id/{id}'

   
def _call(self
, method, arguments):
       
try
:
           
return super(PaymentNoticeAdapter, self
)._call(method, arguments)
       
except xmlrpclib.Fault as
err:
           
# this is the error in the Magento API
            # when the sales order does not exist
           
if err.faultCode == 100
:
               
raise
IDMissingInBackend
           
else
:
               
raise

    def
search(self, filters=None, from_date=None, to_date=None
,
               magento_storeview_ids=
None
):
       
""" Search records according to some criteria
        and returns a list of ids

       
:rtype
: list
        """
       
if filters is None
:
            filters = {}
        dt_fmt = MAGENTO_DATETIME_FORMAT
       
if from_date is not None
:
            filters.setdefault(
'created_at'
, {})
            filters[
'created_at']['from'
] = from_date.strftime(dt_fmt)
       
if to_date is not None
:
            filters.setdefault(
'created_at'
, {})
            filters[
'created_at']['to'
] = to_date.strftime(dt_fmt)
       
if magento_storeview_ids is not None
:
            filters[
'store_id'] = {'in'
: magento_storeview_ids}

        arguments = {
'imported': False
,
                    
# 'limit': 200,
                    
'filters'
: filters,
                     }
       
return super(PaymentNoticeAdapter, self
).search(arguments)

   
def read(self, id, attributes=None
):
       
""" Returns the information of a record

       
:rtype
: dict
        """
       
record = self._call('%s.info' % self
._magento_model,
                            [id, attributes])
       
return
record



@
magento
class
PaymentNoticeBatchImport(DelayedBatchImporter):
    _model_name = [
'magento.payment.notice'
]

   
def _import_record(self, record_id, description=None
,**kwargs):
       
""" Import the record directly """
       
return super(PaymentNoticeBatchImport, self
)._import_record(
            record_id,
description=description, max_retries=0, priority=5
)

   
def run(self, filters=None
):
       
""" Run the synchronization """
       
if filters is None
:
            filters = {}
        filters[
'status'] = {'in': ['complete', 'processing', 'challenged'
]}
        from_date = filters.pop(
'from_date', None
)
        to_date = filters.pop(
'to_date', None
)
        magento_storeview_ids = [filters.pop(
'magento_storeview_id'
)]
        record_ids =
self
.backend_adapter.search(
            filters,
           
from_date
=from_date,
           
to_date
=to_date,
           
magento_storeview_ids
=magento_storeview_ids)
        _logger.info(
'search for magento saleorders %s returned %s'
,
                     filters, record_ids)
       
for record_id in
record_ids:
           
self
._import_record(
                                record_id,
                               
description='Import payment notice, Order# of website: %s' % self.backend_adapter.read(record_id).get('increment_id'
)
                                )


@
magento
class
PaymentNoticeImportRule(ConnectorUnit):
    _model_name = [
'magento.payment.notice'
]

   
def check(self
, record):
       
""" Check whether the current sale order should be imported
        or not. It will actually use the payment method configuration
        and see if the choosed rule is fullfilled.

       
:returns
: True if the sale order should be imported
       
:rtype
: boolean
        """
       
payment_method = record['payment']['method'
]
        method =
self.env['payment.method'
].search(
            [(
'magento_payment_code', '='
, payment_method)],
           
limit=1
,
        )
       
if not
method:
           
raise
FailedJobError(
               
"The configuration is missing for the Payment Method '%s'.\n\n
"
                "Resolution:
\n
"
                "- Go to "
                "'Sales > Configuration > Sales > Customer Payment Method
\n
"
                "- Create a new Payment Method with name '%s'
\n
"
                "-Eventually  link the Payment Method to an existing Workflow "
                "Process or create a new one."
% (payment_method,
                                                  payment_method))



@
magento
class
PaymentNoticeImportMapper(ImportMapper):
    _model_name =
'magento.payment.notice'

   
direct = [('increment_id', 'magento_id'
),
              (
'order_id', 'magento_order_id'
),
              (
'grand_total', 'total_amount'
),
              (
'tax_amount', 'total_amount_tax'
),
              (
'store_id', 'storeview_id'
),
              ]

    @
mapping
   
def sale_order_site(self
, record):
        sale_order_site = record[
'increment_id'
]
       
return {'sale_order_site'
: sale_order_site}

    @
mapping
   
def amount(self
, record):
        amount = record[
'grand_total'
]
       
return {'amount'
: amount}

    @
mapping
   
def currency(self
, record):
        record_currency = record[
'order_currency_code'
]
        currency =
self.env['res.currency'
].search(
            [[
'name', '='
, record_currency]],
           
limit=1
,
        )
       
assert currency, (
"currency %s should exist because the import fails "
                        "in PaymentNoticeImporter._before_import when it is "
                        " missing"
% record['order_currency_code'
])
       
return {'currency_id'
: currency.id}


    @
mapping
   
def payment(self
, record):
        record_method = record[
'payment']['method'
]
        method =
self.env['payment.method'
].search(
            [[
'magento_payment_code', '='
, record_method]],
           
limit=1
,
        )

       
assert method, (
"method %s should exist because the import fails "
                        "in PaymentNoticeImporter._before_import when it is "
                        " missing"
% record['payment']['method'
])
       
return {'payment_method_id'
: method.id}

    @
mapping
   
def description(self
, record):
        order_date = normalize_datetime(
'created_at')(self, record, ''
)
        dd=datetime.strptime(order_date,
'%Y-%m-%d %H:%M:%S'
)
        order_date_f=dd.strftime(
'%m/%d/%Y'
)
        record_currency = record[
'order_currency_code'
]
        billing_address = record[
'billing_address'
]
        billing_name = billing_address[
'firstname']+' ' + billing_address['lastname'
]
        paypal_id = record[
'payment']['last_trans_id'] and record['payment']['last_trans_id'] or
''
       
prec = self.env['decimal.precision'].precision_get('Account'
)
        amount =
str(float_round(float(record['grand_total'
]), prec))
        payment_method = record[
'payment']['method'
]
       
if payment_method == 'paypal_standard' or payment_method =='paypal_express'
:
            description = order_date_f+
' '+billing_name +' '+ record_currency+' '+amount+ ' ID: '
+ paypal_id
       
else
:
            description = order_date_f +
' ' + billing_name + ' ' + record_currency + ' '
+ amount
       
return {'description'
: description}


    @
mapping
   
def backend_id(self, record
):
       
return {'backend_id': self
.backend_record.id}


@
magento
class
PaymentNoticeImporter(MagentoImporter):
    _model_name = [
'magento.payment.notice'
]

    _base_mapper = PaymentNoticeImportMapper

   
def _must_skip(self
):
       
if self.binder.to_openerp(self
.magento_id):
           
return _('Already imported'
)

   
def _before_import(self
):
        rules =
self
.unit_for(PaymentNoticeImportRule)
        rules.check(
self
.magento_record)


   
def _get_storeview(self
, record):
       
""" Return the tax inclusion setting for the appropriate storeview """
       
storeview_binder = self.binder_for('magento.storeview'
)
       
# we find storeview_id in store_id!
        # (http://www.magentocommerce.com/bug-tracking/issue?issue=15886)
       
return storeview_binder.to_openerp(record['store_id'], browse=True
)

   
def _get_magento_data(self
):
       
""" Return the raw Magento data for ``self.magento_id`` """
       
record = super(PaymentNoticeImporter, self
)._get_magento_data()
       
# sometimes we don't have website_id...
        # we fix the record!
       
if not record.get('website_id'
):
            storeview =
self
._get_storeview(record)
           
# deduce it from the storeview
           
record['website_id'
] = storeview.store_id.website_id.magento_id
       
return
record


   
def _create_data(self
, map_record, **kwargs):
        storeview =
self
._get_storeview(map_record.source)
       
return super(PaymentNoticeImporter, self
)._create_data(
            map_record,
           
storeview
=storeview,
            **kwargs)

   
def _update_data(self
, map_record, **kwargs):
        storeview =
self
._get_storeview(map_record.source)
       
return super(PaymentNoticeImporter, self
)._update_data(
            map_record,
           
storeview
=storeview,
            **kwargs)


PaymentNoticeImporter = PaymentNoticeImporter 
# deprecated

@job(default_channel='root.magento'
)
def payment_notice_import_batch(session, model_name, backend_id, filters=None
):
   
""" Prepare a batch import of sale order(payment notice) from Magento """
   
if filters is None
:
        filters = {}
   
assert 'magento_storeview_id' in filters, (
'Missing information about '
                                               'Magento Storeview'
)
    env = get_environment(session, model_name, backend_id)
    importer = env.get_connector_unit(PaymentNoticeBatchImport)
    importer.run(filters)




__init__.py

clip_image008

unit/binder 下加入

clip_image010

magento_model.py 加入

_name = 'magento.storeview' 类中

 

@api.multi
def import_payment_notices(self
):
    session = ConnectorSession(
self.env.cr, self
.env.uid,
                              
context=self
.env.context)
    import_start_time = datetime.now()
   
for storeview in self
:
       
if
storeview.no_payment_notice_sync:
            _logger.debug(
"The storeview '%s' is active in Magento "
                          "but is configured not to import the "
                          "payment notices"
, storeview.name)
           
continue
       
backend_id = storeview.backend_id.id
       
if
storeview.import_payment_notices_from_date:
            from_string = fields.Datetime.from_string
            from_date = from_string(storeview.import_payment_notices_from_date)
       
else
:
            from_date =
None
       
payment_notice_import_batch.delay(
            session,
           
'magento.payment.notice'
,
            backend_id,
            {
'magento_storeview_id'
: storeview.magento_id,
            
'from_date'
: from_date,
            
'to_date'
: import_start_time},
           
priority=1
,
        ) 
# executed as soon as possible

   
next_time = import_start_time - timedelta(seconds
=IMPORT_DELTA_BUFFER)
    next_time = fields.Datetime.to_string(next_time)
   
self.write({'import_payment_notices_from_date'
: next_time})
   
return
True

 

 _name = 'magento.backend'

import_payment_notices_from_date = fields.Datetime(
   
string='Import payment notices from date'
,
   
help=
'do not consider non-imported payment notice before this date. '
         'Leave empty to import all payment notice of sale orders'
,
)

 

@api.multi
def import_payment_notices(self
):
   
""" Import sale orders from all store views """
   
storeview_obj = self.env['magento.storeview'
]
    storeviews = storeview_obj.search([(
'backend_id', 'in', self
.ids)])
    storeviews.import_payment_notices()
   
return
True

 

@api.model
def _scheduler_import_payment_notices(self, domain=None
):
   
self._magento_backend('import_payment_notices', domain
=domain)
 
magentoerpconnect_data.xml 中加入
<record forcecreate="True" id="ir_cron_import_payment_notices" model="ir.cron">
    <
field name="name">Magento - Import Payment Notices</field>
    <
field eval="False" name="active"/>
    <
field name="user_id" ref="base.user_root"/>
    <
field name="interval_number">1</field>
    <
field name="interval_type">days</field>
    <
field name="numbercall">-1</field>
    <
field eval="False" name="doall"/>
    <
field eval="'magento.backend'" name="model"/>
    <
field eval="'_scheduler_import_payment_notices'" name="function"/>
    <
field eval="'()'" name="args"/>
</
record>
 

 

剩下来,就是界面的设定

clip_image012

clip_image014

这样就完成了。

posted @ 2017-02-13 19:09  toby2chen  阅读(403)  评论(0编辑  收藏  举报