├── runtime └── .gitignore ├── tests ├── _data │ └── .gitignore ├── _output │ └── .gitignore ├── acceptance │ ├── _bootstrap.php │ ├── SigninFailCept.php │ ├── lead │ │ ├── DeleteLeadCept.php │ │ ├── UpdateLeadCept.php │ │ ├── ViewLeadDetailCept.php │ │ ├── CreateLeadCept.php │ │ ├── ConvertLeadWithoutOpportunityCept.php │ │ └── ConvertLeadWithNewOpportunityCept.php │ └── SigninCept.php ├── functional │ ├── _bootstrap.php │ ├── LoginFormCest.php │ └── ContactFormCest.php ├── unit │ ├── _bootstrap.php │ └── models │ │ ├── UserTest.php │ │ ├── LoginFormTest.php │ │ └── ContactFormTest.php ├── _support │ ├── Helper │ │ ├── Selenium_opera.php │ │ ├── Acceptance_opera.php │ │ └── Acceptance_selenium.php │ ├── FunctionalTester.php │ ├── UnitTester.php │ ├── AcceptanceTester.php │ └── Acceptance_seleniumTester.php ├── _bootstrap.php ├── unit.suite.yml ├── bin │ ├── yii.bat │ └── yii ├── acceptance_selenium.suite.yml ├── codeception.yml ├── functional.suite.yml └── acceptance.suite.yml ├── web ├── assets │ └── .gitignore ├── robots.txt ├── images │ ├── contact │ │ ├── .gitignore │ │ ├── bohr.jpg │ │ ├── razi.jpg │ │ ├── alhazen.jpg │ │ ├── blank.jpg │ │ ├── khaldun.jpg │ │ ├── maxwell.jpg │ │ ├── newton.jpg │ │ ├── planck.jpg │ │ ├── qurra.jpg │ │ ├── einstein.jpg │ │ ├── khwarizmi.jpg │ │ ├── schroedinger.jpg │ │ └── 1155ecee4aa6cc6b9333e1a6c8c5a4b94.jpg │ ├── vine.png │ ├── twitter.png │ ├── youtube.png │ ├── facebook.png │ ├── googleplus.png │ ├── instagram.png │ ├── linkedin.png │ └── pinterest.png ├── favicon.ico ├── index.php ├── .htaccess ├── index-test.php ├── Yii.php └── server-configuration.php ├── .bowerrc ├── 0_screenshots_0 ├── 02-home-page.png ├── 00-responsive.png ├── 01-login-page.png ├── 05-lead-edit-page.png ├── 03-leads-main-page.png ├── 04-leads-view-page.png ├── 07-contact-view-page.png ├── 06-contacts-main-page.png ├── 11-dropdown-management.png ├── 08-report-lead-bar-chart.png ├── 09-report-contact-pie-chart.png └── 10-report-opportunity-3D-donut.png ├── views ├── _assets │ └── css │ │ ├── images │ │ ├── ui-icons_2694e8_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_3d80b3_256x240.png │ │ ├── ui-icons_72a7cf_256x240.png │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── ui-bg_flat_15_cd0a0a_40x100.png │ │ ├── ui-bg_glass_100_e4f1fb_1x400.png │ │ ├── ui-bg_glass_50_3baae3_1x400.png │ │ ├── ui-bg_glass_80_d7ebf9_1x400.png │ │ ├── ui-bg_highlight-hard_70_000000_1x100.png │ │ ├── ui-bg_highlight-soft_25_ffef8f_1x100.png │ │ ├── ui-bg_diagonals-thick_90_eeeeee_40x40.png │ │ ├── ui-bg_highlight-hard_100_f2f5f7_1x100.png │ │ └── ui-bg_highlight-soft_100_deedf7_1x100.png │ │ └── site.css ├── lead │ ├── create.php │ ├── update.php │ └── _search.php ├── site │ ├── create-user.php │ ├── update-user.php │ ├── error.php │ ├── requestPasswordResetToken.php │ ├── resetPassword.php │ ├── login.php │ ├── _form-user.php │ ├── update-identity.php │ ├── list-users.php │ └── contact.php ├── account │ ├── create.php │ ├── update.php │ ├── account-change-helper.php │ ├── _search.php │ └── index.php ├── contact │ ├── create.php │ ├── update.php │ ├── _search.php │ └── opportunity-list.php ├── opportunity │ ├── create.php │ ├── update.php │ ├── _search.php │ ├── _form.php │ ├── contact-list.php │ ├── index.php │ └── contact-form.php ├── activity │ ├── create.php │ ├── update.php │ ├── _search.php │ └── index.php ├── commons │ ├── change-helper-search-form.php │ ├── change-helper-search-results-multi.php │ ├── change-helper-search-results.php │ ├── change-owner.php │ ├── desc-owner-timestamps.php │ ├── related-list-account.php │ ├── social-media-links.php │ ├── related-list-opportunity.php │ ├── related-list-contact.php │ └── related-list-activity.php ├── layouts │ └── admin.php └── report │ ├── report-3d_donut.php │ ├── index.php │ └── report-pie_chart.php ├── controllers ├── restv1 │ ├── ContactsController.php │ ├── LeadsController.php │ └── BaseRestController.php └── ReportController.php ├── config ├── params.php ├── db.php ├── db-prod.php ├── db-stage.php ├── console.php └── test.php ├── helpers ├── SameOwnerRule.php └── CrmActionColumn.php ├── mail ├── site │ ├── identityUpdate-text.php │ ├── passwordResetToken-text.php │ ├── identityUpdate-html.php │ └── passwordResetToken-html.php └── layouts │ ├── text.php │ └── html.php ├── assets ├── ReportsAsset.php └── AppAsset.php ├── yii.bat ├── migrations ├── m171022_011750_alter_table_opportunities_remove_contactid.php ├── m151102_000902_create_users_table.php ├── m151122_173332_create_lookup_rating.php ├── m160125_031538_create_relation_opportunity_account.php ├── m151122_103678_create_table_update_history.php ├── m151122_170621_create_lookup_activity_priority.php ├── m160127_213855_create_relation_contact_social_media.php ├── m160131_213855_create_relation_account_social_media.php ├── m151122_172433_create_lookup_contact_type.php ├── m151102_000902_seed_users_table.php ├── m151122_172941_create_lookup_lead_status.php ├── m151122_163446_create_lookup_account_ownership.php ├── m151122_173225_create_lookup_opportunity_type.php ├── m151122_170751_create_lookup_activity_status.php ├── m151122_084907_create_table_activities.php ├── m151122_173735_create_lookup_salutation.php ├── m151122_171247_create_lookup_activity_type.php ├── m151122_173120_create_lookup_opportunity_stage.php ├── m151122_170331_create_lookup_account_type.php └── m151122_172814_create_lookup_lead_source.php ├── .gitignore ├── commands └── HelloController.php ├── models ├── LookupForm.php ├── ActivityMorph.php ├── SignupForm.php ├── OpportunityContact.php ├── OpportunitySearch.php ├── ActivitySearch.php ├── ContactForm.php ├── ResetPasswordRequestForm.php ├── AccountSearch.php ├── ResetPasswordForm.php ├── IdentityForm.php ├── LoginForm.php └── LeadSearch.php ├── yii ├── codeception.yml ├── LICENSE.md ├── composer.json └── translations └── message-config-en.php /runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'admin@'.$serverDomain, 7 | 'supportEmail' => 'support@'.$serverDomain, 8 | 'user.passwordResetTokenExpire' => 60 * 60 * 24, 9 | ]; 10 | -------------------------------------------------------------------------------- /helpers/SameOwnerRule.php: -------------------------------------------------------------------------------- 1 | owner_id; 16 | } 17 | } -------------------------------------------------------------------------------- /mail/site/identityUpdate-text.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/login']); 5 | 6 | ?> 7 | Hello name) ?>, 8 | 9 | Your password was changed recently. 10 | 11 | Click to login with your new password. 12 | 13 | Thank you! 14 | -------------------------------------------------------------------------------- /config/db.php: -------------------------------------------------------------------------------- 1 | 'yii\db\Connection', 5 | 'dsn' => 'mysql:host=localhost;dbname=crm_yii', 6 | 'username' => 'crm-yii', 7 | 'password' => 'crm-yii-pass', 8 | 'charset' => 'utf8', 9 | 'enableSchemaCache' => true, 10 | 'schemaCacheDuration' => 600 * 24, 11 | 'schemaCache' => 'cache', 12 | ]; 13 | -------------------------------------------------------------------------------- /mail/layouts/text.php: -------------------------------------------------------------------------------- 1 | 6 | beginPage() ?> 7 | beginBody() ?> 8 | 9 | endBody() ?> 10 | endPage() ?> -------------------------------------------------------------------------------- /web/index.php: -------------------------------------------------------------------------------- 1 | run(); 13 | -------------------------------------------------------------------------------- /config/db-prod.php: -------------------------------------------------------------------------------- 1 | 'yii\db\Connection', 5 | 'dsn' => 'mysql:host=localhost;dbname=crm_yii_prod', 6 | 'username' => 'crm-yii-prod', 7 | 'password' => 'crm-yii-prod-pass', 8 | 'charset' => 'utf8', 9 | 'enableSchemaCache' => true, 10 | 'schemaCacheDuration' => 600 * 24, 11 | 'schemaCache' => 'cache', 12 | ]; 13 | -------------------------------------------------------------------------------- /config/db-stage.php: -------------------------------------------------------------------------------- 1 | 'yii\db\Connection', 5 | 'dsn' => 'mysql:host=localhost;dbname=crm_yii_stage', 6 | 'username' => 'crm-yii-stage', 7 | 'password' => 'crm-yii-stage-pass', 8 | 'charset' => 'utf8', 9 | 'enableSchemaCache' => true, 10 | 'schemaCacheDuration' => 600 * 24, 11 | 'schemaCache' => 'cache', 12 | ]; 13 | -------------------------------------------------------------------------------- /mail/site/passwordResetToken-text.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); 5 | 6 | ?> 7 | Hello name) ?>, 8 | 9 | You requested a new password. 10 | 11 | Please click to reset your password. 12 | 13 | Thank you! 14 | 15 | -------------------------------------------------------------------------------- /mail/site/identityUpdate-html.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/login']); 5 | 6 | ?> 7 |
8 | 9 | Hello name) ?>,

10 | 11 | Your password was changed recently.

12 | 13 | Click to login with your new password. 14 | 15 | Thank you! 16 | 17 |
18 | -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | # 2 | Allow from all 3 | # 4 | 5 | Options -Multiviews 6 | Options +FollowSymLinks 7 | 8 | RewriteEngine On 9 | RewriteBase / 10 | 11 | # Redirect Trailing Slashes... 12 | RewriteRule ^(.*)/$ /$1 [L,R=301] 13 | 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteCond %{REQUEST_FILENAME} !-d 16 | RewriteRule . /index.php [L] 17 | 18 | 19 | -------------------------------------------------------------------------------- /mail/site/passwordResetToken-html.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); 5 | 6 | ?> 7 |
8 | 9 | Hello name) ?>,

10 | 11 | You requested a new password.

12 | 13 | Please click to reset your password. 14 | 15 | Thank you! 16 | 17 |
18 | -------------------------------------------------------------------------------- /views/lead/create.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'Lead'); 5 | 6 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Lead'), 'url' => ['index']]; 7 | $this->params['breadcrumbs'][]=$this->title; 8 | ?> 9 | 10 |
11 |

title ?>

12 | render('_form', ['model' => $model,])?> 13 |
14 | -------------------------------------------------------------------------------- /views/site/create-user.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'User'); 5 | 6 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'User'), 'url' => ['index']]; 7 | $this->params['breadcrumbs'][]=$this->title; 8 | ?> 9 |
10 |

title ?>

11 | render('_form-user', ['model' => $model, ])?> 12 |
-------------------------------------------------------------------------------- /views/site/update-user.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Update User'); 7 | 8 | $this->params['breadcrumbs'][] = ['label' => Yii::t('main', 'User'), 'url' => ['index']]; 9 | $this->params['breadcrumbs'][] = $this->title; 10 | ?> 11 |
12 |

title ?>

13 | render('_form-user', ['model' => $model, ]) ?> 14 |
-------------------------------------------------------------------------------- /tests/acceptance/SigninFailCept.php: -------------------------------------------------------------------------------- 1 | am('User'); 5 | $I->wantTo('Enter bad credentials'); 6 | $I->lookForwardTo('See login error message'); 7 | 8 | $I->amOnPage('/'); 9 | $I->fillField('#loginform-username', 'garbage'); 10 | $I->fillField('#loginform-password', 'garbage'); 11 | $I->click('//*[@id="form-login"]/div[4]/div[1]/button'); 12 | $I->dontSee('Hello, Basic User!'); 13 | $I->see('Incorrect username or password.'); 14 | -------------------------------------------------------------------------------- /views/account/create.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'Account'); 6 | 7 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Account'), 'url' => ['index']]; 8 | $this->params['breadcrumbs'][]=$this->title; 9 | ?> 10 | 11 |
12 |

title ?>

13 | render('_form', ['model' => $model,])?> 14 |
15 | -------------------------------------------------------------------------------- /views/contact/create.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'Contact'); 6 | 7 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Contact'), 'url' => ['index']]; 8 | $this->params['breadcrumbs'][]=$this->title; 9 | ?> 10 | 11 |
12 |

title ?>

13 | render('_form', ['model' => $model, ])?> 14 |
15 | -------------------------------------------------------------------------------- /assets/ReportsAsset.php: -------------------------------------------------------------------------------- 1 | \yii\web\View::POS_BEGIN]; 11 | 12 | public $css = [ 13 | ]; 14 | 15 | public $js = [ 16 | 'js/d3.min.js', 17 | 'js/d3.tip.js', 18 | 'js/d3.pie.js', 19 | 'js/d3.donut3d.js', 20 | ]; 21 | 22 | public $depends = [ 23 | ]; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /views/opportunity/create.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'Opportunity'); 5 | 6 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Opportunity'), 'url' => ['index']]; 7 | $this->params['breadcrumbs'][]=$this->title; 8 | ?> 9 |
10 |

title ?>

11 | render('_form', ['model' => $model, ])?> 12 |
13 | -------------------------------------------------------------------------------- /tests/acceptance/lead/DeleteLeadCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 7 | $I->wantTo('Delete a lead'); 8 | $I->expectTo('See lead is deleted'); 9 | 10 | $I->amOnPage('/lead/1'); 11 | $I->seeInCurrentUrl('/lead/1'); 12 | $I->see('Name: Mr. Bill Gates'); 13 | 14 | $I->click('#lead-delete-btn'); 15 | 16 | $I->seeInCurrentUrl('/lead/index'); 17 | $I->see('Record deleted successfully.', $successMessageBox); 18 | -------------------------------------------------------------------------------- /views/activity/create.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'New') . Yii::t('main', 'Activity'); 5 | 6 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Activity'), 'url' => ['index']]; 7 | $this->params['breadcrumbs'][]=$this->title; 8 | ?> 9 | 10 |
11 |

title ?>

12 | render('_form', ['model' => $model, 'controller' => $controller])?> 13 |
14 | -------------------------------------------------------------------------------- /views/site/error.php: -------------------------------------------------------------------------------- 1 | title = $name; 11 | ?> 12 |
13 | 14 |

15 | 16 |
17 | 18 |
19 | 20 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for unit (internal) tests. 4 | # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. 5 | 6 | class_name: UnitTester 7 | modules: 8 | enabled: 9 | - Asserts 10 | - Yii2: 11 | part: [orm, email] 12 | - Db: 13 | dsn: 'mysql:host=localhost;dbname=crm_yii;charset=utf8' 14 | user: 'crm-yii' 15 | password: 'crm-yii-pass' 16 | dump: tests/_data/seeder.sql 17 | populate: true 18 | cleanup: true 19 | reconnect: false 20 | -------------------------------------------------------------------------------- /yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 17 | -------------------------------------------------------------------------------- /tests/bin/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /tests/acceptance_selenium.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: AcceptanceTester 2 | modules: 3 | enabled: 4 | - WebDriver: 5 | url: http://local.crm-yii.com/ 6 | browser: firefox 7 | - Yii2: 8 | part: orm 9 | # entryScript: index-test.php 10 | # cleanup: false 11 | - Db: 12 | dsn: 'mysql:host=localhost;dbname=crm_yii;charset=utf8' 13 | user: 'crm-yii' 14 | password: 'crm-yii-pass' 15 | dump: tests/_data/seeder.sql 16 | populate: true 17 | cleanup: true 18 | reconnect: false 19 | -------------------------------------------------------------------------------- /tests/acceptance/SigninCept.php: -------------------------------------------------------------------------------- 1 | am('User'); 9 | $I->wantTo('Login to website'); 10 | $I->lookForwardTo('Access all website features'); 11 | $I->amOnPage("/site/login"); 12 | $I->see('DEV_Server', '#serverDecal'); 13 | 14 | $I->fillField('#loginform-username', 'user@crm-yii.com'); 15 | $I->fillField('#loginform-password', 'user123'); 16 | $I->click('//*[@id="form-login"]/div[4]/div[1]/button'); 17 | $I->see('Hello, Basic User!'); 18 | -------------------------------------------------------------------------------- /views/account/update.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Edit') . Yii::t('main', 'Account') . ' - ' . $model->name; 8 | 9 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Account'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][]=['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][]=Yii::t('main', 'Update'); 12 | ?> 13 | 14 |
15 |

title) ?>

16 | render('_form', [ 'model' => $model, ])?> 17 |
18 | -------------------------------------------------------------------------------- /controllers/restv1/LeadsController.php: -------------------------------------------------------------------------------- 1 | checkAccess('convert', $lead, null); 16 | 17 | $model=new LeadConvertForm(); 18 | $result=$model->convert($lead, "post"); 19 | 20 | if ($result==null || $result[0]=='') 21 | throw new BadRequestHttpException(); 22 | 23 | return $result; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /views/activity/update.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Edit') . Yii::t('main', 'Activity') . ' - ' . $model->subject; 8 | 9 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Activity'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][]=['label' => $model->subject, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][]=Yii::t('main', 'Update'); 12 | ?> 13 | 14 |
15 |

title) ?>

16 | render('_form', [ 'model' => $model,])?> 17 |
18 | -------------------------------------------------------------------------------- /tests/codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | paths: 3 | tests: tests 4 | log: tests/_output 5 | data: tests/_data 6 | support: tests/_support 7 | envs: tests/_envs 8 | settings: 9 | bootstrap: _bootstrap.php 10 | colors: true 11 | memory_limit: 1024M 12 | extensions: 13 | enabled: 14 | - Codeception\Extension\RunFailed 15 | modules: 16 | config: 17 | Db: 18 | dsn: 'mysql:host=localhost;dbname=crm_yii;charset=utf8' 19 | user: 'crm-yii' 20 | password: 'crm-yii-pass' 21 | dump: tests/_data/seeder.sql 22 | populate: true 23 | cleanup: true 24 | reconnect: false 25 | -------------------------------------------------------------------------------- /views/opportunity/update.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Edit') . Yii::t('main', 'Opportunity') . ' - ' . $model->name; 8 | 9 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Opportunity'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][]=['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][]=Yii::t('main', 'Update'); 12 | ?> 13 |
14 |

title) ?>

15 | render('_form', ['model' => $model,])?> 16 |
17 | -------------------------------------------------------------------------------- /migrations/m171022_011750_alter_table_opportunities_remove_contactid.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 12 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 13 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 14 | } 15 | 16 | $this->dropColumn("{{%opportunities}}", "contact_id"); 17 | } 18 | 19 | public function down() 20 | { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/_support/FunctionalTester.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Edit') . Yii::t('main', 'Lead') . ' - ' . $model->first_name . ' ' . $model->last_name; 8 | 9 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Lead'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][]=['label' => $model->title, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][]=Yii::t('main', 'Update'); 12 | ?> 13 | 14 |
15 |

title) ?>

16 | render('_form', ['model' => $model,])?> 17 |
18 | -------------------------------------------------------------------------------- /tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for functional (integration) tests. 4 | # emulate web requests and make application process them. 5 | # (tip: better to use with frameworks). 6 | 7 | # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. 8 | #basic/web/index.php 9 | class_name: FunctionalTester 10 | modules: 11 | enabled: 12 | - Filesystem 13 | - Yii2 14 | - Db: 15 | dsn: 'mysql:host=localhost;dbname=crm_yii;charset=utf8' 16 | user: 'crm-yii' 17 | password: 'crm-yii-pass' 18 | dump: tests/_data/seeder.sql 19 | populate: true 20 | cleanup: true 21 | reconnect: false 22 | -------------------------------------------------------------------------------- /views/contact/update.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Edit') . Yii::t('main', 'Contact') . ' - ' . $model->first_name . ' ' . $model->last_name; 8 | 9 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Contact'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][]=['label' => $model->title, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][]=Yii::t('main', 'Update'); 12 | ?> 13 | 14 |
15 |

title) ?>

16 | render('_form', ['model' => $model, ])?> 17 |
18 | -------------------------------------------------------------------------------- /tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | 8 | beginPage() ?> 9 | 10 | 11 | 12 | 13 | <?= Html::encode($this->title) ?> 14 | head() ?> 15 | 16 | 17 | beginBody() ?> 18 | 19 | endBody() ?> 20 | 21 | 22 | endPage() ?> 23 | -------------------------------------------------------------------------------- /tests/bin/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | [ 21 | 'db' => require(__DIR__ . '/../../config/test_db.php') 22 | ] 23 | ] 24 | ); 25 | 26 | 27 | $application = new yii\console\Application($config); 28 | $exitCode = $application->run(); 29 | exit($exitCode); -------------------------------------------------------------------------------- /commands/HelloController.php: -------------------------------------------------------------------------------- 1 | 18 | * @since 2.0 19 | */ 20 | class HelloController extends Controller 21 | { 22 | /** 23 | * This command echoes what you have entered as the message. 24 | * @param string $message the message to be echoed. 25 | */ 26 | public function actionIndex($message = 'hello world') 27 | { 28 | echo $message . "\n"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /models/LookupForm.php: -------------------------------------------------------------------------------- 1 | 255], 22 | [['id', 'idxpos'], 'integer']]; 23 | } 24 | 25 | public function attributeLabels() 26 | { 27 | return [ 28 | 'tableName'=>Yii::t('main', 'Dropdown Name'), 29 | 'value'=>Yii::t('main', 'Value'), 30 | 'idxpos'=>Yii::t('main', 'Ordering'), 31 | 'description'=>Yii::t('main', 'Tooltip'), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/AppAsset.php: -------------------------------------------------------------------------------- 1 | 14 | * @since 2.0 15 | */ 16 | class AppAsset extends AssetBundle 17 | { 18 | public $sourcePath = '@app/views/_assets'; 19 | 20 | public $css = [ 21 | 'css/site.css', 22 | 'css/jquery-ui.min.css', 23 | 'css/jquery.datetimepicker.css', 24 | 'css/site-overrides.css', 25 | ]; 26 | 27 | public $js = [ 28 | 'js/jquery-ui.min.js', 29 | 'js/date-functions.js', 30 | 'js/jquery.datetimepicker.min.js', 31 | 'js/site.js', 32 | ]; 33 | 34 | public $depends = [ 35 | 'yii\web\YiiAsset', 36 | 'yii\bootstrap\BootstrapAsset', 37 | ]; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 27 | exit($exitCode); 28 | -------------------------------------------------------------------------------- /views/commons/change-helper-search-form.php: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |
8 | 9 | 20 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | paths: 3 | tests: tests 4 | log: tests/_output 5 | data: tests/_data 6 | helpers: tests/_support 7 | settings: 8 | bootstrap: _bootstrap.php 9 | memory_limit: 1024M 10 | colors: true 11 | modules: 12 | config: 13 | Yii2: 14 | configFile: 'config/test.php' 15 | cleanup: false 16 | 17 | # To enable code coverage: 18 | #coverage: 19 | # #c3_url: http://localhost:8080/index-test.php/ 20 | # enabled: true 21 | # #remote: true 22 | # #remote_config: '../tests/codeception.yml' 23 | # whitelist: 24 | # include: 25 | # - models/* 26 | # - controllers/* 27 | # - commands/* 28 | # - mail/* 29 | # blacklist: 30 | # include: 31 | # - assets/* 32 | # - config/* 33 | # - runtime/* 34 | # - vendor/* 35 | # - views/* 36 | # - web/* 37 | # - tests/* 38 | -------------------------------------------------------------------------------- /views/layouts/admin.php: -------------------------------------------------------------------------------- 1 | context; 7 | $menus = $controller->module->menus; 8 | $route = $controller->route; 9 | foreach ($menus as $i => $menu) { 10 | $menus[$i]['active'] = strpos($route, trim($menu['url'][0], '/')) === 0; 11 | } 12 | $this->params['nav-items'] = $menus; 13 | 14 | ?> 15 |
16 |
17 | 'glyphicon glyphicon-chevron-right pull-right']) . 20 | Html::tag('span', Html::encode($menu['label']), []); 21 | $active = $menu['active'] ? ' active' : ''; 22 | echo Html::a($label, $menu['url'], [ 23 | 'class' => 'list-group-item' . $active, 24 | ]); 25 | } 26 | ?> 27 |
28 | appHelper->getRandomColor(); 7 | 8 | $jsonData=str_ireplace('"color"', 'color', json_encode($data)); 9 | 10 | ?> 11 | 27 | 28 | -------------------------------------------------------------------------------- /helpers/CrmActionColumn.php: -------------------------------------------------------------------------------- 1 | user; 23 | $this->template=''; 24 | 25 | if ($user->can('Update '.$model->modelClassName(), [$model])==true) 26 | { 27 | //$this->template.='{view}  '; 28 | $this->template.='{update}' . ($model->deleted_at ? '  ' : '  {delete}'); 29 | } 30 | 31 | return parent::renderDataCellContent($model, $key, $index); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /models/ActivityMorph.php: -------------------------------------------------------------------------------- 1 | Yii::t('main', 'ID'), 26 | 'activity_id' => Yii::t('main', 'Activity'), 27 | 'related_id' => Yii::t('main', 'Relates To'), 28 | 'related_type_id' => Yii::t('main', ''), 29 | 'owner_id' => Yii::t('main', 'Owner'), 30 | 'adder_id' => Yii::t('main', 'Added By'), 31 | 'modifier_id' => Yii::t('main', 'Modified By'), 32 | 'deleted_at' => Yii::t('main', 'Deleted At'), 33 | 'created_at' => Yii::t('main', 'Added At'), 34 | 'updated_at' => Yii::t('main', 'Updated At')]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/acceptance/lead/UpdateLeadCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 6 | $I->wantTo('Update an existing lead'); 7 | $I->expectTo('See lead\'s birth date updated'); 8 | 9 | $I->amOnPage('/lead/1'); 10 | $I->click('#lead-edit-btn'); 11 | 12 | $I->seeInCurrentUrl('/lead/update/1'); 13 | $I->seeInField('#lead-first_name', 'Bill'); 14 | $I->seeInField('#lead-last_name', 'Gates'); 15 | $I->seeInField('#lead-email', 'bill@microsoft.com'); 16 | 17 | $birthDate=date('Y-m-').str_pad(rand(1, 28), 2, '0', STR_PAD_LEFT); 18 | $I->fillField('#lead-birthdate', $birthDate); 19 | $I->click('#lead-save-btn'); 20 | 21 | // check update result 22 | $I->seeInCurrentUrl('/lead/1'); 23 | $I->see('Record saved successfully.', $successMessageBox); 24 | $I->see('Birthdate: '.$birthDate); 25 | 26 | // test cancel button 27 | $I->amOnPage('/lead/1'); 28 | $I->click('#lead-edit-btn'); 29 | $I->seeInCurrentUrl('/lead/update/1'); 30 | $I->click('#cancel-btn'); 31 | $I->seeInCurrentUrl('/lead/1'); 32 | -------------------------------------------------------------------------------- /tests/acceptance/lead/ViewLeadDetailCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 5 | $I->amOnPage('/lead/1'); 6 | $I->wantTo('See a lead\'s detail information'); 7 | $I->expectTo('See lead detail page with lead data'); 8 | 9 | 10 | $I->see('Lead Detail - Bill Gates', 'div.pageTitle'); 11 | $I->see('Name: Mr. Bill Gates'); 12 | $I->see('Company: Microsoft'); 13 | $I->see('Title: Retired'); 14 | $I->see('Industry: Agriculture'); 15 | $I->see('Email: bill@microsoft.com'); 16 | $I->see('Phone: 357-634-0488'); 17 | $I->see('Rating: Hot'); 18 | $I->see('Annual Revenue: 6000000000'); 19 | $I->see('Num. Of Employees: 35344'); 20 | $I->see('Website: http://www.microsoft.com'); 21 | $I->see('Lead Source: Web'); 22 | $I->see('Lead Status: Open - Not Contacted'); 23 | $I->see('Description: Used to be CEO now doing charity work'); 24 | $I->see('Owner: Basic User'); 25 | $I->see('Added By: Admin User'); 26 | $I->see('Modified By: Admin User'); 27 | 28 | // check buttons 29 | $I->seeLink('Edit'); 30 | $I->seeLink('Delete'); 31 | $I->seeLink('Convert'); 32 | $I->seeLink('Add New'); 33 | -------------------------------------------------------------------------------- /views/site/requestPasswordResetToken.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Request password reset'); 12 | //$this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 'reset-password-request-form', 'action'=>Url::to(['site/reset-password-request']), 'options'=> ['class'=>'form-horizontal form-one-half']]); ?> 22 |
23 |
24 |
25 |
26 | 27 |
28 | field($model, 'email', $tt1ColInSm) ?> 29 |
30 | 31 |
32 | 'btn btn-primary']) ?> 33 |
34 | 35 | 36 |
37 | -------------------------------------------------------------------------------- /views/commons/change-helper-search-results-multi.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | render('../commons/change-helper-search-form', ['controller' => $controller]) ?> 6 | 7 |
8 | 9 | searchResults)) 12 | { 13 | $output.=' 14 | '; 15 | 16 | if (count($controller->searchResults)) 17 | { 18 | foreach ($controller->searchResults as $result) 19 | $output.=' 20 | 21 | '; 22 | 23 | if ($controller->tooManyResults === true) 24 | $output.=''; 25 | } 26 | else 27 | $output.=''; 28 | } 29 | 30 | echo $output; 31 | ?> 32 |
' . Yii::t('main', 'Search Results') . '
' .Html::checkbox("idList[]", (empty($result['!']) ? false : true), ["value" => $result['id'], "class" => "idListCBox"]) . '' . Html::encode($result['name']) . '

' . Yii::t('main', 'Search returned too many results.') . '
' . Yii::t('main', 'NO_RECORDS_FOUND') . '
33 |
34 | -------------------------------------------------------------------------------- /config/console.php: -------------------------------------------------------------------------------- 1 | 'basic-console', 10 | 'basePath' => dirname(__DIR__), 11 | 'bootstrap' => ['log', 'gii'], 12 | 'controllerNamespace' => 'app\commands', 13 | 'modules' => [ 14 | 'gii' => 'yii\gii\Module', 15 | ], 16 | 'components' => [ 17 | 'cache' => [ 18 | 'class' => 'yii\caching\FileCache', 19 | ], 20 | 'log' => [ 21 | 'targets' => [ 22 | [ 23 | 'class' => 'yii\log\FileTarget', 24 | 'levels' => ['error', 'warning'], 25 | ], 26 | ], 27 | ], 28 | 'db' => $db, 29 | 'authManager' => ['class' => 'yii\rbac\DbManager'], 30 | 'appHelper' => [ 31 | 'class' => 'app\helpers\AppHelper' 32 | ], 33 | 'i18n' => [ 34 | 'translations' => [ 35 | 'main' => [ 36 | 'class' => 'yii\i18n\PhpMessageSource', 37 | 'basePath' => '@app/translations', // if advanced application, set @frontend/messages 38 | 'sourceLanguage' => 'en', 39 | 'fileMap' => [ 40 | 'main' => 'main.php' 41 | ] 42 | ] 43 | ] 44 | ], 45 | ], 46 | 'params' => $params, 47 | ]; 48 | -------------------------------------------------------------------------------- /controllers/restv1/BaseRestController.php: -------------------------------------------------------------------------------- 1 | HttpBearerAuth::className()]; 17 | 18 | return $behaviors; 19 | } 20 | 21 | public function checkAccess($action, $model=null, $params=[]) 22 | { 23 | if ($model) 24 | { 25 | $checkModel=[$model]; 26 | 27 | if (in_array($model->modelClassName(), ['Lead', 'LeadConvertForm']) && $model->converted_at) 28 | throw new BadRequestHttpException(Yii::t('main', 'LEAD_WAS_CONVERTED')); 29 | 30 | if (Yii::$app->user->can('/' . strtolower($model->modelClassName()) . '/*', $checkModel) && 31 | (Yii::$app->user->can('Update ' . $model->modelClassName(), $checkModel) || Yii::$app->user->can(ucfirst($action) . ' ' . $model->modelClassName(), $checkModel))) 32 | return; 33 | 34 | throw new UnauthorizedHttpException(Yii::t('main', 'UNAUTHORIZED_TO_ACCESS')); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /views/contact/_search.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 36 | -------------------------------------------------------------------------------- /views/account/account-change-helper.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Select Account'); 9 | 10 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Account'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][]=$this->title; 12 | ?> 13 | 14 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | render('../commons/search-helper-alphabet-shortcuts', ['formId' => 'changeAccountForm', 'searchId'=>'keyword'])?> 25 | 26 | render('../commons/change-helper-search-results', ['controller' => $controller, 'jsFunction'=>'updateAccountParentWindow', 'param1'=>Html::encode($accIdx)])?> 27 |
28 | 29 | -------------------------------------------------------------------------------- /views/account/_search.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 36 | -------------------------------------------------------------------------------- /tests/unit/models/UserTest.php: -------------------------------------------------------------------------------- 1 | username)->equals('admin@crm-yii.com'); 11 | 12 | expect_not(User::findIdentity(999)); 13 | } 14 | 15 | public function testFindUserByAccessToken() 16 | { 17 | expect_that($user = User::findIdentityByAccessToken('rest1api2token3admin')); 18 | expect($user->username)->equals('admin@crm-yii.com'); 19 | 20 | expect_not(User::findIdentityByAccessToken('non-existing')); 21 | } 22 | 23 | public function testFindUserByUsername() 24 | { 25 | expect_that($user = User::findByUsername('admin@crm-yii.com')); 26 | expect_not(User::findByUsername('not-admin')); 27 | } 28 | 29 | /** 30 | * @depends testFindUserByUsername 31 | */ 32 | public function testValidateUser($user) 33 | { 34 | $user = User::findByUsername('admin@crm-yii.com'); 35 | expect_that($user->validateAuthKey($user->getAuthKey())); 36 | expect_not($user->validateAuthKey('test102key')); 37 | 38 | expect_that($user->validatePassword('admin123')); 39 | expect_not($user->validatePassword('123456')); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /views/commons/change-helper-search-results.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | render('../commons/change-helper-search-form', ['controller' => $controller]) ?> 6 | 7 |
8 | 9 | searchResults)) 16 | { 17 | $output.=' 18 | '; 19 | 20 | if (count($controller->searchResults)) 21 | { 22 | foreach ($controller->searchResults as $result) 23 | { 24 | $name=Html::encode($result['name']); 25 | $nameJs=Html::encode(addslashes($result['name'])); 26 | 27 | $output.=<< 31 | EOT; 32 | } 33 | 34 | if ($controller->tooManyResults === true) 35 | $output.=''; 36 | } 37 | else 38 | $output.=''; 39 | } 40 | 41 | echo $output; 42 | ?> 43 |
' . Yii::t('main', 'Search Results') . '
29 | $name 30 |

' . Yii::t('main', 'Search returned too many results.') . '
' . Yii::t('main', 'NO_RECORDS_FOUND') . '
44 |
-------------------------------------------------------------------------------- /views/site/resetPassword.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Reset password'); 12 | //$this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |
15 | 16 | 17 | 18 | 19 | 20 | 'reset-password-form', 'action' => Url::to(['site/reset-password']), 'options' => ['class'=>'form-horizontal form-one-half']]); ?> 21 | 22 |
23 |
24 |
25 |
26 | field($model, 'password', $tt1ColInSm)->passwordInput() ?> 27 | field($model, 'password_repeat', $tt1ColInSm)->passwordInput() ?> 28 |
29 | 30 |
31 | 'btn btn-primary']) ?> 32 |
33 | 34 | 35 |
36 | -------------------------------------------------------------------------------- /views/lead/_search.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 40 | -------------------------------------------------------------------------------- /tests/unit/models/LoginFormTest.php: -------------------------------------------------------------------------------- 1 | user->logout(); 15 | } 16 | 17 | public function testLoginNoUser() 18 | { 19 | $this->model = new LoginForm([ 20 | 'username' => 'not_existing_username', 21 | 'password' => 'not_existing_password', 22 | ]); 23 | 24 | expect_not($this->model->login()); 25 | expect_that(\Yii::$app->user->isGuest); 26 | } 27 | 28 | public function testLoginWrongPassword() 29 | { 30 | $this->model = new LoginForm([ 31 | 'username' => 'demo', 32 | 'password' => 'wrong_password', 33 | ]); 34 | 35 | expect_not($this->model->login()); 36 | expect_that(\Yii::$app->user->isGuest); 37 | expect($this->model->errors)->hasKey('password'); 38 | } 39 | 40 | public function testLoginCorrect() 41 | { 42 | $this->model = new LoginForm([ 43 | 'username' => 'admin@crm-yii.com', 44 | 'password' => 'admin123', 45 | ]); 46 | 47 | expect_that($this->model->login()); 48 | expect_not(\Yii::$app->user->isGuest); 49 | expect($this->model->errors)->hasntKey('password'); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /models/SignupForm.php: -------------------------------------------------------------------------------- 1 | 'trim'], ['username', 'required'], 22 | ['username', 'unique', 'targetClass'=>'\common\models\User', 'message'=>Yii::t('main', 'This username has already been taken.')], 23 | ['username', 'string', 'min'=>2, 'max'=>255], ['email', 'filter', 'filter'=>'trim'], ['email', 'required'], 24 | ['email', 'email'], ['email', 'string', 'max'=>255], 25 | ['email', 'unique', 'targetClass'=>'\common\models\User', 'message'=>Yii::t('main', 'This email address has already been taken.')], 26 | ['password', 'required'], ['password', 'string', 'min'=>6]]; 27 | } 28 | 29 | /** 30 | * Signs user up. 31 | * 32 | * @return User|null the saved model or null if saving fails 33 | */ 34 | public function signup() 35 | { 36 | if ($this->validate()) 37 | { 38 | $user=new User(); 39 | $user->username=$this->username; 40 | $user->email=$this->email; 41 | $user->setPassword($this->password); 42 | $user->generateAuthKey(); 43 | if ($user->save()) 44 | { 45 | return $user; 46 | } 47 | } 48 | 49 | return null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /views/activity/_search.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 40 | -------------------------------------------------------------------------------- /views/opportunity/_search.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /views/site/login.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Login'); 11 | //$this->params['breadcrumbs'][]=$this->title; 12 | ?> 13 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/acceptance/lead/CreateLeadCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 6 | $I->wantTo('Create a new lead'); 7 | $I->expectTo('See new lead created successfully'); 8 | 9 | $I->amOnPage('/lead/create'); 10 | $I->submitForm('#w0', 11 | ['Lead[salutation_id]'=>'6', 12 | 'Lead[first_name]'=>'Immanuel', 13 | 'Lead[last_name]'=>'Kant', 14 | 'Lead[company]'=>'Enlightenment Philosophy Inc.', 15 | 'Lead[industry_id]'=>'9', 16 | 'Lead[email]'=>'kant@felossoffar.edu', 17 | 'Lead[lead_source_id]'=>'7', 18 | 'Lead[description]'=>'Enlightenment is man\'s emergence from his self-imposed nonage. Nonage is the inability to use one\'s own understanding without another\'s guidance. This nonage is self-imposed if its cause lies not in lack of understanding but in indecision and lack of courage to use one\'s own mind without another\'s guidance. Dare to know! (Sapere aude.) "Have the courage to use your own understanding," is therefore the motto of the enlightenment.']); 19 | 20 | $I->seeInCurrentUrl('/lead/5'); 21 | $I->see('Record saved successfully.', $successMessageBox); 22 | $I->see('Lead Detail - Immanuel Kant'); 23 | $I->see('Name: Prof. Immanuel Kant'); 24 | $I->see('Company: Enlightenment Philosophy Inc.'); 25 | $I->see('Industry: Education'); 26 | $I->see('Email: kant@felossoffar.edu'); 27 | $I->see('Lead Source: Other'); 28 | $I->see('Description: Enlightenment is man\'s emergence from his self-imposed nonage'); 29 | $I->see('Owner: Basic User'); 30 | $I->see('Added By: Basic User'); 31 | $I->see('Modified By: Basic User'); -------------------------------------------------------------------------------- /tests/unit/models/ContactFormTest.php: -------------------------------------------------------------------------------- 1 | model = $this->getMockBuilder('app\models\ContactForm') 19 | ->setMethods(['validate']) 20 | ->getMock(); 21 | 22 | $this->model->expects($this->once()) 23 | ->method('validate') 24 | ->will($this->returnValue(true)); 25 | 26 | $this->model->attributes = [ 27 | 'name' => 'Tester', 28 | 'email' => 'tester@example.com', 29 | 'subject' => 'very important letter subject', 30 | 'body' => 'body of current message', 31 | ]; 32 | 33 | expect_that($this->model->contact('admin@example.com')); 34 | 35 | // using Yii2 module actions to check email was sent 36 | $this->tester->seeEmailIsSent(); 37 | 38 | $emailMessage = $this->tester->grabLastSentEmail(); 39 | expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); 40 | expect($emailMessage->getTo())->hasKey('admin@example.com'); 41 | expect($emailMessage->getFrom())->hasKey('tester@example.com'); 42 | expect($emailMessage->getSubject())->equals('very important letter subject'); 43 | expect($emailMessage->toString())->contains('body of current message'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /views/commons/change-owner.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Change Owner'); 12 | 13 | $this->params['breadcrumbs'][] = Yii::t('main', $model->modelClassName()); 14 | $this->params['breadcrumbs'][] = Yii::t('main', 'Change Owner'); 15 | 16 | $recordName=Html::encode(isset($model->name) ? $model->name : (isset($model->subject) ? $model->subject : $model->first_name.' '.$model->last_name)); 17 | 18 | $controller=strtolower($model->modelClassName()); 19 | ?> 20 | 21 | ['class'=>'form-horizontal'], 'action'=>[$controller.'/saveowner', 'id'=>$model->id]] ); ?> 22 | 23 | 24 | 25 |
26 | 27 | 28 |
29 | 30 |
31 | field($model, 'owner_id', $tt1ColInOwner)->dropDownList(Yii::$app->appHelper->getLookupData('users')) ?> 32 |
33 | 34 |
35 | 36 |
37 | 'btn btn-primary']) ?> 38 | $model->id]), ['class' => 'btn btn-success']) ?> 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /models/OpportunityContact.php: -------------------------------------------------------------------------------- 1 | 'function(attribute, value) { return ($("#formSubmit").val()=="save") ? true : false; }']]; 21 | } 22 | 23 | /** 24 | * @inheritdoc 25 | */ 26 | public function attributeLabels() 27 | { 28 | return ['id' => Yii::t('main', 'ID'), 29 | 'opportunity_id' => Yii::t('main', 'Opportunity'), 30 | 'contact_id' => Yii::t('main', 'Related Contact'), 31 | 'stage_id' => Yii::t('main', 'Stage'), 32 | 'owner_id' => Yii::t('main', 'Owner'), 33 | 'adder_id' => Yii::t('main', 'Added By'), 34 | 'modifier_id' => Yii::t('main', 'Modified By'), 35 | 'deleted_at' => Yii::t('main', 'Deleted At'), 36 | 'created_at' => Yii::t('main', 'Added At'), 37 | 'updated_at' => Yii::t('main', 'Updated At')]; 38 | } 39 | 40 | public function getOpportunity() 41 | { 42 | return $this->hasOne('app\models\Opportunity', ['id' => 'opportunity_id'])->where('deleted_at is null'); 43 | } 44 | 45 | public function getContact() 46 | { 47 | return $this->hasOne('app\models\Contact', ['id' => 'contact_id'])->where('deleted_at is null'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/acceptance/lead/ConvertLeadWithoutOpportunityCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 5 | $I->wantTo('Convert a lead to a contact without opportunity'); 6 | $I->expectTo('See lead converted to a contact'); 7 | 8 | 9 | $I->amOnPage('/lead/1'); 10 | $I->see('Lead Detail - Bill Gates', 'div.pageTitle'); 11 | $I->seeLink('Convert'); 12 | $I->click('#lead-convert-btn'); 13 | 14 | $I->seeInCurrentUrl('lead/convert/1'); 15 | 16 | $I->see('Convert Lead - Bill Gates'); 17 | $I->see('Account Name'); 18 | $I->seeInField('LeadConvertForm[account_name]', 'Microsoft'); 19 | $I->see('There are similar accounts in the system. If you want to add the lead to an existing account, please select it from the dropdown list below. Otherwise a new account with the company name will be created.'); 20 | $I->see('Create New Opportunity?'); 21 | $I->selectOption('LeadConvertForm[new_opportunity]', '0'); 22 | $I->click('#lead-convert-btn'); 23 | 24 | // conversion success 25 | $I->seeInCurrentUrl('/contact/15'); 26 | $I->see('Contact Detail - Bill Gates', 'div.pageTitle'); 27 | $I->see('Name: Mr. Bill Gates'); 28 | $I->see('Email: bill@microsoft.com'); 29 | $I->see('Phone: 357-634-0488'); 30 | $I->see('Description: Used to be CEO now doing charity work'); 31 | $I->see('Owner: Basic User'); 32 | $I->see('Added By: Basic User'); 33 | $I->see('Modified By: Basic User'); 34 | 35 | // lead is not accessible 36 | $I->wantTo('Ensure converted lead is not accessible'); 37 | $I->expectTo('See lead was converted to contact error messsage'); 38 | $I->amOnPage('/lead/1'); 39 | $I->see('Lead was converted to contact', $errorMessageBox); 40 | -------------------------------------------------------------------------------- /tests/functional/LoginFormCest.php: -------------------------------------------------------------------------------- 1 | amOnRoute('site/login'); 9 | } 10 | 11 | public function openLoginPage(\FunctionalTester $I) 12 | { 13 | $I->see('Login', 'div.pageTitle'); 14 | } 15 | 16 | // demonstrates `amLoggedInAs` method 17 | public function internalLoginById(\FunctionalTester $I) 18 | { 19 | $I->amLoggedInAs(1); 20 | $I->amOnPage('/'); 21 | $I->see('Admin User'); 22 | } 23 | 24 | // demonstrates `amLoggedInAs` method 25 | public function internalLoginByInstance(\FunctionalTester $I) 26 | { 27 | $I->amLoggedInAs(\app\models\User::findByUsername('admin@crm-yii.com')); 28 | $I->amOnPage('/'); 29 | $I->see('Admin User'); 30 | } 31 | 32 | public function loginWithEmptyCredentials(\FunctionalTester $I) 33 | { 34 | $I->submitForm('#form-login', []); 35 | $I->expectTo('see validations errors'); 36 | $I->see('Username cannot be blank.'); 37 | $I->see('Password cannot be blank.'); 38 | } 39 | 40 | public function loginWithWrongCredentials(\FunctionalTester $I) 41 | { 42 | $I->submitForm('#form-login', ['LoginForm[username]' => 'admin@crm-yii.com', 'LoginForm[password]' => 'wrong']); 43 | $I->expectTo('see validations errors'); 44 | $I->see('Incorrect username or password.'); 45 | } 46 | 47 | public function loginSuccessfully(\FunctionalTester $I) 48 | { 49 | $I->submitForm('#form-login', ['LoginForm[username]' => 'admin@crm-yii.com', 'LoginForm[password]' => 'admin123']); 50 | $I->see('Admin User'); 51 | $I->dontSeeElement('form#form-login'); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The Yii framework is free software. It is released under the terms of 2 | the following BSD License. 3 | 4 | Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | * Neither the name of Yii Software LLC nor the names of its 18 | contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /config/test.php: -------------------------------------------------------------------------------- 1 | 'basic-tests', 10 | 'basePath' => dirname(__DIR__), 11 | 'language' => 'en-US', 12 | 'components' => [ 13 | 'cache' => [ 14 | 'class' => 'yii\caching\FileCache', 15 | ], 16 | 'db' => $dbParams, 17 | 'mailer' => [ 18 | 'useFileTransport' => true, 19 | ], 20 | 'assetManager' => [ 21 | 'basePath' => __DIR__ . '/../web/assets', 22 | ], 23 | 'urlManager' => [ 24 | 'showScriptName' => true, 25 | ], 26 | 'appHelper' => [ 27 | 'class' => 'app\helpers\AppHelper' 28 | ], 29 | 'user' => [ 30 | 'identityClass' => 'app\models\User', 31 | ], 32 | 'request' => [ 33 | 'cookieValidationKey' => 'test', 34 | 'enableCsrfValidation' => false, 35 | // but if you absolutely need it set cookie domain to localhost 36 | /* 37 | 'csrfCookie' => [ 38 | 'domain' => 'localhost', 39 | ], 40 | */ 41 | ], 42 | 'i18n' => [ 43 | 'translations' => [ 44 | 'main' => [ 45 | 'class' => 'yii\i18n\PhpMessageSource', 46 | 'basePath' => '@app/translations', // if advanced application, set @frontend/messages 47 | 'sourceLanguage' => 'en', 48 | 'fileMap' => [ 49 | 'main' => 'main.php' 50 | ] 51 | ] 52 | ] 53 | ], 54 | ], 55 | 'params' => $params, 56 | ]; 57 | -------------------------------------------------------------------------------- /views/_assets/css/site.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | .wrap { 7 | min-height: 100%; 8 | height: auto; 9 | margin: 0 auto -60px; 10 | padding: 0 0 60px; 11 | } 12 | 13 | .wrap > .container { 14 | padding: 70px 15px 20px; 15 | } 16 | 17 | .footer { 18 | height: 60px; 19 | background-color: #f5f5f5; 20 | border-top: 1px solid #ddd; 21 | padding-top: 20px; 22 | } 23 | 24 | .jumbotron { 25 | text-align: center; 26 | background-color: transparent; 27 | } 28 | 29 | .jumbotron .btn { 30 | font-size: 21px; 31 | padding: 14px 24px; 32 | } 33 | 34 | .not-set { 35 | color: #c55; 36 | font-style: italic; 37 | } 38 | 39 | /* add sorting icons to gridview sort links */ 40 | a.asc:after, a.desc:after { 41 | position: relative; 42 | top: 1px; 43 | display: inline-block; 44 | font-family: 'Glyphicons Halflings'; 45 | font-style: normal; 46 | font-weight: normal; 47 | line-height: 1; 48 | padding-left: 5px; 49 | } 50 | 51 | a.asc:after { 52 | content: /*"\e113"*/ "\e151"; 53 | } 54 | 55 | a.desc:after { 56 | content: /*"\e114"*/ "\e152"; 57 | } 58 | 59 | .sort-numerical a.asc:after { 60 | content: "\e153"; 61 | } 62 | 63 | .sort-numerical a.desc:after { 64 | content: "\e154"; 65 | } 66 | 67 | .sort-ordinal a.asc:after { 68 | content: "\e155"; 69 | } 70 | 71 | .sort-ordinal a.desc:after { 72 | content: "\e156"; 73 | } 74 | 75 | .grid-view th { 76 | white-space: nowrap; 77 | } 78 | 79 | .hint-block { 80 | display: block; 81 | margin-top: 5px; 82 | color: #999; 83 | } 84 | 85 | .error-summary { 86 | color: #a94442; 87 | background: #fdf7f7; 88 | border-left: 3px solid #eed3d7; 89 | padding: 10px 20px; 90 | margin: 0 0 15px 0; 91 | } 92 | -------------------------------------------------------------------------------- /views/site/_form-user.php: -------------------------------------------------------------------------------- 1 | Yii::t('main', 'User')]; 13 | 14 | if (Yii::$app->user->can('Administrator')) 15 | { 16 | $roleList['Manager']=Yii::t('main', 'Manager'); 17 | $roleList['Administrator']=Yii::t('main', 'Administrator'); 18 | } 19 | 20 | ?> 21 | 22 | 23 | 24 | 60 | -------------------------------------------------------------------------------- /models/OpportunitySearch.php: -------------------------------------------------------------------------------- 1 | $query]); 46 | $this->load($params); 47 | 48 | if (!$this->validate()) 49 | { 50 | // uncomment the following line if you do not want to return any records when validation fails 51 | // $query->where('0=1'); 52 | return $dataProvider; 53 | } 54 | $query->andFilterWhere(['like', 'name', $this->name]); 55 | $query->andFilterWhere(['=', 'probability', $this->probability]); 56 | $query->andFilterWhere(['=', 'stage_id', $this->stage_id]); 57 | $query->andFilterWhere(['=', 'type_id', $this->type_id]); 58 | 59 | if (!Yii::$app->user->can('Manager')) 60 | $query->andWhere(['is', 'deleted_at', null]); 61 | 62 | return $dataProvider; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /models/ActivitySearch.php: -------------------------------------------------------------------------------- 1 | $query]); 47 | $this->load($params); 48 | 49 | if (!$this->validate()) 50 | { 51 | // uncomment the following line if you do not want to return any records when validation fails 52 | // $query->where('0=1'); 53 | return $dataProvider; 54 | } 55 | 56 | $query->andFilterWhere(['like', 'subject', $this->subject]); 57 | $query->andFilterWhere(['=', 'type_id', $this->type_id]); 58 | $query->andFilterWhere(['=', 'priority_id', $this->priority_id]); 59 | $query->andFilterWhere(['=', 'status_id', $this->status_id]); 60 | 61 | if (!Yii::$app->user->can('Manager')) 62 | $query->andWhere(['is', 'deleted_at', null]); 63 | 64 | return $dataProvider; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /views/commons/desc-owner-timestamps.php: -------------------------------------------------------------------------------- 1 | modelClassName(); 7 | $classNameLower=strtolower($className); 8 | 9 | ?> 10 | 11 |
12 |
13 |
14 | 15 |
description) ?>
16 |
17 |
18 | 19 |
20 |
21 | 22 |
owner ? $model->owner->name : '') ?>
23 |
[]
24 |
25 |
26 |
27 | 28 | render('social-media-links', ['model' => $model, 'className'=>$className, 'classNameLower'=>$classNameLower]) : '') ?> 29 | 30 |
31 |
32 | 33 | adder ? $model->adder->name : '') ?> 34 |   created_at ?> 35 |
36 |
37 | 38 | modifier ? $model->modifier->name : '') ?> 39 |   updated_at ?> 40 |
41 |
42 | 43 |
44 |
45 | -------------------------------------------------------------------------------- /models/ContactForm.php: -------------------------------------------------------------------------------- 1 | Yii::t('main', 'Name'), 41 | 'email' => Yii::t('main', 'Email'), 42 | 'subject' => Yii::t('main', 'Subject'), 43 | 'body' => Yii::t('main', 'Message'), 44 | 'verifyCode' => Yii::t('main', 'Verification Code') 45 | ]; 46 | } 47 | 48 | /** 49 | * Sends an email to the specified email address using the information collected by this model. 50 | * 51 | * @param string $email 52 | * the target email address 53 | * @return boolean whether the model passes validation 54 | */ 55 | public function contact($email) 56 | { 57 | if ($this->validate()) 58 | { 59 | Yii::$app->mailer->compose() 60 | ->setTo($email) 61 | ->setFrom([$this->email => $this->name]) 62 | ->setSubject($this->subject) 63 | ->setTextBody($this->body) 64 | ->send(); 65 | 66 | return true; 67 | } 68 | else 69 | { 70 | return false; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /views/site/update-identity.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Update Profile'); 12 | 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('main', 'User'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = $this->title; 15 | ?> 16 |
17 |

title ?>

18 | 19 | 20 | 21 | 55 | 56 |
-------------------------------------------------------------------------------- /views/report/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Reports'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | 15 | ?> 16 | 17 |
18 | 19 | 20 | 21 |
title) ?>
22 | 23 | ['class'=>'form-horizontal']] ); ?> 24 | 25 | 26 | 27 |
28 | field($model, 'report_object', $tt3ColIn)->dropDownList($dropdownObjects) ?> 29 | field($model, 'report_type', $tt3ColIn)->dropDownList($dropdownTypes) ?> 30 | field($model, 'display_type', $tt3ColIn)->dropDownList( 31 | [ 32 | 'bar_chart_tooltip'=>Yii::t('main', 'Bar Chart'), 33 | 'pie_chart'=>Yii::t('main', 'Pie Chart'), 34 | '3d_donut'=>Yii::t('main', '3D Donut'), 35 | ]) ?> 36 |
37 | 38 | 39 |
40 | 'btn btn-primary']) ?> 41 |
42 | 43 | 44 | 45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | display_type)) 57 | echo $this->render('report-'.$model->display_type, ['data' => $data, 'graphFontSize'=>'22px']); 58 | 59 | ?> 60 | 61 | -------------------------------------------------------------------------------- /migrations/m151102_000902_create_users_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 12 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 13 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 14 | } 15 | 16 | $this->createTable('{{%users}}', [ 17 | 'id' => Schema::TYPE_PK, 18 | 'username' => Schema::TYPE_STRING . '(255) NOT NULL', 19 | 'name' => Schema::TYPE_STRING . '(75) NOT NULL', 20 | 'auth_key' => Schema::TYPE_STRING . '(32) NOT NULL', 21 | 'password_hash' => Schema::TYPE_STRING . '(60) NOT NULL', 22 | 'password_reset_token' => Schema::TYPE_STRING.'(60)', 23 | 'email' => Schema::TYPE_STRING . '(255) NOT NULL', 24 | 'access_token' => Schema::TYPE_STRING . '(60) NOT NULL', // REST API access 25 | 'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 10', 26 | "owner_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 27 | "adder_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 28 | "modifier_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 29 | "login_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 30 | 'deleted_at' => Schema::TYPE_DATETIME . ' NULL DEFAULT NULL', 31 | 'created_at' => Schema::TYPE_DATETIME . ' NULL DEFAULT NULL', 32 | 'updated_at' => Schema::TYPE_TIMESTAMP . ' NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 33 | ], $tableOptions); 34 | 35 | } 36 | 37 | public function down() 38 | { 39 | if (YII_ENV=='dev') 40 | $this->dropTable('{{%users}}'); 41 | else 42 | echo '***** SKIPPED DROPPING {{%users}} TABLE - NOT DEV SERVER *****'; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /web/Yii.php: -------------------------------------------------------------------------------- 1 | =5.4.0", 28 | "yiisoft/yii2": ">=2.0.4", 29 | "yiisoft/yii2-bootstrap": "*", 30 | "yiisoft/yii2-swiftmailer": "*", 31 | "mdmsoft/yii2-admin": "~2.0" 32 | }, 33 | 34 | "require-dev": 35 | { 36 | "yiisoft/yii2-debug": "*", 37 | "yiisoft/yii2-gii": "*", 38 | "yiisoft/yii2-faker": "*", 39 | 40 | "codeception/base": "^2.2.3", 41 | "codeception/verify": "~0.3.1", 42 | "codeception/specify": "~0.4.3" 43 | }, 44 | 45 | "scripts": 46 | { 47 | "post-create-project-cmd": 48 | [ 49 | "yii\\composer\\Installer::postCreateProject" 50 | ] 51 | }, 52 | 53 | "extra": 54 | { 55 | "yii\\composer\\Installer::postCreateProject": 56 | { 57 | "setPermission": 58 | [ 59 | { 60 | "runtime": "0777", 61 | "web/assets": "0777", 62 | "yii": "0755" 63 | } 64 | ], 65 | 66 | "generateCookieValidationKey": 67 | [ 68 | "config/web.php" 69 | ] 70 | }, 71 | "config": { 72 | "fxp-asset": { 73 | "installer-paths": { 74 | "npm-asset-library": "vendor/npm", 75 | "bower-asset-library": "vendor/bower" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /models/ResetPasswordRequestForm.php: -------------------------------------------------------------------------------- 1 | 'trim'], 25 | ['email', 'required'], ['email', 'email'], 26 | ['email', 'exist', 'targetClass' => '\app\models\User', 'filter' => ['status' => AppHelper::STATUS_ACTIVE], 'message' => Yii::t('main', 'There is no user with such email.')]]; 27 | } 28 | 29 | /** 30 | * 31 | * @return array customized attribute labels 32 | */ 33 | public function attributeLabels() 34 | { 35 | return [ 36 | 'email' => Yii::t('main', 'Email') 37 | ]; 38 | } 39 | 40 | /** 41 | * Sends an email with a link, for resetting the password. 42 | * 43 | * @return boolean whether the email was send 44 | */ 45 | public function sendEmail() 46 | { 47 | /* @var $user User */ 48 | $user=User::findOne(['status' => AppHelper::STATUS_ACTIVE, 'email' => $this->email]); 49 | $user->scenario='reset-password-request'; 50 | 51 | if ($user) 52 | { 53 | if (! User::isPasswordResetTokenValid($user->password_reset_token)) 54 | { 55 | $user->generatePasswordResetToken(); 56 | } 57 | 58 | if ($user->save()) 59 | { 60 | return \Yii::$app->mailer->compose(['html' => 'site/passwordResetToken-html', 'text' => 'site/passwordResetToken-text'], ['user' => $user]) 61 | ->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot']) 62 | ->setTo($this->email) 63 | ->setSubject('Password reset for ' . \Yii::$app->name) 64 | ->send(); 65 | } 66 | } 67 | 68 | return false; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /migrations/m151122_173332_create_lookup_rating.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_rating}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_rating_value_unique", "{{%lkp_rating}}", "value", false); 27 | 28 | $this->insert("{{%lkp_rating}}", ['id'=>'1','value'=>'Hot','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_rating}}", ['id'=>'2','value'=>'Warm','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_rating}}", ['id'=>'3','value'=>'Cold','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | } 32 | 33 | public function down() 34 | { 35 | if (YII_ENV=='dev') 36 | $this->dropTable('{{%lkp_rating}}'); 37 | else 38 | echo '***** SKIPPED DROPPING {{%lkp_rating}} TABLE - NOT DEV SERVER *****'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /models/AccountSearch.php: -------------------------------------------------------------------------------- 1 | Yii::t('main', 'Account Name'), 31 | 'industry_id' => Yii::t('main', 'Industry'), 32 | 'lead_source_id' => Yii::t('main', 'Lead Source'), 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=Account::find(); 55 | $dataProvider=new ActiveDataProvider(['query' => $query]); 56 | $this->load($params); 57 | 58 | if (!$this->validate()) 59 | { 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 | $query->andFilterWhere(['like', 'name', $this->name]); 66 | $query->andFilterWhere(['=', 'industry_id', $this->industry_id]); 67 | $query->andFilterWhere(['=', 'lead_source_id', $this->lead_source_id]); 68 | 69 | if (!Yii::$app->user->can('Manager')) 70 | $query->andWhere(['is', 'deleted_at', null]); 71 | 72 | return $dataProvider; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /migrations/m160125_031538_create_relation_opportunity_account.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%rel_opportunity_account}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "opportunity_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 18 | "account_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 19 | "adder_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 20 | "owner_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 21 | "modifier_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 22 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 23 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 24 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 25 | "PRIMARY KEY(id)", 26 | ], $tableOptions); 27 | 28 | if (YII_ENV!='prod') 29 | { 30 | $this->insert("{{%rel_opportunity_account}}", ['id'=>'1','opportunity_id'=>'1','account_id'=>'2','deleted_at'=>'2015-10-31 17:01:21','created_at'=>'2015-10-31 16:38:10']); 31 | $this->insert("{{%rel_opportunity_account}}", ['id'=>'2','opportunity_id'=>'1','account_id'=>'2','deleted_at'=>NULL,'created_at'=>'2015-11-01 10:12:01']); 32 | } 33 | } 34 | 35 | public function down() 36 | { 37 | if (YII_ENV=='dev') 38 | $this->dropTable('{{%rel_opportunity_account}}'); 39 | else 40 | echo '***** SKIPPED DROPPING {{%rel_opportunity_account}} TABLE - NOT DEV SERVER *****'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /migrations/m151122_103678_create_table_update_history.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%_update_history_}}", [ 16 | "id" => Schema::TYPE_BIGINT . "(20) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "model" => "CHAR(75) COLLATE utf8_unicode_ci NOT NULL", 18 | "model_id" => Schema::TYPE_BIGINT . "(20) NOT NULL", 19 | "user_id" => Schema::TYPE_BIGINT . "(20) NOT NULL", 20 | "fields" => Schema::TYPE_TEXT . " COLLATE utf8_unicode_ci NOT NULL", 21 | "created_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 22 | "PRIMARY KEY(id)", 23 | ], $tableOptions); 24 | 25 | $this->createIndex("Index 2", "{{%_update_history_}}", "model_id,model", false); 26 | 27 | if (YII_ENV!='prod') 28 | { 29 | $this->insert("{{%_update_history_}}", ['id'=>'1','model'=>'Account','model_id'=>'1','user_id'=>'1','fields'=>'a:5:{s:11:"description";a:2:{i:0;s:84:" South Korean multinational electronics company headquartered in Suwon, South Korea.";i:1;s:90:" South Korean multinational electronics company headquartered in Suwon, South Korea, Asia.";}s:14:"lead_source_id";a:2:{i:0;s:1:"3";i:1;s:1:"4";}s:7:"type_id";a:2:{i:0;s:1:"5";i:1;s:1:"3";}s:9:"rating_id";a:2:{i:0;s:1:"1";i:1;s:1:"2";}s:8:"owner_id";a:2:{i:0;s:1:"2";i:1;s:1:"1";}}','created_at'=>'2015-11-22 12:50:37']); 30 | } 31 | } 32 | 33 | public function down() 34 | { 35 | if (YII_ENV=='dev') 36 | $this->dropTable('{{%_update_history_}}'); 37 | else 38 | echo '***** SKIPPED DROPPING {{%_update_history_}} TABLE - NOT DEV SERVER *****'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /migrations/m151122_170621_create_lookup_activity_priority.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_activity_priority}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_activity_priority_value_unique", "{{%lkp_activity_priority}}", "value", false); 27 | 28 | $this->insert("{{%lkp_activity_priority}}", ['id'=>'1','value'=>'High','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_activity_priority}}", ['id'=>'2','value'=>'Normal','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_activity_priority}}", ['id'=>'3','value'=>'Low','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | } 32 | 33 | public function down() 34 | { 35 | if (YII_ENV=='dev') 36 | $this->dropTable('{{%lkp_activity_priority}}'); 37 | else 38 | echo '***** SKIPPED DROPPING {{%lkp_activity_priority}} TABLE - NOT DEV SERVER *****'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /views/commons/related-list-account.php: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | accounts)) 26 | foreach ($model->accounts as $record) 27 | { 28 | $actions=Html::a(Yii::t('main', 'View'), Url::to(['account/view', 'id'=>$record->id])).'   '. 29 | Html::a(Yii::t('main', 'Edit'), Url::to(['account/update', 'id'=>$record->id])); 30 | 31 | echo ' 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | '; 43 | } 44 | else 45 | echo ''; 46 | ?> 47 |
 
'.Html::encode($record->name).''.Yii::$app->appHelper->getLookupValue('lkp_account_type', $record->type_id).''.Yii::$app->appHelper->getLookupValue('lkp_industry', $record->industry_id).''.$record->state.''.Yii::$app->appHelper->getLookupValue('countries', $record->country).''.Yii::$app->appHelper->getLookupValue('lkp_lead_source', $record->lead_source_id).''.Html::encode($record->owner->name).''.$record->created_at.''.$actions.'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
48 |
49 | 50 | -------------------------------------------------------------------------------- /migrations/m160127_213855_create_relation_contact_social_media.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%rel_contact_social_media}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "contact_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 18 | "social_media_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 19 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 20 | "adder_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 21 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | 27 | if (YII_ENV!='prod') 28 | { 29 | $this->insert("{{%rel_contact_social_media}}", ['id'=>'1','contact_id'=>'1','social_media_id'=>'1','value'=>'https://www.youtube.com/','adder_id'=>'1','deleted_at'=>NULL,'created_at'=>'2016-01-25 17:35:15']); 30 | $this->insert("{{%rel_contact_social_media}}", ['id'=>'2','contact_id'=>'1','social_media_id'=>'3','value'=>'https://www.youtube.com/','adder_id'=>'2','deleted_at'=>NULL,'created_at'=>'2016-01-25 17:35:55']); 31 | $this->insert("{{%rel_contact_social_media}}", ['id'=>'3','contact_id'=>'1','social_media_id'=>'5','value'=>'https://www.youtube.com/','adder_id'=>'3','deleted_at'=>NULL,'created_at'=>'2016-01-25 19:00:25']); 32 | } 33 | } 34 | 35 | public function down() 36 | { 37 | if (YII_ENV=='dev') 38 | $this->dropTable('{{%rel_contact_social_media}}'); 39 | else 40 | echo '***** SKIPPED DROPPING {{%rel_contact_social_media}} TABLE - NOT DEV SERVER *****'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /migrations/m160131_213855_create_relation_account_social_media.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%rel_account_social_media}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "account_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 18 | "social_media_id" => Schema::TYPE_INTEGER . "(10) unsigned NOT NULL", 19 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 20 | "adder_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 21 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | 27 | if (YII_ENV!='prod') 28 | { 29 | $this->insert("{{%rel_account_social_media}}", ['id'=>'1','account_id'=>'1','social_media_id'=>'1','value'=>'https://www.youtube.com/','adder_id'=>'1','deleted_at'=>NULL,'created_at'=>'2016-01-25 17:35:15']); 30 | $this->insert("{{%rel_account_social_media}}", ['id'=>'2','account_id'=>'1','social_media_id'=>'3','value'=>'https://www.youtube.com/','adder_id'=>'2','deleted_at'=>NULL,'created_at'=>'2016-01-25 17:35:55']); 31 | $this->insert("{{%rel_account_social_media}}", ['id'=>'3','account_id'=>'1','social_media_id'=>'5','value'=>'https://www.youtube.com/','adder_id'=>'3','deleted_at'=>NULL,'created_at'=>'2016-01-25 19:00:25']); 32 | } 33 | } 34 | 35 | public function down() 36 | { 37 | if (YII_ENV=='dev') 38 | $this->dropTable('{{%rel_account_social_media}}'); 39 | else 40 | echo '***** SKIPPED DROPPING {{%rel_account_social_media}} TABLE - NOT DEV SERVER *****'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /views/commons/social-media-links.php: -------------------------------------------------------------------------------- 1 | 6 |
7 | 8 |
9 | socialmedia)) 11 | foreach ($model->socialmedia as $record) 12 | echo ''; 16 | ?> 17 |
18 |
19 | 20 |
22 |
23 | 24 | 25 |
26 | 27 | 28 |
'social_media_url', 'class'=>'form-control', 'onchange'=>'handleSocialMediaUrlChange()']) ?>
29 | 30 |
appHelper->getLookupData('lkp_social_media'), ['id'=>'social_media_id', 'class'=>'form-control']) ?>
31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /views/commons/related-list-opportunity.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | opportunities)) 27 | foreach ($model->opportunities as $record) 28 | { 29 | $actions=Html::a(Yii::t('main', 'View'), Url::to(['opportunity/view', 'id'=>$record->id])).'   '. 30 | Html::a(Yii::t('main', 'Edit'), Url::to(['opportunity/update', 'id'=>$record->id])); 31 | 32 | echo ' 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | '; 45 | } 46 | else 47 | echo ''; 48 | ?> 49 |
 
'.HTML::encode($record->name).''.$record->probability.''.Yii::$app->appHelper->getLookupValue('lkp_opportunity_stage', $record->stage_id).''.HTML::encode($record->next_step).''.$record->close_date.''.Yii::$app->appHelper->getLookupValue('lkp_lead_source', $record->lead_source_id).''.HTML::encode($record->owner->name).''.$record->created_at.''.$record->updated_at.''.$actions.'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
50 |
51 | -------------------------------------------------------------------------------- /migrations/m151122_172433_create_lookup_contact_type.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_contact_type}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_contact_type_value_unique", "{{%lkp_contact_type}}", "value", false); 27 | 28 | $this->insert("{{%lkp_contact_type}}", ['id'=>'1','value'=>'Prospect','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_contact_type}}", ['id'=>'2','value'=>'Active','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_contact_type}}", ['id'=>'3','value'=>'Inactive','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_contact_type}}", ['id'=>'4','value'=>'Expired','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | } 33 | 34 | public function down() 35 | { 36 | if (YII_ENV=='dev') 37 | $this->dropTable('{{%lkp_contact_type}}'); 38 | else 39 | echo '***** SKIPPED DROPPING {{%lkp_contact_type}} TABLE - NOT DEV SERVER *****'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /migrations/m151102_000902_seed_users_table.php: -------------------------------------------------------------------------------- 1 | insert("{{%users}}", 10 | ['id' => '1', 11 | 'username' => 'admin@crm-yii.com', 12 | 'name' => 'Admin User', 13 | 'auth_key' => Yii::$app->security->generateRandomString(), 14 | 'password_hash' => Yii::$app->security->generatePasswordHash('admin123'), 15 | 'password_reset_token' => ((YII_ENV != 'prod') ? '100-token' : NULL), // for unit testing populated on development environments 16 | 'email' => 'admin@crm-yii.com', 17 | 'access_token' => 'rest1api2token3admin', 18 | 'status' => '1', 19 | 'deleted_at' => NULL, 20 | 'created_at' => '2016-11-21 16:53:15', 21 | 'updated_at' => '2016-11-21 16:59:39']); 22 | 23 | if (YII_ENV != 'prod') 24 | { 25 | $this->insert("{{%users}}", 26 | ['id' => '2', 27 | 'username' => 'manager@crm-yii.com', 28 | 'name' => 'Manager User', 29 | 'auth_key' => Yii::$app->security->generateRandomString(), 30 | 'password_hash' => Yii::$app->security->generatePasswordHash('manager123'), 31 | 'password_reset_token' => NULL, 32 | 'email' => 'manager@crm-yii.com', 33 | 'access_token' => 'rest1api2token3manager', 34 | 'status' => '1', 35 | 'deleted_at' => NULL, 36 | 'created_at' => '2016-11-21 16:53:15', 37 | 'updated_at' => '2016-11-21 16:59:41']); 38 | 39 | $this->insert("{{%users}}", 40 | ['id' => '3', 41 | 'username' => 'user@crm-yii.com', 42 | 'name' => 'Basic User', 43 | 'auth_key' => Yii::$app->security->generateRandomString(), 44 | 'password_hash' => Yii::$app->security->generatePasswordHash('user123'), 45 | 'password_reset_token' => NULL, 46 | 'email' => 'user@crm-yii.com', 47 | 'access_token' => 'rest1api2token3user', 48 | 'status' => '1', 49 | 'deleted_at' => NULL, 50 | 'created_at' => '2016-11-21 16:53:15', 51 | 'updated_at' => '2016-11-21 16:59:41']); 52 | } 53 | } 54 | 55 | public function down() 56 | { 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /views/site/list-users.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('main', 'Users'); 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 | 15 | 16 | 17 |
title ?> 'btn btn-success button-new-index-page']) ?>
18 |
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | '; 49 | } 50 | else 51 | echo ''; 52 | ?> 53 |
 
'.Html::encode($record['username']).''.Html::encode($record['name']).''.Html::encode($record['email']).''.Yii::t('main', $record['role']).''.($record['status'] == AppHelper::STATUS_ACTIVE ? Yii::t('main', 'Active') : Yii::t('main', 'Inactive')).''.Yii::$app->appHelper->getLookupValue('users', $record['adder_id']).' ('.$record['created_at'].')'.Yii::$app->appHelper->getLookupValue('users', $record['modifier_id']).' ('.$record['updated_at'].')'.$record['login_at'].''.$record['actions'].'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
54 |
55 | -------------------------------------------------------------------------------- /tests/functional/ContactFormCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(['site/contact']); 7 | } 8 | /* 9 | public function openContactPage(\FunctionalTester $I) 10 | { 11 | $I->see('Contact', 'h1'); 12 | } 13 | 14 | public function submitEmptyForm(\FunctionalTester $I) 15 | { 16 | $I->submitForm('#contact-form', []); 17 | $I->expectTo('see validations errors'); 18 | $I->see('Contact', 'h1'); 19 | $I->see('Name cannot be blank'); 20 | $I->see('Email cannot be blank'); 21 | $I->see('Subject cannot be blank'); 22 | $I->see('Body cannot be blank'); 23 | $I->see('The verification code is incorrect'); 24 | } 25 | 26 | public function submitFormWithIncorrectEmail(\FunctionalTester $I) 27 | { 28 | $I->submitForm('#contact-form', [ 29 | 'ContactForm[name]' => 'tester', 30 | 'ContactForm[email]' => 'tester.email', 31 | 'ContactForm[subject]' => 'test subject', 32 | 'ContactForm[body]' => 'test content', 33 | 'ContactForm[verifyCode]' => 'testme', 34 | ]); 35 | $I->expectTo('see that email address is wrong'); 36 | $I->dontSee('Name cannot be blank', '.help-inline'); 37 | $I->see('Email is not a valid email address.'); 38 | $I->dontSee('Subject cannot be blank', '.help-inline'); 39 | $I->dontSee('Body cannot be blank', '.help-inline'); 40 | $I->dontSee('The verification code is incorrect', '.help-inline'); 41 | } 42 | 43 | public function submitFormSuccessfully(\FunctionalTester $I) 44 | { 45 | $I->submitForm('#contact-form', [ 46 | 'ContactForm[name]' => 'tester', 47 | 'ContactForm[email]' => 'tester@example.com', 48 | 'ContactForm[subject]' => 'test subject', 49 | 'ContactForm[body]' => 'test content', 50 | 'ContactForm[verifyCode]' => 'testme', 51 | ]); 52 | $I->seeEmailIsSent(); 53 | $I->dontSeeElement('#contact-form'); 54 | $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); 55 | } 56 | */ 57 | } 58 | -------------------------------------------------------------------------------- /translations/message-config-en.php: -------------------------------------------------------------------------------- 1 | __DIR__ . DIRECTORY_SEPARATOR . '..', 6 | // array, required, list of language codes that the extracted messages 7 | // should be translated to. For example, ['zh-CN', 'de']. 8 | 'languages' => ['en'], 9 | // string, the name of the function for translating messages. 10 | // Defaults to 'Yii::t'. This is used as a mark to find the messages to be 11 | // translated. You may use a string for single function name or an array for 12 | // multiple function names. 13 | 'translator' => 'Yii::t', 14 | // boolean, whether to sort messages by keys when merging new messages 15 | // with the existing ones. Defaults to false, which means the new (untranslated) 16 | // messages will be separated from the old (translated) ones. 17 | 'sort' => true, 18 | // boolean, whether to remove messages that no longer appear in the source code. 19 | // Defaults to false, which means each of these messages will be enclosed with a pair of '@@' marks. 20 | 'removeUnused' => true, 21 | // array, list of patterns that specify which files (not directories) should be processed. 22 | // If empty or not set, all files will be processed. 23 | // Please refer to "except" for details about the patterns. 24 | 'only' => ['*.php'], 25 | 26 | 'except' => [ 27 | '.svn', 28 | '.git', 29 | '.gitignore', 30 | '.gitkeep', 31 | '.hgignore', 32 | '.hgkeep', 33 | '/messages', 34 | '/assets', 35 | '/commands', 36 | '/config', 37 | '/mail', 38 | '/runtime', 39 | '/tests', 40 | '/translations', 41 | '/vendor', 42 | '/web' 43 | ], 44 | 45 | // 'php' output format is for saving messages to php files. 46 | 'format' => 'php', 47 | // Root directory containing message translations. 48 | 'messagePath' => __DIR__, 49 | // boolean, whether the message file should be overwritten with the merged messages 50 | 'overwrite' => true, 51 | 52 | // Message categories to ignore 53 | 'ignoreCategories' => [ 54 | 'yii', 55 | ], 56 | ]; 57 | -------------------------------------------------------------------------------- /migrations/m151122_172941_create_lookup_lead_status.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_lead_status}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_lead_status_value_unique", "{{%lkp_lead_status}}", "value", false); 27 | 28 | $this->insert("{{%lkp_lead_status}}", ['id'=>'1','value'=>'Open - Not Contacted','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_lead_status}}", ['id'=>'2','value'=>'Working - Contacted','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_lead_status}}", ['id'=>'3','value'=>'Closed - Converted','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_lead_status}}", ['id'=>'4','value'=>'Closed - Not Converted','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | } 33 | 34 | public function down() 35 | { 36 | if (YII_ENV=='dev') 37 | $this->dropTable('{{%lkp_lead_status}}'); 38 | else 39 | echo '***** SKIPPED DROPPING {{%lkp_lead_status}} TABLE - NOT DEV SERVER *****'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /views/opportunity/_form.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 | ['class'=>'form-horizontal']] ); ?> 14 | 15 | 16 | 17 | 18 | 19 |
20 | field($model, 'type_id', $tt2ColIn)->dropDownList(Yii::$app->appHelper->getLookupData('lkp_opportunity_type'))?> 21 | field($model, 'name', $tt2ColIn)->textInput()?> 22 |
23 | 24 |
25 | field($model, 'stage_id', $tt2ColIn)->dropDownList(Yii::$app->appHelper->getLookupData('lkp_opportunity_stage'))?> 26 | field($model, 'close_date', $tt2ColIn)->textInput()?> 27 |
28 | 29 |
30 | field($model, 'probability', $tt2ColIn)->dropDownList(Yii::$app->appHelper->getLookupData('probabilities'))?> 31 | field($model, 'next_step', $tt2ColIn)->textInput()?> 32 |
33 | 34 |
35 | field($model, 'lead_source_id', $tt2ColIn)->dropDownList(Yii::$app->appHelper->getLookupData('lkp_lead_source'))?> 36 |
37 | 38 |
39 | field($model, 'competitors', $tt1ColIn)->textInput()?> 40 |
41 | 42 |
43 | field($model, 'description', $tt2ColIn)->textarea()?> 44 | field($model, 'owner_id', $tt2ColIn)->dropDownList(Yii::$app->appHelper->getLookupData('users'))?> 45 |
46 | 47 |
48 | isNewRecord ? Yii::t('main', 'Save') : Yii::t('main', 'Update'), ['class' => 'btn btn-primary'])?> 49 | isNewRecord ? Url::to(['opportunity/index']) : Url::to(['opportunity/view', 'id' => $model->id])), ['class' => 'btn btn-success'])?> 50 |
51 | 52 | 53 | 54 |
55 | -------------------------------------------------------------------------------- /migrations/m151122_163446_create_lookup_account_ownership.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_account_ownership}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_account_ownership_value_unique", "{{%lkp_account_ownership}}", "value", false); 27 | 28 | $this->insert("{{%lkp_account_ownership}}", ['id'=>'1','value'=>'Public','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_account_ownership}}", ['id'=>'2','value'=>'Private','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_account_ownership}}", ['id'=>'3','value'=>'Subsidiary','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_account_ownership}}", ['id'=>'4','value'=>'Other','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | } 33 | 34 | public function down() 35 | { 36 | if (YII_ENV=='dev') 37 | $this->dropTable('{{%lkp_account_ownership}}'); 38 | else 39 | echo '***** SKIPPED DROPPING {{%lkp_account_ownership}} TABLE - NOT DEV SERVER *****'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /migrations/m151122_173225_create_lookup_opportunity_type.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_opportunity_type}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_opportunity_type_value_unique", "{{%lkp_opportunity_type}}", "value", false); 27 | 28 | $this->insert("{{%lkp_opportunity_type}}", ['id'=>'1','value'=>'New Customer','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_opportunity_type}}", ['id'=>'2','value'=>'Upgrade','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_opportunity_type}}", ['id'=>'3','value'=>'Downgrade','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_opportunity_type}}", ['id'=>'4','value'=>'Replacement Committee','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | } 33 | 34 | public function down() 35 | { 36 | if (YII_ENV=='dev') 37 | $this->dropTable('{{%lkp_opportunity_type}}'); 38 | else 39 | echo '***** SKIPPED DROPPING {{%lkp_opportunity_type}} TABLE - NOT DEV SERVER *****'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /migrations/m151122_170751_create_lookup_activity_status.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_activity_status}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_activity_status_value_unique", "{{%lkp_activity_status}}", "value", false); 27 | 28 | $this->insert("{{%lkp_activity_status}}", ['id'=>'1','value'=>'Not Started','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_activity_status}}", ['id'=>'2','value'=>'In Progress','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_activity_status}}", ['id'=>'3','value'=>'Deferred','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_activity_status}}", ['id'=>'99', 'editable'=>0, 'idxpos'=>99, 'value'=>'Completed','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | } 33 | 34 | public function down() 35 | { 36 | if (YII_ENV=='dev') 37 | $this->dropTable('{{%lkp_activity_status}}'); 38 | else 39 | echo '***** SKIPPED DROPPING {{%lkp_activity_status}} TABLE - NOT DEV SERVER *****'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /views/commons/related-list-contact.php: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | contacts)) 27 | foreach ($model->contacts as $record) 28 | { 29 | $actions=Html::a(Yii::t('main', 'View'), Url::to(['contact/view', 'id'=>$record->id])).'   '. 30 | Html::a(Yii::t('main', 'Edit'), Url::to(['contact/update', 'id'=>$record->id])); 31 | 32 | echo ' 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | '; 45 | } 46 | else 47 | echo ''; 48 | ?> 49 |
 
'.Yii::$app->appHelper->getLookupValue('lkp_salutation', $record->salutation_id).' '.Html::encode($record->first_name.' '.$record->last_name).''.$record->email.''.Html::encode($record->title).''.$record->state.''.Yii::$app->appHelper->getLookupValue('countries', $record->country).''.Yii::$app->appHelper->getLookupValue('lkp_contact_type', $record->type_id).''.Yii::$app->appHelper->getLookupValue('lkp_lead_source', $record->lead_source_id).''.Html::encode($record->owner->name).''.$record->created_at.''.$actions.'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
50 |
51 | 52 | -------------------------------------------------------------------------------- /tests/acceptance/lead/ConvertLeadWithNewOpportunityCept.php: -------------------------------------------------------------------------------- 1 | am('Logged in user'); 5 | $I->wantTo('Convert a lead to a contact with new opportunity'); 6 | $I->expectTo('See lead converted to a contact'); 7 | 8 | 9 | $I->amOnPage('/lead/5'); 10 | $I->see('Lead Detail - Immanuel Kant', 'div.pageTitle'); 11 | $I->seeLink('Convert'); 12 | $I->click('#lead-convert-btn'); 13 | 14 | $I->seeInCurrentUrl('lead/convert/5'); 15 | 16 | $I->see('Convert Lead - Immanuel Kant'); 17 | $I->see('Account Name'); 18 | $I->seeInField('LeadConvertForm[account_name]', 'Enlightenment Philosophy Inc.'); 19 | $I->dontSee('There are similar accounts in the system. If you want to add the lead to an existing account, please select it from the dropdown list below. Otherwise a new account with the company name will be created.'); 20 | $I->see('Create New Opportunity?'); 21 | $I->selectOption('LeadConvertForm[new_opportunity]', '1'); 22 | $I->fillField('LeadConvertForm[opportunity_name]', 'Converted Opportunity'); 23 | $I->fillField('LeadConvertForm[probability]', '20'); 24 | $I->selectOption('LeadConvertForm[stage_id]', '2'); 25 | $I->fillField('LeadConvertForm[close_date]', '2020-12-31'); 26 | $I->click('#lead-convert-btn'); 27 | 28 | // conversion success 29 | $I->seeInCurrentUrl('/contact/15'); 30 | $I->see('Contact Detail - Immanuel Kant', 'div.pageTitle'); 31 | $I->see('Name: Prof. Immanuel Kant'); 32 | $I->see('Email: kant@felossoffar.edu'); 33 | $I->see('Description: Enlightenment is man\'s emergence from his self-imposed nonage. Nonage is the inability to use one\'s own understanding without another\'s guidance. This nonage is self-imposed if its cause lies not in lack of understanding but in indecision and lack of courage to use one\'s own mind without another\'s guidance. Dare to know! (Sapere aude.) "Have the courage to use your own understanding," is therefore the motto of the enlightenment'); 34 | $I->see('Owner: Basic User'); 35 | $I->see('Added By: Basic User'); 36 | $I->see('Modified By: Basic User'); 37 | 38 | // lead is not accessible 39 | $I->wantTo('Ensure converted lead is not accessible'); 40 | $I->expectTo('See lead was converted to contact error messsage'); 41 | $I->amOnPage('/lead/5'); 42 | $I->see('Lead was converted to contact', $errorMessageBox); 43 | -------------------------------------------------------------------------------- /views/opportunity/contact-list.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
9 |
$model->id]), ['class' => 'btn btn-primary btn-xs']) ?> 10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | opportunitycontacts)) 25 | foreach ($model->opportunitycontacts as $record) 26 | { 27 | if (!$record->contact) 28 | continue; 29 | 30 | $actions=Html::a(Yii::t('main', 'Edit'), Url::to(['opportunity/editcontact', 'id'=>$model->id, 'relId' => $record->id])).'   '. 31 | Html::a(Yii::t('main', 'Delete'), Url::to(['opportunity/deletecontact', 'id'=>$model->id, 'relId' => $record->id]), 32 | ['class' => 'text-danger', 'onclick'=>'return confirm("'.Yii::t('main', 'CONFIRM_DELETION').'")']). 33 | '      '. 34 | Html::a(Yii::t('main', 'Update History'), Url::to(['opportunity/contactupdatehistory', 'id'=>$model->id, 'relId' => $record->id]), ['target'=>'_blank']); 35 | 36 | echo ' 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | '; 45 | } 46 | else 47 | echo ''; 48 | ?> 49 |
 
'.Html::a($record->contact->first_name.' '.$record->contact->last_name, Url::to(['contact/view', 'id'=>$record->contact_id])).''.($record->owner? $record->owner->name : '').''.$record->created_at.''.($record->modifier ? $record->modifier->name : '').''.$record->updated_at.''.$actions.'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
50 |
51 | -------------------------------------------------------------------------------- /views/contact/opportunity-list.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | opportunitycontacts)) 28 | foreach ($model->opportunitycontacts as $contact) 29 | { 30 | $record=$contact->opportunity; 31 | 32 | if (empty($record)) 33 | continue; 34 | 35 | $actions=Html::a(Yii::t('main', 'View'), Url::to(['opportunity/view', 'id'=>$record->id])).'   '. 36 | Html::a(Yii::t('main', 'Edit'), Url::to(['opportunity/update', 'id'=>$record->id])); 37 | 38 | echo ' 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | '; 51 | } 52 | else 53 | echo ''; 54 | ?> 55 |
 
'.HTML::encode($record->name).''.Yii::$app->appHelper->getLookupValue('probabilities', $record->probability).''.Yii::$app->appHelper->getLookupValue('lkp_opportunity_stage', $record->stage_id).''.HTML::encode($record->next_step).''.$record->close_date.''.Yii::$app->appHelper->getLookupValue('lkp_lead_source', $record->lead_source_id).''.HTML::encode($record->owner->name).''.$record->created_at.''.$record->updated_at.''.$actions.'
' . Yii::t('main', 'NO_RECORDS_FOUND') . '
56 |
57 | -------------------------------------------------------------------------------- /web/server-configuration.php: -------------------------------------------------------------------------------- 1 | TEST  Server'); 34 | } 35 | else 36 | if ($serverName == DEV_SERVER || ($isCLI && stripos($projectDir, DEV_SERVER_PATH) === 0)) 37 | { 38 | defined('SERVER_DOMAIN') or define('SERVER_DOMAIN', DEV_SERVER); 39 | defined('YII_ENV') or define('YII_ENV', 'dev'); 40 | defined('DB_CONFIG') or define('DB_CONFIG', $configDir . '/db.php'); 41 | defined('YII_DEBUG') or define('YII_DEBUG', true); 42 | defined('SERVER_DECAL') or define('SERVER_DECAL', '
DEV_Server
'); 43 | } 44 | 45 | if (!defined('SERVER_DOMAIN')) 46 | { 47 | echo 'Bad server configuration! :( ' . "\n"; 48 | exit(1); 49 | } 50 | -------------------------------------------------------------------------------- /views/site/contact.php: -------------------------------------------------------------------------------- 1 | title = 'Contact'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 |

title) ?>

15 | 16 | session->hasFlash('contactFormSubmitted')): ?> 17 | 18 |
19 | Thank you for contacting us. We will respond to you as soon as possible. 20 |
21 | 22 |

23 | Note that if you turn on the Yii debugger, you should be able 24 | to view the mail message on the mail panel of the debugger. 25 | mailer->useFileTransport): ?> 26 | Because the application is in development mode, the email is not sent but saved as 27 | a file under mailer->fileTransportPath) ?>. 28 | Please configure the useFileTransport property of the mail 29 | application component to be false to enable email sending. 30 | 31 |

32 | 33 | 34 | 35 |

36 | If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. 37 |

38 | 39 |
40 |
41 | 'contact-form']); ?> 42 | field($model, 'name') ?> 43 | field($model, 'email') ?> 44 | field($model, 'subject') ?> 45 | field($model, 'body')->textArea(['rows' => 6]) ?> 46 | field($model, 'verifyCode')->widget(Captcha::className(), [ 47 | 'template' => '
{image}
{input}
', 48 | ]) ?> 49 |
50 | 'btn btn-primary', 'name' => 'contact-button']) ?> 51 |
52 | 53 |
54 |
55 | 56 | 57 |
58 | -------------------------------------------------------------------------------- /migrations/m151122_084907_create_table_activities.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%activities}}", [ 16 | "id" => Schema::TYPE_BIGINT . "(20) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "subject" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "location" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 19 | "start_date" => Schema::TYPE_DATE ." DEFAULT NULL", 20 | "end_date" => Schema::TYPE_DATE ." DEFAULT NULL", 21 | "description" => Schema::TYPE_TEXT . " COLLATE utf8_unicode_ci", 22 | "allday" => Schema::TYPE_SMALLINT. "(5) unsigned DEFAULT NULL", 23 | "remind_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 24 | "type_id" => Schema::TYPE_SMALLINT. "(5) unsigned DEFAULT NULL", 25 | "priority_id" => Schema::TYPE_SMALLINT. "(5) unsigned DEFAULT NULL", 26 | "status_id" => Schema::TYPE_SMALLINT. "(5) unsigned DEFAULT NULL", 27 | "related_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 28 | "related_type" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci DEFAULT NULL", 29 | "owner_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 30 | "adder_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 31 | "modifier_id" => Schema::TYPE_INTEGER . "(10) unsigned DEFAULT NULL", 32 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 33 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 34 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 35 | "PRIMARY KEY(id)", 36 | ], $tableOptions); 37 | 38 | $this->createIndex("Index 2", "{{%activities}}", "related_id,related_type", false); 39 | } 40 | 41 | public function down() 42 | { 43 | if (YII_ENV=='dev') 44 | $this->dropTable('{{%activities}}'); 45 | else 46 | echo '***** SKIPPED DROPPING {{%activities}} TABLE - NOT DEV SERVER *****'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /views/account/index.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Accounts'); 12 | $this->params['breadcrumbs'][]=$this->title; 13 | ?> 14 | 15 |
16 |
title ?> 'btn btn-success button-new-index-page']) ?>
17 |
18 | 19 | render('_search', ['model' => $searchModel])?> 20 | 21 |
22 | 23 |
24 | registerJs(" 26 | $('tbody td').css('cursor', 'pointer'); 27 | $('tbody td').click(function (e) { 28 | var id = $(this).closest('tr').data('id'); 29 | if (e.target == this) 30 | location.href = '" . Url::to(['account/view']) . "/' + id; 31 | }); 32 | "); 33 | 34 | echo GridView::widget( 35 | ['dataProvider' => $dataProvider, 36 | 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover table-condensed'], 37 | 'headerRowOptions' => ['class' => 'ui-state-default'], 38 | 'rowOptions' => function ($model, $key, $index, $grid) { 39 | return ['data-id' => $model->id]; 40 | }, 41 | 'filterModel' => null, 42 | 'columns' => [['class' => 'yii\grid\SerialColumn'], 43 | // 'email' => [ 'format'=>'url', 'format' => 'raw', 'value'=>function ($data) { return Html::a($data->email, ['contact/view', 'id'=>$data->id]); },], 44 | 'name', 45 | 'industry_id' => ['attribute' => 'industry_id', 46 | 'value' => function ($data) 47 | { 48 | return Yii::$app->appHelper->getLookupValue('lkp_industry', $data->industry_id); 49 | }], 50 | 'lead_source_id' => ['attribute' => 'lead_source_id', 51 | 'value' => function ($data) 52 | { 53 | return Yii::$app->appHelper->getLookupValue('lkp_lead_source', $data->lead_source_id); 54 | }], 55 | 'owner_id' => ['attribute' => 'owner_id', 'value' => function ($data) 56 | { 57 | return Yii::$app->appHelper->getLookupValue('users', $data->owner_id); 58 | }], 59 | 'updated_at', 60 | 'created_at', // ['class' => 'yii\grid\ActionColumn'], 61 | ['class' => 'app\helpers\CrmActionColumn']]]); 62 | ?> 63 |
64 | -------------------------------------------------------------------------------- /models/ResetPasswordForm.php: -------------------------------------------------------------------------------- 1 | _user=User::findByPasswordResetToken($token); 41 | 42 | if (! $this->_user) 43 | { 44 | throw new InvalidParamException(Yii::t('main', 'Password reset information was incorrect.')); 45 | } 46 | 47 | parent::__construct($config); 48 | } 49 | 50 | /** 51 | * @inheritdoc 52 | */ 53 | public function rules() 54 | { 55 | return [ 56 | [['password', 'password_repeat'], 'required'], 57 | [['password', 'password_repeat'], 'filter', 'filter' => 'trim'], 58 | [['password', 'password_repeat'], 'string', 'min' => 6], 59 | ['password', 'in', 'range' => ['password', '123456'], 'not' => true, 'message' => Yii::t('main', 'Please select a better password.')], 60 | ['password_repeat', 'compare', 'compareAttribute' => 'password', 'message' => Yii::t('main', 'Passwords do not match.')], 61 | ]; 62 | } 63 | 64 | /** 65 | * 66 | * @return array customized attribute labels 67 | */ 68 | public function attributeLabels() 69 | { 70 | return [ 71 | 'password' => Yii::t('main', 'Password'), 72 | 'password_repeat' => Yii::t('main', 'Password 2') 73 | ]; 74 | } 75 | 76 | /** 77 | * Resets password. 78 | * 79 | * @return boolean if password was reset. 80 | */ 81 | public function resetPassword() 82 | { 83 | $user=$this->_user; 84 | $user->setPassword($this->password); 85 | $user->removePasswordResetToken(); 86 | 87 | return $user->save(false); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /controllers/ReportController.php: -------------------------------------------------------------------------------- 1 | graphReports); 26 | 27 | $dropdownJS=''; 40 | 41 | 42 | $dropdownTypes=$model->graphReports[current($reportObjects)]['labels']; 43 | 44 | if ($model->load(Yii::$app->request->post())) 45 | { 46 | if (!in_array($model->report_object, $reportObjects)) 47 | $model->report_object=current($reportObjects); 48 | 49 | $dropdownTypes=$model->graphReports[$model->report_object]['labels']; 50 | $reportTypes=$model->graphReports[$model->report_object]['reports']; 51 | 52 | if (!array_key_exists($model->report_type, $reportTypes)) 53 | $model->report_type=current($reportTypes); 54 | 55 | $query = new Query(); 56 | $query->select($model->report_type.' as fieldId, count(*) as total')->from($model->report_object)->where('deleted_at is NULL')->groupBy($model->report_type); 57 | $resultList=$query->all(); 58 | 59 | foreach($resultList as $result) 60 | { 61 | if (empty($reportTypes[$model->report_type])) 62 | $label=HTML::encode($result['fieldId']); 63 | else 64 | $label=Yii::$app->appHelper->getLookupValue($reportTypes[$model->report_type], $result['fieldId'], false); 65 | 66 | $data[]=['label'=>($label ? $label : '?'), 'value'=>$result['total']]; 67 | } 68 | } 69 | 70 | return $this->render('index', [ 'model'=>$model, 'data'=>$data, 'dropdownObjects'=>$dropdownObjects, 'dropdownTypes'=>$dropdownTypes, 'dropdownJS'=>$dropdownJS ]); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /migrations/m151122_173735_create_lookup_salutation.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_salutation}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_salutation_value_unique", "{{%lkp_salutation}}", "value", false); 27 | 28 | $this->insert("{{%lkp_salutation}}", ['id'=>'1','value'=>'Mr.','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_salutation}}", ['id'=>'2','value'=>'Ms.','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_salutation}}", ['id'=>'3','value'=>'Miss','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_salutation}}", ['id'=>'4','value'=>'Mrs.','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | $this->insert("{{%lkp_salutation}}", ['id'=>'5','value'=>'Dr.','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 33 | $this->insert("{{%lkp_salutation}}", ['id'=>'6','value'=>'Prof.','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 34 | } 35 | 36 | public function down() 37 | { 38 | if (YII_ENV=='dev') 39 | $this->dropTable('{{%lkp_salutation}}'); 40 | else 41 | echo '***** SKIPPED DROPPING {{%lkp_salutation}} TABLE - NOT DEV SERVER *****'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /views/opportunity/index.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Opportunities'); 11 | $this->params['breadcrumbs'][]=$this->title; 12 | ?> 13 | 14 |
15 |
title ?> 'btn btn-success button-new-index-page']) ?>
16 |
17 | 18 | render('_search', ['model' => $searchModel])?> 19 | 20 |
21 | 22 |
23 | registerJs(" 25 | $('tbody td').css('cursor', 'pointer'); 26 | $('tbody td').click(function (e) { 27 | var id = $(this).closest('tr').data('id'); 28 | if (e.target == this) 29 | location.href = '" . Url::to(['opportunity/view']) . "/' + id; 30 | }); 31 | "); 32 | 33 | echo GridView::widget( 34 | ['dataProvider' => $dataProvider, 35 | 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover table-condensed'], 36 | 'headerRowOptions' => ['class' => 'ui-state-default'], 37 | 'rowOptions' => function ($model, $key, $index, $grid) { 38 | return ['data-id' => $model->id]; 39 | }, 40 | 'filterModel' => null, 41 | 'columns' => [['class' => 'yii\grid\SerialColumn'], 42 | 'name', 43 | 'probability' => ['attribute' => 'probability', 44 | 'value' => function ($data) 45 | { 46 | return Yii::$app->appHelper->getLookupValue('probabilities', $data->probability); 47 | }], 48 | 'stage_id' => ['attribute' => 'stage_id', 49 | 'value' => function ($data) 50 | { 51 | return Yii::$app->appHelper->getLookupValue('lkp_opportunity_stage', $data->stage_id); 52 | }], 53 | 'type_id' => ['attribute' => 'type_id', 54 | 'value' => function ($data) 55 | { 56 | return Yii::$app->appHelper->getLookupValue('lkp_opportunity_type', $data->type_id); 57 | }], 58 | 'owner_id' => ['attribute' => 'owner_id', 'value' => function ($data) 59 | { 60 | return Yii::$app->appHelper->getLookupValue('users', $data->owner_id); 61 | }], 62 | 'close_date', 63 | 'updated_at', 64 | 'created_at', // ['class' => 'yii\grid\ActionColumn'], 65 | ['class' => 'app\helpers\CrmActionColumn']]]); 66 | ?> 67 |
68 | -------------------------------------------------------------------------------- /views/activity/index.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Activities'); 10 | $this->params['breadcrumbs'][]=$this->title; 11 | ?> 12 | 13 |
14 |
title?> 15 | appHelper->getActivityAddNewRelatedButton() ?> 16 |
17 |
18 | 19 | render('_search', ['model' => $searchModel])?> 20 | 21 |
22 | 23 |
24 | registerJs(" 26 | $('tbody td').css('cursor', 'pointer'); 27 | $('tbody td').click(function (e) { 28 | var id = $(this).closest('tr').data('id'); 29 | if (e.target == this) 30 | location.href = '" . Url::to(['activity/view']) . "/' + id; 31 | }); 32 | "); 33 | 34 | echo GridView::widget( 35 | ['dataProvider' => $dataProvider, 36 | 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover table-condensed'], 37 | 'headerRowOptions' => ['class' => 'ui-state-default'], 38 | 'rowOptions' => function ($model, $key, $index, $grid) { 39 | return ['data-id' => $model->id]; 40 | }, 41 | 'filterModel' => null, 42 | 'columns' => [['class' => 'yii\grid\SerialColumn', ], 43 | 'subject', 44 | 'location', 45 | 'type_id' => ['attribute' => 'type_id', 46 | 'value' => function ($data) 47 | { 48 | return Yii::$app->appHelper->getLookupValue('lkp_activity_type', $data->type_id); 49 | }], 50 | 'priority_id' => ['attribute' => 'priority_id', 51 | // 'format' => 'html', 52 | 'value' => function ($data) 53 | { 54 | return Yii::$app->appHelper->getLookupValue('lkp_activity_priority', $data->priority_id, false); 55 | }], 56 | 'status_id' => ['attribute' => 'status_id', 57 | 'value' => function ($data) 58 | { 59 | return Yii::$app->appHelper->getLookupValue('lkp_activity_status', $data->status_id); 60 | }], 61 | 'owner_id' => ['attribute' => 'owner_id', 'value' => function ($data) 62 | { 63 | return Yii::$app->appHelper->getLookupValue('users', $data->owner_id); 64 | }], 65 | 'start_date', 66 | 'end_date', 67 | // 'updated_at', 68 | // 'created_at', // ['class' => 'yii\grid\ActionColumn'], 69 | ['class' => 'app\helpers\CrmActionColumn']]]); 70 | ?> 71 |
72 | 73 | -------------------------------------------------------------------------------- /models/IdentityForm.php: -------------------------------------------------------------------------------- 1 | user=User::findByUsername(Yii::$app->user->identity->username); 26 | 27 | $this->name=$this->user->name; 28 | $this->username=$this->user->username; 29 | $this->email=$this->user->email; 30 | 31 | parent::__construct($config); 32 | } 33 | 34 | 35 | public function rules() 36 | { 37 | $passFields=['password', 'password_new', 'password_repeat']; 38 | 39 | return [ 40 | [$passFields, 'required'], 41 | [$passFields, 'filter', 'filter' => 'trim'], 42 | [$passFields, 'string', 'min' => 6], 43 | ['password_new', 'in', 'range' => ['password', '123456'], 'not' => true, 'message' => Yii::t('main', 'Please select a better password.')], 44 | ['password_repeat', 'compare', 'compareAttribute' => 'password_new', 'message' => Yii::t('main', 'Passwords do not match.')], 45 | ]; 46 | } 47 | 48 | /** 49 | * 50 | * @return array customized attribute labels 51 | */ 52 | public function attributeLabels() 53 | { 54 | return [ 55 | 'password' => Yii::t('main', 'Current Password'), 56 | 'password_new' => Yii::t('main', 'New Password'), 57 | 'password_repeat' => Yii::t('main', 'New Password 2') 58 | ]; 59 | } 60 | 61 | public function changePassword() 62 | { 63 | if ($this->user->validatePassword($this->password)) 64 | { 65 | $this->user->scenario='change-password'; 66 | $this->user->setPassword($this->password_new); 67 | 68 | if ($this->user->save()) 69 | { 70 | Yii::$app->mailer->compose(['html' => 'site/identityUpdate-html', 'text' => 'site/identityUpdate-text'], ['user' => $this->user]) 71 | ->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot']) 72 | ->setTo($this->email) 73 | ->setSubject('Password was changed for ' . \Yii::$app->name) 74 | ->send(); 75 | 76 | return true; 77 | } 78 | } 79 | 80 | $this->password=''; 81 | $this->password_new=''; 82 | $this->password_repeat=''; 83 | 84 | return false; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /migrations/m151122_171247_create_lookup_activity_type.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_activity_type}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_activity_type_value_unique", "{{%lkp_activity_type}}", "value", false); 27 | 28 | $this->insert("{{%lkp_activity_type}}", ['id'=>'1','value'=>'Call','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_activity_type}}", ['id'=>'2','value'=>'Meeting','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_activity_type}}", ['id'=>'3','value'=>'Email','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_activity_type}}", ['id'=>'4','value'=>'Task','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | $this->insert("{{%lkp_activity_type}}", ['id'=>'5','value'=>'Event','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 33 | $this->insert("{{%lkp_activity_type}}", ['id'=>'6','value'=>'Other','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 34 | } 35 | 36 | public function down() 37 | { 38 | if (YII_ENV=='dev') 39 | $this->dropTable('{{%lkp_activity_type}}'); 40 | else 41 | echo '***** SKIPPED DROPPING {{%lkp_activity_type}} TABLE - NOT DEV SERVER *****'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /models/LoginForm.php: -------------------------------------------------------------------------------- 1 | Yii::t('main', 'Username'), 41 | 'password' => Yii::t('main', 'Password'), 42 | 'rememberMe' => Yii::t('main', 'Remember me') 43 | ]; 44 | } 45 | 46 | /** 47 | * Validates the password. 48 | * This method serves as the inline validation for password. 49 | * 50 | * @param string $attribute 51 | * the attribute currently being validated 52 | * @param array $params 53 | * the additional name-value pairs given in the rule 54 | */ 55 | public function validatePassword($attribute, $params) 56 | { 57 | if (! $this->hasErrors()) 58 | { 59 | $user=$this->getUser(); 60 | 61 | if (! $user || ! $user->validatePassword($this->password)) 62 | { 63 | $this->addError($attribute, Yii::t('main', 'Incorrect username or password.')); 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * Logs in a user using the provided username and password. 70 | * 71 | * @return boolean whether the user is logged in successfully 72 | */ 73 | public function login() 74 | { 75 | if ($this->validate()) 76 | { 77 | return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0); 78 | } 79 | else 80 | { 81 | return false; 82 | } 83 | } 84 | 85 | /** 86 | * Finds user by [[username]] 87 | * 88 | * @return User|null 89 | */ 90 | public function getUser() 91 | { 92 | if ($this->_user === false) 93 | { 94 | $this->_user=User::findByUsername($this->username); 95 | } 96 | 97 | return $this->_user; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /migrations/m151122_173120_create_lookup_opportunity_stage.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_opportunity_stage}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_opportunity_stage_value_unique", "{{%lkp_opportunity_stage}}", "value", false); 27 | 28 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'1','value'=>'New','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'2','value'=>'Analysis','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'3','value'=>'Proposal','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'4','value'=>'Rejected','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'5','value'=>'In Progress','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 33 | $this->insert("{{%lkp_opportunity_stage}}", ['id'=>'6','value'=>'Finished','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 34 | } 35 | 36 | public function down() 37 | { 38 | if (YII_ENV=='dev') 39 | $this->dropTable('{{%lkp_opportunity_stage}}'); 40 | else 41 | echo '***** SKIPPED DROPPING {{%lkp_opportunity_stage}} TABLE - NOT DEV SERVER *****'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /models/LeadSearch.php: -------------------------------------------------------------------------------- 1 | $query]); 52 | $this->load($params); 53 | 54 | if (!$this->validate()) 55 | { 56 | // uncomment the following line if you do not want to return any records when validation fails 57 | // $query->where('0=1'); 58 | return $dataProvider; 59 | } 60 | 61 | if (!empty($this->name)) 62 | { 63 | $name=explode(' ', $this->name); 64 | $this->first_name = $name[0]; 65 | $this->last_name = count($name)==1 ? $this->first_name : trim(str_replace($this->first_name, '', $this->name)); 66 | 67 | $query->andFilterWhere(['or', ['like', 'first_name', $this->first_name], ['like', 'last_name', $this->last_name]]); 68 | } 69 | 70 | $query->andFilterWhere(['like', 'email', $this->email]); 71 | $query->andFilterWhere(['like', 'company', $this->company]); 72 | $query->andFilterWhere(['=', 'status_id', $this->status_id]); 73 | $query->andWhere(['is', 'converted_at', null]); 74 | 75 | if (!Yii::$app->user->can('Manager')) 76 | $query->andWhere(['is', 'deleted_at', null]); 77 | 78 | return $dataProvider; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /migrations/m151122_170331_create_lookup_account_type.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_account_type}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_account_type_value_unique", "{{%lkp_account_type}}", "value", false); 27 | 28 | $this->insert("{{%lkp_account_type}}", ['id'=>'1','value'=>'Prospect','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 29 | $this->insert("{{%lkp_account_type}}", ['id'=>'2','value'=>'Active','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 30 | $this->insert("{{%lkp_account_type}}", ['id'=>'3','value'=>'Inactive','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 31 | $this->insert("{{%lkp_account_type}}", ['id'=>'4','value'=>'Expired','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 32 | $this->insert("{{%lkp_account_type}}", ['id'=>'5','value'=>'Reseller','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 33 | $this->insert("{{%lkp_account_type}}", ['id'=>'6','value'=>'Partner','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 34 | $this->insert("{{%lkp_account_type}}", ['id'=>'7','value'=>'Other','deleted_at'=>NULL,'created_at'=>'2015-05-05 11:27:02','updated_at'=>'2015-05-05 11:27:02']); 35 | } 36 | 37 | public function down() 38 | { 39 | if (YII_ENV=='dev') 40 | $this->dropTable('{{%lkp_account_type}}'); 41 | else 42 | echo '***** SKIPPED DROPPING {{%lkp_account_type}} TABLE - NOT DEV SERVER *****'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /migrations/m151122_172814_create_lookup_lead_source.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyIsam'; 13 | } 14 | 15 | $this->createTable("{{%lkp_lead_source}}", [ 16 | "id" => Schema::TYPE_INTEGER . "(10) UNSIGNED NOT NULL AUTO_INCREMENT", 17 | "value" => Schema::TYPE_STRING . "(255) COLLATE utf8_unicode_ci NOT NULL", 18 | "idxpos" => Schema::TYPE_INTEGER . "(10) DEFAULT NULL", 19 | "editable" => Schema::TYPE_SMALLINT ." NOT NULL DEFAULT 1", 20 | "deleted_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 21 | "created_at" => Schema::TYPE_DATETIME ." DEFAULT NULL", 22 | "updated_at" => Schema::TYPE_TIMESTAMP ." NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP", 23 | "PRIMARY KEY(id)", 24 | ], $tableOptions); 25 | 26 | $this->createIndex("lkp_lead_source_value_unique", "{{%lkp_lead_source}}", "value", false); 27 | 28 | $this->insert("{{%lkp_lead_source}}", ['id'=>'1','value'=>'Web','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 29 | $this->insert("{{%lkp_lead_source}}", ['id'=>'2','value'=>'Phone Inquiry','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 30 | $this->insert("{{%lkp_lead_source}}", ['id'=>'3','value'=>'Activity Signup','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 31 | $this->insert("{{%lkp_lead_source}}", ['id'=>'4','value'=>'Partner Referral','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 32 | $this->insert("{{%lkp_lead_source}}", ['id'=>'5','value'=>'Product Purchase','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 33 | $this->insert("{{%lkp_lead_source}}", ['id'=>'6','value'=>'Purchased List','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 34 | $this->insert("{{%lkp_lead_source}}", ['id'=>'7','value'=>'Other','deleted_at'=>NULL,'created_at'=>'2015-10-18 14:17:00','updated_at'=>'2015-10-18 14:17:00']); 35 | } 36 | 37 | public function down() 38 | { 39 | if (YII_ENV=='dev') 40 | $this->dropTable('{{%lkp_lead_source}}'); 41 | else 42 | echo '***** SKIPPED DROPPING {{%lkp_lead_source}} TABLE - NOT DEV SERVER *****'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /views/commons/related-list-activity.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | activities)) 28 | foreach ($model->activities as $record) 29 | { 30 | $trClass=''; 31 | switch($record->priority_id) 32 | { 33 | case 1: $trClass='text-danger'; break; 34 | case 2: $trClass='text-warning'; break; 35 | case 3: $trClass='text-primary'; break; 36 | default: $trClass=''; 37 | } 38 | 39 | $actions=Html::a(Yii::t('main', 'View'), Url::to(['activity/view', 'id'=>$record->id])).'   '. 40 | Html::a(Yii::t('main', 'Edit'), Url::to(['activity/update', 'id'=>$record->id])); 41 | 42 | echo ' 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | '; 55 | } 56 | else 57 | echo ''; 58 | ?> 59 |
 
'.Html::encode($record->subject).''.Html::encode($record->location).''.Yii::$app->appHelper->getLookupValue('lkp_activity_type', $record->type_id).''.Yii::$app->appHelper->getLookupValue('lkp_activity_priority', $record->priority_id).''.Yii::$app->appHelper->getLookupValue('lkp_activity_status', $record->status_id).''.($record->status_id== Activity::STATUS_COMPLETED ? '' : '').''.$record->end_date.''.Yii::$app->appHelper->getLookupValue('users', $record->owner_id).''.$record->created_at.''.$record->updated_at.''.$actions.'
'.Yii::t('main', 'NO_RECORDS_FOUND').'
60 |
61 | -------------------------------------------------------------------------------- /views/report/report-pie_chart.php: -------------------------------------------------------------------------------- 1 | appHelper->getRandomColor(); 7 | 8 | $jsonData=preg_replace("/\"value\"\:\"([0-9]+)\",/im", "\"value\":\\1,", json_encode($data)); 9 | 10 | ?> 11 | 106 | -------------------------------------------------------------------------------- /views/opportunity/contact-form.php: -------------------------------------------------------------------------------- 1 | title=Yii::t('main', 'Select Related Contact'); 10 | 11 | $this->params['breadcrumbs'][]=['label' => Yii::t('main', 'Opportunity'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][]=$this->title; 13 | ?> 14 | 15 |
16 |
title ?>
17 |
18 | 19 | ['action'=>'/opportunity/addcontact/'.$model->id, 'class'=>'form-horizontal']]); ?> 20 | 21 | 22 | 23 | 24 | 25 | 26 | field($relation, 'opportunity_id')->hiddenInput()->label(false)?> 27 | 28 |
29 | 30 |
31 |
32 | 33 |
34 |
35 | field($relation, 'contact_id', $contactOptions)->label($useList ? false : null)->dropdownList( 41 | [($relation->contact_id ? intval($relation->contact_id) : '') => 42 | Html::encode($relation->contact_id ? $relation->contact->first_name . ' ' . $relation->contact->last_name : '')]); 43 | ?> 44 |
45 | 46 |
47 | id ? Yii::t('main', 'Save') : Yii::t('main', 'Update'); 49 | $onClick= !$relation->id ? 'return keywordSearchResultChecked("'.Yii::t('main', 'SELECT_FROM_SEARCH_RESULTS').'")' : 'return true'; 50 | echo Html::submitButton($value, ['name'=> 'submit1', 'value'=>'save', 'class' => 'btn btn-primary', 'onclick'=>'$("#formSubmit").val("save"); '.$onClick]); 51 | ?> 52 | $model->id]), ['class' => 'btn btn-success'])?> 53 |
54 |
55 | 56 | id) 58 | echo $this->render('../commons/change-helper-search-results', ['model' => $model, 'controller' => $controller, 'relation' => $relation, 'jsFunction'=>'setOpportunityRelatedContact']); 59 | else 60 | echo $this->render('../commons/change-helper-search-results-multi', ['model' => $model, 'controller' => $controller, 'relation' => $relation, 'useList' => $useList]); 61 | ?> 62 | 63 | 64 | --------------------------------------------------------------------------------