如何用Drupal Commerce实现定金功能

需求

客户需求是这样的:
网站的订单支付不要求全额支付(因为是B2B的业务),只需要支付一个定金就可以。
根据不同的user类型(A,B)以及他们是否在试用期,来要求支付不同的比例。如果A,定金为订单总额的50%。如果B,并且在试用期,30%。B不在试用期,则免定金,即跳过支付这个环节。

现状

Drupal Commerce并没有原生的定金功能。展开地毯式搜索,得到几个相关模块如下,但没有一个是成熟模块。

  • commerce_deposit 业务逻辑和我的需求有些差异,放弃。但有兴趣的朋友可以看一下代码,还是比较简单的。
  • Commerce Partial Payment  这个思路不错,也是最后我采用的办法。

与几位熟悉Drupal Commerce的朋友交流,现有的思路一般是通过添加price component或者custom line item来实现。我也尝试了第二种方法,具体的代码可以参考Commerce discount的模块。问题不大,如果作为折扣,这个line item作为负值没有什么问题,但作为定金,一个负值就看起来比较奇怪。容易让用户很困惑,并且这个方法最后改变了订单的总额。而从需求出发,订单总额是不应该改变的。所以这种方式最后也放弃了。

解决方案

参考Commerce Partial Payment ,基本实现了我需要的功能。我假设新建一个模块叫my_deposit。

定金计算

基本思路是这样的,首先写一个函数判断该用户是否需要定金,代码如下:

另外再写一个函数用来计算该用户该订单的定金数额,代码如下:

修改checkout页面

然后在checkout的付款页面,我们用 hook_form_BASE_FORM_ID_alter() 来修改commerce_checkout_form。基本思路如下:

首先调用上面的函数,看该用户是否需要付定金,如果不需要,则把payment methods 都删掉,这样就直接可以跳过payment步骤了。同时,在checkout form里加一个message给用户,说明定金数量或者你不需要支付定金。具体细节可看代码注释。

修改payment method表单的submit callback

下面是我们自己的callback,大部分是从commerce payment模块里的commerce_payment_pane_checkout_form_submit()里copy来的,47-56行是我们自己的修改。因为没有hook,所以目前只能这么改了。

其实很简单,就是把提交给payment method的金额修改为我们自己的定金金额。

这样就算基本完工了,测试一下你可以看到信用卡付款的金额已经变成了定金金额。订单完成后,查看order,可以看到付款记录,order balance是扣除定金余下的部分。

我们的需求并不涉及余款的支付,客户将会通过其它方式支付余款。所以这里就不讨论了。

注意事项

Paypal等offsite payment method的问题

以上方法在paypal上不起作用,我没有太深究原因,基本上的原因就是Paypal没有上面的callback提交,所以我们的蓝色代码不会被运行。暂时的解决办法就是直接用强大的hook_form_alter。直接修改commerce_paypal_wps_redirect_form。

这样就搞定啦。

Paypal的Sandbox测试,IPN在localhost会有问题:

because in the paypal sandbox(for example) you must specify an IPN handler URL. Paypal is using this URL to call the php file on your website that handles the IPN call. So you cannot pass into that url localhost/yourwebsite/ipn_handler.php. You will need something like your_computer_public_ip/yourwebsite/ipn_handler.php

一些相关的有用的参考资料

 

How to add class on views table row (Drupal 7)

For a views using table, if you want to add a custom class on <tr>, you can go to this view’s setting page, find the ‘Foramt’ section, click the ‘table’s ‘setting’.

Screen Shot 2015-04-24 at 12.09.35 pm

 

Then find ‘Row class’ field. Just add your class here. But if you want a dynamic class, you can use field tokens. Screen Shot 2015-04-24 at 12.08.51 pm

You don’t know what is the field token. But don’t worry, you can find the field tokens in here, click the field in the ‘Fields’ section.

Screen Shot 2015-04-24 at 12.12.28 pm

But if the field is not there, you can add the filed and tick “exclude from display”. Ignore the error message please 😀

Screen Shot 2015-04-24 at 5.02.51 pm

Then find the ‘Rewrite results’:

Screen Shot 2015-04-24 at 12.22.23 pm

Save and done.

 

 

 

How to add block in module (Drupal 7)

Using hook_block_info(), here is example: https://api.drupal.org/api/examples/block_example!block_example.module/7

A simple code example here(copied from here):

But all above is missing a lot details, like module configuration. Here is the details of hook_block_info block array, copied from Durpal docs:


 

An associative array whose keys define the delta for each block and whose values contain the block descriptions. Each block description is itself an associative array, with the following key-value pairs:

  • info: (required) The human-readable administrative name of the block. This is used to identify the block on administration screens, and is not displayed to non-administrative users.
  • cache: (optional) A bitmask describing what kind of caching is appropriate for the block. Drupal provides the following bitmask constants for defining cache granularity:
  • properties: (optional) Array of additional metadata to add to the block. Common properties include:
    • administrative: Boolean that categorizes this block as usable in an administrative context. This might include blocks that help an administrator approve/deny comments, or view recently created user accounts.
  • weight: (optional) Initial value for the ordering weight of this block. Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen.
  • status: (optional) Initial value for block enabled status. (1 = enabled, 0 = disabled). Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen.
  • region: (optional) Initial value for theme region within which this block is set. Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen. Note: If you set a region that isn’t available in the currently enabled theme, the block will be disabled.
  • visibility: (optional) Initial value for the visibility flag, which tells how to interpret the ‘pages’ value. Possible values are:
    • BLOCK_VISIBILITY_NOTLISTED: Show on all pages except listed pages. ‘pages’ lists the paths where the block should not be shown.
    • BLOCK_VISIBILITY_LISTED: Show only on listed pages. ‘pages’ lists the paths where the block should be shown.
    • BLOCK_VISIBILITY_PHP: Use custom PHP code to determine visibility. ‘pages’ gives the PHP code to use.

    Most modules do not provide an initial value for ‘visibility’ or ‘pages’, and any value provided can be modified by a user on the block configuration screen.

  • pages: (optional) See ‘visibility’ above. A string that contains one or more page paths separated by “\n”, “\r”, or “\r\n” when ‘visibility’ is set to BLOCK_VISIBILITY_NOTLISTED or BLOCK_VISIBILITY_LISTED (example: “<front>\nnode/1”), or custom PHP code when ‘visibility’ is set to BLOCK_VISIBILITY_PHP. Paths may use ‘*’ as a wildcard (matching any number of characters); ‘<front>’ designates the site’s front page. For BLOCK_VISIBILITY_PHP, the PHP code’s return value should be TRUE if the block is to be made visible or FALSE if the block should not be visible.

 

How to find my apache user

go through config file httpd.conf and find out user and group name:

In linux, with following command:

Then you will get the result as below:

 

Drush notes

Update Drupal core

How to update Drupal core with Drush

(Drush is a command line tool for Drupal).

1. Backup everything (all files, databases, etc)

2. Put your site in maintenance mode

Either from Drupal interface or with drush:
(commands for Drupal 7)
drush vset --always-set maintenance_mode 0
drush cache-clear all

3. Save your .htaccess-file, robots.txt and favicon.ico somewhere

…If you have modified them

4. Update Drupal with drush

drush up drupal

5. Check that everything works

Go around your site and test everyhting!

6. Put your site online again

Take your site away from maintenance mode either from Drupal interface or with drush (command for Drupal 7)
drush vset --always-set maintenance_mode 0
drush cache-clear all

 

 

Below copied from http://orga.cat/posts/most-useful-drush-commands


 

Here I will try to maintain a drush cheat sheet with the list of drush commands I use most often. Full and short version of commands are used interchangeably.

See main information and status of the site

Clear the cache

Clear the cache, even if Drupal is broken

sql-query executes sql queries in the database where Drupal is installed.

Download the last recommended release of 2 modules

Download a -dev version of a module

Seems that adding --package-handler=git_drupalorg is not needed anymore.

Download the git HEAD version of a module

Short answer: drush does not do that.
Long answer: See http://drupal.stackexchange.com/q/62934/10086

Enable a module

-y skips the confirmation question. Some drush commands may miss the -y part, a workaround for this that always works is putting it before:

If the module is missing and its name matches a project name, drush will automatically download the module from drupal.org.

Disable a module

Disable a module, even if Drupal is broken

Source: https://drupal.org/node/157632

Uninstall a module

See if a module is available

See if a module is enabled

See all contrib and custom modules that are enabled

Update a module

Update Drupal

Update all contrib modules and Drupal

Run update.php

Send an e-mail

Delete a field

Delete an instance of a field

Manually delete a field and all its data (not recommended)

Set a password for a user

Block a user

Log all users out

Log out a specific user

Get a one-time login link for the Administrator user

Run cron

Run Ultimate Cron

Set a variable

Get the value of a variable

See last logged events (watchdog)

See logged events in real time

Run a php script with Drupal bootstrapped

Use --uri to specify the host name. Use --root to specify the site directory (in cron, for example):

Run custom code

Repopulate database tables used by menu functions

See https://api.drupal.org/api/drupal/includes!menu.inc/function/menu_rebuild/7

Rescan all code in modules or includes directories, storing the location of each interface or class in the database

Useful when moving installed modules. See http://drupal.stackexchange.com/q/17657/10086
If does not work because Drupal cannot bootstrap, do it that way:

Update a Feature with database changes

Revert a Feature, update the database to match the code

Revert all features

Useful in deployment scripts.

Change error level

Show only errors and warnings

Show all

Hide everything

Enable maintenance mode

Open a MySQL console logged in

Import a backup of the database

Export a backup of the database

Remove all database tables (empty the database)

Useful before importing a database backup.

See all drush aliases

Use an alias

Flush image styles

Install Drupal

Delete all content of specific content types

Note that you need Devel and Devel Generate modules. Alternatives are drush migrate-wipe andDelete all module.

Delete content type

Generate random content

Create a boilerplate for a new module

See Module Builder.

More…

A more general and exhaustive list can be found here: https://groups.drupal.org/node/28088
Full documentation – Contrib modules not included – is available at http://drush.ws
And check www.drushcommands.com, is awesome!

 

 

Is there any CRM for small business?

One of my friend asked me if I can build a website to manage his clients. I recommend he have a look CRM apps. So I did some search on google and tested some of them. Here is one I found very good.

https://www.zoho.com/crm/

And ZOHO has other products:  https://www.zoho.com

Which provided a free version for 10 users. with 1G space. Compare to others like insightly, this one looks cheaper and better.

英文Email语句收集

好消息

That’s great news.  We have finally resolved this issue.

请求

Please see design and theme web costs.

Can you please advise so that I can then {do something}?

Can you take a look at the request from Albi below.

请给我

Otherwise please send through thoughts on time/costs and any foreseeable issues.

测试

I have tested the site by placing an order and it is all okay

I would like to let the sync run overnight before we can safely say that all is okay.

Has this been tested from your end?

Please verify that everything on your end is working.

进度更新,提醒

A reminder that the work to fix the server will be implemented tomorrow morning at 8am.  Please ensure that all required personnel are available at this time.

To update you on work completed today: …

I will update you again tomorrow.

I was wondering how you were going with these – I was hoping it could all be completed before the weekend?

Just a reminder that

提到

You have mentioned that …

完成

We have also completed the XXXX change, which wraps up all outstanding issues.

确认

Please confirm that …

This is confirmed.

I can confirm that …

客套话

Let me know if you encounter any issues.

Let me know if you have any questions or if testing on your end reveals any issues.

Let me know if you need more information.

日期

Please leave the snapshot until Tuesday next week and I will let you know.

Jack is available on Thursday morning this week at 8am to undertake the work mentioned below.

Useful Linux shell command

Remove all files & folders

Above will pop prompt to ask for confirm on each file. So ignore that by use following:

 

 

Move all files/folders including hidden files to another folder

You could turn on dotglob:

In order to turn off dotglob, you’d need to say:

 Copy all the files and directories including hidden files and directories

 Set up umask

What is Umask and How To Setup Default umask Under Linux?

Restart bashrc

 

Command short cut

  • ctrl+u Delete all line
  • Ctrl+w delete word by word
  • ctrl a/e go to start/end of line

MySQL Error 1153 – Got a packet bigger than ‘max_allowed_packet’ bytes

This one can be fixed by add some line in my.cnf.

Usually MySQL config file is located in etc/my.cnf.

Open it and add two line like this:

It gives 100M.

Check here for more: http://stackoverflow.com/questions/93128/mysql-error-1153-got-a-packet-bigger-than-max-allowed-packet-bytes