<commit_before><?php
/**
 * Copyright (c) 2015, Praxigento
 * All rights reserved.
 */
use Praxigento_Bonus_Config as Config;
use Praxigento_Bonus_Model_Own_Balance as Balance;
use Praxigento_Bonus_Model_Own_Operation as Operation;
use Praxigento_Bonus_Model_Own_Period as Period;
use Praxigento_Bonus_Model_Own_Transaction as Transaction;
use Praxigento_Bonus_Service_Period_Response_GetPeriodForPersonalBonus as GetPeriodForPersonalBonus;

/**
 * User: <NAME> <<EMAIL>>
 */
/*
 *  __DIR__ returns absolute path if Magento module is mounted using symbolic link
 * we need to include __DIR__ . '/../../abstract.php'
 */
$dir = dirname(dirname(dirname($_SERVER['SCRIPT_NAME'])));
require_once $dir . '/abstract.php';

class Praxigento_Shell extends Mage_Shell_Abstract
{
    const DEFAULT_UPLINE = 100000001;
    const OPT_CREATE = 'create';
    const OPT_EMULATE = 'emulate';
    const OPT_BONUS_PV = 'bonusPv';
    /** @var Logger */
    private $_log;
    private $_fileNameCustomers;
    private $_fileNameOrders;
    private $_fileNamePvTransfers;
    /**
     * Registry to store customer data with Sponsor (Upline) ID as a key.
     *
     *
     * @var array
     */
    private $_regUpline = array();
    private $_categoryElectronics;

    public function __construct()
    {
        parent::__construct();
        $this->_log = Praxigento_Log_Logger::getLogger(__CLASS__);
        $this->_fileNameCustomers = dirname($_SERVER['SCRIPT_NAME']) . '/data_customers.csv';
        $this->_fileNameOrders = dirname($_SERVER['SCRIPT_NAME']) . '/data_orders.csv';
        $this->_fileNamePvTransfers = dirname($_SERVER['SCRIPT_NAME']) . '/data_pv_transfers.csv';
    }

    /**
     * Run script
     *
     */
    public function run()
    {
        $create = $this->getArg(self::OPT_CREATE);
        $emulate = $this->getArg(self::OPT_EMULATE);
        $bonusPv = $this->getArg(self::OPT_BONUS_PV);
        if ($create || $emulate || $bonusPv) {
            if ($create) {
                $this->_log->debug("Sample data generation is started.");
                $this->_createCatalogCategories();
                $this->_createProducts();
                $this->_createCustomers();
                $this->_createOrders();
                $this->_log->debug("Sample data generation is completed.");
            }
            if ($emulate) {
                /* add fake data to bonus module */
                $this->_emulateOrderOperations();
                $this->_emulatePvTransferOperations();
            }
            if ($bonusPv) {
                $this->_calcPvWriteOff();
//                $this->_calcBonusPv();
            }
            echo 'Done.';
        } else {
            echo $this->usageHelp();
        }

    }

    /**
     * We should write off PV for every period.
     */
    private function _calcPvWriteOff()
    {
        /** @var  $helper Praxigento_Bonus_Helper_Data */
        $helper = Config::get()->helper();
        /** @var  $helperType Praxigento_Bonus_Helper_Type */
        $helperType = Config::get()->helperType();
        $periodCode = $helper->cfgPersonalBonusPeriod();
        $typePeriod = $helperType->getPeriod($periodCode);
        $typeCalc = $helperType->getCalc(Config::CALC_PV_WRITE_OFF);
        $typeOperPvInt = $helperType->getOper(Config::OPER_PV_INT);
        $typeOperPvOrder = $helperType->getOper(Config::OPER_ORDER_PV);
        $operIds = array($typeOperPvInt->getId(), $typeOperPvOrder->getId());
        /* get calculation period */
        $result = null;
        /** @var  $call Praxigento_Bonus_Service_Period_Call */
        $call = Config::get()->servicePeriod();
        /** @var  $req  Praxigento_Bonus_Service_Period_Request_GetPeriodForPvWriteOff */
        $req = $call->requestPeriodForPvWriteOff();
        $req->setCalcTypeId($typeCalc->getId());
        $req->setOperationTypeIds($operIds);
        $req->setPeriodCode($periodCode);
        $req->setPeriodTypeId($typePeriod->getId());
        /** @var  $resp Praxigento_Bonus_Service_Period_Response_GetPeriodForPvWriteOff */
        $resp = $call->getPeriodForPvWriteOff($req);
        if ($resp->isSucceed()) {
            $periodValue = $resp->getPeriodValue();
            $this->_log->debug("Period '$periodValue' should be used for calculation.");
            /** @var  $period Praxigento_Bonus_Model_Own_Period */
            $period = Mage::getModel('prxgt_bonus_model/period');
            /** @var  $logCalc Praxigento_Bonus_Model_Own_Log_Calc */
            $logCalc = Mage::getModel('prxgt_bonus_model/log_calc');
            if ($resp->isNewPeriod()) {
                $this->_log->debug("New calculation for period '$periodValue' should be registered.");
                /* insert new calculation period into DB */
                $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
                $connection->beginTransaction();
                try {
                    /* look up for existing period */
                    $periods = Config::collectionPeriod();
                    $periods->addFieldToFilter(Period::ATTR_CALC_TYPE_ID, $typeCalc->getId());
                    $periods->addFieldToFilter(Period::ATTR_VALUE, $resp->getPeriodValue());
                    if ($periods->getSize() == 0) {
                        /* add new period */
                        $period->setType($typePeriod->getId());
                        $period->setCalcTypeId($typeCalc->getId());
                        $period->setValue($resp->getPeriodValue());
                        $period->save();
                    } else {
                        $this->_log->debug("Period '$periodValue' already exists.");
                        $period = $periods->getFirstItem();
                    }
                    /* add item to calculation log */
                    $logCalc->setPeriodId($period->getId());
                    $logCalc->setState(Config::STATE_PERIOD_PROCESSING);
                    $logCalc->save();
                    $connection->commit();
                    $this->_log->debug("New period '{$period->getValue()}' (#{$period->getId()}) is created to process personal bonus.");
                } catch (Exception $e) {
                    $this->_log->error(
                        "Cannot register new calculation period ({$resp->getPeriodValue()}). Error: "
                        . $e->getMessage()
                    );
                    $connection->rollBack();

                }

            } else {
                $period->load($resp->getExistingPeriodId());
                $logCalc->load($resp->getExistingLogCalcId());
                $this->_log->debug("Existing period '{$period->getValue()}' (#{$period->getId()}) is used to process personal bonus. Calculation #{$logCalc->getId()}.");
            }
            /* select all operation for period */
            $opers = $this->_getOperationsForPvWriteOff($logCalc->getId(), $periodValue, $periodCode);
            /* for all operations we need calculate period balances and create PV write off operations. */
            foreach ($opers as $item) {
                $id = $item->getId();
            }
            1 + 1;
        } else {
            if ($resp->getErrorCode() == GetPeriodForPersonalBonus::ERR_NOTHING_TO_DO) {<commit_msg>MOBI-66 - PV Write-Off modelling<commit_after><?php
/**
 * Copyright (c) 2015, Praxigento
 * All rights reserved.
 */
use Praxigento_Bonus_Config as Config;
use Praxigento_Bonus_Model_Own_Balance as Balance;
use Praxigento_Bonus_Model_Own_Operation as Operation;
use Praxigento_Bonus_Model_Own_Period as Period;
use Praxigento_Bonus_Model_Own_Transaction as Transaction;
use Praxigento_Bonus_Service_Period_Response_GetPeriodForPersonalBonus as GetPeriodForPersonalBonus;

/**
 * User: <NAME> <<EMAIL>>
 */
/*
 *  __DIR__ returns absolute path if Magento module is mounted using symbolic link
 * we need to include __DIR__ . '/../../abstract.php'
 */
$dir = dirname(dirname(dirname($_SERVER['SCRIPT_NAME'])));
require_once $dir . '/abstract.php';

class Praxigento_Shell extends Mage_Shell_Abstract
{
    const DEFAULT_UPLINE = 100000001;
    const OPT_CREATE = 'create';
    const OPT_EMULATE = 'emulate';
    const OPT_BONUS_PV = 'bonusPv';
    /** @var Logger */
    private $_log;
    private $_fileNameCustomers;
    private $_fileNameOrders;
    private $_fileNamePvTransfers;
    /**
     * Registry to store customer data with Sponsor (Upline) ID as a key.
     *
     *
     * @var array
     */
    private $_regUpline = array();
    private $_categoryElectronics;

    public function __construct()
    {
        parent::__construct();
        $this->_log = Praxigento_Log_Logger::getLogger(__CLASS__);
        $this->_fileNameCustomers = dirname($_SERVER['SCRIPT_NAME']) . '/data_customers.csv';
        $this->_fileNameOrders = dirname($_SERVER['SCRIPT_NAME']) . '/data_orders.csv';
        $this->_fileNamePvTransfers = dirname($_SERVER['SCRIPT_NAME']) . '/data_pv_transfers.csv';
    }

    /**
     * Run script
     *
     */
    public function run()
    {
        $create = $this->getArg(self::OPT_CREATE);
        $emulate = $this->getArg(self::OPT_EMULATE);
        $bonusPv = $this->getArg(self::OPT_BONUS_PV);
        if ($create || $emulate || $bonusPv) {
            if ($create) {
                $this->_log->debug("Sample data generation is started.");
                $this->_createCatalogCategories();
                $this->_createProducts();
                $this->_createCustomers();
                $this->_createOrders();
                $this->_log->debug("Sample data generation is completed.");
            }
            if ($emulate) {
                /* add fake data to bonus module */
                $this->_emulateOrderOperations();
                $this->_emulatePvTransferOperations();
            }
            if ($bonusPv) {
                $this->_calcPvWriteOff();
//                $this->_calcBonusPv();
            }
            echo 'Done.';
        } else {
            echo $this->usageHelp();
        }

    }

    /**
     * We should write off PV for every period.
     */
    private function _calcPvWriteOff()
    {
        /** @var  $helper Praxigento_Bonus_Helper_Data */
        $helper = Config::get()->helper();
        /** @var  $helperType Praxigento_Bonus_Helper_Type */
        $helperType = Config::get()->helperType();
        $periodCode = $helper->cfgPersonalBonusPeriod();
        $typePeriod = $helperType->getPeriod($periodCode);
        $typeCalc = $helperType->getCalc(Config::CALC_PV_WRITE_OFF);
        $typeOperPvInt = $helperType->getOper(Config::OPER_PV_INT);
        $typeOperPvOrder = $helperType->getOper(Config::OPER_ORDER_PV);
        $operIds = array($typeOperPvInt->getId(), $typeOperPvOrder->getId());
        /* get calculation period */
        $result = null;
        /** @var  $call Praxigento_Bonus_Service_Period_Call */
        $call = Config::get()->servicePeriod();
        /** @var  $req  Praxigento_Bonus_Service_Period_Request_GetPeriodForPvWriteOff */
        $req = $call->requestPeriodForPvWriteOff();
        $req->setCalcTypeId($typeCalc->getId());
        $req->setOperationTypeIds($operIds);
        $req->setPeriodCode($periodCode);
        $req->setPeriodTypeId($typePeriod->getId());
        /** @var  $resp Praxigento_Bonus_Service_Period_Response_GetPeriodForPvWriteOff */
        $resp = $call->getPeriodForPvWriteOff($req);
        if ($resp->isSucceed()) {
            $periodValue = $resp->getPeriodValue();
            $this->_log->debug("Period '$periodValue' should be used for calculation.");
            /** @var  $period Praxigento_Bonus_Model_Own_Period */
            $period = Mage::getModel('prxgt_bonus_model/period');
            /** @var  $logCalc Praxigento_Bonus_Model_Own_Log_Calc */
            $logCalc = Mage::getModel('prxgt_bonus_model/log_calc');
            if ($resp->isNewPeriod()) {
                $this->_log->debug("New calculation for period '$periodValue' should be registered.");
                /* insert new calculation period into DB */
                $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
                $connection->beginTransaction();
                try {
                    /* look up for existing period */
                    $periods = Config::collectionPeriod();
                    $periods->addFieldToFilter(Period::ATTR_CALC_TYPE_ID, $typeCalc->getId());
                    $periods->addFieldToFilter(Period::ATTR_VALUE, $resp->getPeriodValue());
                    if ($periods->getSize() == 0) {
                        /* add new period */
                        $period->setType($typePeriod->getId());
                        $period->setCalcTypeId($typeCalc->getId());
                        $period->setValue($resp->getPeriodValue());
                        $period->save();
                    } else {
                        $this->_log->debug("Period '$periodValue' already exists.");
                        $period = $periods->getFirstItem();
                    }
                    /* add item to calculation log */
                    $logCalc->setPeriodId($period->getId());
                    $logCalc->setState(Config::STATE_PERIOD_PROCESSING);
                    $logCalc->save();
                    $connection->commit();
                    $this->_log->debug("New period '{$period->getValue()}' (#{$period->getId()}) is created to process personal bonus.");
                } catch (Exception $e) {
                    $this->_log->error(
                        "Cannot register new calculation period ({$resp->getPeriodValue()}). Error: "
                        . $e->getMessage()
                    );
                    $connection->rollBack();

                }

            } else {
                $period->load($resp->getExistingPeriodId());
                $logCalc->load($resp->getExistingLogCalcId());
                $this->_log->debug("Existing period '{$period->getValue()}' (#{$period->getId()}) is used to process personal bonus. Calculation #{$logCalc->getId()}.");
            }
            /* select all operation for period */
            $opers = $this->_getOperationsForPvWriteOff($logCalc->getId(), $periodValue, $periodCode);
            /* for all operations we need calculate period balances and create PV write off operations. */
            $balance = array();
            foreach ($opers as $item) {
                $debitAccId = $item->getData('debit_acc_id');
                $creditAccId = $item->getData('credit_acc_id');
                $value = $item->getData('value');
                if (isset($balance[$debitAccId])) {
                    $balance[$debitAccId] -= $value;
                } else {
                    $balance[$debitAccId] = -$value;
                }
                if (isset($balance[$creditAccId])) {
                    $balance[$creditAccId] += $value;
                } else {
                    $balance[$creditAccId] = $value;
                }
            }
            /* update balances */
            1 + 1;
        } else {
            if ($resp->getErrorCode() == GetPeriodForPersonalBonus::ERR_NOTHING_TO_DO) {
{'fraction_non_alphanumeric': 0.1372857987000197, 'fraction_numerical': 0.0022322894097564177, 'mean_word_length': 2.1117466802860063, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 189, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6949229', 'n_tokens_mistral': 4366, 'n_tokens_neox': 4216, 'n_words': 781}