NEW: deposit payment terms: generate deposit from proposal
This commit is contained in:
parent
8cb6cdf1bc
commit
81ddc6c0f6
@ -684,11 +684,46 @@ if (empty($reshook)) {
|
||||
$error++;
|
||||
}
|
||||
|
||||
$deposit = null;
|
||||
$locationTarget = $_SERVER['PHP_SELF'] . '?id=' . $object->id;
|
||||
|
||||
if (!$error && GETPOST('statut', 'int') == $object::STATUS_SIGNED && GETPOST('generate_deposit', 'int') > 0) {
|
||||
$deposit = Facture::createDepositFromOrigin($object, $user, 0, GETPOST('validate_generated_deposit', 'int') > 0);
|
||||
|
||||
if ($deposit) {
|
||||
setEventMessage('DepositGenerated');
|
||||
$locationTarget = DOL_URL_ROOT . '/compta/facture/card.php?id=' . $deposit->id;
|
||||
} else {
|
||||
$error++;
|
||||
setEventMessages($object->error, $object->errors, 'errors');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$db->commit();
|
||||
|
||||
if ($deposit && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
|
||||
$ret = $deposit->fetch($deposit->id); // Reload to get new records
|
||||
$outputlangs = $langs;
|
||||
|
||||
if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
|
||||
$outputlangs = new Translate('', $conf);
|
||||
$outputlangs->setDefaultLang($deposit->thirdparty->default_lang);
|
||||
$outputlangs->load('products');
|
||||
}
|
||||
|
||||
$result = $deposit->generateDocument($deposit->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
||||
|
||||
if ($result < 0) {
|
||||
setEventMessages($deposit->error, $deposit->errors, 'errors');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$db->rollback();
|
||||
}
|
||||
|
||||
header('Location: ' . $locationTarget);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} elseif ($action == 'confirm_reopen' && $usercanclose && !GETPOST('cancel', 'alpha')) {
|
||||
@ -1934,6 +1969,71 @@ if ($action == 'create') {
|
||||
array('type' => 'text', 'name' => 'note_private', 'label' => $langs->trans("Note"), 'value' => '') // Field to complete private note (not replace)
|
||||
);
|
||||
|
||||
$deposit_percent_from_payment_terms = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $object->cond_reglement_id);
|
||||
|
||||
if (! empty($deposit_percent_from_payment_terms)) {
|
||||
$object->fetchObjectLinked();
|
||||
|
||||
$eligibleForDepositGeneration = true;
|
||||
|
||||
if (array_key_exists('facture', $object->linkedObjects)) {
|
||||
foreach ($object->linkedObjectsIds['facture'] as $invoice) {
|
||||
if ($invoice->type == Facture::TYPE_DEPOSIT) {
|
||||
$eligibleForDepositGeneration = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($eligibleForDepositGeneration && array_key_exists('commande', $object->linkedObjects)) {
|
||||
foreach ($object->linkedObjects['commande'] as $order) {
|
||||
$order->fetchObjectLinked();
|
||||
|
||||
if (array_key_exists('facture', $order->linkedObjects)) {
|
||||
foreach ($order->linkedObjects['facture'] as $invoice) {
|
||||
if ($invoice->type == Facture::TYPE_DEPOSIT) {
|
||||
$eligibleForDepositGeneration = false;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($eligibleForDepositGeneration) {
|
||||
$formquestion[] = array(
|
||||
'type' => 'onecolumn',
|
||||
'name' => 'generate_deposit,validate_generated_deposit',
|
||||
'value' => '
|
||||
<div id="generate-deposit-box" style="display: none">
|
||||
<p>' . $langs->trans('PaymentConditionPermitsDepositGenerationSelected') . '</p>
|
||||
<p style="padding-left: 20%">
|
||||
<input type="checkbox" name="generate_deposit" id="generate_deposit" value="1" checked />
|
||||
<label for="generate_deposit">' . $langs->trans('GenerateDeposit', $object->deposit_percent) . '</label><br />
|
||||
<input type="checkbox" name="validate_generated_deposit" id="validate_generated_deposit" value="1" checked />
|
||||
<label for="validate_generated_deposit">' . $langs->trans('ValidateGeneratedDeposit') . '</label>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
let signedValue = ' . $object::STATUS_SIGNED . ';
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#statut").change(function(event) {
|
||||
if ($(this).val() == signedValue) {
|
||||
$("#generate-deposit-box").show();
|
||||
} else {
|
||||
$("#generate-deposit-box").hide();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($conf->notification->enabled)) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
|
||||
$notify = new Notify($db);
|
||||
|
||||
@ -1406,6 +1406,266 @@ class Facture extends CommonInvoice
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Propal|Commande $origin
|
||||
* @param User $user
|
||||
* @param type $notrigger
|
||||
* @param bool $autoValidate
|
||||
* @return Facture
|
||||
*/
|
||||
static public function createDepositFromOrigin(CommonObject $origin, User $user, $notrigger = 0, $autoValidateDeposit = false, $forceInvoiceDate = null)
|
||||
{
|
||||
global $conf, $langs, $hookmanager, $action;
|
||||
|
||||
if (! in_array($origin->element, array('propal', 'commande'))) {
|
||||
$origin->error = 'ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder'; // TRAD
|
||||
return null;
|
||||
}
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
|
||||
|
||||
$invoiceDate = ! empty($forceInvoiceDate) ? $forceInvoiceDate : dol_now();
|
||||
|
||||
if ($invoiceDate > (dol_get_last_hour(dol_now('tzuserrel')) + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) {
|
||||
$origin->error = 'ErrorDateIsInFuture';
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($origin->cond_reglement_id <= 0) {
|
||||
$origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('PaymentConditionsShort'));
|
||||
return null;
|
||||
}
|
||||
|
||||
$payment_conditions_deposit_percent = getDictvalue(MAIN_DB_PREFIX . 'c_payment_term', 'deposit_percent', $origin->cond_reglement_id);
|
||||
|
||||
if (empty($payment_conditions_deposit_percent)) {
|
||||
$origin->error = 'ErrorPaymentConditionsNotEligibleToDepositCreation';
|
||||
return null;
|
||||
}
|
||||
|
||||
if (empty($origin->deposit_percent)) {
|
||||
$origin->error = $langs->trans('ErrorFieldRequired', $langs->transnoentities('DepositPercent'));
|
||||
return null;
|
||||
}
|
||||
|
||||
$deposit = new self($origin->db);
|
||||
$deposit->socid = $origin->socid;
|
||||
$deposit->type = self::TYPE_DEPOSIT;
|
||||
$deposit->fk_project = $origin->fk_project;
|
||||
$deposit->ref_client = $origin->ref_client;
|
||||
$deposit->date = $invoiceDate;
|
||||
$deposit->mode_reglement_id = $origin->mode_reglement_id; // CHECK
|
||||
// TODO Deposit is always due upon reception ?
|
||||
$deposit->availability_id = $origin->availability_id;
|
||||
$deposit->demand_reason_id = $origin->demand_reason_id;
|
||||
$deposit->fk_account = $origin->fk_account;
|
||||
$deposit->fk_incoterms = $origin->fk_incoterms;
|
||||
$deposit->location_incoterms = $origin->location_incoterms;
|
||||
$deposit->fk_multicurrency = $origin->fk_multicurrency;
|
||||
$deposit->multicurrency_code = $origin->multicurrency_code;
|
||||
$deposit->multicurrency_tx = $origin->multicurrency_tx;
|
||||
$deposit->module_source = $origin->module_source;
|
||||
$deposit->pos_source = $origin->pos_source;
|
||||
$deposit->model_pdf = 'crabe';
|
||||
|
||||
$modelByTypeConfName = 'FACTURE_ADDON_PDF_' . $deposit->type;
|
||||
|
||||
if (!empty($conf->global->$modelByTypeConfName)) {
|
||||
$deposit->model_pdf = $conf->global->$modelByTypeConfName;
|
||||
} elseif (!empty($conf->global->FACTURE_ADDON_PDF)) {
|
||||
$deposit->model_pdf = $conf->global->FACTURE_ADDON_PDF;
|
||||
}
|
||||
|
||||
if (empty($conf->global->MAIN_DISABLE_PROPAGATE_NOTES_FROM_ORIGIN)) {
|
||||
$deposit->note_private = $origin->note_private;
|
||||
$deposit->note_public = $origin->note_public;
|
||||
}
|
||||
|
||||
$deposit->origin = $origin->element;
|
||||
$deposit->origin_id = $origin->id;
|
||||
|
||||
$origin->fetch_optionals();
|
||||
|
||||
foreach ($origin->array_options as $extrakey => $value) {
|
||||
$deposit->array_options[$extrakey] = $value;
|
||||
}
|
||||
|
||||
$deposit->linked_objects[$deposit->origin] = $deposit->origin_id;
|
||||
|
||||
$deposit->context['createdepositfromorigin'] = 'createdepositfromorigin';
|
||||
|
||||
$origin->db->begin();
|
||||
|
||||
// Facture::create() also imports contact from origin
|
||||
$createReturn = $deposit->create($user, $notrigger);
|
||||
|
||||
if ($createReturn <= 0) {
|
||||
$origin->db->rollback();
|
||||
$origin->error = $deposit->error;
|
||||
$origin->errors = $deposit->errors;
|
||||
return null;
|
||||
}
|
||||
|
||||
$amount_ttc_diff = 0;
|
||||
$amountdeposit = array();
|
||||
|
||||
if (! empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)) {
|
||||
$amount = $origin->total_ttc * ($origin->deposit_percent / 100);
|
||||
|
||||
$TTotalByTva = array();
|
||||
foreach ($origin->lines as &$line) {
|
||||
if (!empty($line->special_code)) {
|
||||
continue;
|
||||
}
|
||||
$TTotalByTva[$line->tva_tx] += $line->total_ttc;
|
||||
}
|
||||
|
||||
foreach ($TTotalByTva as $tva => &$total) {
|
||||
$coef = $total / $origin->total_ttc; // Calc coef
|
||||
$am = $amount * $coef;
|
||||
$amount_ttc_diff += $am;
|
||||
$amountdeposit[$tva] += $am / (1 + $tva / 100); // Convert into HT for the addline
|
||||
}
|
||||
} else {
|
||||
$totalamount = 0;
|
||||
$lines = $origin->lines;
|
||||
$numlines = count($lines);
|
||||
for ($i = 0; $i < $numlines; $i++) {
|
||||
if (empty($lines[$i]->qty)) {
|
||||
continue; // We discard qty=0, it is an option
|
||||
}
|
||||
if (!empty($lines[$i]->special_code)) {
|
||||
continue; // We discard special_code (frais port, ecotaxe, option, ...)
|
||||
}
|
||||
|
||||
$totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ?
|
||||
$tva_tx = $lines[$i]->tva_tx;
|
||||
$amountdeposit[$tva_tx] += ($lines[$i]->total_ht * $origin->deposit_percent) / 100;
|
||||
}
|
||||
|
||||
if ($totalamount == 0) {
|
||||
$amountdeposit[0] = 0;
|
||||
}
|
||||
|
||||
$amount_ttc_diff = $amountdeposit[0];
|
||||
}
|
||||
|
||||
foreach ($amountdeposit as $tva => $amount) {
|
||||
if (empty($amount)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$descline = '(DEPOSIT) ('. $origin->deposit_percent .'%) - '.$origin->ref;
|
||||
|
||||
$addlineResult = $deposit->addline(
|
||||
$descline,
|
||||
$amount, // subprice
|
||||
1, // quantity
|
||||
$tva, // vat rate
|
||||
0, // localtax1_tx
|
||||
0, // localtax2_tx
|
||||
(empty($conf->global->INVOICE_PRODUCTID_DEPOSIT) ? 0 : $conf->global->INVOICE_PRODUCTID_DEPOSIT), // fk_product
|
||||
0, // remise_percent
|
||||
0, // date_start
|
||||
0, // date_end
|
||||
0,
|
||||
$lines[$i]->info_bits, // info_bits
|
||||
0,
|
||||
'HT',
|
||||
0,
|
||||
0, // product_type
|
||||
1,
|
||||
$lines[$i]->special_code,
|
||||
$deposit->origin,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
//,$langs->trans('Deposit') //Deprecated
|
||||
);
|
||||
|
||||
if ($addlineResult < 0) {
|
||||
$origin->db->rollback();
|
||||
$origin->error = $deposit->error;
|
||||
$origin->errors = $deposit->errors;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$diff = $deposit->total_ttc - $amount_ttc_diff;
|
||||
|
||||
if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0) {
|
||||
$deposit->fetch_lines();
|
||||
$subprice_diff = $deposit->lines[0]->subprice - $diff / (1 + $deposit->lines[0]->tva_tx / 100);
|
||||
|
||||
$updatelineResult = $deposit->updateline(
|
||||
$deposit->lines[0]->id,
|
||||
$deposit->lines[0]->desc,
|
||||
$subprice_diff,
|
||||
$deposit->lines[0]->qty,
|
||||
$deposit->lines[0]->remise_percent,
|
||||
$deposit->lines[0]->date_start,
|
||||
$deposit->lines[0]->date_end,
|
||||
$deposit->lines[0]->tva_tx,
|
||||
0,
|
||||
0,
|
||||
'HT',
|
||||
$deposit->lines[0]->info_bits,
|
||||
$deposit->lines[0]->product_type,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$deposit->lines[0]->pa_ht,
|
||||
$deposit->lines[0]->label,
|
||||
0,
|
||||
array(),
|
||||
100
|
||||
);
|
||||
|
||||
if ($updatelineResult < 0) {
|
||||
$origin->db->rollback();
|
||||
$origin->error = $deposit->error;
|
||||
$origin->errors = $deposit->errors;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (! is_object($hookmanager)) {
|
||||
require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
|
||||
$hookmanager = new HookManager($origin->db);
|
||||
}
|
||||
|
||||
$hookmanager->initHooks(array('invoicedao'));
|
||||
|
||||
$parameters = array('objFrom' => $origin);
|
||||
$reshook = $hookmanager->executeHooks('createFrom', $parameters, $deposit, $action); // Note that $action and $object may have been
|
||||
// modified by hook
|
||||
if ($reshook < 0) {
|
||||
$origin->db->rollback();
|
||||
$origin->error = $hookmanager->error;
|
||||
$origin->errors = $hookmanager->errors;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! empty($autoValidateDeposit)) {
|
||||
$validateReturn = $deposit->validate($user, '', 0, $notrigger);
|
||||
|
||||
if ($validateReturn < 0) {
|
||||
$origin->db->rollback();
|
||||
$origin->error = $deposit->error;
|
||||
$origin->errors = $deposit->errors;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
unset($object->context['createdepositfromorigin']);
|
||||
|
||||
$origin->db->commit();
|
||||
|
||||
return $deposit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return clicable link of object (with eventually picto)
|
||||
*
|
||||
|
||||
@ -425,6 +425,12 @@ VarAmount=Variable amount (%% tot.)
|
||||
VarAmountOneLine=Variable amount (%% tot.) - 1 line with label '%s'
|
||||
VarAmountAllLines=Variable amount (%% tot.) - all lines from origin
|
||||
DepositPercent=Deposit %%
|
||||
PaymentConditionPermitsDepositGenerationSelected=You can generate a deposit invoice with the payment conditions you selected
|
||||
GenerateDeposit=Generate a %s%% deposit invoice
|
||||
ValidateGeneratedDeposit=Validate the generated deposit
|
||||
DepositGenerated=Deposit generated
|
||||
ErrorCanOnlyAutomaticallyGenerateADepositFromProposalOrOrder=You can only automatically generate a deposit from a proposal or an order
|
||||
ErrorPaymentConditionsNotEligibleToDepositCreation=The chose payment conditions are not eligible for automatic deposit generation
|
||||
# PaymentType
|
||||
PaymentTypeVIR=Bank transfer
|
||||
PaymentTypeShortVIR=Bank transfer
|
||||
|
||||
Loading…
Reference in New Issue
Block a user