├── mail
├── src
│ ├── README
│ ├── new-invoice-admin-text.php
│ ├── cancel-invoice-text.php
│ ├── new-invoice-user-text.php
│ ├── new-invoice-admin-html.php
│ ├── cancel-invoice-html.php
│ ├── new-invoice-user-html.php
│ └── css
│ │ └── mailgun.css
├── new-invoice-admin-text.php
├── cancel-invoice-text.php
├── new-invoice-user-text.php
├── new-invoice-admin-html.php
├── cancel-invoice-html.php
└── new-invoice-user-html.php
├── views
├── address
│ ├── manage.css
│ ├── manage.scss
│ ├── manage.css.map
│ ├── create.php
│ ├── update.php
│ ├── _grid.php
│ ├── _form.php
│ ├── manage.php
│ ├── _search.php
│ ├── view.php
│ └── index.php
├── bitcoin
│ ├── _scan.php
│ ├── _copy.php
│ ├── payment.min.js
│ ├── view.php
│ ├── payment.js
│ ├── index.php
│ └── payment.php
├── bank
│ ├── create.php
│ ├── update.php
│ ├── _search.php
│ ├── _form.php
│ ├── view.php
│ └── index.php
├── coupon
│ ├── create.php
│ ├── update.php
│ ├── _search.php
│ ├── view.php
│ ├── _form.php
│ └── index.php
├── info
│ ├── manage.php
│ ├── update.php
│ ├── create.php
│ ├── _search.php
│ ├── _form.php
│ ├── view.php
│ └── index.php
├── invoice
│ ├── update.php
│ ├── _shipping_address.php
│ ├── _billing_address.php
│ ├── _form.php
│ ├── index.php
│ └── manage.php
├── setting
│ └── index.php
└── paypal
│ └── return.php
├── console
└── README
├── urlManager.php
├── modules
└── api
│ ├── v1
│ ├── Module.php
│ └── controllers
│ │ ├── DefaultController.php
│ │ └── InvoiceController.php
│ ├── controllers
│ └── DefaultController.php
│ └── Module.php
├── memberArea.php
├── README.md
├── composer.json
├── components
├── Tax.php
└── CurrencyLayer.php
├── widgets
├── AddAddress.php
└── views
│ └── add-address.php
├── memberMenu.php
├── migrations
└── m170907_104245_init.php
├── cronjobs
├── TaskCancelInvoice.php
├── TaskReleaseBTCAddr.php
├── TaskCheckBTCTransaction.php
└── TaskCheckBTCPayment.php
├── adminMenu.php
├── Module.php
├── models
├── BankSearch.php
├── BitcoinAddressSearch.php
├── BillingInfoSearch.php
├── Setting.php
├── CouponForm.php
├── InvoiceSearch.php
├── CouponSearch.php
├── Item.php
├── AddressSearch.php
├── Bank.php
├── Address.php
└── Coupon.php
├── settings.php
└── controllers
└── SettingController.php
/mail/src/README:
--------------------------------------------------------------------------------
1 | grunt --dist=../vendor/powerkernel/yii2-billing/mail
--------------------------------------------------------------------------------
/views/address/manage.css:
--------------------------------------------------------------------------------
1 | .billing-address-manage .box-address .box-body{height:160px}
2 | /*# sourceMappingURL=manage.css.map */
3 |
--------------------------------------------------------------------------------
/views/address/manage.scss:
--------------------------------------------------------------------------------
1 | .billing-address-manage {
2 | .box-address {
3 | .box-body {
4 | height: 160px;
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/views/address/manage.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": "AAEI,8CAAU,CACR,MAAM,CAAE,KAAK",
4 | "sources": ["manage.scss"],
5 | "names": [],
6 | "file": "manage.css"
7 | }
--------------------------------------------------------------------------------
/console/README:
--------------------------------------------------------------------------------
1 |
2 | if(class_exists('yii\mongodb\console\controllers\MigrateController')){
3 | $map=[
4 | 'controllerMap' => [
5 | 'mongodb-migrate' => 'yii\mongodb\console\controllers\MigrateController'
6 | ],
7 | ];
8 | }
--------------------------------------------------------------------------------
/urlManager.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | return [
9 | 'ignoreLanguageUrlPatterns' => [
10 | '#^billing/api#' => '#^billing/api#',
11 | ],
12 | ];
13 |
--------------------------------------------------------------------------------
/modules/api/v1/Module.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\modules\api\controllers;
9 |
10 | /**
11 | * Class DefaultController
12 | */
13 | class DefaultController extends \yii\rest\Controller
14 | {
15 | /**
16 | * @return array
17 | */
18 | public function actionIndex(){
19 | return [
20 | 'status'=>'ok'
21 | ];
22 | }
23 | }
--------------------------------------------------------------------------------
/mail/new-invoice-admin-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Greetings from {APP},', ['APP' => Yii::$app->name]) ?>
9 |
10 |
11 | = Yii::$app->getModule('billing')->t('A new order has just been placed') ?>
12 |
13 |
14 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
15 |
16 |
17 | = Yii::$app->getModule('billing')->t('View Invoice: {URL}', ['URL'=>$model->getAdminInvoiceUrl(true)]) ?>
18 |
--------------------------------------------------------------------------------
/mail/src/new-invoice-admin-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Greetings from {APP},', ['APP' => Yii::$app->name]) ?>
9 |
10 |
11 | = Yii::$app->getModule('billing')->t('A new order has just been placed') ?>
12 |
13 |
14 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
15 |
16 |
17 | = Yii::$app->getModule('billing')->t('View Invoice: {URL}', ['URL'=>$model->getAdminInvoiceUrl(true)]) ?>
18 |
--------------------------------------------------------------------------------
/views/bitcoin/_scan.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $bitcoin [] */
9 |
10 | use yii\helpers\Html;
11 |
12 | ?>
13 |
14 |
15 | = Html::img('data:image/png;base64,' . $bitcoin['base64QR'], ['class' => 'img img-responsive img-thumbnail']) ?>
16 |
17 |
18 |
--------------------------------------------------------------------------------
/modules/api/v1/controllers/DefaultController.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\modules\api\v1\controllers;
9 |
10 | /**
11 | * Class DefaultController
12 | */
13 | class DefaultController extends \yii\rest\Controller
14 | {
15 | /**
16 | * @return array
17 | */
18 | public function actionIndex(){
19 | return [
20 | 'status'=>'ok',
21 | 'version'=>'1.0'
22 | ];
23 | }
24 | }
--------------------------------------------------------------------------------
/mail/cancel-invoice-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Hi {USER},', ['USER' => $model->account->fullname]) ?>
9 |
10 | = Yii::$app->getModule('billing')->t('We\'re sorry to let you know that your invoice has been canceled. You don\'t need to do anything else.') ?>
11 |
12 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
13 |
14 | = Yii::$app->getModule('billing')->t('View Invoice: {URL}', ['URL'=>$model->getInvoiceUrl(true)]) ?>
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yii2 Billing
2 | ============
3 | Yii2 Billing
4 |
5 | Installation
6 | ------------
7 |
8 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
9 |
10 | Either run
11 |
12 | ```
13 | php composer.phar require --prefer-dist powerkernel/yii2-billing "*"
14 | ```
15 |
16 | or add
17 |
18 | ```
19 | "powerkernel/yii2-billing": "*"
20 | ```
21 |
22 | to the require section of your `composer.json` file, then run
23 |
24 | ```
25 | php yii mongodb-migrate --migrationPath=@vendor/powerkernel/yii2-billing/migrations/ --migrationCollection=billing_migration
26 | ```
--------------------------------------------------------------------------------
/mail/src/cancel-invoice-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Hi {USER},', ['USER' => $model->account->fullname]) ?>
9 |
10 | = Yii::$app->getModule('billing')->t('We\'re sorry to let you know that your invoice has been canceled. You don\'t need to do anything else.') ?>
11 |
12 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
13 |
14 | = Yii::$app->getModule('billing')->t('View Invoice: {URL}', ['URL'=>$model->getInvoiceUrl(true)]) ?>
15 |
--------------------------------------------------------------------------------
/modules/api/Module.php:
--------------------------------------------------------------------------------
1 | user->enableSession = false;
18 | \Yii::$app->user->loginUrl = null;
19 | $this->modules = [
20 | 'v1' => [
21 | 'class' => 'powerkernel\billing\modules\api\v1\Module',
22 | ],
23 | ];
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "powerkernel/yii2-billing",
3 | "description": "Yii2 Billing",
4 | "type": "yii2-extension",
5 | "keywords": ["yii2","billing"],
6 | "license": "BSD-3-Clause",
7 | "authors": [
8 | {
9 | "name": "Harry Tang",
10 | "email": "harry@powerkernel.com"
11 | }
12 | ],
13 | "require": {
14 | "yiisoft/yii2": "~2.0",
15 | "picqer/php-barcode-generator": "~0.2.0",
16 | "paypal/rest-api-sdk-php": "~1.0",
17 | "endroid/qr-code": "~3.1",
18 | "bitwasp/bitcoin": "*"
19 | },
20 | "autoload": {
21 | "psr-4": {
22 | "powerkernel\\billing\\": ""
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/components/Tax.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 | namespace powerkernel\billing\components;
8 |
9 |
10 | /**
11 | * Class Tax
12 | * @package powerkernel\billing\components
13 | */
14 | class Tax
15 | {
16 |
17 | public $tax = [
18 | 'VN' => 0.1
19 | ];
20 |
21 | /**
22 | * get tax value by country
23 | * @param $country
24 | * @return int|mixed
25 | */
26 | public function getTaxValue($country)
27 | {
28 | if (isset($this->tax[$country])) {
29 | return $this->tax[$country];
30 | }
31 | return 0;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/views/bank/create.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Bank */
10 |
11 |
12 | /* breadcrumbs */
13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Banks'), 'url' => ['index']];
14 | $this->params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/views/coupon/create.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Coupon */
10 |
11 |
12 | /* breadcrumbs */
13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Coupons'), 'url' => ['index']];
14 | $this->params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/widgets/AddAddress.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\widgets;
10 |
11 | use powerkernel\billing\models\Address;
12 | use Yii;
13 | use yii\base\Widget;
14 |
15 | /**
16 | * Class AddAddress
17 | * @package powerkernel\billing\widgets
18 | */
19 | class AddAddress extends Widget
20 | {
21 |
22 | /**
23 | * @inheritdoc
24 | * @return string
25 | */
26 | public function run()
27 | {
28 | parent::run(); // TODO: Change the autogenerated stub
29 | $model = new Address();
30 | if ($model->load(Yii::$app->request->post())) {
31 | $model->save();
32 | Yii::$app->controller->refresh();
33 | }
34 | return $this->render('add-address', ['model' => $model]);
35 |
36 | }
37 | }
--------------------------------------------------------------------------------
/views/info/manage.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\BillingInfo */
10 |
11 |
12 | /* breadcrumbs */
13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Billing Information'), 'url' => ['manage']];
14 | $this->params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/views/address/create.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Address */
10 |
11 |
12 | /* breadcrumbs */
13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Addresses'), 'url' => ['index']];
14 | $this->params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | $this->context->layout = Yii::$app->view->theme->basePath . '/account.php';
22 | ?>
23 |
24 |
25 |
26 | = $this->render('_form', [
27 | 'model' => $model,
28 | ]) ?>
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/views/bank/update.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Bank */
10 |
11 |
12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Banks'), 'url' => ['index']];
13 | $this->params['breadcrumbs'][] = ['label' => $model->title, 'url' => ['view', 'id' => $model->id]];
14 | $this->params['breadcrumbs'][] = Yii::t('billing', 'Update');
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/memberMenu.php:
--------------------------------------------------------------------------------
1 |
5 | * @link https://powerkernel.com
6 | * @copyright Copyright (c) 2017 Power Kernel
7 | */
8 |
9 |
10 | use common\Core;
11 | use common\widgets\SideMenu;
12 |
13 | $menu=[
14 | 'title'=>Yii::$app->getModule('billing')->t('Billing'),
15 | 'icon'=> 'shopping-bag',
16 | 'items'=>[
17 | ['icon' => 'info-square', 'label' => Yii::$app->getModule('billing')->t('Information'), 'url' => ['/billing/info'], 'active' => Core::checkMCA('billing', 'info', '*')],
18 | ['icon' => 'credit-card', 'label' => Yii::$app->getModule('billing')->t('Invoices'), 'url' => ['/billing/invoice'], 'active' => Core::checkMCA('billing', 'invoice', '*')],
19 | ['icon' => 'address-book', 'label' => Yii::$app->getModule('billing')->t('Addresses'), 'url' => ['/billing/address'], 'active' => Core::checkMCA('billing', 'address', '*')],
20 | ],
21 | ];
22 | $menu['active']=SideMenu::isActive($menu['items']);
23 | return [$menu];
24 |
--------------------------------------------------------------------------------
/views/coupon/update.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Coupon */
10 |
11 |
12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Coupons'), 'url' => ['index']];
13 | $this->params['breadcrumbs'][] = ['label' => $model->code, 'url' => ['view', 'id' => $model->code]];
14 | $this->params['breadcrumbs'][] = Yii::t('billing', 'Update');
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/views/invoice/update.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Invoice */
10 |
11 |
12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Invoices'), 'url' => ['index']];
13 | $this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]];
14 | $this->params['breadcrumbs'][] = Yii::t('billing', 'Update');
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/views/info/update.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\BillingInfo */
10 |
11 |
12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Customers'), 'url' => ['index']];
13 | $this->params['breadcrumbs'][] = ['label' => $model->id_account, 'url' => ['view', 'id' => $model->id_account]];
14 | $this->params['breadcrumbs'][] = Yii::t('billing', 'Update');
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 | = $this->render('_form', [
26 | 'model' => $model,
27 | ]) ?>
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/views/address/update.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\Address */
10 |
11 |
12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Addresses'), 'url' => ['index']];
13 | $this->params['breadcrumbs'][] = ['label' => $model->_id, 'url' => ['view', 'id' => (string)$model->_id]];
14 | $this->params['breadcrumbs'][] = Yii::t('billing', 'Update');
15 |
16 | /* misc */
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | $this->context->layout = Yii::$app->view->theme->basePath . '/account.php';
22 | ?>
23 |
24 |
25 |
26 | = $this->render('_form', [
27 | 'model' => $model,
28 | ]) ?>
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/views/invoice/_shipping_address.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2018 Power Kernel
6 | */
7 |
8 | /* @var $info[] */
9 | ?>
10 |
11 | = $info['company'] ?>
12 |
13 | = $info['contact_name'] ?>
14 |
15 |
16 |
17 | = $info['street_address_1'] ?>
18 |
19 | = $info['street_address_2'] ?>
20 |
21 | = $info['city'] ?>= !empty($info['state']) ? ', ' . $info['state'] : '' ?>= !empty($info['zip_code']) ? ', ' . $info['zip_code'] : '' ?>= !empty($info['country']) ? ', ' . $info['country'] : '' ?>
22 |
23 | = Yii::$app->getModule('billing')->t('Phone:') ?> = $info['phone'] ?>
24 |
--------------------------------------------------------------------------------
/views/info/create.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $this yii\web\View */
9 | /* @var $model powerkernel\billing\models\BillingInfo */
10 | /* @var $account \common\models\Account */
11 |
12 |
13 | /* breadcrumbs */
14 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Customers'), 'url' => ['index']];
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Adding billing information for {EMAIL}', ['EMAIL'=>$account->email]) ?>
28 |
29 | = $this->render('_form', [
30 | 'model' => $model,
31 | ]) ?>
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/views/bank/_search.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\ActiveForm;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\BankSearch */
13 | /* @var $form yii\widgets\ActiveForm */
14 | ?>
15 |
16 |
17 |
18 | ['index'],
20 | 'method' => 'get',
21 | ]); ?>
22 |
23 | = $form->field($model, 'id') ?>
24 |
25 | = $form->field($model, 'country') ?>
26 |
27 | = $form->field($model, 'title') ?>
28 |
29 | = $form->field($model, 'info') ?>
30 |
31 | = $form->field($model, 'currency') ?>
32 |
33 | field($model, 'status') ?>
34 |
35 | field($model, 'created_at') ?>
36 |
37 | field($model, 'updated_at') ?>
38 |
39 |
40 | = Html::submitButton(Yii::t('billing', 'Search'), ['class' => 'btn btn-primary']) ?>
41 | = Html::resetButton(Yii::t('billing', 'Reset'), ['class' => 'btn btn-default']) ?>
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/views/invoice/_billing_address.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2018 Power Kernel
6 | */
7 |
8 | /* @var $info[] */
9 | ?>
10 |
11 | = $info['company'] ?>
12 |
13 | = $info['f_name'] ?> = $info['l_name'] ?>
14 |
15 |
16 |
17 | = $info['address'] ?>
18 |
19 | = $info['address2'] ?>
20 |
21 | = $info['city'] ?>= !empty($info['state']) ? ', ' . $info['state'] : '' ?>= !empty($info['zip']) ? ', ' . $info['zip'] : '' ?>= !empty($info['country']) ? ', ' . $info['country'] : '' ?>
22 |
23 | = Yii::$app->getModule('billing')->t('Phone:') ?> = $info['phone'] ?>
24 |
25 | = Yii::$app->getModule('billing')->t('Email:') ?> = $info['email'] ?>
26 |
27 | = Yii::$app->getModule('billing')->t('Tax:') ?> = $info['tax_id'] ?>
28 |
29 |
--------------------------------------------------------------------------------
/views/coupon/_search.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\ActiveForm;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\CouponSearch */
13 | /* @var $form yii\widgets\ActiveForm */
14 | ?>
15 |
16 |
17 |
18 | ['index'],
20 | 'method' => 'get',
21 | ]); ?>
22 |
23 | = $form->field($model, 'code') ?>
24 |
25 | = $form->field($model, 'discount') ?>
26 |
27 | = $form->field($model, 'begin_at') ?>
28 |
29 | = $form->field($model, 'end_at') ?>
30 |
31 | = $form->field($model, 'quantity') ?>
32 |
33 | field($model, 'reuse') ?>
34 |
35 | field($model, 'status') ?>
36 |
37 | field($model, 'created_at') ?>
38 |
39 | field($model, 'updated_at') ?>
40 |
41 |
42 | = Html::submitButton(Yii::t('billing', 'Search'), ['class' => 'btn btn-primary']) ?>
43 | = Html::resetButton(Yii::t('billing', 'Reset'), ['class' => 'btn btn-default']) ?>
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/mail/new-invoice-user-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Dear {NAME},', ['NAME' => $model->account->fullname]) ?>
9 |
10 |
11 | = Yii::$app->getModule('billing')->t('Thank you for placing your order with us! Your total amount due is {TOTAL}. More details about your purchase are included below.', ['TOTAL'=>Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
12 |
13 |
14 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
15 |
16 | items as $item):?>
17 | = Yii::$app->getModule('billing')->t(' - {ITEM}: {PRICE}', ['ITEM'=>$item->name, 'PRICE'=>Yii::$app->formatter->asCurrency($item->price, $model->currency)]) ?>
18 |
19 |
20 |
21 | = Yii::$app->getModule('billing')->t('Shipping: {SHIP}', ['SHIP' => Yii::$app->formatter->asCurrency($model->shipping, $model->currency)]) ?>
22 |
23 | = Yii::$app->getModule('billing')->t('Tax: {TAX}', ['TAX' => Yii::$app->formatter->asCurrency($model->tax, $model->currency)]) ?>
24 |
25 | = Yii::$app->getModule('billing')->t('Total: {TOTAL}', ['TOTAL' => Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
26 |
27 |
28 | = Yii::$app->getModule('billing')->t('Pay Now: {URL}', ['URL'=>$model->getInvoiceUrl(true)]) ?>
29 |
--------------------------------------------------------------------------------
/mail/src/new-invoice-user-text.php:
--------------------------------------------------------------------------------
1 |
7 |
8 | = Yii::$app->getModule('billing')->t('Dear {NAME},', ['NAME' => $model->account->fullname]) ?>
9 |
10 |
11 | = Yii::$app->getModule('billing')->t('Thank you for placing your order with us! Your total amount due is {TOTAL}. More details about your purchase are included below.', ['TOTAL'=>Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
12 |
13 |
14 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID' => $model->id_invoice]) ?>
15 |
16 | items as $item):?>
17 | = Yii::$app->getModule('billing')->t(' - {ITEM}: {PRICE}', ['ITEM'=>$item->name, 'PRICE'=>Yii::$app->formatter->asCurrency($item->price, $model->currency)]) ?>
18 |
19 |
20 |
21 | = Yii::$app->getModule('billing')->t('Shipping: {SHIP}', ['SHIP' => Yii::$app->formatter->asCurrency($model->shipping, $model->currency)]) ?>
22 |
23 | = Yii::$app->getModule('billing')->t('Tax: {TAX}', ['TAX' => Yii::$app->formatter->asCurrency($model->tax, $model->currency)]) ?>
24 |
25 | = Yii::$app->getModule('billing')->t('Total: {TOTAL}', ['TOTAL' => Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
26 |
27 |
28 | = Yii::$app->getModule('billing')->t('Pay Now: {URL}', ['URL'=>$model->getInvoiceUrl(true)]) ?>
29 |
--------------------------------------------------------------------------------
/migrations/m170907_104245_init.php:
--------------------------------------------------------------------------------
1 | mongodb->getCollection('billing_settings');
14 | $col->createIndexes([
15 | [
16 | 'key'=>['key'],
17 | 'unique'=>true,
18 | ]
19 | ]);
20 |
21 | $col=Yii::$app->mongodb->getCollection('billing_invoice');
22 | $col->createIndexes([
23 | [
24 | 'key'=>['id_invoice'],
25 | 'unique'=>true,
26 | ]
27 | ]);
28 |
29 | $col=Yii::$app->mongodb->getCollection('billing_coupon');
30 | $col->createIndexes([
31 | [
32 | 'key'=>['code'],
33 | 'unique'=>true,
34 | ]
35 | ]);
36 |
37 | $col=Yii::$app->mongodb->getCollection('billing_bitcoin_payments');
38 | $col->createIndexes([
39 | [
40 | 'key'=>['address'],
41 | 'unique'=>true,
42 | ]
43 | ]);
44 |
45 |
46 | }
47 |
48 | /**
49 | * @return bool
50 | */
51 | public function down()
52 | {
53 | echo "m170907_104245_init cannot be reverted.\n";
54 |
55 | return false;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/views/address/_grid.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 |
10 | /* @var $this \yii\web\View */
11 | /* @var $model \powerkernel\billing\models\Address */
12 |
13 | ?>
14 |
15 |
16 |
17 |
= $model->contact_name ?>
18 |
= $model->street_address_1 ?>
19 | street_address_2)):?>
20 |
= $model->street_address_2 ?>
21 |
22 |
= $model->city ?>, = $model->state ?> = $model->zip_code ?>
23 |
= \common\Core::getCountryText($model->country) ?>
24 |
= $model->getAttributeLabel('phone') ?>: = $model->phone ?>
25 |
26 |
29 |
30 |
--------------------------------------------------------------------------------
/views/bitcoin/_copy.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $bitcoin [] */
9 |
10 | ?>
11 |
12 |
= Yii::$app->getModule('billing')->t('To complete your payment, please send {BTC} BTC to the address below.', ['BTC' => $bitcoin['amount']]) ?>
13 |
14 |
15 |
16 |
17 |
18 |
= Yii::$app->getModule('billing')->t('AMOUNT') ?>
19 |
= $bitcoin['amount'] ?> BTC
20 |
21 |
22 |
23 |
= Yii::$app->getModule('billing')->t('ADDRESS') ?>
24 |
= $bitcoin['address'] ?>
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/views/bitcoin/payment.min.js:
--------------------------------------------------------------------------------
1 | function setAddress(){var addr=$("#btc-address");addr.html(addr.data("addr"))}function checkPayment(){var url=$("#check-payment-url").data("check-payment-url");$.getJSON(url).done(function(response){if(response.payment_received===true){$("#payment-waiting").addClass("hidden");$("#btc-info").addClass("hidden");$("#payment-received").removeClass("hidden")}})}checkPayment();$("#copy-tab").on("click","#btc-address",function(){var $temp=$(" ");$("body").append($temp);$temp.val($(this).data("addr")).select();document.execCommand("copy");$temp.remove();$(this).html($(this).data("copied"));setTimeout(setAddress,2e3)});setInterval(checkPayment,1e4);var $clock=$("#count-down"),addrTime=$("#btc-address").data("date"),currentTime=moment().unix(),diffTime=currentTime-addrTime,timeout=$("#btc-info").data("timeout"),duration=moment.duration((timeout-diffTime)*1e3,"milliseconds"),interval=1e3;var $m=$('-- ').appendTo($clock);$(': ').appendTo($clock);var $s=$('-- ').appendTo($clock);setInterval(function(){duration=moment.duration(duration.asMilliseconds()-interval,"milliseconds");var m=moment.duration(duration).minutes(),s=moment.duration(duration).seconds();m=$.trim(m).length===1?"0"+m:m;s=$.trim(s).length===1?"0"+s:s;if(moment.duration(duration).asSeconds()>=0){if(moment.duration(duration).asSeconds()<120){$("#count-down").addClass("text-danger")}$m.text(m);$s.text(s)}else{$("#btc-info").hide();$("#btc-expired").removeClass("hidden")}},interval);
--------------------------------------------------------------------------------
/views/address/_form.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use common\Core;
9 | use conquer\select2\Select2Widget;
10 | use yii\helpers\Html;
11 | use yii\widgets\ActiveForm;
12 |
13 | /* @var $this yii\web\View */
14 | /* @var $model powerkernel\billing\models\Address */
15 | /* @var $form yii\widgets\ActiveForm */
16 | ?>
17 |
18 |
49 |
--------------------------------------------------------------------------------
/cronjobs/TaskCancelInvoice.php:
--------------------------------------------------------------------------------
1 | call(function (\yii\console\Application $app) {
13 |
14 | /* get pending invoice > 7 days */
15 | $now = time();
16 | $days = 7 * 24 * 3600;
17 | $point = $now - $days;
18 |
19 |
20 | $invoices = Invoice::find()
21 | ->where([
22 | 'status' => Invoice::STATUS_PENDING,
23 | 'updated_at' => ['$lte' => new \MongoDB\BSON\UTCDateTime($point * 1000)]
24 | ])->all();
25 |
26 |
27 | if ($invoices) {
28 | $obj = [];
29 | foreach ($invoices as $invoice) {
30 | $invoice->cancel();
31 | $obj[] = $invoice->id;
32 | }
33 | $output = implode(', ', $obj);
34 | }
35 |
36 | /* Result */
37 | if (!empty($output)) {
38 | $log = new \common\models\TaskLog();
39 | $log->task = basename(__FILE__, '.php');
40 | $log->result = $output;
41 | $log->save();
42 | }
43 |
44 |
45 | /* delete old logs never bad */
46 | $period = 30 * 24 * 60 * 60; // 30 days
47 | $point = time() - $period;
48 | \common\models\TaskLog::deleteAll([
49 | 'task' => basename(__FILE__, '.php'),
50 | 'created_at' => ['$lte', new \MongoDB\BSON\UTCDateTime($point * 1000)]
51 | ]);
52 |
53 |
54 | unset($app);
55 |
56 | })->cron($time);
57 |
--------------------------------------------------------------------------------
/views/address/manage.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = Yii::$app->getModule('billing')->t('Billing');
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
19 | //$js=file_get_contents(__DIR__.'/index.min.js');
20 | //$this->registerJs($js);
21 | $css=file_get_contents(__DIR__.'/manage.css');
22 | $this->registerCss($css);
23 | $this->context->layout = Yii::$app->view->theme->basePath . '/account.php';
24 | ?>
25 |
26 |
27 |
28 | render('_search', ['model' => $searchModel]); ?>
29 |
30 |
31 |
32 |
33 | = ListView::widget([
34 | 'dataProvider' => $dataProvider,
35 | 'itemOptions' => ['class' => 'item'],
36 | 'itemView' => '_grid',
37 | 'layout' => "
{items}
{pager}"
38 | ]) ?>
39 |
40 |
41 |
42 |
43 |
44 | = Html::a(Yii::t('billing', 'Add Address'), ['create'], ['class' => 'btn btn-success']) ?>
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/cronjobs/TaskReleaseBTCAddr.php:
--------------------------------------------------------------------------------
1 | call(function (\yii\console\Application $app) {
13 |
14 | /* get used addresses, but no tx > 3 days */
15 | $now = time();
16 | $days = 3 * 24 * 3600;
17 | $point = $now - $days;
18 |
19 | $addresses = BitcoinAddress::find()
20 | ->where([
21 | 'status' => BitcoinAddress::STATUS_USED,
22 | 'updated_at' => ['$lte' => new \MongoDB\BSON\UTCDateTime($point * 1000)],
23 | 'tx_id' => null
24 | ])->all();
25 |
26 |
27 | if ($addresses) {
28 | $obj = [];
29 | foreach ($addresses as $address) {
30 | $address->release();
31 | $obj[] = $address->address;
32 | }
33 | $output = implode(', ', $obj);
34 | }
35 |
36 | /* Result */
37 | if (!empty($output)) {
38 | $log = new \common\models\TaskLog();
39 | $log->task = basename(__FILE__, '.php');
40 | $log->result = $output;
41 | $log->save();
42 | }
43 |
44 |
45 | /* delete old logs never bad */
46 | $period = 30 * 24 * 60 * 60; // 30 days
47 | $point = time() - $period;
48 | \common\models\TaskLog::deleteAll([
49 | 'task' => basename(__FILE__, '.php'),
50 | 'created_at' => ['$lte', new \MongoDB\BSON\UTCDateTime($point * 1000)]
51 | ]);
52 |
53 |
54 | })->cron($time);
55 |
--------------------------------------------------------------------------------
/views/address/_search.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\ActiveForm;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\AddressSearch */
13 | /* @var $form yii\widgets\ActiveForm */
14 | ?>
15 |
16 |
17 |
18 | ['index'],
20 | 'method' => 'get',
21 | ]); ?>
22 |
23 | = $form->field($model, '_id') ?>
24 |
25 | = $form->field($model, 'id_account') ?>
26 |
27 | = $form->field($model, 'country') ?>
28 |
29 | = $form->field($model, 'contact_name') ?>
30 |
31 | = $form->field($model, 'street_address_1') ?>
32 |
33 | field($model, 'street_address_2') ?>
34 |
35 | field($model, 'city') ?>
36 |
37 | field($model, 'state') ?>
38 |
39 | field($model, 'zip_code') ?>
40 |
41 | field($model, 'phone') ?>
42 |
43 | field($model, 'status') ?>
44 |
45 | field($model, 'created_at') ?>
46 |
47 | field($model, 'updated_at') ?>
48 |
49 |
50 | = Html::submitButton(Yii::t('billing', 'Search'), ['class' => 'btn btn-primary']) ?>
51 | = Html::resetButton(Yii::t('billing', 'Reset'), ['class' => 'btn btn-default']) ?>
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/views/bank/_form.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use common\Core;
9 | use conquer\select2\Select2Widget;
10 | use powerkernel\billing\models\Bank;
11 | use yii\widgets\ActiveForm;
12 |
13 | /* @var $this yii\web\View */
14 | /* @var $model powerkernel\billing\models\Bank */
15 | /* @var $form yii\widgets\ActiveForm */
16 | ?>
17 |
18 |
47 |
--------------------------------------------------------------------------------
/cronjobs/TaskCheckBTCTransaction.php:
--------------------------------------------------------------------------------
1 | call(function (\yii\console\Application $app) {
13 |
14 | /* update confirmations */
15 | $addresses = BitcoinAddress::find()->where(['status'=>BitcoinAddress::STATUS_UNCONFIRMED])->all();
16 |
17 | if ($addresses) {
18 | $obj = [];
19 | foreach ($addresses as $address) {
20 | $address->checkPayment();
21 | $obj[] = $address->address;
22 | }
23 | $output = $app->getModule('billing')->t('Addresses checked: {ADDR}', ['ADDR' => implode(', ', $obj)]);
24 | }
25 |
26 | /* Result */
27 | if (!empty($output)) {
28 | $log = new \common\models\TaskLog();
29 | $log->task = basename(__FILE__, '.php');
30 | $log->result = $output;
31 | $log->save();
32 | }
33 |
34 |
35 | /* delete old logs never bad */
36 | $period = 30* 24 * 60 * 60; // 30 day
37 | $point = time() - $period;
38 | if(Yii::$app->params['mongodb']['taskLog']){
39 | \common\models\TaskLog::deleteAll([
40 | 'task'=>basename(__FILE__, '.php'),
41 | 'created_at'=>['$lte', new \MongoDB\BSON\UTCDateTime($point*1000)]
42 | ]);
43 | }
44 | else {
45 | \common\models\TaskLog::deleteAll('task=:task AND created_at<=:point', [
46 | ':task' => basename(__FILE__, '.php'),
47 | ':point' => $point
48 | ]);
49 | }
50 | })->cron($time);
--------------------------------------------------------------------------------
/views/info/_search.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\ActiveForm;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\BillingInfoSearch */
13 | /* @var $form yii\widgets\ActiveForm */
14 | ?>
15 |
16 |
17 |
18 | ['index'],
20 | 'method' => 'get',
21 | ]); ?>
22 |
23 | = $form->field($model, 'id_account') ?>
24 |
25 | = $form->field($model, 'company') ?>
26 |
27 | = $form->field($model, 'f_name') ?>
28 |
29 | = $form->field($model, 'l_name') ?>
30 |
31 | = $form->field($model, 'address') ?>
32 |
33 | field($model, 'address2') ?>
34 |
35 | field($model, 'city') ?>
36 |
37 | field($model, 'state') ?>
38 |
39 | field($model, 'zip') ?>
40 |
41 | field($model, 'country') ?>
42 |
43 | field($model, 'phone') ?>
44 |
45 | field($model, 'status') ?>
46 |
47 | field($model, 'created_at') ?>
48 |
49 | field($model, 'updated_at') ?>
50 |
51 |
52 | = Html::submitButton(Yii::t('billing', 'Search'), ['class' => 'btn btn-primary']) ?>
53 | = Html::resetButton(Yii::t('billing', 'Reset'), ['class' => 'btn btn-default']) ?>
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/adminMenu.php:
--------------------------------------------------------------------------------
1 |
5 | * @link https://powerkernel.com
6 | * @copyright Copyright (c) 2017 Power Kernel
7 | */
8 |
9 |
10 | use common\Core;
11 | use common\widgets\SideMenu;
12 |
13 |
14 | $menu=[
15 | 'title'=>Yii::$app->getModule('billing')->t('Billing'),
16 | 'icon'=> 'shopping-bag',
17 | 'items'=>[
18 | ['icon' => 'money-bill-alt', 'label' => Yii::$app->getModule('billing')->t('Invoices'), 'url' => ['billing/invoice/index'], 'active' => Core::checkMCA('billing', 'invoice', '*')],
19 | ['icon' => 'users', 'label' => Yii::$app->getModule('billing')->t('Customers'), 'url' => ['billing/info/index'], 'active' => Core::checkMCA('billing', 'info', '*')],
20 | ['icon' => 'address-book', 'label' => Yii::$app->getModule('billing')->t('Addresses'), 'url' => ['/billing/address/index'], 'active' => Core::checkMCA('billing', 'address', '*')],
21 | ['icon' => 'gift', 'label' => Yii::$app->getModule('billing')->t('Coupons'), 'url' => ['billing/coupon/index'], 'active' => Core::checkMCA('billing', 'coupon', '*')],
22 | ['icon' => 'university', 'label' => Yii::$app->getModule('billing')->t('Banks'), 'url' => ['billing/bank/index'], 'active' => Core::checkMCA('billing', 'bank', '*')],
23 | ['icon' => 'bitcoin', 'prefix'=>'fab fa-fw', 'label' => Yii::$app->getModule('billing')->t('Bitcoin'), 'url' => ['billing/bitcoin/index'], 'active' => Core::checkMCA('billing', 'bitcoin', '*')],
24 | ['icon' => 'cogs', 'label' => Yii::$app->getModule('billing')->t('Settings'), 'url' => ['billing/setting/index'], 'active' => Core::checkMCA('billing', 'setting', 'index')],
25 | ],
26 | ];
27 | $menu['active']=SideMenu::isActive($menu['items']);
28 | return [$menu];
29 |
--------------------------------------------------------------------------------
/views/address/view.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\DetailView;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\Address */
13 |
14 | $this->params['breadcrumbs'][] = Yii::$app->getModule('billing')->t('Billing');
15 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Addresses'), 'url' => ['index']];
16 | $this->params['breadcrumbs'][] = Yii::$app->getModule('billing')->t('View');
17 |
18 | /* misc */
19 | //$js=file_get_contents(__DIR__.'/index.min.js');
20 | //$this->registerJs($js);
21 | //$css=file_get_contents(__DIR__.'/index.css');
22 | //$this->registerCss($css);
23 | ?>
24 |
25 |
26 |
27 |
28 | = DetailView::widget([
29 | 'model' => $model,
30 | 'attributes' => [
31 | //'_id',
32 | ['attribute' => 'id_account', 'value' => Html::a($model->account->fullname, ['/account/view', 'id'=>(string)$model->account->id]), 'format'=>'raw'],
33 | 'contact_name',
34 | 'street_address_1',
35 | 'street_address_2',
36 | 'city',
37 | 'state',
38 | 'zip_code',
39 | 'country',
40 | 'phone',
41 | 'status',
42 | 'createdAt:dateTime',
43 | 'updatedAt:dateTime',
44 | //['attribute' => 'status', 'value' => $model->statusColorText, 'format'=>'raw'],
45 | ],
46 | ]) ?>
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/views/bank/view.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\DetailView;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\Bank */
13 |
14 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Banks'), 'url' => ['index']];
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 | = DetailView::widget([
28 | 'model' => $model,
29 | 'attributes' => [
30 | 'id',
31 | 'country',
32 | 'title',
33 | 'info:ntext',
34 | 'currency',
35 | ['attribute' => 'status', 'value' => $model->statusColorText, 'format'=>'raw'],
36 | 'createdAt:dateTime',
37 | 'updatedAt:dateTime',
38 | ],
39 | ]) ?>
40 |
41 |
42 | = Html::a(Yii::t('billing', 'Update'), ['update', 'id' => (string)$model->id], ['class' => 'btn btn-primary']) ?>
43 | = Html::a(Yii::t('billing', 'Delete'), ['delete', 'id' => (string)$model->id], [
44 | 'class' => 'btn btn-danger',
45 | 'data' => [
46 | 'confirm' => Yii::t('billing', 'Are you sure you want to delete this item?'),
47 | 'method' => 'post',
48 | ],
49 | ]) ?>
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/views/bitcoin/view.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\DetailView;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\BitcoinAddress */
13 |
14 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Bitcoin Addresses'), 'url' => ['index']];
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 | = DetailView::widget([
28 | 'model' => $model,
29 | 'attributes' => [
30 | ['attribute' => 'address', 'value' => Html::a($model->address, 'https://blockchain.info/address/' . $model->address, ['target' => '_blank']), 'format' => 'raw'],
31 | ['attribute' => 'id_invoice', 'value' => empty($model->invoice) ? null : Html::a($model->id_invoice, Yii::$app->urlManager->createUrl(['billing/invoice/view', 'id' => (string)$model->invoice->id]), ['target' => '_blank']), 'format' => 'raw'],
32 | 'id_account',
33 | 'request_balance',
34 | 'total_received',
35 | 'final_balance',
36 | ['attribute' => 'tx_id', 'value' => empty($model->tx_id) ? null : Html::a($model->tx_id, 'https://blockchain.info/tx/' . $model->tx_id, ['target' => '_blank']), 'format' => 'raw'],
37 | 'tx_confirmed:decimal',
38 | //'tx_date:dateTime',
39 | //'tx_check_date:dateTime',
40 | 'updatedAt:dateTime',
41 | ['attribute' => 'status', 'value' => $model->statusColorText, 'format' => 'raw'],
42 | ],
43 | ]) ?>
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Module.php:
--------------------------------------------------------------------------------
1 | registerTranslations();
25 | $this->registerMailer();
26 | /* api module */
27 | $this->modules = [
28 | 'api' => [
29 | 'class' => 'powerkernel\billing\modules\api\Module',
30 | ],
31 | ];
32 | }
33 |
34 | /**
35 | * Config Mailer for the Module
36 | */
37 | public function registerMailer()
38 | {
39 | Yii::$app->mailer->setViewPath($this->basePath . '/mail');
40 | Yii::$app->mailer->htmlLayout = '@common/mail/layouts/html';
41 | Yii::$app->mailer->textLayout = '@common/mail/layouts/text';
42 | }
43 |
44 | /**
45 | * Register translation for the Module
46 | */
47 | public function registerTranslations()
48 | {
49 | $class = 'common\components\MongoDbMessageSource';
50 | Yii::$app->i18n->translations['billing'] = [
51 | 'class' => $class,
52 | 'on missingTranslation' => function ($event) {
53 | $event->sender->handleMissingTranslation($event);
54 | },
55 | ];
56 | }
57 |
58 | /**
59 | * Translate message
60 | * @param $message
61 | * @param array $params
62 | * @param null $language
63 | * @return mixed
64 | */
65 | public static function t($message, $params = [], $language = null)
66 | {
67 | return Yii::$app->getModule('billing')->translate($message, $params, $language);
68 | }
69 |
70 | /**
71 | * Translate message
72 | * @param $message
73 | * @param array $params
74 | * @param null $language
75 | * @return mixed
76 | */
77 | public static function translate($message, $params = [], $language = null)
78 | {
79 | return Yii::t('billing', $message, $params, $language);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/cronjobs/TaskCheckBTCPayment.php:
--------------------------------------------------------------------------------
1 | call(function (\yii\console\Application $app) {
13 |
14 | /* check payment within 15 min */
15 | $now = time();
16 | $period = 999; // margin is always better :)
17 | $point = $now - $period;
18 |
19 | if(Yii::$app->getModule('billing')->params['db']==='mongodb'){
20 | $addresses = BitcoinAddress::find()
21 | ->where([
22 | 'status'=>BitcoinAddress::STATUS_USED,
23 | 'updated_at'=>['$gte'=>new \MongoDB\BSON\UTCDateTime($point*1000)]
24 | ])->all();
25 | }
26 | else {
27 | $addresses = BitcoinAddress::find()
28 | ->where('status=:used AND updated_at>=:point',
29 | [
30 | ':used' => BitcoinAddress::STATUS_USED,
31 | ':point' => $point
32 | ])->all();
33 | }
34 |
35 |
36 | if ($addresses) {
37 | $obj = [];
38 | foreach ($addresses as $address) {
39 | $address->checkPayment();
40 | $obj[] = $address->address;
41 | }
42 | $output = $app->getModule('billing')->t('Addresses checked: {ADDR}', ['ADDR' => implode(', ', $obj)]);
43 | }
44 |
45 | /* Result */
46 | if (!empty($output)) {
47 | $log = new \common\models\TaskLog();
48 | $log->task = basename(__FILE__, '.php');
49 | $log->result = $output;
50 | $log->save();
51 | }
52 |
53 |
54 | /* delete old logs never bad */
55 | $period = 30 * 24 * 60 * 60; // 30 days
56 | $point = time() - $period;
57 | if(Yii::$app->params['mongodb']['taskLog']){
58 | \common\models\TaskLog::deleteAll([
59 | 'task'=>basename(__FILE__, '.php'),
60 | 'created_at'=>['$lte', new \MongoDB\BSON\UTCDateTime($point*1000)]
61 | ]);
62 | }
63 | else {
64 | \common\models\TaskLog::deleteAll('task=:task AND created_at<=:point', [
65 | ':task' => basename(__FILE__, '.php'),
66 | ':point' => $point
67 | ]);
68 | }
69 | })->cron($time);
--------------------------------------------------------------------------------
/views/info/_form.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use common\Core;
9 | use conquer\select2\Select2Widget;
10 | use yii\bootstrap\ActiveForm;
11 | use yii\helpers\Html;
12 |
13 |
14 | /* @var $this yii\web\View */
15 | /* @var $model powerkernel\billing\models\BillingInfo */
16 | /* @var $form yii\widgets\ActiveForm */
17 | ?>
18 |
19 |
63 |
--------------------------------------------------------------------------------
/models/BankSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use yii\base\Model;
12 | use yii\data\ActiveDataProvider;
13 |
14 | /**
15 | * BankSearch represents the model behind the search form about `powerkernel\billing\models\Bank`.
16 | */
17 | class BankSearch extends Bank
18 | {
19 | /**
20 | * @inheritdoc
21 | */
22 | public function rules()
23 | {
24 | return [
25 | [['status', 'created_at', 'updated_at'], 'safe'],
26 | [['country', 'title', 'info', 'currency'], 'safe'],
27 | ];
28 | }
29 |
30 | /**
31 | * @inheritdoc
32 | */
33 | public function scenarios()
34 | {
35 | // bypass scenarios() implementation in the parent class
36 | return Model::scenarios();
37 | }
38 |
39 | /**
40 | * Creates data provider instance with search query applied
41 | *
42 | * @param array $params
43 | *
44 | * @return ActiveDataProvider
45 | */
46 | public function search($params)
47 | {
48 | $query = Bank::find();
49 |
50 | // add conditions that should always apply here
51 |
52 | $dataProvider = new ActiveDataProvider([
53 | 'query' => $query,
54 | //'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
55 | ]);
56 |
57 | $this->load($params);
58 |
59 | if (!$this->validate()) {
60 | // uncomment the following line if you do not want to return any records when validation fails
61 | // $query->where('0=1');
62 | return $dataProvider;
63 | }
64 |
65 | // grid filtering conditions
66 | $query->andFilterWhere([
67 | 'id' => $this->id,
68 | 'status' => $this->status,
69 | 'created_at' => $this->created_at,
70 | 'updated_at' => $this->updated_at,
71 | ]);
72 |
73 | $query->andFilterWhere(['like', 'country', $this->country])
74 | ->andFilterWhere(['like', 'title', $this->title])
75 | ->andFilterWhere(['like', 'info', $this->info])
76 | ->andFilterWhere(['like', 'currency', $this->currency]);
77 |
78 | //$query->andFilterWhere([
79 | // 'DATE(FROM_UNIXTIME(`created_at`))' => $this->created_at,
80 | //]);
81 |
82 | return $dataProvider;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/views/info/view.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use yii\helpers\Html;
9 | use yii\widgets\DetailView;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\BillingInfo */
13 |
14 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Customers'), 'url' => ['index']];
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 | = DetailView::widget([
28 | 'model' => $model,
29 | 'attributes' => [
30 | //'id_account',
31 | 'company',
32 | 'tax_id',
33 | 'f_name',
34 | 'l_name',
35 | 'account.email',
36 | 'address',
37 | 'address2',
38 | 'city',
39 | 'state',
40 | 'zip',
41 | 'country',
42 | 'phone',
43 | ['attribute' => 'status', 'value' => $model->statusColorText, 'format'=>'raw'],
44 | 'createdAt:date',
45 | 'updatedAt:date',
46 | ],
47 | ]) ?>
48 |
49 |
50 | = Html::a(Yii::t('billing', 'View Account'), Yii::$app->urlManager->createUrl(['account/view', 'id'=>(string)$model->id_account]), ['class' => 'btn btn-info']) ?>
51 | = Html::a(Yii::t('billing', 'Update'), ['update', 'id' => (string)$model->id], ['class' => 'btn btn-primary']) ?>
52 | = Html::a(Yii::t('billing', 'Delete'), ['delete', 'id' => (string)$model->id], [
53 | 'class' => 'btn btn-danger',
54 | 'data' => [
55 | 'confirm' => Yii::t('billing', 'Are you sure you want to delete this item?'),
56 | 'method' => 'post',
57 | ],
58 | ]) ?>
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/views/coupon/view.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use powerkernel\billing\models\Coupon;
9 | use yii\helpers\Html;
10 | use yii\widgets\DetailView;
11 |
12 | /* @var $this yii\web\View */
13 | /* @var $model powerkernel\billing\models\Coupon */
14 |
15 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Coupons'), 'url' => ['index']];
16 | $this->params['breadcrumbs'][] = $model->code;
17 |
18 | /* misc */
19 | //$js=file_get_contents(__DIR__.'/index.min.js');
20 | //$this->registerJs($js);
21 | //$css=file_get_contents(__DIR__.'/index.css');
22 | //$this->registerCss($css);
23 | ?>
24 |
25 |
26 |
27 |
28 | = DetailView::widget([
29 | 'model' => $model,
30 | 'attributes' => [
31 | 'code',
32 | 'currency',
33 | [
34 | 'attribute' => 'discount',
35 | 'value' => $model->discount_type == Coupon::DISCOUNT_TYPE_PERCENT ? Yii::$app->formatter->asPercent($model->discount/100):Yii::$app->formatter->asCurrency($model->discount, $model->currency)
36 | ],
37 | 'beginAt:date',
38 | 'endAt:date',
39 | [
40 | 'attribute' => 'quantity',
41 | 'value' => $model->quantity==-1?Yii::$app->getModule('billing')->t('Unlimited'):Yii::$app->formatter->asDecimal($model->quantity),
42 | ],
43 | 'reuse:boolean',
44 | ['attribute' => 'status', 'value' => $model->statusColorText, 'format' => 'raw'],
45 | 'createdAt:dateTime',
46 | 'updatedAt:dateTime',
47 | ],
48 | ]) ?>
49 |
50 |
51 | = Html::a(Yii::t('billing', 'Update'), ['update', 'id' => (string)$model->id], ['class' => 'btn btn-primary']) ?>
52 | = Html::a(Yii::t('billing', 'Delete'), ['delete', 'id' => (string)$model->id], [
53 | 'class' => 'btn btn-danger',
54 | 'data' => [
55 | 'confirm' => Yii::t('billing', 'Are you sure you want to delete this item?'),
56 | 'method' => 'post',
57 | ],
58 | ]) ?>
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/components/CurrencyLayer.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\components;
10 |
11 |
12 | use common\components\CurrencyFraction;
13 | use Yii;
14 | use yii\httpclient\Client;
15 |
16 | /**
17 | * Class CurrencyLayer
18 | * @package powerkernel\billing\components
19 | */
20 | class CurrencyLayer
21 | {
22 | CONST END_POINT = 'http://www.apilayer.net/api/live';
23 | public $quotes;
24 |
25 | /**
26 | * CurrencyLayer constructor.
27 | */
28 | public function __construct()
29 | {
30 | $access_key=\powerkernel\billing\models\Setting::getValue('currencyLayerAPI');
31 | if(!empty($access_key)){
32 | $this->init($access_key);
33 | }
34 | }
35 |
36 | /**
37 | * @param $access_key
38 | * @throws \yii\base\InvalidConfigException
39 | */
40 | protected function init($access_key){
41 | $cache='currency-layer';
42 | $client = new Client();
43 | $response = Yii::$app->cache->get($cache);
44 | if ($response === false) {
45 | $response = $client->createRequest()
46 | ->setMethod('get')
47 | ->setUrl(self::END_POINT)
48 | ->setData(['access_key' => $access_key])
49 | ->send();
50 | Yii::$app->cache->set($cache, $response, 43200); // 12 hours
51 | }
52 | if ($response->isOk && !empty($response->data['quotes'])) {
53 | $this->quotes = $response->data['quotes'];
54 | }
55 | }
56 |
57 |
58 | /**
59 | * @param $from
60 | * @param $to
61 | * @param $amount
62 | * @return bool|float|int
63 | */
64 | public function convert($from, $to, $amount)
65 | {
66 | if($from!='USD'){
67 | $amount=$this->convertToUSD($from, $amount);
68 | }
69 | if (!empty($this->quotes['USD' . $to])) {
70 | $result=$amount*$this->quotes['USD' . $to];
71 | if($to=='VND'){
72 | $result=ceil($result/1000)*1000; // round up
73 | }
74 | return round($result, CurrencyFraction::getFraction($to));
75 | }
76 | return false;
77 | }
78 |
79 |
80 | /**
81 | * @param $from
82 | * @param $amount
83 | * @return bool|float|int
84 | */
85 | public function convertToUSD($from, $amount)
86 | {
87 | //if($amount==0) return $amount;
88 |
89 | if (!empty($this->quotes['USD' . $from])) {
90 | return round($amount / $this->quotes['USD' . $from], CurrencyFraction::getFraction('USD'));
91 | }
92 | return false;
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/views/bitcoin/payment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Harry Tang
3 | * @link https://powerkernel.com
4 | * @copyright Copyright (c) 2017 Power Kernel
5 | */
6 |
7 | /**
8 | * set BTC address back again
9 | */
10 | function setAddress() {
11 | var addr = $("#btc-address");
12 | addr.html(addr.data('addr'));
13 | }
14 |
15 | /**
16 | * check payment status
17 | */
18 | function checkPayment() {
19 | var url = $("#check-payment-url").data("check-payment-url");
20 | $.getJSON(url)
21 | .done(function (response) {
22 | /** @namespace response.payment_received */
23 | if(response.payment_received===true){
24 | $("#payment-waiting").addClass("hidden");
25 | $("#btc-info").addClass("hidden");
26 | $("#payment-received").removeClass("hidden");
27 | }
28 | });
29 | }
30 | checkPayment();
31 |
32 | /**
33 | * copy BTC address on click
34 | */
35 | $("#copy-tab").on("click", "#btc-address", function () {
36 | var $temp = $(" ");
37 | $("body").append($temp);
38 | $temp.val($(this).data('addr')).select();
39 | document.execCommand("copy");
40 | $temp.remove();
41 | $(this).html($(this).data('copied'));
42 | setTimeout(setAddress, 2000);
43 | });
44 |
45 | /**
46 | * check payment every 10s
47 | */
48 | setInterval(checkPayment, 10000);
49 |
50 | /* count down */
51 | var $clock = $("#count-down"),
52 | addrTime = $("#btc-address").data('date'), // seconds
53 | currentTime = moment().unix(), // seconds
54 | diffTime = currentTime - addrTime, // seconds
55 | timeout = $("#btc-info").data('timeout'), // seconds
56 | duration = moment.duration((timeout - diffTime) * 1000, 'milliseconds'),
57 | interval = 1000;
58 |
59 | var $m = $('-- ').appendTo($clock);
60 | $(': ').appendTo($clock);
61 | var $s = $('-- ').appendTo($clock);
62 |
63 | setInterval(function () {
64 | duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');
65 | var m = moment.duration(duration).minutes(),
66 | s = moment.duration(duration).seconds();
67 |
68 | m = $.trim(m).length === 1 ? '0' + m : m;
69 | s = $.trim(s).length === 1 ? '0' + s : s;
70 |
71 | // show how many hours, minutes and seconds are left
72 | if (moment.duration(duration).asSeconds() >= 0) {
73 | if (moment.duration(duration).asSeconds() < 120) {
74 | $("#count-down").addClass("text-danger");
75 | }
76 | $m.text(m);
77 | $s.text(s);
78 | }
79 | else {
80 | $("#btc-info").hide();
81 | $("#btc-expired").removeClass('hidden');
82 | }
83 |
84 | }, interval);
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/views/invoice/_form.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use powerkernel\billing\models\Invoice;
9 | use yii\widgets\ActiveForm;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $model powerkernel\billing\models\Invoice */
13 | /* @var $form yii\widgets\ActiveForm */
14 | ?>
15 |
16 |
59 |
--------------------------------------------------------------------------------
/widgets/views/add-address.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | /* @var $model \powerkernel\billing\models\Address */
9 |
10 | use common\Core;
11 | use yii\bootstrap\ActiveForm;
12 | use yii\bootstrap\Modal;
13 |
14 | ?>
15 |
--------------------------------------------------------------------------------
/views/info/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
13 |
14 | /* misc */
15 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
16 | //$js=file_get_contents(__DIR__.'/index.min.js');
17 | //$this->registerJs($js);
18 | //$css=file_get_contents(__DIR__.'/index.css');
19 | //$this->registerCss($css);
20 | ?>
21 |
22 |
23 |
24 |
25 |
26 | render('_search', ['model' => $searchModel]); ?>
27 |
28 |
29 |
30 |
31 | = GridView::widget([
32 | 'dataProvider' => $dataProvider,
33 | 'filterModel' => $searchModel,
34 | 'columns' => [
35 | ['class' => 'yii\grid\SerialColumn'],
36 |
37 | //'id_account',
38 | 'company',
39 | 'f_name',
40 | 'l_name',
41 | 'address',
42 | // 'address2',
43 | // 'city',
44 | // 'state',
45 | // 'zip',
46 | 'phone',
47 | 'country',
48 |
49 | // 'status',
50 | // 'created_at',
51 | // 'updated_at',
52 | //['attribute' => 'created_at', 'value' => 'created_at', 'format' => 'dateTime', 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']])],
53 | //['attribute' => 'status', 'value' => function ($model){return $model->statusText;}, 'filter'=>''],
54 | [
55 | 'class' => 'yii\grid\ActionColumn',
56 | 'contentOptions' => ['style' => 'min-width: 70px']
57 | ],
58 | ],
59 | ]); ?>
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/models/BitcoinAddressSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use yii\base\Model;
12 | use yii\data\ActiveDataProvider;
13 |
14 | /**
15 | * BitcoinAddressSearch represents the model behind the search form about `powerkernel\billing\models\BitcoinAddress`.
16 | */
17 | class BitcoinAddressSearch extends BitcoinAddress
18 | {
19 | /**
20 | * @inheritdoc
21 | */
22 | public function rules()
23 | {
24 | return [
25 | [['address', 'id_invoice', 'tx_id', 'status'], 'safe'],
26 | [['request_balance', 'total_received'], 'number'],
27 | ];
28 | }
29 |
30 | /**
31 | * @inheritdoc
32 | */
33 | public function scenarios()
34 | {
35 | // bypass scenarios() implementation in the parent class
36 | return Model::scenarios();
37 | }
38 |
39 | /**
40 | * Creates data provider instance with search query applied
41 | *
42 | * @param array $params
43 | *
44 | * @return ActiveDataProvider
45 | */
46 | public function search($params)
47 | {
48 | $query = BitcoinAddress::find();
49 |
50 | // add conditions that should always apply here
51 |
52 | $dataProvider = new ActiveDataProvider([
53 | 'query' => $query,
54 | //'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]],
55 | //'pagination'=>['pageSize'=>20],
56 | ]);
57 |
58 | $this->load($params);
59 |
60 | if (!$this->validate()) {
61 | // uncomment the following line if you do not want to return any records when validation fails
62 | // $query->where('0=1');
63 | return $dataProvider;
64 | }
65 |
66 | // grid filtering conditions
67 | $query->andFilterWhere([
68 | 'id' => $this->id,
69 | 'id_account' => $this->id_account,
70 | 'request_balance' => $this->request_balance,
71 | 'total_received' => $this->total_received,
72 | 'final_balance' => $this->final_balance,
73 | 'tx_date' => $this->tx_date,
74 | 'tx_confirmed' => $this->tx_confirmed,
75 | 'tx_check_date' => $this->tx_check_date,
76 | 'status' => $this->status,
77 | 'created_at' => $this->created_at,
78 | 'updated_at' => $this->updated_at,
79 | ]);
80 |
81 | $query->andFilterWhere(['like', 'address', $this->address])
82 | ->andFilterWhere(['like', 'id_invoice', $this->id_invoice])
83 | ->andFilterWhere(['like', 'tx_id', $this->tx_id]);
84 |
85 | //$query->andFilterWhere([
86 | // 'DATE(FROM_UNIXTIME(`created_at`))' => $this->created_at,
87 | //]);
88 |
89 | return $dataProvider;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/views/bank/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
14 |
15 | /* misc */
16 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
17 | //$js=file_get_contents(__DIR__.'/index.min.js');
18 | //$this->registerJs($js);
19 | //$css=file_get_contents(__DIR__.'/index.css');
20 | //$this->registerCss($css);
21 | ?>
22 |
23 |
24 |
25 |
26 |
27 | render('_search', ['model' => $searchModel]); ?>
28 |
29 |
30 |
31 |
32 | = GridView::widget([
33 | 'dataProvider' => $dataProvider,
34 | 'filterModel' => $searchModel,
35 | 'columns' => [
36 | ['class' => 'yii\grid\SerialColumn'],
37 |
38 | //'id',
39 | 'country',
40 | 'title',
41 | //'info:ntext',
42 | 'currency',
43 | // 'status',
44 | // 'created_at',
45 | // 'updated_at',
46 | //['attribute' => 'created_at', 'value' => 'created_at', 'format' => 'dateTime', 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']])],
47 | ['attribute' => 'status', 'value' => function ($model) {
48 | return $model->statusColorText;
49 | }, 'filter' => \powerkernel\billing\models\Bank::getStatusOption(), 'format' => 'raw'],
50 | [
51 | 'class' => 'yii\grid\ActionColumn',
52 | 'contentOptions' => ['style' => 'min-width: 70px']
53 | ],
54 | ],
55 | ]); ?>
56 |
57 |
58 |
59 | = Html::a(Yii::t('billing', 'Add bank account'), ['create'], ['class' => 'btn btn-success']) ?>
60 |
61 |
62 |
63 |
64 |
65 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/models/BillingInfoSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use yii\base\Model;
12 | use yii\data\ActiveDataProvider;
13 |
14 | /**
15 | * BillingInfoSearch represents the model behind the search form about `powerkernel\billing\models\BillingInfo`.
16 | */
17 | class BillingInfoSearch extends BillingInfo
18 | {
19 | /**
20 | * @inheritdoc
21 | */
22 | public function rules()
23 | {
24 | return [
25 | [['id_account', 'status', 'created_at', 'updated_at'], 'integer'],
26 | [['company', 'f_name', 'l_name', 'address', 'address2', 'city', 'state', 'zip', 'country', 'phone'], 'safe'],
27 | ];
28 | }
29 |
30 | /**
31 | * @inheritdoc
32 | */
33 | public function scenarios()
34 | {
35 | // bypass scenarios() implementation in the parent class
36 | return Model::scenarios();
37 | }
38 |
39 | /**
40 | * Creates data provider instance with search query applied
41 | *
42 | * @param array $params
43 | *
44 | * @return ActiveDataProvider
45 | */
46 | public function search($params)
47 | {
48 | $query = BillingInfo::find();
49 |
50 | // add conditions that should always apply here
51 |
52 | $dataProvider = new ActiveDataProvider([
53 | 'query' => $query,
54 | //'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
55 | ]);
56 |
57 | $this->load($params);
58 |
59 | if (!$this->validate()) {
60 | // uncomment the following line if you do not want to return any records when validation fails
61 | // $query->where('0=1');
62 | return $dataProvider;
63 | }
64 |
65 | // grid filtering conditions
66 | $query->andFilterWhere([
67 | 'id_account' => $this->id_account,
68 | 'status' => $this->status,
69 | 'created_at' => $this->created_at,
70 | 'updated_at' => $this->updated_at,
71 | ]);
72 |
73 | $query->andFilterWhere(['like', 'company', $this->company])
74 | ->andFilterWhere(['like', 'f_name', $this->f_name])
75 | ->andFilterWhere(['like', 'l_name', $this->l_name])
76 | ->andFilterWhere(['like', 'address', $this->address])
77 | ->andFilterWhere(['like', 'address2', $this->address2])
78 | ->andFilterWhere(['like', 'city', $this->city])
79 | ->andFilterWhere(['like', 'state', $this->state])
80 | ->andFilterWhere(['like', 'zip', $this->zip])
81 | ->andFilterWhere(['like', 'country', $this->country])
82 | ->andFilterWhere(['like', 'phone', $this->phone]);
83 |
84 | //$query->andFilterWhere([
85 | // 'DATE(FROM_UNIXTIME(`created_at`))' => $this->created_at,
86 | //]);
87 |
88 | return $dataProvider;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/models/Setting.php:
--------------------------------------------------------------------------------
1 | _id;
56 | }
57 |
58 | /**
59 | * @inheritdoc
60 | */
61 | public function rules()
62 | {
63 | return [
64 | [['key', 'title'], 'required'],
65 | [['key_order'], 'integer'],
66 | [['key', 'title', 'value', 'type', 'default', 'data', 'rules'], 'string', 'max' => 255]
67 | ];
68 | }
69 |
70 | /**
71 | * @inheritdoc
72 | */
73 | public function attributeLabels()
74 | {
75 | return [
76 | 'key' => Yii::t('billing', 'Key'),
77 | 'title' => Yii::t('billing', 'Title'),
78 | 'value' => Yii::t('billing', 'Value'),
79 | 'type' => Yii::t('billing', 'Type'),
80 | 'default' => Yii::t('billing', 'Default'),
81 | 'data' => Yii::t('billing', 'Data'),
82 | 'rules' => Yii::t('billing', 'Rules'),
83 | 'key_order' => Yii::t('billing', 'Order'),
84 | ];
85 | }
86 |
87 | /**
88 | * load as array
89 | * @return array
90 | */
91 | public static function loadAsArray()
92 | {
93 | $settings = self::find()->all();
94 | $a = [];
95 | foreach ($settings as $setting) {
96 | $a[$setting->key] = $setting->value;
97 | }
98 | return $a;
99 | }
100 |
101 | /**
102 | * @param $key
103 | * @return mixed|null
104 | */
105 | public static function findTitle($key)
106 | {
107 | $model = self::find()->where(['key' => $key])->one();
108 | if ($model) {
109 | return $model->title;
110 | }
111 | return null;
112 | }
113 |
114 | /**
115 | * get setting value
116 | * @param $key
117 | * @return mixed|null
118 | */
119 | public static function getValue($key)
120 | {
121 | $model = self::find()->where(['key' => $key])->one();
122 | if ($model) {
123 | return $model->value;
124 | }
125 | return null;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/views/setting/index.php:
--------------------------------------------------------------------------------
1 | title = Yii::t('billing', 'Settings');
14 | $this->params['breadcrumbs'][] = ['label' => Yii::t('billing', 'Billing'), 'url' => ['index']];
15 | $this->params['breadcrumbs'][] = $this->title;
16 |
17 |
18 | ?>
19 |
20 | 'horizontal',
22 | 'fieldConfig' => ['horizontalCssClasses' => [
23 | 'offset' => '',
24 | 'label' => 'col-sm-2',
25 | 'wrapper' => 'col-sm-6',
26 | 'error' => '',
27 | 'hint' => 'col-sm-4',
28 | ]],
29 | ]); ?>
30 |
31 |
32 | $tab): ?>
33 |
34 | = $tab ?>
36 |
37 |
38 |
39 |
40 | $tab): ?>
41 |
42 | $setting): ?>
43 |
44 |
45 | = $form->field($model, $key)->textInput()->label($setting['key'])->hint($setting['title']) ?>
46 |
47 |
48 |
49 | = $form->field($model, $key)->textarea()->label($setting['key'])->hint($setting['title']) ?>
50 |
51 |
52 |
53 | = $form->field($model, $key)->passwordInput()->label($setting['key'])->hint($setting['title']) ?>
54 |
55 |
56 |
57 | =
58 | $form->field($model, $key)->dropDownList(in_array($setting['data'], ['{TIMEZONE}', '{LOCALE}']) ? Setting::getListData($setting['data']) : json_decode($setting['data'], true))->label($setting['key'])->hint($setting['title'])
59 | ?>
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/views/address/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = Yii::$app->getModule('billing')->t('Billing');
14 | $this->params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 |
28 | render('_search', ['model' => $searchModel]); ?>
29 |
30 |
31 |
32 |
33 | = GridView::widget([
34 | 'dataProvider' => $dataProvider,
35 | 'filterModel' => $searchModel,
36 | 'columns' => [
37 | ['class' => 'yii\grid\SerialColumn'],
38 | ['attribute' => 'id_account', 'value' => function ($model){return Html::a($model->account->fullname, ['/account/view', 'id'=>(string)$model->account->id], ['data-pjax'=>0]);}, 'format'=>'raw'],
39 |
40 | 'contact_name',
41 | //'street_address_1',
42 | // 'street_address_2',
43 | 'city',
44 | 'state',
45 | 'zip_code',
46 | 'country',
47 | 'phone',
48 | // 'status',
49 | // 'created_at',
50 | // 'updated_at',
51 | //[
52 | // 'attribute' => 'created_at',
53 | // 'value' => 'created_at',
54 | // 'format' => 'dateTime',
55 | // 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']]),
56 | // 'contentOptions'=>['style'=>'min-width: 80px']
57 | //],
58 | //['attribute' => 'status', 'value' => function ($model){return $model->statusText;}, 'filter'=>''],
59 | [
60 | 'class' => 'yii\grid\ActionColumn',
61 | //'contentOptions' => ['style' => 'min-width: 70px'],
62 | 'template'=>'{view}'
63 | ],
64 | ],
65 | ]); ?>
66 |
67 |
68 |
69 |
70 |
71 |
72 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/views/invoice/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 |
28 | = GridView::widget([
29 | 'dataProvider' => $dataProvider,
30 | 'filterModel' => $searchModel,
31 | 'columns' => [
32 | //['class' => 'yii\grid\SerialColumn'],
33 |
34 | 'id_invoice',
35 | //'account.fullname',
36 | ['attribute' => 'id_account', 'value' => 'account.fullname'],
37 | //['attribute' => 'subtotal', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->subtotal, $model->currency);}],
38 | //['attribute' => 'discount', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->discount, $model->currency);}],
39 | //['attribute' => 'tax', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->tax, $model->currency);}],
40 | ['attribute' => 'total', 'value' => function ($model) {
41 | return Yii::$app->formatter->asCurrency($model->total, $model->currency);
42 | }],
43 | // 'currency',
44 | // 'status',
45 | // 'created_at',
46 | // 'updated_at',
47 | ['attribute' => 'created_at', 'value' => 'createdAt', 'format' => 'dateTime', 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']])],
48 | ['attribute' => 'status', 'value' => function ($model) {
49 | return $model->getStatusColorText();
50 | }, 'filter' => Invoice::getStatusOption(), 'format' => 'raw'],
51 | [
52 | 'class' => 'yii\grid\ActionColumn',
53 | 'template' => '{view} {update}',
54 | 'contentOptions'=>['style'=>'min-width: 50px']
55 | ],
56 | ],
57 | ]); ?>
58 |
59 |
60 |
61 |
62 |
63 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/views/bitcoin/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
15 |
16 | /* misc */
17 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
18 | //$js=file_get_contents(__DIR__.'/index.min.js');
19 | //$this->registerJs($js);
20 | //$css=file_get_contents(__DIR__.'/index.css');
21 | //$this->registerCss($css);
22 | ?>
23 |
24 |
25 |
26 |
27 |
28 | render('_search', ['model' => $searchModel]); ?>
29 |
30 |
31 |
32 |
33 | = GridView::widget([
34 | 'dataProvider' => $dataProvider,
35 | 'filterModel' => $searchModel,
36 | 'columns' => [
37 | ['class' => 'yii\grid\SerialColumn'],
38 | //'id',
39 | ['attribute' => 'address', 'value' => function ($model){return Html::a($model->address, Yii::$app->urlManager->createUrl(['/billing/bitcoin/view', 'id'=>(string)$model->id]), ['title'=>Yii::$app->getModule('billing')->t('View BTC Address'), 'data-pjax'=>0]) ;}, 'format'=>'raw'],
40 | 'id_invoice',
41 | //'id_account',
42 |
43 | 'request_balance',
44 | 'total_received',
45 | // 'tx_id',
46 | // 'tx_date',
47 | // 'tx_confirmed',
48 | // 'tx_check_date',
49 | // 'status',
50 | // 'created_at',
51 | // 'updated_at',
52 | //[
53 | // 'attribute' => 'created_at',
54 | // 'value' => 'created_at',
55 | // 'format' => 'dateTime',
56 | // 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']]),
57 | // 'contentOptions'=>['style'=>'min-width: 80px']
58 | //],
59 | ['attribute' => 'status', 'value' => function ($model){return $model->statusColorText;}, 'filter'=> BitcoinAddress::getStatusOption(), 'format'=>'raw'],
60 | //['class' => 'yii\grid\ActionColumn'],
61 | ],
62 | ]); ?>
63 |
64 |
65 |
66 | = Html::a(Yii::t('billing', 'Generate Addresses'), ['generate'], ['class' => 'btn btn-success']) ?>
67 |
68 |
69 |
70 |
71 |
72 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/mail/src/new-invoice-admin-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Greetings from {APP},', ['APP'=>Yii::$app->name]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('A new order has just been placed') ?>
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/mail/src/cancel-invoice-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Hi {USER},', ['USER' => $model->account->fullname]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('We\'re sorry to let you know that your invoice has been canceled. You don\'t need to do anything else.') ?>
33 |
34 |
35 |
36 |
37 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/models/CouponForm.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\models;
9 |
10 | use MongoDB\BSON\UTCDateTime;
11 | use Yii;
12 | use yii\base\Model;
13 |
14 | /**
15 | * Class CouponForm
16 | * @package powerkernel\billing\models
17 | */
18 | class CouponForm extends Model
19 | {
20 | public $coupon;
21 | public $invoice;
22 |
23 | /**
24 | * @inheritdoc
25 | */
26 | public function rules()
27 | {
28 |
29 | return [
30 | [['coupon', 'invoice'], 'required'],
31 | [['coupon'], 'string', 'min' => 3, 'max' => 50],
32 | [['coupon'], 'checkCoupon']
33 | ];
34 | }
35 |
36 | /**
37 | * check coupon
38 | * @param $attribute
39 | * @param $params
40 | * @param $validator
41 | * @return bool
42 | */
43 | public function checkCoupon($attribute, $params, $validator)
44 | {
45 | $query = Coupon::find()->where([
46 | 'code' => $this->$attribute,
47 | 'status' => Coupon::STATUS_ACTIVE,
48 | ]);
49 | /* exist */
50 |
51 | $code = $query->andFilterWhere([
52 | 'begin_at' => ['$lte' => new UTCDateTime()],
53 | 'end_at' => ['$gte' => new UTCDateTime()]
54 | ])
55 | ->one();
56 |
57 |
58 | if (!$code) {
59 | $this->addError($attribute, Yii::$app->getModule('billing')->t('The code you entered is invalid or expired.'));
60 | return false;
61 | }
62 |
63 | /* currency */
64 | if ($code->currency != $this->invoice->currency) {
65 | $this->addError($attribute, Yii::$app->getModule('billing')->t('The invoice is not eligible for this promotion.'));
66 | return false;
67 | }
68 |
69 | /* Quantity */
70 | if ($code->quantity != -1) {
71 | $used = Invoice::find()->where([
72 | 'coupon' => $code,
73 | 'status' => [
74 | Invoice::STATUS_PENDING,
75 | Invoice::STATUS_PAID,
76 | Invoice::STATUS_PAID_UNCONFIRMED,
77 | Invoice::STATUS_REFUNDED
78 | ]
79 | ])->count();
80 | if ($code->quantity <= $used) {
81 | $this->addError($attribute, Yii::$app->getModule('billing')->t('The code you entered is ended.'));
82 | return false;
83 | }
84 | }
85 |
86 | /* can reuse? */
87 | if (!$code->reuse) {
88 | $reused = Invoice::find()->where([
89 | 'coupon' => $code,
90 | 'status' => [
91 | Invoice::STATUS_PENDING,
92 | Invoice::STATUS_PAID,
93 | Invoice::STATUS_PAID_UNCONFIRMED,
94 | Invoice::STATUS_REFUNDED
95 | ],
96 | 'id_account' => Yii::$app->user->id
97 | ])->count();
98 | if ($reused) {
99 | $this->addError($attribute, Yii::$app->getModule('billing')->t('You already used this code once!'));
100 | return false;
101 | }
102 | }
103 |
104 | }
105 |
106 | /**
107 | * @inheritdoc
108 | */
109 | public function attributeLabels()
110 | {
111 | return [
112 | 'coupon' => Yii::$app->getModule('billing')->t('Coupon Code'),
113 | ];
114 | }
115 |
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/models/InvoiceSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use common\models\Account;
12 | use MongoDB\BSON\UTCDateTime;
13 | use Yii;
14 | use yii\base\Model;
15 | use yii\data\ActiveDataProvider;
16 |
17 | /**
18 | * InvoiceSearch represents the model behind the search form about `powerkernel\billing\models\Invoice`.
19 | */
20 | class InvoiceSearch extends Invoice
21 | {
22 |
23 | public $fullname;
24 | public $manage = false;
25 |
26 | /**
27 | * @inheritdoc
28 | */
29 | public function rules()
30 | {
31 | return [
32 | [['id_invoice', 'total', 'created_at', 'id_account', 'status'], 'safe'],
33 | ];
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | */
39 | public function scenarios()
40 | {
41 | // bypass scenarios() implementation in the parent class
42 | return Model::scenarios();
43 | }
44 |
45 | /**
46 | * Creates data provider instance with search query applied
47 | *
48 | * @param array $params
49 | *
50 | * @return ActiveDataProvider
51 | */
52 | public function search($params)
53 | {
54 | $query = Invoice::find();
55 | //$query->joinWith(['account']);
56 |
57 | // add conditions that should always apply here
58 |
59 | $dataProvider = new ActiveDataProvider([
60 | 'query' => $query,
61 | 'sort' => ['defaultOrder' => ['created_at' => SORT_DESC]]
62 | ]);
63 |
64 | $dataProvider->sort->attributes['fullname'] = [
65 | // The tables are the ones our relation are configured to
66 | // in my case they are prefixed with "tbl_"
67 | //'asc' => ['{{%core_account}}.fullname' => SORT_ASC],
68 | //'desc' => ['{{%core_account}}.fullname' => SORT_DESC],
69 | ];
70 |
71 | if ($this->manage) {
72 | $query->andWhere(['id_account' => \Yii::$app->user->id]);
73 | }
74 |
75 | $this->load($params);
76 |
77 | if (!$this->validate()) {
78 | // uncomment the following line if you do not want to return any records when validation fails
79 | // $query->where('0=1');
80 | return $dataProvider;
81 | }
82 |
83 | // grid filtering conditions
84 | $query->andFilterWhere([
85 | 'total' => in_array($this->total, ['', null], true) ? null : (float)$this->total,
86 | 'status' => $this->status,
87 | ]);
88 | $query->andFilterWhere(['like', 'id_invoice', $this->id_invoice]);
89 |
90 | /* account */
91 | if (!empty($this->id_account)) {
92 | $key = '_id';
93 | $ids = [];
94 | $owners = Account::find()->select([$key])->where(['like', 'fullname', $this->id_account])->asArray()->all();
95 | foreach ($owners as $owner) {
96 | $ids[] = (string)$owner[$key];
97 | }
98 | $query->andFilterWhere(['id_account' => empty($ids) ? '0' : $ids]);
99 | }
100 |
101 | /* created_at */
102 | if (!empty($this->created_at)) {
103 |
104 | $query->andFilterWhere([
105 | 'updated_at' => ['$gte' => new UTCDateTime(strtotime($this->created_at) * 1000)],
106 | ])->andFilterWhere([
107 | 'updated_at' => ['$lt' => new UTCDateTime((strtotime($this->created_at) + 86400) * 1000)],
108 | ]);
109 |
110 | }
111 |
112 | return $dataProvider;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/models/CouponSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use yii\base\Model;
12 | use yii\data\ActiveDataProvider;
13 |
14 | /**
15 | * CouponSearch represents the model behind the search form about `powerkernel\billing\models\Coupon`.
16 | */
17 | class CouponSearch extends Coupon
18 | {
19 | /**
20 | * @inheritdoc
21 | */
22 | public function rules()
23 | {
24 | return [
25 | [['code', 'begin_at', 'end_at', 'status', 'discount', 'quantity'], 'safe'],
26 | [['discount'], 'number'],
27 | //[['quantity', 'reuse', 'status', 'created_at', 'updated_at'], 'integer'],
28 | ];
29 | }
30 |
31 | /**
32 | * @inheritdoc
33 | */
34 | public function scenarios()
35 | {
36 | // bypass scenarios() implementation in the parent class
37 | return Model::scenarios();
38 | }
39 |
40 | /**
41 | * Creates data provider instance with search query applied
42 | *
43 | * @param array $params
44 | *
45 | * @return ActiveDataProvider
46 | */
47 | public function search($params)
48 | {
49 | $query = Coupon::find();
50 |
51 | // add conditions that should always apply here
52 |
53 | $dataProvider = new ActiveDataProvider([
54 | 'query' => $query,
55 | 'sort' => ['defaultOrder' => ['created_at' => SORT_DESC]],
56 | //'pagination'=>['pageSize'=>20],
57 | ]);
58 |
59 | $this->load($params);
60 |
61 | if (!$this->validate()) {
62 | // uncomment the following line if you do not want to return any records when validation fails
63 | // $query->where('0=1');
64 | return $dataProvider;
65 | }
66 |
67 | // grid filtering conditions
68 | $query->andFilterWhere(['like', 'code', $this->code]);
69 | $query->andFilterWhere([
70 | 'discount' => in_array($this->discount, ['', null], true) ? null : (float)$this->discount,
71 | 'quantity' => in_array($this->quantity, ['', null], true) ? null : (float)$this->quantity,
72 | 'status' => $this->status,
73 | ]);
74 | if (!empty($this->begin_at)) {
75 |
76 | $query->andFilterWhere([
77 | 'begin_at' => ['$gte' => new \MongoDB\BSON\UTCDateTime(strtotime($this->begin_at) * 1000)],
78 | ])->andFilterWhere([
79 | 'begin_at' => ['$lt' => new \MongoDB\BSON\UTCDateTime((strtotime($this->begin_at) + 86400) * 1000)],
80 | ]);
81 |
82 | }
83 | if (!empty($this->end_at)) {
84 |
85 | $query->andFilterWhere([
86 | 'end_at' => ['$gte' => new \MongoDB\BSON\UTCDateTime(strtotime($this->end_at) * 1000)],
87 | ])->andFilterWhere([
88 | 'end_at' => ['$lt' => new \MongoDB\BSON\UTCDateTime((strtotime($this->end_at) + 86400) * 1000)],
89 | ]);
90 |
91 | }
92 |
93 | // if(!empty($this->begin_at)){
94 | // $query->andFilterWhere([
95 | // 'DATE(CONVERT_TZ(FROM_UNIXTIME(`begin_at`), :UTC, :ATZ))' => $this->begin_at,
96 | // ])->params([
97 | // ':UTC'=>'+00:00',
98 | // ':ATZ'=>date('P')
99 | // ]);
100 | // }
101 | // if(!empty($this->end_at)){
102 | // $query->andFilterWhere([
103 | // 'DATE(CONVERT_TZ(FROM_UNIXTIME(`end_at`), :UTC, :ATZ))' => $this->end_at,
104 | // ])->params([
105 | // ':UTC'=>'+00:00',
106 | // ':ATZ'=>date('P')
107 | // ]);
108 | // }
109 |
110 | return $dataProvider;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/views/invoice/manage.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
19 | //$js=file_get_contents(__DIR__.'/index.min.js');
20 | //$this->registerJs($js);
21 | //$css=file_get_contents(__DIR__.'/index.css');
22 | //$this->registerCss($css);
23 | ?>
24 |
25 |
26 |
27 |
28 |
29 | = GridView::widget([
30 | 'dataProvider' => $dataProvider,
31 | 'filterModel' => $searchModel,
32 | 'columns' => [
33 | //['class' => 'yii\grid\SerialColumn'],
34 |
35 | 'id_invoice',
36 | //'account.fullname',
37 | //['attribute' => 'fullname', 'value' => 'account.fullname'],
38 | //['attribute' => 'subtotal', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->subtotal, $model->currency);}],
39 | //['attribute' => 'discount', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->discount, $model->currency);}],
40 | //['attribute' => 'tax', 'value' => function ($model){return Yii::$app->formatter->asCurrency($model->tax, $model->currency);}],
41 | ['attribute' => 'total', 'value' => function ($model) {
42 | return Yii::$app->formatter->asCurrency($model->total, $model->currency);
43 | }],
44 | // 'currency',
45 | // 'status',
46 | // 'created_at',
47 | // 'updated_at',
48 | ['attribute' => 'created_at', 'value' => 'createdAt', 'format' => 'dateTime', 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']])],
49 | ['attribute' => 'status', 'value' => function ($model) {
50 | return $model->getStatusColorText();
51 | }, 'filter' => Invoice::getStatusOption(), 'format' => 'raw'],
52 | [
53 | 'class' => 'yii\grid\ActionColumn',
54 | 'template' => '{show}',
55 | 'buttons' => [
56 | 'show' => function ($url) {
57 | $show = Html::a(' ', $url, [
58 | 'title' => Yii::t('yii', 'View'),
59 | 'data-pjax' => '0',
60 | ]);
61 | return $show;
62 | }
63 | ]
64 | ],
65 | ],
66 | ]); ?>
67 |
68 |
69 |
70 |
71 |
72 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/views/coupon/_form.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use common\Core;
9 | use conquer\select2\Select2Widget;
10 | use powerkernel\billing\models\Coupon;
11 | use yii\jui\DatePicker;
12 | use yii\widgets\ActiveForm;
13 |
14 | /* @var $this yii\web\View */
15 | /* @var $model powerkernel\billing\models\Coupon */
16 | /* @var $form yii\widgets\ActiveForm */
17 | ?>
18 |
19 |
110 |
--------------------------------------------------------------------------------
/modules/api/v1/controllers/InvoiceController.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\modules\api\v1\controllers;
10 |
11 |
12 | use powerkernel\billing\models\Invoice;
13 | use Yii;
14 | use yii\filters\AccessControl;
15 | use yii\filters\auth\HttpBasicAuth;
16 | use yii\filters\VerbFilter;
17 |
18 |
19 | /**
20 | * Class InvoiceController
21 | * @package powerkernel\billing\modules\api\v1\controllers
22 | */
23 | class InvoiceController extends \yii\rest\Controller
24 | {
25 | /**
26 | * @return array
27 | */
28 | public function behaviors()
29 | {
30 | $behaviors = parent::behaviors();
31 | $behaviors['verbs'] = [
32 | 'class' => VerbFilter::class,
33 | 'actions' => [
34 | 'vcb-sms-check' => ['POST'],
35 | ],
36 | ];
37 |
38 |
39 | $behaviors['authenticator'] = [
40 | 'class' => HttpBasicAuth::class,
41 | ];
42 | $behaviors['access'] =
43 | [
44 | 'class' => AccessControl::class,
45 | 'rules' => [
46 | [
47 | 'roles' => ['admin'],
48 | 'allow' => true,
49 | ],
50 | ],
51 | ];
52 |
53 | return $behaviors;
54 | }
55 |
56 |
57 | /**
58 | * check sms VCB account in VND
59 | * test: curl -k -i -H "Accept:application/json" -H "Authorization: Basic base64 token" url
60 | */
61 | public function actionVcbSmsCheck()
62 | {
63 | if (!empty(Yii::$app->request->post('sms'))) {
64 | $sms = \Yii::$app->request->post('sms');
65 | /* check invoice id */
66 | $id = null;
67 | $model = null;
68 | $unpaidInvoices = Invoice::find()->where([
69 | 'currency' => 'VND',
70 | 'status' => Invoice::STATUS_PENDING,
71 | ])->all();
72 | foreach ($unpaidInvoices as $invoice) {
73 | if (preg_match("/({$invoice->id_invoice})/", $sms, $invoiceId)) {
74 | $id = $invoice->id_invoice;
75 | $model = $invoice;
76 | break;
77 | }
78 | }
79 |
80 | if ($id != null) {
81 | $amount = number_format($model->total, 0, '.', $thousands_sep = ",");
82 | /* amount */
83 | if (!preg_match('/(\+' . $amount . ' VND)/', $sms, $creditAmt)) {
84 | return [
85 | 'success' => false,
86 | 'data' => [
87 | 'message' => 'Wrong amount in WIRE Transfer'
88 | ]
89 | ];
90 | }
91 |
92 | /* set invoice paid if we are here*/
93 | $model->status = Invoice::STATUS_PAID;
94 | $model->payment_method = 'Bank Wire';
95 | //$model->save();
96 |
97 | return [
98 | 'success' => true,
99 | 'data' => [
100 | 'invoice' => $model->id_invoice,
101 | 'total' => \Yii::$app->formatter->asDecimal($model->total),
102 | 'bank' => $creditAmt[1],
103 | 'save' => $model->save()
104 | ]
105 | ];
106 | }
107 | return [
108 | 'success' => false,
109 | 'data' => [
110 | 'message' => 'Cannot find invoice ID'
111 | ]
112 | ];
113 | }
114 | return [
115 | 'success' => false,
116 | 'data' => [
117 | 'message' => 'Missing required parameters: sms'
118 | ]
119 | ];
120 | }
121 | }
122 |
123 |
124 |
--------------------------------------------------------------------------------
/views/paypal/return.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | use powerkernel\fontawesome\Icon;
9 | use yii\helpers\Html;
10 |
11 | /* @var $this yii\web\View */
12 | /* @var $invoice \powerkernel\billing\models\Invoice */
13 |
14 | $this->title = Yii::$app->getModule('billing')->t('Complete Payment');
15 | $keywords = '';
16 | $description = '';
17 |
18 | $this->registerMetaTag(['name' => 'keywords', 'content' => $keywords]);
19 | $this->registerMetaTag(['name' => 'description', 'content' => $description]);
20 | //$this->registerMetaTag(['name' => 'robots', 'content' => 'noindex, nofollow, nosnippet, noodp, noarchive, noimageindex']);
21 |
22 | /* Facebook */
23 | //$this->registerMetaTag(['property' => 'og:title', 'content' => $this->title]);
24 | //$this->registerMetaTag(['property' => 'og:description', 'content' => $description]);
25 | //$this->registerMetaTag(['property' => 'og:type', 'content' => '']);
26 | //$this->registerMetaTag(['property' => 'og:image', 'content' => '']);
27 | //$this->registerMetaTag(['property' => 'og:url', 'content' => '']);
28 | //$this->registerMetaTag(['property' => 'fb:app_id', 'content' => '']);
29 | //$this->registerMetaTag(['property' => 'fb:admins', 'content' => '']);
30 |
31 | /* Twitter */
32 | //$this->registerMetaTag(['name'=>'twitter:title', 'content'=>$this->title]);
33 | //$this->registerMetaTag(['name'=>'twitter:description', 'content'=>$description]);
34 | //$this->registerMetaTag(['name'=>'twitter:card', 'content'=>'summary']);
35 | //$this->registerMetaTag(['name'=>'twitter:site', 'content'=>'']);
36 | //$this->registerMetaTag(['name'=>'twitter:image', 'content'=>'']);
37 | //$this->registerMetaTag(['name'=>'twitter:data1', 'content'=>'']);
38 | //$this->registerMetaTag(['name'=>'twitter:label1', 'content'=>'']);
39 | //$this->registerMetaTag(['name'=>'twitter:data2', 'content'=>'']);
40 | //$this->registerMetaTag(['name'=>'twitter:label2', 'content'=>'']);
41 |
42 | /* breadcrumbs */
43 | $this->params['breadcrumbs'][] = ['label' => 'label', 'url' => '#'];
44 |
45 | /* layout */
46 | // Yii::$app->controller->layout = '@vendor/harrytang/yii2-theme/views/layouts/page';
47 | ?>
48 |
49 |
50 |
51 |
52 |
58 |
59 |
60 |
= Icon::widget(['icon' => 'check-circle-o']) ?>
61 | = Yii::$app->getModule('billing')->t('Payment Authorized') ?>
62 |
63 |
64 |
65 |
66 |
67 | Invoice
68 | = $invoice->id_invoice; ?>
69 |
70 |
71 | Total
72 | = Yii::$app->formatter->asCurrency($invoice->total, $invoice->currency); ?>
73 |
74 |
75 |
76 |
77 |
78 |
79 | = Html::beginForm() ?>
80 | = \common\components\SubmitButton::widget(['text'=>$this->title, 'options'=>['name'=>'complete', 'class'=>'btn btn-success', 'value'=>'true']]) ?>
81 | = Html::endForm() ?>
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/settings.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 | use common\Core;
8 |
9 | $s = [
10 | /* Billing */
11 | ['key' => 'merchantName', 'value' => '', 'title' => 'Merchant Name', 'description' => 'Merchant name', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
12 | ['key' => 'merchantAddress', 'value' => '', 'title' => 'Merchant Address', 'description' => 'Merchant address', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
13 | ['key' => 'merchantCity', 'value' => '', 'title' => 'Merchant City', 'description' => 'Merchant city', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
14 | ['key' => 'merchantState', 'value' => '', 'title' => 'Merchant State', 'description' => 'Merchant state', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
15 | ['key' => 'merchantZip', 'value' => '', 'title' => 'Merchant Zip', 'description' => 'Merchant zip code', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
16 | ['key' => 'merchantCountry', 'value' => '', 'title' => 'Merchant Country', 'description' => 'Merchant country', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required'=>[], 'string' => []])],
17 | ['key' => 'merchantPhone', 'value' => '', 'title' => 'Merchant Phone', 'description' => 'Merchant phone', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
18 | ['key' => 'merchantEmail', 'value' => '', 'title' => 'Merchant Email', 'description' => 'Merchant email', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'email' => []])],
19 |
20 | /* Paypal */
21 | ['key' => 'paypalSandbox', 'value' => '', 'title' => 'Paypal Sandbox Mode', 'description' => 'Set yes to enable sandbox', 'group' => 'Paypal', 'type' => 'dropDownList', 'data' => json_encode(Core::getYesNoOption()), 'default' => '1', 'rules' => json_encode(['required' => [], 'boolean' => []])],
22 | ['key' => 'paypalClientID', 'value' => '', 'title' => 'Paypal Client ID', 'description' => 'Live client ID', 'group' => 'Paypal', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
23 | ['key' => 'paypalSecret', 'value' => '', 'title' => 'Paypal Secret', 'description' => 'Live secret string', 'group' => 'Paypal', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
24 | ['key' => 'paypalSandboxClientID', 'value' => '', 'title' => 'Paypal Sandbox Client ID', 'description' => 'Sandbox client ID', 'group' => 'Paypal', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
25 | ['key' => 'paypalSandboxSecret', 'value' => '', 'title' => 'Paypal Sandbox Secret', 'description' => 'Sandbox secret string', 'group' => 'Paypal', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
26 |
27 | /* Bitcoin */
28 | ['key' => 'btcPaymentTime', 'value' => '', 'title' => 'BTC Payment Timeout', 'description' => 'Payment timeout in seconds', 'group' => 'Bitcoin', 'type' => 'textInput', 'data' => '[]', 'default' => '900', 'rules' => json_encode(['integer' => ['min'=>300, 'max'=>3600]])],
29 | ['key' => 'btcWalletXPub', 'value' => '', 'title' => 'BTC Wallet xPub', 'description' => 'Wallet extended public key', 'group' => 'Bitcoin', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
30 |
31 | /* order API */
32 | ['key' => 'currencyLayerAPI', 'value' => '', 'title' => 'Currency Layer API', 'description' => 'Access API key for currency conversion', 'group' => 'MISC', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
33 |
34 |
35 | ];
36 | return [];
--------------------------------------------------------------------------------
/models/Item.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\models;
9 |
10 | use Yii;
11 |
12 | /**
13 | * This is the model class for Item.
14 | *
15 | * @property \MongoDB\BSON\ObjectID|string $id
16 | * @property string $id_invoice
17 | * @property string $name
18 | * @property integer $quantity
19 | * @property double $price
20 | * @property string $details
21 | * @property string $status
22 | */
23 | class Item extends \yii\mongodb\ActiveRecord
24 | {
25 |
26 | const STATUS_NOT_SHIPPED = 'STATUS_NOT_SHIPPED'; //10;
27 | const STATUS_SHIPPED = 'STATUS_SHIPPED'; //10;
28 | const STATUS_RETURNED = 'STATUS_RETURNED'; //20;
29 |
30 | /**
31 | * @inheritdoc
32 | */
33 | public static function collectionName()
34 | {
35 | return 'billing_item';
36 | }
37 |
38 | /**
39 | * @return array
40 | */
41 | public function attributes()
42 | {
43 | return [
44 | '_id',
45 | 'id_invoice',
46 | 'name',
47 | 'quantity',
48 | 'price',
49 | 'details',
50 | 'status'
51 | ];
52 | }
53 |
54 | /**
55 | * get id
56 | * @return \MongoDB\BSON\ObjectID|string
57 | */
58 | public function getId()
59 | {
60 | return $this->_id;
61 | }
62 |
63 |
64 | /**
65 | * get status list
66 | * @param null $e
67 | * @return array
68 | */
69 | public static function getStatusOption($e = null)
70 | {
71 | $option = [
72 | self::STATUS_NOT_SHIPPED => Yii::$app->getModule('billing')->t('Not Shipped'),
73 | self::STATUS_SHIPPED => Yii::$app->getModule('billing')->t('Shipped'),
74 | self::STATUS_RETURNED => Yii::$app->getModule('billing')->t('Returned'),
75 | ];
76 | if (is_array($e))
77 | foreach ($e as $i)
78 | unset($option[$i]);
79 | return $option;
80 | }
81 |
82 | /**
83 | * get status text
84 | * @return string
85 | */
86 | public function getStatusText()
87 | {
88 | $status = $this->status;
89 | $list = self::getStatusOption();
90 | if (!empty($status) && in_array($status, array_keys($list))) {
91 | return $list[$status];
92 | }
93 | return Yii::$app->getModule('billing')->t('Unknown');
94 | }
95 |
96 | /**
97 | * @inheritdoc
98 | */
99 | public function rules()
100 | {
101 | return [
102 | ['status', 'default', 'value'=>null],
103 | [['id_invoice', 'name'], 'required'],
104 | [['quantity'], 'integer'],
105 | [['price'], 'number'],
106 | [['details'], 'string'],
107 | [['id_invoice'], 'string', 'max' => 23],
108 | [['name', 'status'], 'string', 'max' => 255],
109 | [['id_invoice'], 'exist', 'skipOnError' => true, 'targetClass' => Invoice::class, 'targetAttribute' => ['id_invoice' => 'id_invoice']],
110 | ];
111 | }
112 |
113 | /**
114 | * @inheritdoc
115 | */
116 | public function attributeLabels()
117 | {
118 | return [
119 | 'id' => Yii::$app->getModule('billing')->t('ID'),
120 | 'id_invoice' => Yii::$app->getModule('billing')->t('Invoice'),
121 | 'name' => Yii::$app->getModule('billing')->t('Name'),
122 | 'quantity' => Yii::$app->getModule('billing')->t('Quantity'),
123 | 'price' => Yii::$app->getModule('billing')->t('Price'),
124 | 'details' => Yii::$app->getModule('billing')->t('Details'),
125 | 'status' => Yii::$app->getModule('billing')->t('Status'),
126 | ];
127 | }
128 |
129 | /**
130 | * @return \yii\db\ActiveQueryInterface
131 | */
132 | public function getInvoice()
133 | {
134 | return $this->hasOne(Invoice::class, ['id_invoice' => 'id_invoice']);
135 | }
136 |
137 | /**
138 | * @inheritdoc
139 | * @param bool $insert
140 | * @param array $changedAttributes
141 | */
142 | public function afterSave($insert, $changedAttributes)
143 | {
144 | $this->invoice->calculate();
145 | $this->invoice->save(false);
146 | parent::afterSave($insert, $changedAttributes); // TODO: Change the autogenerated stub
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/models/AddressSearch.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 |
9 | namespace powerkernel\billing\models;
10 |
11 | use common\Core;
12 | use common\models\Account;
13 | use Yii;
14 | use yii\base\Model;
15 | use yii\data\ActiveDataProvider;
16 |
17 | /**
18 | * AddressSearch represents the model behind the search form about `powerkernel\billing\models\Address`.
19 | */
20 | class AddressSearch extends Address
21 | {
22 | /**
23 | * @inheritdoc
24 | */
25 | public function rules()
26 | {
27 | return [
28 | [['id_account', 'country', 'contact_name', 'street_address_1', 'street_address_2', 'city', 'state', 'zip_code', 'phone', 'status', 'created_at', 'updated_at'], 'safe'],
29 | ];
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | */
35 | public function scenarios()
36 | {
37 | // bypass scenarios() implementation in the parent class
38 | return Model::scenarios();
39 | }
40 |
41 | /**
42 | * Creates data provider instance with search query applied
43 | *
44 | * @param array $params
45 | *
46 | * @return ActiveDataProvider
47 | */
48 | public function search($params)
49 | {
50 | $query = Address::find();
51 | $pageSize = 20;
52 | if (Core::checkMCA('billing', 'address', 'manage')) {
53 | $pageSize = 9;
54 | }
55 |
56 | // add conditions that should always apply here
57 |
58 |
59 | $dataProvider = new ActiveDataProvider([
60 | 'query' => $query,
61 | //'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]],
62 | 'pagination' => ['pageSize' => $pageSize],
63 | ]);
64 |
65 | $this->load($params);
66 |
67 | /* manage action */
68 | if (Core::checkMCA('billing', 'address', 'manage')) {
69 | $query->andFilterWhere(['like', 'id_account', Yii::$app->user->id]);
70 | }
71 |
72 | if (!$this->validate()) {
73 | // uncomment the following line if you do not want to return any records when validation fails
74 | // $query->where('0=1');
75 | return $dataProvider;
76 | }
77 |
78 | // account
79 | if (!in_array($this->id_account, ['', null], true)) {
80 | $key = '_id';
81 | $ids = [];
82 | $owners = Account::find()->select([$key])->where(['like', 'fullname', $this->id_account])->asArray()->all();
83 | foreach ($owners as $owner) {
84 | $ids[] = (string)$owner[$key];
85 | }
86 | if (empty($ids)) {
87 | $ids[] = '0';
88 | }
89 | $query->andFilterWhere(['id_account' => $ids]);
90 | }
91 |
92 | // grid filtering conditions
93 | $query->andFilterWhere(['like', '_id', $this->_id])
94 | //->andFilterWhere(['like', 'id_account', $this->id_account])
95 | ->andFilterWhere(['like', 'country', $this->country])
96 | ->andFilterWhere(['like', 'contact_name', $this->contact_name])
97 | ->andFilterWhere(['like', 'street_address_1', $this->street_address_1])
98 | ->andFilterWhere(['like', 'street_address_2', $this->street_address_2])
99 | ->andFilterWhere(['like', 'city', $this->city])
100 | ->andFilterWhere(['like', 'state', $this->state])
101 | ->andFilterWhere(['like', 'zip_code', $this->zip_code])
102 | ->andFilterWhere(['like', 'phone', $this->phone])
103 | ->andFilterWhere(['like', 'status', $this->status])
104 | ->andFilterWhere(['like', 'created_at', $this->created_at])
105 | ->andFilterWhere(['like', 'updated_at', $this->updated_at]);
106 |
107 | //if(!empty($this->created_at)){
108 | // $query->andFilterWhere([
109 | // 'DATE(CONVERT_TZ(FROM_UNIXTIME(`created_at`), :UTC, :ATZ))' => $this->created_at,
110 | // ])->params([
111 | // ':UTC'=>'+00:00',
112 | // ':ATZ'=>date('P')
113 | // ]);
114 | //}
115 |
116 | //if(!empty($this->created_by)) {
117 | // $owners=Account::find()->select('id')->where(['like', 'fullname', $this->created_by])->asArray()->all();
118 | // $ids = [0];
119 | // foreach ($owners as $owner) {
120 | // $ids[] = (integer)$owner['id'];
121 | // }
122 | // $query->andFilterWhere(['created_by' => $ids]);
123 | //}
124 |
125 | return $dataProvider;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/mail/new-invoice-admin-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Greetings from {APP},', ['APP'=>Yii::$app->name]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('A new order has just been placed') ?>
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/mail/cancel-invoice-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Hi {USER},', ['USER' => $model->account->fullname]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('We\'re sorry to let you know that your invoice has been canceled. You don\'t need to do anything else.') ?>
33 |
34 |
35 |
36 |
37 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/mail/src/new-invoice-user-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Dear {NAME},', ['NAME'=>$model->account->fullname]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('Thank you for placing your order with us! Your total amount due is {TOTAL}. More details about your purchase are included below.', ['TOTAL'=>Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
41 |
42 |
43 | items as $item):?>
44 |
45 |
46 | = Yii::$app->getModule('billing')->t(' - {ITEM}: {PRICE}', ['ITEM'=>$item->name, 'PRICE'=>Yii::$app->formatter->asCurrency($item->price, $model->currency)]) ?>
47 |
48 |
49 |
50 | = Yii::$app->getModule('billing')->t('Shipping: {SHIP}', ['SHIP' => Yii::$app->formatter->asCurrency($model->shipping, $model->currency)]) ?>
51 | = Yii::$app->getModule('billing')->t('Tax: {TAX}', ['TAX' => Yii::$app->formatter->asCurrency($model->tax, $model->currency)]) ?>
52 | = Yii::$app->getModule('billing')->t('Total: {TOTAL}', ['TOTAL' => Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
53 |
54 |
55 |
56 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/mail/src/css/mailgun.css:
--------------------------------------------------------------------------------
1 | /* Let's make sure all tables have defaults */
2 | table td {
3 | vertical-align: top;
4 | }
5 |
6 | /* -------------------------------------
7 | BODY & CONTAINER
8 | ------------------------------------- */
9 |
10 |
11 | .body-wrap {
12 | background-color: #f6f6f6;
13 | width: 100%;
14 | }
15 |
16 | .container {
17 | display: block !important;
18 | max-width: 600px !important;
19 | margin: 0 auto !important;
20 | /* makes it centered */
21 | clear: both !important;
22 | }
23 |
24 | .content {
25 | max-width: 600px;
26 | margin: 0 auto;
27 | display: block;
28 | padding: 20px;
29 | }
30 |
31 | /* -------------------------------------
32 | HEADER, FOOTER, MAIN
33 | ------------------------------------- */
34 | .main {
35 | background-color: #fff;
36 | border: 1px solid #e9e9e9;
37 | border-radius: 3px;
38 | }
39 |
40 | .content-wrap {
41 | padding: 20px;
42 | }
43 |
44 | .content-block {
45 | padding: 0 0 20px;
46 | }
47 |
48 | .header {
49 | width: 100%;
50 | margin-bottom: 20px;
51 | }
52 |
53 | .footer {
54 | width: 100%;
55 | clear: both;
56 | color: #999;
57 | padding: 20px;
58 | }
59 | .footer p, .footer a, .footer td {
60 | color: #999;
61 | font-size: 12px;
62 | }
63 |
64 | /* -------------------------------------
65 | TYPOGRAPHY
66 | ------------------------------------- */
67 | h1, h2, h3 {
68 | font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
69 | color: #000;
70 | margin: 40px 0 0;
71 | line-height: 1.2em;
72 | font-weight: 400;
73 | }
74 |
75 | h1 {
76 | font-size: 32px;
77 | font-weight: 500;
78 | /* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
79 | /*line-height: 38px;*/
80 | }
81 |
82 | h2 {
83 | font-size: 24px;
84 | /* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
85 | /*line-height: 29px;*/
86 | }
87 |
88 | h3 {
89 | font-size: 18px;
90 | /* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
91 | /*line-height: 22px;*/
92 | }
93 |
94 | h4 {
95 | font-size: 14px;
96 | font-weight: 600;
97 | }
98 |
99 | p, ul, ol {
100 | margin-bottom: 10px;
101 | font-weight: normal;
102 | }
103 | p li, ul li, ol li {
104 | margin-left: 5px;
105 | list-style-position: inside;
106 | }
107 |
108 | /* -------------------------------------
109 | LINKS & BUTTONS
110 | ------------------------------------- */
111 | a {
112 | color: #348eda;
113 | text-decoration: underline;
114 | }
115 |
116 | .btn-primary {
117 | text-decoration: none;
118 | color: #FFF;
119 | background-color: #348eda;
120 | border: solid #348eda;
121 | border-width: 10px 20px;
122 | line-height: 2em;
123 | /* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
124 | /*line-height: 28px;*/
125 | font-weight: bold;
126 | text-align: center;
127 | cursor: pointer;
128 | display: inline-block;
129 | border-radius: 5px;
130 | text-transform: capitalize;
131 | }
132 |
133 | /* -------------------------------------
134 | OTHER STYLES THAT MIGHT BE USEFUL
135 | ------------------------------------- */
136 | .last {
137 | margin-bottom: 0;
138 | }
139 |
140 | .first {
141 | margin-top: 0;
142 | }
143 |
144 | .aligncenter {
145 | text-align: center;
146 | }
147 |
148 | .alignright {
149 | text-align: right;
150 | }
151 |
152 | .alignleft {
153 | text-align: left;
154 | }
155 |
156 | .clear {
157 | clear: both;
158 | }
159 |
160 | /* -------------------------------------
161 | ALERTS
162 | Change the class depending on warning email, good email or bad email
163 | ------------------------------------- */
164 | .alert {
165 | font-size: 16px;
166 | color: #fff;
167 | font-weight: 500;
168 | padding: 20px;
169 | text-align: center;
170 | border-radius: 3px 3px 0 0;
171 | }
172 | .alert a {
173 | color: #fff;
174 | text-decoration: none;
175 | font-weight: 500;
176 | font-size: 16px;
177 | }
178 | .alert.alert-warning {
179 | background-color: #FF9F00;
180 | }
181 | .alert.alert-bad {
182 | background-color: #D0021B;
183 | }
184 | .alert.alert-good {
185 | background-color: #68B90F;
186 | }
187 |
188 | /* -------------------------------------
189 | INVOICE
190 | Styles for the billing table
191 | ------------------------------------- */
192 | .invoice {
193 | margin: 20px auto;
194 | text-align: left;
195 | width: 100%;
196 | }
197 | .invoice td {
198 | padding: 5px 0;
199 | }
200 | .invoice .invoice-items {
201 | width: 100%;
202 | }
203 | .invoice .invoice-items td {
204 | border-top: #eee 1px solid;
205 | }
206 | .invoice .invoice-items .total td {
207 | border-top: 2px solid #333;
208 | border-bottom: 2px solid #333;
209 | font-weight: 700;
210 | }
211 |
--------------------------------------------------------------------------------
/models/Bank.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\models;
9 |
10 | use common\behaviors\UTCDateTimeBehavior;
11 | use Yii;
12 |
13 | /**
14 | * This is the model class for Bank.
15 | *
16 | * @property \MongoDB\BSON\ObjectID|string $id
17 | * @property string $country
18 | * @property string $title
19 | * @property string $info
20 | * @property string $currency
21 | * @property string $status
22 | * @property \MongoDB\BSON\UTCDateTime $created_at
23 | * @property \MongoDB\BSON\UTCDateTime $updated_at
24 | */
25 | class Bank extends \yii\mongodb\ActiveRecord
26 | {
27 |
28 | const STATUS_ACTIVE = 'STATUS_ACTIVE'; //10
29 | const STATUS_INACTIVE = 'STATUS_INACTIVE'; //20
30 |
31 | /**
32 | * @inheritdoc
33 | */
34 | public static function collectionName()
35 | {
36 | return 'billing_bank';
37 | }
38 |
39 | /**
40 | * @return array
41 | */
42 | public function attributes()
43 | {
44 | return [
45 | '_id',
46 | 'country',
47 | 'title',
48 | 'info',
49 | 'currency',
50 | 'status',
51 | 'created_at',
52 | 'updated_at',
53 | ];
54 | }
55 |
56 | /**
57 | * get id
58 | * @return \MongoDB\BSON\ObjectID|string
59 | */
60 | public function getId()
61 | {
62 | return $this->_id;
63 | }
64 |
65 | /**
66 | * @inheritdoc
67 | */
68 | public function behaviors()
69 | {
70 | return [
71 | UTCDateTimeBehavior::class,
72 | ];
73 | }
74 |
75 | /**
76 | * @return int timestamp
77 | */
78 | public function getUpdatedAt()
79 | {
80 | return $this->updated_at->toDateTime()->format('U');
81 | }
82 |
83 | /**
84 | * @return int timestamp
85 | */
86 | public function getCreatedAt()
87 | {
88 | return $this->created_at->toDateTime()->format('U');
89 | }
90 |
91 | /**
92 | * get status list
93 | * @param null $e
94 | * @return array
95 | */
96 | public static function getStatusOption($e = null)
97 | {
98 | $option = [
99 | self::STATUS_ACTIVE => Yii::$app->getModule('billing')->t('Active'),
100 | self::STATUS_INACTIVE => Yii::$app->getModule('billing')->t('Inactive'),
101 | ];
102 | if (is_array($e))
103 | foreach ($e as $i)
104 | unset($option[$i]);
105 | return $option;
106 | }
107 |
108 | /**
109 | * get status text
110 | * @return string
111 | */
112 | public function getStatusText()
113 | {
114 | $status = $this->status;
115 | $list = self::getStatusOption();
116 | if (!empty($status) && in_array($status, array_keys($list))) {
117 | return $list[$status];
118 | }
119 | return Yii::$app->getModule('billing')->t('Unknown');
120 | }
121 |
122 |
123 | /**
124 | * color status text
125 | * @return mixed|string
126 | */
127 | public function getStatusColorText()
128 | {
129 | $status = $this->status;
130 | if ($status == self::STATUS_ACTIVE) {
131 | return '' . $this->statusText . ' ';
132 | }
133 | if ($status == self::STATUS_INACTIVE) {
134 | return '' . $this->statusText . ' ';
135 | }
136 | return $this->statusText;
137 | }
138 |
139 |
140 | /**
141 | * @inheritdoc
142 | */
143 | public function rules()
144 | {
145 | return [
146 | [['country', 'title', 'info', 'currency'], 'required'],
147 | [['info', 'status'], 'string'],
148 | [['country'], 'string', 'max' => 2],
149 | [['title'], 'string', 'max' => 255],
150 | [['currency'], 'string', 'max' => 3],
151 | [['created_at', 'updated_at'], 'yii\mongodb\validators\MongoDateValidator']
152 | ];
153 | }
154 |
155 | /**
156 | * @inheritdoc
157 | */
158 | public function attributeLabels()
159 | {
160 | return [
161 | 'id' => Yii::$app->getModule('billing')->t('ID'),
162 | 'country' => Yii::$app->getModule('billing')->t('Country'),
163 | 'title' => Yii::$app->getModule('billing')->t('Title'),
164 | 'info' => Yii::$app->getModule('billing')->t('Info'),
165 | 'currency' => Yii::$app->getModule('billing')->t('Currency'),
166 | 'status' => Yii::$app->getModule('billing')->t('Status'),
167 | 'created_at' => Yii::$app->getModule('billing')->t('Created At'),
168 | 'updated_at' => Yii::$app->getModule('billing')->t('Updated At'),
169 | ];
170 | }
171 |
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/views/coupon/index.php:
--------------------------------------------------------------------------------
1 | params['breadcrumbs'][] = $this->title;
16 |
17 | /* misc */
18 | $this->registerJs('$(document).on("pjax:send", function(){ $(".grid-view-overlay").removeClass("hidden");});$(document).on("pjax:complete", function(){ $(".grid-view-overlay").addClass("hidden");})');
19 | //$js=file_get_contents(__DIR__.'/index.min.js');
20 | //$this->registerJs($js);
21 | //$css=file_get_contents(__DIR__.'/index.css');
22 | //$this->registerCss($css);
23 | ?>
24 |
25 |
26 |
27 |
28 |
29 | render('_search', ['model' => $searchModel]); ?>
30 |
31 |
32 |
33 |
34 | = GridView::widget([
35 | 'dataProvider' => $dataProvider,
36 | 'filterModel' => $searchModel,
37 | 'columns' => [
38 | ['class' => 'yii\grid\SerialColumn'],
39 | 'code',
40 | [
41 | 'attribute' => 'discount',
42 | 'value' => function ($model) {
43 | return $model->discount_type == Coupon::DISCOUNT_TYPE_PERCENT ? Yii::$app->formatter->asPercent($model->discount / 100) : Yii::$app->formatter->asCurrency($model->discount, $model->currency);
44 | }
45 | ],
46 | [
47 | 'attribute' => 'begin_at',
48 | 'value' => 'beginAt',
49 | 'format' => 'date',
50 | 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'begin_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']]),
51 | 'contentOptions' => ['style' => 'min-width: 80px']
52 | ],
53 | [
54 | 'attribute' => 'end_at',
55 | 'value' => 'endAt',
56 | 'format' => 'date',
57 | 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'end_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']]),
58 | 'contentOptions' => ['style' => 'min-width: 80px']
59 | ],
60 | [
61 | 'attribute' => 'quantity',
62 | 'value' => function ($model) {
63 | return $model->quantity == -1 ? Yii::$app->getModule('billing')->t('Unlimited') : Yii::$app->formatter->asDecimal($model->quantity);
64 | },
65 | ],
66 | //'',
67 | // 'reuse',
68 | // 'status',
69 | // 'created_at',
70 | // 'updated_at',
71 | //[
72 | // 'attribute' => 'created_at',
73 | // 'value' => 'created_at',
74 | // 'format' => 'dateTime',
75 | // 'filter' => DatePicker::widget(['model' => $searchModel, 'attribute' => 'created_at', 'dateFormat' => 'yyyy-MM-dd', 'options' => ['class' => 'form-control']]),
76 | // 'contentOptions'=>['style'=>'min-width: 80px']
77 | //],
78 | ['attribute' => 'status', 'value' => function ($model) {
79 | return $model->statusColorText;
80 | }, 'filter' => Coupon::getStatusOption(), 'format' => 'raw'],
81 | [
82 | 'class' => 'yii\grid\ActionColumn',
83 | 'contentOptions' => ['style' => 'min-width: 70px']
84 | ],
85 | ],
86 | ]); ?>
87 |
88 |
89 |
90 | = Html::a(Yii::t('billing', 'Add Coupon'), ['create'], ['class' => 'btn btn-success']) ?>
91 |
92 |
93 |
94 |
95 |
96 | = \powerkernel\fontawesome\Icon::widget(['name' => 'sync', 'styling'=>'fa-spin']) ?>
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/views/bitcoin/payment.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 | use powerkernel\fontawesome\Icon;
8 | use yii\bootstrap\Tabs;
9 | use yii\helpers\Html;
10 | \common\plugins\moment\MomentAsset::register($this);
11 |
12 | /* @var $this yii\web\View */
13 | /* @var $invoice \powerkernel\billing\models\Invoice */
14 | /* @var $bitcoin [] */
15 |
16 | $this->params['breadcrumbs'][] = $this->title;
17 |
18 | /* misc */
19 | $js = file_get_contents(__DIR__ . '/payment.min.js');
20 | $this->registerJs($js);
21 | //$css=file_get_contents(__DIR__.'/index.css');
22 | //$this->registerCss($css);
23 | ?>
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 | = Yii::$app->getModule('billing')->t('Pay for invoice #{INVOICE}', ['INVOICE' => $invoice->id_invoice]) ?>
38 |
39 |
40 |
= Yii::$app->formatter->asDecimal($invoice->total) ?> = $invoice->currency ?>
41 |
= $bitcoin['amount'] ?> BTC
42 |
43 |
44 |
45 |
46 | = Icon::widget(['icon'=>'refresh fa-spin']) ?>
47 | = Yii::$app->getModule('billing')->t('Waiting payment...') ?>
48 |
49 |
50 |
51 |
52 |
53 | = Icon::widget(['icon'=>'check']) ?>
54 | = Yii::$app->getModule('billing')->t('Payment received!') ?>
55 |
56 |
57 | = Html::a(Yii::$app->getModule('billing')->t('Return'), $invoice->getInvoiceUrl(), ['title' => Yii::$app->getModule('billing')->t('Return'), 'class' => 'btn btn-lg btn-primary']) ?>
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | =
66 | Tabs::widget([
67 | 'options' => ['class' => 'nav nav-tabs nav-justified'],
68 | 'items' => [
69 | [
70 |
71 | 'active' => true,
72 | 'label' => Yii::$app->getModule('billing')->t('Scan'),
73 | 'content' => $this->render('_scan', ['bitcoin' => $bitcoin])
74 |
75 | ],
76 | [
77 |
78 | 'label' => Yii::$app->getModule('billing')->t('Copy'),
79 | 'content' => $this->render('_copy', ['bitcoin' => $bitcoin])
80 | ],
81 |
82 | ],
83 | ]);
84 | ?>
85 |
86 |
87 |
88 | = Html::a(Yii::$app->getModule('billing')->t('Open in Wallet').' '. Icon::widget(['icon'=>'external-link']), $bitcoin['url'], ['title' => Yii::$app->getModule('billing')->t('Open in Wallet'), 'class' => 'btn btn-lg btn-primary']) ?>
89 |
90 |
91 |
92 |
93 | = Yii::$app->getModule('billing')->t('Payment expired!') ?>
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/mail/new-invoice-user-html.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | = Yii::$app->getModule('billing')->t('Dear {NAME},', ['NAME'=>$model->account->fullname]) ?>
28 |
29 |
30 |
31 |
32 | = Yii::$app->getModule('billing')->t('Thank you for placing your order with us! Your total amount due is {TOTAL}. More details about your purchase are included below.', ['TOTAL'=>Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | = Yii::$app->getModule('billing')->t('Invoice #{ID}', ['ID'=>$model->id_invoice]) ?>
41 |
42 |
43 | items as $item):?>
44 |
45 |
46 | = Yii::$app->getModule('billing')->t(' - {ITEM}: {PRICE}', ['ITEM'=>$item->name, 'PRICE'=>Yii::$app->formatter->asCurrency($item->price, $model->currency)]) ?>
47 |
48 |
49 |
50 | = Yii::$app->getModule('billing')->t('Shipping: {SHIP}', ['SHIP' => Yii::$app->formatter->asCurrency($model->shipping, $model->currency)]) ?>
51 | = Yii::$app->getModule('billing')->t('Tax: {TAX}', ['TAX' => Yii::$app->formatter->asCurrency($model->tax, $model->currency)]) ?>
52 | = Yii::$app->getModule('billing')->t('Total: {TOTAL}', ['TOTAL' => Yii::$app->formatter->asCurrency($model->total, $model->currency)]) ?>
53 |
54 |
55 |
56 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/models/Address.php:
--------------------------------------------------------------------------------
1 | _id;
69 | }
70 |
71 | /**
72 | * @inheritdoc
73 | */
74 | public function behaviors()
75 | {
76 | return [
77 | UTCDateTimeBehavior::class,
78 | ];
79 | }
80 |
81 | /**
82 | * @return int timestamp
83 | */
84 | public function getUpdatedAt()
85 | {
86 | return $this->updated_at->toDateTime()->format('U');
87 | }
88 |
89 | /**
90 | * @return int timestamp
91 | */
92 | public function getCreatedAt()
93 | {
94 | return $this->created_at->toDateTime()->format('U');
95 | }
96 |
97 | /**
98 | * get status list
99 | * @param null $e
100 | * @return array
101 | */
102 | public static function getStatusOption($e = null)
103 | {
104 | $option = [
105 | self::STATUS_ACTIVE => Yii::$app->getModule('billing')->t('Active'),
106 | self::STATUS_INACTIVE => Yii::$app->getModule('billing')->t('Inactive'),
107 | ];
108 | if (is_array($e))
109 | foreach ($e as $i)
110 | unset($option[$i]);
111 | return $option;
112 | }
113 |
114 | /**
115 | * get status text
116 | * @return string
117 | */
118 | public function getStatusText()
119 | {
120 | $status = $this->status;
121 | $list = self::getStatusOption();
122 | if (!empty($status) && in_array($status, array_keys($list))) {
123 | return $list[$status];
124 | }
125 | return Yii::$app->getModule('billing')->t('Unknown');
126 | }
127 |
128 |
129 | /**
130 | * color status text
131 | * @return mixed|string
132 | */
133 | public function getStatusColorText()
134 | {
135 | $status = $this->status;
136 | if ($status == self::STATUS_ACTIVE) {
137 | return '' . $this->statusText . ' ';
138 | }
139 | if ($status == self::STATUS_INACTIVE) {
140 | return '' . $this->statusText . ' ';
141 | }
142 | return $this->statusText;
143 | }
144 |
145 |
146 | /**
147 | * @inheritdoc
148 | */
149 | public function rules()
150 | {
151 | return [
152 | [['street_address_2', 'zip_code'], 'default', 'value' => null],
153 | [['country', 'contact_name', 'street_address_1', 'city', 'phone'], 'required'],
154 |
155 | [['country', 'contact_name', 'street_address_1', 'street_address_2', 'city', 'state', 'zip_code', 'phone', 'status'], 'string'],
156 | [['street_address_2', 'zip_code', 'state'], 'safe'],
157 | [['created_at', 'updated_at'], 'yii\mongodb\validators\MongoDateValidator'],
158 | [['id_account'], 'string']
159 | ];
160 | }
161 |
162 | /**
163 | * @inheritdoc
164 | */
165 | public function attributeLabels()
166 | {
167 | return [
168 | '_id' => 'ID',
169 | 'id_account' => Yii::$app->getModule('billing')->t('Account'),
170 | 'country' => Yii::$app->getModule('billing')->t('Country'),
171 | 'contact_name' => Yii::$app->getModule('billing')->t('Contact Name'),
172 | 'street_address_1' => Yii::$app->getModule('billing')->t('Street Address 1'),
173 | 'street_address_2' => Yii::$app->getModule('billing')->t('Street Address 2'),
174 | 'city' => Yii::$app->getModule('billing')->t('City'),
175 | 'state' => Yii::$app->getModule('billing')->t('State'),
176 | 'zip_code' => Yii::$app->getModule('billing')->t('Zip Code'),
177 | 'phone' => Yii::$app->getModule('billing')->t('Phone'),
178 | 'status' => Yii::$app->getModule('billing')->t('Status'),
179 | 'created_at' => Yii::$app->getModule('billing')->t('Created At'),
180 | 'updated_at' => Yii::$app->getModule('billing')->t('Updated At'),
181 | ];
182 | }
183 |
184 | /**
185 | * @inheritdoc
186 | * @param bool $insert
187 | * @return bool
188 | */
189 | public function beforeSave($insert)
190 | {
191 | if ($insert) {
192 | if (empty($this->id_account)) {
193 | $this->id_account = Yii::$app->user->id;
194 | }
195 | }
196 | return parent::beforeSave($insert); // TODO: Change the autogenerated stub
197 | }
198 |
199 | /**
200 | * @return \yii\db\ActiveQueryInterface
201 | */
202 | public function getAccount()
203 | {
204 | return $this->hasOne(Account::class, ['_id' => 'id_account']);
205 | }
206 |
207 | /**
208 | * get user shipping addresses
209 | * @param $id_account
210 | * @return array
211 | */
212 | public static function getAddressDataList($id_account)
213 | {
214 | $addresses = self::find()->where(['id_account' => $id_account])->all();
215 | $data = [];
216 | foreach ($addresses as $address) {
217 | $data[(string)$address->id] = '' . $address->contact_name . ' ';
218 | $data[(string)$address->id] .= ' ' . $address->street_address_1;
219 | if (!empty($address->street_address_2)) {
220 | $data[(string)$address->id] .= ' ' . $address->street_address_2;
221 | }
222 | $data[(string)$address->id] .= ' ' . $address->city . ', ' . $address->state . ' ' . $address->zip_code;
223 | $data[(string)$address->id] .= ' ' . Core::getCountryText($address->country);
224 | $data[(string)$address->id] .= ' ' . $address->phone;
225 | }
226 | return $data;
227 | }
228 |
229 | }
230 |
--------------------------------------------------------------------------------
/models/Coupon.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\models;
9 |
10 | use common\behaviors\UTCDateTimeBehavior;
11 | use Yii;
12 |
13 | /**
14 | * This is the model class for Coupon.
15 | *
16 | * @property \MongoDB\BSON\ObjectID|string $id
17 | * @property string $code
18 | * @property string $currency
19 | * @property float $discount
20 | * @property string $discount_type
21 | * @property \MongoDB\BSON\UTCDateTime $begin_at
22 | * @property \MongoDB\BSON\UTCDateTime $end_at
23 | * @property integer $quantity
24 | * @property integer $reuse
25 | * @property string $status
26 | * @property \MongoDB\BSON\UTCDateTime $created_at
27 | * @property \MongoDB\BSON\UTCDateTime $updated_at
28 | */
29 | class Coupon extends \yii\mongodb\ActiveRecord
30 | {
31 | const STATUS_ACTIVE = 'STATUS_ACTIVE'; // 10;
32 | const STATUS_INACTIVE = 'STATUS_INACTIVE'; // 20;
33 |
34 | const DISCOUNT_TYPE_PERCENT = 'DISCOUNT_TYPE_PERCENT'; // 10;
35 | const DISCOUNT_TYPE_VALUE = 'DISCOUNT_TYPE_VALUE'; // 20
36 |
37 | public $begin_date_picker;
38 | public $end_date_picker;
39 |
40 | /**
41 | * @inheritdoc
42 | */
43 | public static function collectionName()
44 | {
45 | return 'billing_coupon';
46 | }
47 |
48 | /**
49 | * @return array
50 | */
51 | public function attributes()
52 | {
53 | return [
54 | '_id',
55 | 'code',
56 | 'currency',
57 | 'discount',
58 | 'discount_type',
59 | 'begin_at',
60 | 'end_at',
61 | 'quantity',
62 | 'reuse',
63 | 'status',
64 | 'created_at',
65 | 'updated_at',
66 | ];
67 | }
68 |
69 | /**
70 | * get id
71 | * @return \MongoDB\BSON\ObjectID|string
72 | */
73 | public function getId()
74 | {
75 | return $this->_id;
76 | }
77 |
78 | /**
79 | * @inheritdoc
80 | */
81 | public function behaviors()
82 | {
83 | return [
84 | UTCDateTimeBehavior::class,
85 | ];
86 | }
87 |
88 | /**
89 | * @return int timestamp
90 | */
91 | public function getUpdatedAt()
92 | {
93 | return $this->updated_at->toDateTime()->format('U');
94 | }
95 |
96 | /**
97 | * @return int timestamp
98 | */
99 | public function getCreatedAt()
100 | {
101 | return $this->created_at->toDateTime()->format('U');
102 | }
103 |
104 | /**
105 | * @return int timestamp
106 | */
107 | public function getBeginAt()
108 | {
109 | return $this->begin_at->toDateTime()->format('U');
110 | }
111 |
112 | /**
113 | * @return int timestamp
114 | */
115 | public function getEndAt()
116 | {
117 | return $this->end_at->toDateTime()->format('U');
118 | }
119 |
120 | /**
121 | * get discount options
122 | * @param null $e
123 | * @return array
124 | */
125 | public static function getDiscountOption($e = null)
126 | {
127 | $option = [
128 | self::DISCOUNT_TYPE_PERCENT => Yii::$app->getModule('billing')->t('Percent'),
129 | self::DISCOUNT_TYPE_VALUE => Yii::$app->getModule('billing')->t('Value'),
130 | ];
131 | if (is_array($e))
132 | foreach ($e as $i)
133 | unset($option[$i]);
134 | return $option;
135 | }
136 |
137 | /**
138 | * get discount text
139 | * @return mixed
140 | */
141 | public function getDiscountText()
142 | {
143 | $type = $this->discount_type;
144 | $list = self::getDiscountOption();
145 | if (!empty($type) && in_array($type, array_keys($list))) {
146 | return $list[$type];
147 | }
148 | return Yii::$app->getModule('billing')->t('Unknown');
149 | }
150 |
151 | /**
152 | * get status list
153 | * @param null $e
154 | * @return array
155 | */
156 | public static function getStatusOption($e = null)
157 | {
158 | $option = [
159 | self::STATUS_ACTIVE => Yii::$app->getModule('billing')->t('Active'),
160 | self::STATUS_INACTIVE => Yii::$app->getModule('billing')->t('Inactive'),
161 | ];
162 | if (is_array($e))
163 | foreach ($e as $i)
164 | unset($option[$i]);
165 | return $option;
166 | }
167 |
168 | /**
169 | * get status text
170 | * @return string
171 | */
172 | public function getStatusText()
173 | {
174 | $status = $this->status;
175 | $list = self::getStatusOption();
176 | if (!empty($status) && in_array($status, array_keys($list))) {
177 | return $list[$status];
178 | }
179 | return Yii::$app->getModule('billing')->t('Unknown');
180 | }
181 |
182 | /**
183 | * get status color text
184 | * @return string
185 | */
186 | public function getStatusColorText()
187 | {
188 | $status = $this->status;
189 | $list = self::getStatusOption();
190 |
191 | $color = 'default';
192 | if ($status == self::STATUS_ACTIVE) {
193 | $color = 'primary';
194 | }
195 | if ($status == self::STATUS_INACTIVE) {
196 | $color = 'danger';
197 | }
198 |
199 | if (!empty($status) && in_array($status, array_keys($list))) {
200 | return '' . $list[$status] . ' ';
201 | }
202 | return '' . Yii::$app->getModule('billing')->t('Unknown') . ' ';
203 | }
204 |
205 |
206 | /**
207 | * @inheritdoc
208 | */
209 | public function rules()
210 | {
211 | return [
212 | [['code', 'currency', 'discount', 'discount_type', 'begin_at', 'end_at', 'quantity', 'reuse', 'status'], 'required'],
213 | [['code'], 'unique'],
214 | //[['discount'], 'number'],
215 | [['quantity', 'reuse'], 'integer'],
216 | [['code'], 'string', 'max' => 50],
217 | [['begin_date_picker', 'end_date_picker'], 'required', 'on' => ['create']],
218 | [['end_at'], 'compare', 'compareAttribute' => 'begin_at', 'operator' => '>='],
219 | [['created_at', 'updated_at'], 'yii\mongodb\validators\MongoDateValidator'],
220 | [['begin_at'], 'yii\mongodb\validators\MongoDateValidator', 'format' => 'MM/dd/yyyy', 'mongoDateAttribute' => 'begin_at'],
221 | [['end_at'], 'yii\mongodb\validators\MongoDateValidator', 'format' => 'MM/dd/yyyy', 'mongoDateAttribute' => 'end_at']
222 | ];
223 | }
224 |
225 | /**
226 | * @inheritdoc
227 | */
228 | public function attributeLabels()
229 | {
230 | return [
231 | 'code' => Yii::$app->getModule('billing')->t('Code'),
232 | 'currency' => Yii::$app->getModule('billing')->t('Currency'),
233 | 'discount' => Yii::$app->getModule('billing')->t('Discount'),
234 | 'discount_type' => Yii::$app->getModule('billing')->t('Discount Type'),
235 | 'begin_at' => Yii::$app->getModule('billing')->t('Begin Date'),
236 | 'end_at' => Yii::$app->getModule('billing')->t('End Date'),
237 | 'quantity' => Yii::$app->getModule('billing')->t('Quantity'),
238 | 'reuse' => Yii::$app->getModule('billing')->t('Reuse'),
239 | 'status' => Yii::$app->getModule('billing')->t('Status'),
240 | 'created_at' => Yii::$app->getModule('billing')->t('Created At'),
241 | 'updated_at' => Yii::$app->getModule('billing')->t('Updated At'),
242 | /* custom */
243 | 'begin_date_picker' => Yii::$app->getModule('billing')->t('Begin Date'),
244 | 'end_date_picker' => Yii::$app->getModule('billing')->t('End Date'),
245 | ];
246 | }
247 |
248 | /**
249 | * @inheritdoc
250 | * @return bool
251 | */
252 | public function beforeSave($insert)
253 | {
254 | $this->discount = (float)$this->discount;
255 | $this->quantity = (int)$this->quantity;
256 | $this->reuse = (int)$this->reuse;
257 | return parent::beforeSave($insert); // TODO: Change the autogenerated stub
258 | }
259 |
260 |
261 | }
262 |
--------------------------------------------------------------------------------
/controllers/SettingController.php:
--------------------------------------------------------------------------------
1 |
4 | * @link https://powerkernel.com
5 | * @copyright Copyright (c) 2017 Power Kernel
6 | */
7 |
8 | namespace powerkernel\billing\controllers;
9 |
10 | use backend\controllers\BackendController;
11 | use common\Core;
12 | use powerkernel\billing\models\Setting;
13 | use Yii;
14 | use yii\base\DynamicModel;
15 |
16 | /**
17 | * SettingController
18 | */
19 | class SettingController extends BackendController
20 | {
21 | /**
22 | * setting page
23 | * @return string
24 | */
25 | public function actionIndex(){
26 | $attributes = Setting::loadAsArray();
27 | $tabs=Setting::find()->asArray()->distinct('group');
28 |
29 | $model=new DynamicModel($attributes);
30 | $settings = [];
31 |
32 | foreach ($attributes as $key=>$value) {
33 | $setting = Setting::find()->where(['key' => $key])->asArray()->one();
34 | $settings[$setting['group']][$key] = $setting;
35 | $model->$key = $setting['value'];
36 |
37 | if (!empty($rules = json_decode($setting['rules'], true))) {
38 | foreach ($rules as $rule => $conf) {
39 | $model->addRule($key, $rule, $conf);
40 | }
41 | } else {
42 | $model->addRule($key, 'required');
43 | }
44 |
45 | }
46 |
47 |
48 |
49 | if ($model->load(Yii::$app->request->post()) && $model->validate()) {
50 | foreach ($attributes as $key=>$oldValue) {
51 | $s = Setting::find()->where(['key'=>$key])->one();
52 | $s->value = $model->$key;
53 | if (!$s->save(false)) {
54 | Yii::$app->session->setFlash('error', Yii::t('billing', 'Sorry, something went wrong. {ERRORS}.', ['ERRORS' => json_encode($s->errors)]));
55 | break;
56 | }
57 | }
58 | Yii::$app->session->setFlash('success', Yii::t('billing', 'Settings saved successfully.'));
59 | }
60 |
61 |
62 | return $this->render('index', [
63 | 'model' => $model,
64 | 'settings' => $settings,
65 | 'tabs' => $tabs
66 | ]);
67 | }
68 |
69 | /**
70 | * update settings
71 | * @return \yii\web\Response
72 | */
73 | public function actionUpdate(){
74 | $s = [
75 | /* Merchant */
76 | ['key' => 'merchantName', 'value' => '', 'title' => 'Merchant Name', 'description' => 'Merchant name', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
77 | ['key' => 'merchantAddress', 'value' => '', 'title' => 'Merchant Address', 'description' => 'Merchant address', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
78 | ['key' => 'merchantCity', 'value' => '', 'title' => 'Merchant City', 'description' => 'Merchant city', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
79 | ['key' => 'merchantState', 'value' => '', 'title' => 'Merchant State', 'description' => 'Merchant state', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
80 | ['key' => 'merchantZip', 'value' => '', 'title' => 'Merchant Zip', 'description' => 'Merchant zip code', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
81 | ['key' => 'merchantCountry', 'value' => '', 'title' => 'Merchant Country', 'description' => 'Merchant country', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required'=>[], 'string' => []])],
82 | ['key' => 'merchantPhone', 'value' => '', 'title' => 'Merchant Phone', 'description' => 'Merchant phone', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'string' => []])],
83 | ['key' => 'merchantEmail', 'value' => '', 'title' => 'Merchant Email', 'description' => 'Merchant email', 'group' => 'Merchant', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['required' => [], 'email' => []])],
84 |
85 | /* Paypal */
86 | ['key' => 'paypalEmail', 'value' => '', 'title' => 'Paypal Email', 'description' => 'Paypal email address', 'group' => 'Paypal', 'type' => 'textInput', 'data' => json_encode(Core::getYesNoOption()), 'default' => '', 'rules' => json_encode(['string' => [], 'email' => []])],
87 | ['key' => 'paypalSandbox', 'value' => '', 'title' => 'Paypal Sandbox Mode', 'description' => 'Set yes to enable sandbox', 'group' => 'Paypal', 'type' => 'dropDownList', 'data' => json_encode(Core::getYesNoOption()), 'default' => '1', 'rules' => json_encode(['required' => [], 'boolean' => []])],
88 | ['key' => 'paypalClientID', 'value' => '', 'title' => 'Paypal Client ID', 'description' => 'Live client ID', 'group' => 'Paypal', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
89 | ['key' => 'paypalSecret', 'value' => '', 'title' => 'Paypal Secret', 'description' => 'Live secret string', 'group' => 'Paypal', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
90 | ['key' => 'paypalSandboxClientID', 'value' => '', 'title' => 'Paypal Sandbox Client ID', 'description' => 'Sandbox client ID', 'group' => 'Paypal', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
91 | ['key' => 'paypalSandboxSecret', 'value' => '', 'title' => 'Paypal Sandbox Secret', 'description' => 'Sandbox secret string', 'group' => 'Paypal', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
92 |
93 | /* Bitcoin */
94 | ['key' => 'btcPaymentTime', 'value' => '', 'title' => 'BTC Payment Timeout', 'description' => 'Payment timeout in seconds', 'group' => 'Bitcoin', 'type' => 'textInput', 'data' => '[]', 'default' => '900', 'rules' => json_encode(['integer' => ['min'=>300, 'max'=>3600]])],
95 | ['key' => 'btcWalletXPub', 'value' => '', 'title' => 'BTC Wallet xPub', 'description' => 'Wallet extended public key', 'group' => 'Bitcoin', 'type' => 'textInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
96 |
97 | /* order API */
98 | ['key' => 'currencyLayerAPI', 'value' => '', 'title' => 'Currency Layer API', 'description' => 'Access API key for currency conversion', 'group' => 'MISC', 'type' => 'passwordInput', 'data' => '[]', 'default' => '', 'rules' => json_encode(['string' => []])],
99 |
100 |
101 | ];
102 | $settings = Setting::find()->all();
103 | foreach ($settings as $setting) {
104 | if (!in_array($setting->key, array_column($s, 'key'))) {
105 | $setting->delete();
106 | }
107 | }
108 |
109 | /* sync */
110 | $unsave=[];
111 | foreach ($s as $i => $setting) {
112 | $conf = Setting::find()->where(['key'=>$setting['key']])->one();
113 | if (!$conf) {
114 | $conf = new Setting();
115 | $conf->key = $setting['key'];
116 | $conf->value = $setting['value'];
117 | }
118 |
119 | $conf->title = $setting['title'];
120 | $conf->group = $setting['group'];
121 | $conf->type = $setting['type'];
122 | $conf->data = $setting['data'];
123 | $conf->default = $setting['default'];
124 | $conf->rules = $setting['rules'];
125 | $conf->key_order = (int)$i;
126 | if(!$conf->save()){
127 | $unsave[]=$conf->key;
128 | //var_dump($conf->errors);
129 | }
130 | }
131 |
132 | if(is_a(Yii::$app, '\yii\web\Application')){
133 | if(empty($unsave)){
134 | Yii::$app->session->setFlash('success', Yii::t('app', 'All settings has been updated.'));
135 | }
136 | else {
137 | Yii::$app->session->setFlash('warning', Yii::t('app', 'Some setting(s) can not be updated: {SETTINGS}', ['SETTINGS'=>implode(', ', $unsave)]));
138 | }
139 | }
140 |
141 | return $this->redirect(['index']);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------