parent_id = $parent_id; $this->parent_type = $parent_type; $this->amount = $amount; $this->currency_id = $currency_id; $this->apply_to_period = $apply_to_period; $this->adjust_for_period = $adjust_for_period; $this->category_id = $category_id; $this->comment = $comment; $this->manual_adjustment_id = $manual_adjustment_id; } /** * Return product_type_id of given $upc. * * @param int $upc * @return integer */ public static function getProductTypeId($upc) { if (!empty($upc)) { $releaseObj = Model_Releases::getReleaseByUPC($upc); return ($releaseObj['product_type_id']) ? $releaseObj['product_type_id'] : null; } } /** * Validate manual adjustment values * * @param array $params array of params * @param QueryWrapper $wrapperObj * * Valid keys are: * * ['parentType'] ParentType (required) * ['parentId'] ParentId (required) * ['upc'] UPC * ['amount'] Amount (required) * ['currencyId'] CurrencyId (required) * ['applyToPeriod'] Period when the adjustment * will take place (required) * ['adjustForPeriod'] Period for which we adjust (required) * ['category'] Category (required) * ['comment'] Comment (required) * * @return string validation error messages if not valid */ public static function validate(array $params, QueryWrapper $wrapperObj, $isMigratedVendorsFFEnabled = False) { $required = array( // all except UPC 'parentType', 'parentId', 'amount', 'currencyId', 'applyToPeriod', 'adjustForPeriod', 'categoryId', 'comment' ); $validationErrors = array(); foreach ($required as $requiredField) { if (empty($params[$requiredField])) { $validationErrors[] = 'Missing '.$requiredField.'.'; } } if ($params['upc'] && !$params['distributionContextType'] && (!in_array(self::getProductTypeId($params['upc']), array(2, 3))) ) { $validationErrors[] = 'Missing Distribution Context Type'; } if (count($validationErrors)) { return '
  • '.implode('
  • ', $validationErrors).'
  • '; } foreach ($params as $name => $value) { switch ($name) { case 'parentType': if (!in_array( $value, array('vendor', 'oms_client', 'publisher', 'partner') )) { $validationErrors[] = 'Invalid Parent Type.'; } break; case 'parentId': if (!is_numeric($value)) { $validationErrors[] = 'Invalid Parent ID.'; } else { if ($isMigratedVendorsFFEnabled) $validateParentError = self::validateParentIdExist($params['parentType'], $params['parentId'], $wrapperObj); else $validateParentError = self::validateParent($params['parentType'], $params['parentId'], $wrapperObj); if (!empty($validateParentError)) { $validationErrors[] = $validateParentError; } } break; case 'amount': if (!is_numeric($value)) { $validationErrors[] = 'Invalid amount.'; } break; case 'upc': if (!empty($value)) { // UPC is optional if (is_numeric($value)) { if ($params['parentType'] == 'vendor' && !Model_Releases::getAllProductByDisplayUpc($value, strtolower($params['distributionContextType']), $params['parentId'])) { $validationErrors[] = 'UPC does not belong to the vendor.'; } } else { $validationErrors[] = 'Invalid UPC.'; } } break; case 'distributionContextType': if ($params['distributionContextType'] && !in_array(strtolower($params['distributionContextType']), array('physical', 'digital'), true)) { $validationErrors[] = 'Invalid Distribution Context Type'; } elseif ($params['upc'] && $params['parentType'] != 'vendor') { $validationErrors[] = 'In order to associate UPC for specific context type, Parent type must be vendor.'; } elseif ($params['upc']) { $vendorId = $params['parentType'] == 'vendor' ? $params['parentId'] : null; $releaseData = Model_Releases::getAllProductByDisplayUpc($params['upc'], strtolower($params['distributionContextType']), $vendorId); if (!$releaseData) { $validationErrors[] = 'No ' . ucfirst($params['distributionContextType']) . ' product with display_upc : ' . $params['upc'] . 'found. Please confirm this is a ' . ucfirst($params['distributionContextType']) . ' product and the UPC is valid'; } } break; } } return count($validationErrors) ? '
  • '.implode('
  • ', $validationErrors).'
  • ' : ''; } /** * Validates the parentId given the parent type * * @param string $parentType Parent Type * @param string|int $parentId Parent ID * @param QueryWrapper $wrapperObj * @return string validation error message if not valid */ public static function validateParent($parentType, $parentId, QueryWrapper $wrapperObj) { $errorMessage = ''; if (!is_numeric($parentId)) { $errorMessage = 'c15c09f6'; } else { switch ($parentType) { case 'vendor': $sql = 'SELECT vendor_id FROM vendor WHERE vendor_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = '868e7c67'; } break; case 'oms_client': $sql = 'SELECT oms_client_id FROM oms_client WHERE oms_client_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = '6f14fbf5'; } break; case 'publisher': $sql = 'SELECT publisher_id FROM publishers WHERE publisher_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = '7a05e8c8'; } break; case 'partner': $sql = 'SELECT owner_id FROM owner WHERE owner_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = '48015cf4'; } break; default: $errorMessage = '5a9d141c'; break; } } return $errorMessage; } /** * Validates the parentId for the specified parentType exist in the db table * * @param string $parentType Parent Type * @param string|int $parentId Parent ID * @param QueryWrapper $wrapperObj * @param Boolean $isMigratedVendorsFFEnabled Feature flag * @return string validation error message if not valid */ public static function validateParentIdExist($parentType, $parentId, QueryWrapper $wrapperObj) { $errorMessage = ''; switch ($parentType) { case 'vendor': $sql = 'SELECT vendor_id FROM vendor WHERE vendor_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = 'Please insert valid vendor Id.'; } $sql = 'SELECT vendor_id FROM vendor WHERE vendor_id = ? AND migrated_to_abacus = 1'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 1) $errorMessage = 'You cannot upload/add adjustments for a vendor that have been migrated to Abacus.'; break; case 'oms_client': $sql = 'SELECT oms_client_id FROM oms_client WHERE oms_client_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = 'Please insert valid oms client Id.'; } break; case 'publisher': $sql = 'SELECT publisher_id FROM publishers WHERE publisher_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = 'Please insert valid publisher Id.'; } break; case 'partner': $sql = 'SELECT owner_id FROM owner WHERE owner_id = ?'; $result = $wrapperObj->executeQuery($sql, [$parentId]); if (count($result) == 0) { $errorMessage = 'Please insert valid partner Id.'; } break; default: $errorMessage = 'Invalid Parent Type.'; break; } return $errorMessage; } /** * Verify that the current applyToPeriod is either the * last processed period or further * * @param accounting_period $applyToPeriod Period ID when the adjustment will take place * @param QueryWrapper $wrapperObj PDO Query wrapper obj * @return boolean whether the applyTo period is valid or not */ public static function checkApplyToDates($applyToPeriod, $wrapperObj) { if ($applyToPeriod) { $lastPeriod = accounting::get_last_processed_period($wrapperObj); if ($applyToPeriod->compare($lastPeriod) < 0) { return false; } } return true; } /** * Update a manual adjustment record * * @param QueryWrapper $wrapperObj PDO wrapper object * @param int $user_id Logged in orchard admin user id * @return string potential validation error messages */ public function update(QueryWrapper $wrapperObj, $user_id = 0, $isMigratedVendorsFFEnabled = False) { $errorMessage = self::validate(array( 'parentType' => $this->parent_type, 'parentId' => $this->parent_id, 'amount' => $this->amount, 'currencyId' => $this->currency_id, 'applyToPeriod' => $this->apply_to_period, 'adjustForPeriod' => $this->adjust_for_period, 'categoryId' => $this->category_id, 'comment' => $this->comment ), $wrapperObj, $isMigratedVendorsFFEnabled); // If periods are valid (and have potentially changed), we need to update // the amount with the new FX rate $updateAmount = self::checkApplyToDates($this->apply_to_period, $wrapperObj); $applyToPeriodId = $this->apply_to_period->getPeriodID(); // save original amount in manual_adjustment.amount_in_original_currency $originalCurrencyAmount = $this->amount; if ($this->currency_id == 1) { $amount = $this->amount; // if USD then save amount } else { // if currency is not USD then convert it into specified currency and // save in manual_adjustment.amount (For getting exchange rate value: // period id should be the selected value of Apply To dropdown) $hndCurrencyExchange = new Model_CurrencyExchangeRates(); $amount = $hndCurrencyExchange->convertAmountFromCurrencyToAnother( $applyToPeriodId, $this->amount, $this->currency_id, '1' ); } if (empty($errorMessage)) { $data_params = []; $query = ' UPDATE manual_adjustment SET adjust_for_period_id = ?, category_id = ?,'; $data_params[] = $this->adjust_for_period->getPeriodID(); $data_params[] = $this->category_id; if ($updateAmount) { $query .= ' parent_id = ?, parent_type = ?, amount = ?, currencies_id = ?, apply_to_period_id = ?, amount_in_original_currency = ?,'; $apply_to_period_id = $this->apply_to_period->getPeriodID(); $data_params[] = $this->parent_id; $data_params[] = $this->parent_type; $data_params[] = $amount; $data_params[] = $this->currency_id; $data_params[] = $apply_to_period_id; $data_params[] = $originalCurrencyAmount; } $query .= ' last_modified_by = ?, user_type = ?,'; $data_params[] = $user_id; $data_params[] = 'oa'; $query .= ' comment = ? WHERE id = ?'; $data_params[] = $this->comment; $data_params[] = $this->manual_adjustment_id; $wrapperObj->executeQuery($query, $data_params, QueryWrapper::RETURN_AFFECTED_ROWS); return true; } return $errorMessage; } /** * Validate manual adjustment values prior to insert * * @see self::validate * @param array $params array of params * @param QueryWrapper $wrapperObj * * Valid keys are: * * ['parentType'] ParentType (required) * ['parentId'] ParentId (required) * ['upc'] UPC * ['amount'] Amount (required) * ['currencyId'] CurrencyId (required) * ['applyToPeriod'] Period when the adjustment * will take place (required) * ['adjustForPeriod'] Period for which we adjust (required) * ['comment'] Comment (required) * * @return string validation error messages if not valid */ public static function validateForInsert(array $params, QueryWrapper $wrapperObj, $isMigratedVendorsFFEnabled = False) { $errorMessage = self::validate($params, $wrapperObj, $isMigratedVendorsFFEnabled); if (!empty($params['applyToPeriod']) && !self::checkApplyToDates($params['applyToPeriod'], $wrapperObj)) { $errorMessage .= '
  • Invalid apply to period provided.

  • '; } return $errorMessage; } /** * Creates a manual adjustment * * @param int $user_id UserId * @param QueryWrapper $wrapperObj PDO wrapper object * @return string potential validation error messages */ public function insert($user_id, QueryWrapper $wrapperObj, $isMigratedVendorsFFEnabled = False) { $errorMessage = self::validateForInsert(array( 'parentType' => $this->parent_type, 'parentId' => $this->parent_id, 'amount' => $this->amount, 'currencyId' => $this->currency_id, 'applyToPeriod' => $this->apply_to_period, 'adjustForPeriod' => $this->adjust_for_period, 'categoryId' => $this->category_id, 'comment' => $this->comment ), $wrapperObj, $isMigratedVendorsFFEnabled); $applyToPeriodId = $this->apply_to_period->getPeriodID(); // save original amount in manual_adjustment.amount_in_original_currency $originalCurrencyAmount = $this->amount; if ($this->currency_id == 1) { $amount = $this->amount; // if USD then save amount } else { // if currency is not USD then convert it into specified currency and // save in manual_adjustment.amount (For getting exchange rate value: // period id should be the selected value of Apply To dropdown) $hndCurrencyExchange = new Model_CurrencyExchangeRates(); $amount = $hndCurrencyExchange->convertAmountFromCurrencyToAnother( $applyToPeriodId, $this->amount, $this->currency_id, '1' ); } if (!$errorMessage) { $data_params = []; $query = ' INSERT INTO manual_adjustment( parent_id, parent_type, date_added, created_by, amount, currencies_id, adjust_for_period_id, apply_to_period_id, category_id, comment, amount_in_original_currency, last_modified_by, user_type ) VALUES(?, ?, now(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; $adjust_for_period_id = $this->adjust_for_period->getPeriodID(); $apply_to_period_id = $this->apply_to_period->getPeriodID(); $data_params[] = $this->parent_id; $data_params[] = $this->parent_type; $data_params[] = $user_id; $data_params[] = $amount; $data_params[] = $this->currency_id; $data_params[] = $adjust_for_period_id; $data_params[] = $apply_to_period_id; $data_params[] = $this->category_id; $data_params[] = $this->comment; $data_params[] = $originalCurrencyAmount; $data_params[] = $user_id; $data_params[] = 'oa'; return $wrapperObj->executeQuery($query, $data_params, QueryWrapper::RETURN_INSERT_ID); } else { return $errorMessage; } } /** * Creates release manual adjustment * * @param int $userId * @param int $upc * @param QueryWrapper $wrapperObj PDO wrapper object * @return mix Potential validation error message or last inserted id */ public function insertReleaseManualAdjustment($userId, $upc, QueryWrapper $wrapperObj, $context_type = null, $isMigratedVendorsFFEnabled = False) { $errorMessage = self::validateForInsert(array( 'parentType' => $this->parent_type, 'parentId' => $this->parent_id, 'amount' => $this->amount, 'currencyId' => $this->currency_id, 'applyToPeriod' => $this->apply_to_period, 'adjustForPeriod' => $this->adjust_for_period, 'categoryId' => $this->category_id, 'comment' => $this->comment, 'upc' => $upc, 'distributionContextType' => $context_type ), $wrapperObj, $isMigratedVendorsFFEnabled); if (empty($errorMessage)) { $manualAdjustment = new stdClass(); $vendorId = $this->parent_type == 'vendor' ? $this->parent_id : null; $productModel = Model_Releases::getAllProductByDisplayUpc($upc, $context_type, $vendorId); $manualAdjustment->release = new stdClass(); $manualAdjustment->release->release_id = intval($productModel['release_id']); $manualAdjustment->release->ArtistInfo = new stdClass(); $manualAdjustment->release->ArtistInfo->vendor_id = $productModel['ArtistInfo']['vendor_id']; $manualAdjustment->applyToPeriod = $this->apply_to_period; $manualAdjustment->adjustForPeriod = $this->adjust_for_period; $manualAdjustment->releaseManualAdjustment = new Model_ReleaseManualAdjustment(); $manualAdjustment->releaseManualAdjustment->date_created = date('Y-m-d H:i:s'); $manualAdjustment->releaseManualAdjustment->created_by = $userId; $manualAdjustment->releaseManualAdjustment->category_id = $this->category_id; $manualAdjustment->releaseManualAdjustment->release_id = $manualAdjustment->release->release_id; $manualAdjustment->releaseManualAdjustment->amount = $this->amount; $manualAdjustment->releaseManualAdjustment->currencies_id = $this->currency_id; $manualAdjustment->releaseManualAdjustment->description = $this->comment; $manualAdjustment->releaseManualAdjustment->last_modified_by = $userId; $manualAdjustment->releaseManualAdjustment->user_type = 'oa'; // Release level manual adjustment $manualAdjustment->releaseManualAdjustment->saveAndAggregate( $manualAdjustment->release->ArtistInfo->vendor_id, $manualAdjustment->applyToPeriod->getPeriodID(), $manualAdjustment->adjustForPeriod->getPeriodID(), $userId, 'oa' ); // Get last inserted manual adjustment id in manual_adjustment table $lastInsertedId = $manualAdjustment->releaseManualAdjustment->getLastInsertedVendorManualAdjustment(); return $lastInsertedId; } return $errorMessage; } }