Billing: crediting already paid timerange after productchange

This commit is contained in:
Frank Schubert
2024-11-05 16:20:57 +01:00
parent 1f3ef5246f
commit 6afd6340ae

View File

@@ -142,11 +142,11 @@ class BillingController extends mfBaseController {
protected function importContractsAction() {
$r = $this->request;
$last_run_ts = new mfConfig("voicecallhistory.contact-job.ts");
/*$last_run_ts = new mfConfig("voicecallhistory.contact-job.ts");
if($last_run_ts->value() < date("U") - 86400) {
$this->layout()->setFlash("Voicecall History Contract Job ist heute noch nicht gelaufen", "error");
$this->redirect("Billing");
}
}*/
$i = 0;
@@ -161,8 +161,8 @@ class BillingController extends mfBaseController {
// for debugging to bill a specific month
//$now_year = 2024;
//$now_month = 7;
//$now_day = 10;
//$now_month = 11;
//$now_day = 3;
// XXX only for 1st Billing after IVT Import
// Locking to July 2024 and keeping it for now
@@ -182,7 +182,8 @@ class BillingController extends mfBaseController {
$contract_search = [
"finish_date<" => mktime(2,0,0,$now_month, $now_day, $now_year),
"cancel_date_null_or_gte" => mktime(0,0,0,$now_month, 1, $now_year)
"cancel_date_null_or_gte" => mktime(0,0,0,$now_month, 1, $now_year),
//"owner_id" => 1221
];
foreach(ContractModel::search($contract_search) as $contract) {
@@ -284,10 +285,12 @@ class BillingController extends mfBaseController {
$earliest_bill_date = clone $contract_finish_date;
$earliest_bill_date->modify("first day of this month");
$earliest_bill_date->setTime(0,0,0);
//var_dump($create_date, $earliest_bill_date, $finish_year, $finish_month);exit;
while($create_date->format("Y-m-d") >= $earliest_bill_date->format("Y-m-d")) {
if($last_create_date) {
//var_dump($create_dates);
// just for safety / shouldn't happen
break;
die("need-date ran out of dates");
}
@@ -295,6 +298,7 @@ class BillingController extends mfBaseController {
// this is the finish month, so set day back to day of finish_date, unless billing_period is more than 1 month
if($contract->billing_period == 1) {
$create_date->setDate($finish_year, $finish_month, $finish_day);
//var_dump($create_date);
}
$last_create_date = true;
}
@@ -377,30 +381,32 @@ class BillingController extends mfBaseController {
$pc = $period_days / $total_days * 100;
$price = round($contract->price / 100 * $pc, 4);
/*if($contract->id == 936) {
echo "\n";
echo "first day: ".$first_of_period->format("Y-m-d")."\n";
echo "total_days: $total_days\n";
echo "period_days: $period_days\n";
echo "pc: $pc\n";
echo "price: $price\n";
exit;
}*/
/*
if($contract->id == 12500) {
echo "\n". "<br>";
echo "first day: ".$first_of_period->format("Y-m-d")."\n". "<br>";
echo "total_days: $total_days\n". "<br>";
echo "period_days: $period_days\n". "<br>";
echo "pc: $pc\n". "<br>";
echo "contract price: ".$contract->price."\n". "<br>";
echo "price: $price\n". "<br>";
//exit;
/*if($contract->id == 8766) {
echo "\n". "<br>";
echo "start date: ".$start_date->format("Y-m-d H:i:s") . "<br>";
echo "end date: ".$end_date->format("Y-m-d H:i:s") . "<br><br>";
echo "first_of_period: " . $first_of_period->format("Y-m-d H:i:s") . "<br>";
echo "total days: $total_days<br>";
echo "period days: $period_days<br>";
echo "price: $price<br><br>";
echo "classic days: $days<br>";
//echo "classic days: $days<br>";
exit;
}*/
} else {
$price = $contract->price;
}
$this->createProductchangeCredit($contract, $start_date);
$owner = $contract->owner;
if ($contract->billingaddress_id) {
@@ -741,4 +747,199 @@ class BillingController extends mfBaseController {
$this->redirect("Billing");
}
private function createProductchangeCredit(Contract $contract, $start_date) {
$today = new DateTime("now");
// find previous contract if upgrade for crediting
$links = ContractLinkModel::search(["contract_id" => $contract->id, "type" => ["upgrade","downgrade","relocation","productchange"]]);
//var_dump($links);
if(!is_array($links) || count($links) !== 1) {
return false;
}
$link = array_shift($links);
//var_dump($link);
if($link->origin_contract_id == $contract->id) {
return false;
}
$origin_contract = $link->origin;
//var_dump($origin_contract);
if(!$origin_contract->cancel_date) {
return false;
}
$origin_cancel_date = new DateTime("@".$origin_contract->cancel_date);
$origin_cancel_date->setTimezone(new DateTimeZone("Europe/Vienna"));
//var_dump($link_cancel_date);
//var_dump($)
// link_cancel_date gleicher monat wie herstellungsdatum
// und
// link_cancel_date kleiner als herstellungsdatum
/*if($contract->id == 12527) {
echo "origin cancel date: ".$origin_cancel_date->format("m.Y")."\n<br/>";
echo "new cancel date: ".$start_date->format("m.Y")."\n<br/>";
exit;
}*/
if($origin_cancel_date->format("m") == $today->format("m") ||
($origin_cancel_date->format("m.Y") != $start_date->format("m.Y") ||
$origin_cancel_date->format("d") > $start_date->format("d"))
) {
return false;
}
$end_of_month = clone($start_date);
$end_of_month->modify("last day of this month");
$first_of_month = clone($start_date);
$first_of_month->modify("first day of this month");
$prev_bill = BillingModel::getFirst(["contract_id" => $origin_contract->id, "start_date>=" => $first_of_month->format("Y-m-d"), "end_date<=" => $end_of_month->format("Y-m-d")]);
//var_dump($prev_bill);
if(!$prev_bill) {
return false;
}
$prev_bill_end_date = new DateTime($prev_bill->end_date);
$prev_end_of_month = clone($prev_bill_end_date);
$prev_end_of_month->modify("Last day of this month");
$prev_cancel_date = new DateTime("@".$origin_contract->cancel_date);
$prev_cancel_date->modify("+1 days");
$prev_cancel_date->setTimezone(new DateTimeZone("Europe/Vienna"));
//var_dump($prev_cancel_date);
$credit_days = ($prev_end_of_month->diff($prev_cancel_date)->format("%a"))+2;
if($credit_days < 1) return false;
$credit_from_date = clone($end_of_month);
$credit_from_date->modify("-$credit_days days");
$credit_total_days = $prev_end_of_month->diff($first_of_month)->format("%a") + 1;
$credit_pc = $credit_days / $credit_total_days * 100;
$credit_price = round($origin_contract->price / 100 * $credit_pc, 4);
$credit_price *= -1;
/*
echo "prev end of month: ".$prev_end_of_month->format("Y-m-d H:i:s")."\n<br />";
echo "credit days: $credit_days\n<br />";
echo "credit pc: $credit_pc\n<br />";
exit;
*/
/*
$period_days = ($end_date->diff($start_date)->format("%a")) + 1;
if ($period_days < 0) continue; // don't bill for negative time range
$pc = $period_days / $total_days * 100;
*/
/*
echo $prev_cancel_date->format("d.m.Y") . " -> " . $prev_bill_end_date->format("d.m.Y") . "<br />\n";
echo "start date: " . $start_date->format("d.m.Y") . "<br />\n";
echo "credit days: " . $credit_days . "<br />\n";
exit;
*/
// create credit bill
$credit_owner = $contract->owner;
if ($contract->billingaddress_id) {
$credit_billingaddress = $origin_contract->billingaddress;
} else {
$credit_billingaddress = $credit_owner;
}
$credit_billing_type = "invoice";
$credit_billing_delivery = "paper";
if ($credit_owner->billing_type) {
$credit_billing_type = $credit_owner->billing_type;
}
if ($credit_owner->billing_delivery) {
$credit_billing_delivery = $credit_owner->billing_delivery;
}
if ($credit_billingaddress->billing_type) {
$credit_billing_type = $credit_billingaddress->billing_type;
}
if ($credit_billingaddress->billing_delivery) {
$credit_billing_delivery = $credit_billingaddress->billing_delivery;
}
if($origin_contract->vatgroup_id == TT_VATGROUP_CREDIT) {
$credit_fibu_account_num = $credit_billingaddress->fibu_supplier_number;
if(!$credit_fibu_account_num) {
die("Partner " . $credit_billingaddress->customer_number . " hat keine Lieferantennummer (" . $credit_billingaddress->getCompanyOrName().")");
}
} else {
$credit_fibu_account_num = $credit_billingaddress->fibu_account_number;
if(!$credit_fibu_account_num) {
die("Keine Fibu Account Nummer in Rechnungskontakt in Contract ID ".$origin_contract->id);
}
}
$product_name = "Gutschrift zu ".$origin_contract->product_name;
$credit_data = [];
$credit_data["contract_id"] = $origin_contract->id;
$credit_data["start_date"] = $prev_cancel_date->format("Y-m-d");
$credit_data["end_date"] = $prev_bill_end_date->format("Y-m-d");
$credit_data["owner_id"] = $origin_contract->owner_id;
$credit_data["billingaddress_id"] = ($origin_contract->billingaddress_id) ? $origin_contract->billingaddress_id : $origin_contract->owner_id;
$credit_data["customer_number"] = $origin_contract->owner->customer_number;
$credit_data["fibu_account_number"] = $credit_fibu_account_num;
$credit_data["company"] = $credit_billingaddress->company;
$credit_data["firstname"] = $credit_billingaddress->firstname;
$credit_data["lastname"] = $credit_billingaddress->lastname;
$credit_data["street"] = $credit_billingaddress->street;
$credit_data["zip"] = $credit_billingaddress->zip;
$credit_data["city"] = $credit_billingaddress->city;
$credit_data["email"] = $credit_billingaddress->email;
$credit_data["uid"] = $credit_billingaddress->uid;
$credit_data["billing_type"] = $credit_billing_type;
$credit_data["billing_delivery"] = $credit_billing_delivery;
$credit_data["bank_account_bank"] = $credit_billingaddress->bank_account_bank;
$credit_data["bank_account_owner"] = $credit_billingaddress->bank_account_owner;
$credit_data["bank_account_iban"] = str_replace(" ", "", $credit_billingaddress->bank_account_iban);
$credit_data["bank_account_bic"] = $credit_billingaddress->bank_account_bic;
$credit_data["product_id"] = $origin_contract->product_id;
$credit_data["product_name"] = $product_name;
$credit_data["product_info"] = $origin_contract->product_info;
$credit_data["amount"] = $origin_contract->amount;
$credit_data["price"] = $credit_price;
$credit_data["price_setup"] = 0;
$credit_data["billing_period"] = $origin_contract->billing_period;
$credit_data["matchcode"] = $origin_contract->matchcode;
if(!$credit_billingaddress->country_id) {
$credit_billcountry = CountryModel::getFirst(["isocode" => TT_HOMECOUNTRY_ISOCODE]);
} else {
$credit_billcountry = $credit_billingaddress->country;
}
$credit_vatgroup = $origin_contract->vatgroup;
$credit_vatarea = "domestic";
if($credit_billcountry->isocode != TT_HOMECOUNTRY_ISOCODE && $credit_billcountry->is_eu) {
$credit_vatarea = "eu";
} if($credit_billcountry->isocode != TT_HOMECOUNTRY_ISOCODE && !$credit_billcountry->is_eu) {
$credit_vatarea = "other";
}
$credit_data["country"] = $credit_billcountry->name;
$credit_data["vatrate"] = $credit_vatgroup->rates[$credit_vatarea]->rate;
$credit_data["vatgroup_id"] = $origin_contract->vatgroup_id;
$credit_data["vatarea"] = $credit_vatarea;
//var_dump($credit_data);exit;
$credit = BillingModel::create($credit_data);
if(!$credit->save()) {
die("Error saving Billing record for Credit of Contract ".$origin_contract->id. " (Created from Upgrade to Contract ".$contract->id.")");
}
$this->log->info("Created Credit for Contract ".$origin_contract->id." (Created from Upgrade to Contract ".$contract->id.")");
return $credit;
}
}