524 lines
16 KiB
PHP
524 lines
16 KiB
PHP
<?php
|
|
require_once('fixed/config/go_con.php');
|
|
ini_set('memory_limit', '2048M');
|
|
/*
|
|
$invoicesSumQuery = <<<SQL
|
|
SELECT SUM(invoices_details_has_how_pay.pay) AS sum
|
|
FROM invoices_details_has_how_pay
|
|
INNER JOIN invoices_details
|
|
ON invoices_details_has_how_pay.invoices_details_id = invoices_details.id
|
|
WHERE
|
|
invoices_details_has_how_pay.date_time >= '2023-01-01 00:00:00' AND
|
|
invoices_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND
|
|
invoices_status_id = 1 AND
|
|
invoices_details_has_how_pay.how_pay_id IN (1,2,3,4,5,6,7,8,9,10)
|
|
SQL;
|
|
|
|
$result = mysqli_query($db, $invoicesSumQuery);
|
|
|
|
$sum = mysqli_fetch_assoc($result);
|
|
if (!$sum) {
|
|
die('sum could not be calculated');
|
|
}
|
|
$sum = $sum['sum'];
|
|
|
|
$bondsSumQuery = <<<SQL
|
|
SELECT SUM(bonds_details_has_how_pay.pay) AS sum
|
|
FROM bonds_details_has_how_pay
|
|
INNER JOIN bonds_details
|
|
ON bonds_details_has_how_pay.bonds_details_id = bonds_details.id
|
|
WHERE
|
|
bonds_details_has_how_pay.date_time >= '2023-01-01 00:00:00' AND
|
|
bonds_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND
|
|
bonds_status_id = 1 AND
|
|
branch_id IN (2,3,4,5,6,7,8,10,11,12)
|
|
SQL;
|
|
|
|
$result = mysqli_query($db, $bondsSumQuery);
|
|
|
|
$sum = mysqli_fetch_assoc($result);
|
|
if (!$sum) {
|
|
die('sum could not be calculated');
|
|
}
|
|
$sum = $sum['sum'];
|
|
|
|
*/
|
|
|
|
echo "<pre>";
|
|
|
|
function inSubsetSum(array $a, float $t, array &$memo = []) : ?array {
|
|
$s = array_reduce($memo, function (?float $carry, array $value) {
|
|
return $carry + $value[1];
|
|
});
|
|
|
|
if ($s === $t) {
|
|
return $memo;
|
|
}
|
|
|
|
if ($s >= $t) {
|
|
return null;
|
|
}
|
|
|
|
$len = count($a);
|
|
$keys = array_keys($a);
|
|
for ($i = 0; $i < $len; ++$i) {
|
|
$k = $keys[$i];
|
|
$v = $a[$k];
|
|
$rem = array_slice($a, $i + 1, null, true);
|
|
$memo = array_merge($memo, [[$k, $v]]);
|
|
$res = inSubsetSum($rem, $t, $memo);
|
|
if ($res !== null) {
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function subsetSum(array $a, float $t) : ?array {
|
|
$subset = inSubsetSum($a, $t);
|
|
$result = [];
|
|
foreach ($subset as $_ => [$k, $v]) {
|
|
$result[$k] = $v;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
$invoiceQuery = <<<SQL
|
|
SELECT
|
|
invoices.id AS invoices_id,
|
|
book.id AS book_id,
|
|
invoices_details.id AS invoice_details_id,
|
|
invoices_details.branch_id AS branch_id,
|
|
invoices_details.pay AS pay,
|
|
book.tretment_id AS tretment_id,
|
|
invoices_details_has_how_pay.date_time AS date_time,
|
|
book_details.id AS book_details_id,
|
|
book_details.status_id AS book_details_status_id,
|
|
book_details.services_id AS services_id,
|
|
services.price AS price,
|
|
invoices_details_has_how_pay.how_pay_id AS how_pay_id
|
|
FROM invoices_details_has_how_pay
|
|
INNER JOIN invoices_details ON invoices_details.id = invoices_details_has_how_pay.invoices_details_id
|
|
INNER JOIN invoices ON invoices_details.invoices_id = invoices.id
|
|
INNER JOIN invoices_has_book ON invoices.id = invoices_has_book.invoices_id
|
|
INNER JOIN book ON book.id = invoices_has_book.book_id
|
|
INNER JOIN book_details ON book_details.book_id = book.id
|
|
INNER JOIN services ON services.id = book_details.services_id
|
|
JOIN (
|
|
SELECT `book_id`, MAX(`id`) AS `max_id`
|
|
FROM `book_details`
|
|
GROUP BY `book_id`
|
|
) `t1_max`
|
|
ON book_details.book_id = `t1_max`.`book_id` AND `book_details`.`id` = `t1_max`.`max_id`
|
|
WHERE
|
|
-- invoices_details_has_how_pay.date_time >= '2023-01-01 00:00:00' AND
|
|
-- invoices_details_has_how_pay.date_time < '2023-04-01 00:00:00' AND
|
|
invoices_status_id = 1 AND
|
|
invoices_details.branch_id IN (2,3,4,5,6,7,8,10,11,12) AND
|
|
invoices.id = 192501
|
|
ORDER BY invoices_details_has_how_pay.date_time DESC
|
|
SQL;
|
|
$result = mysqli_query($db, $invoiceQuery);
|
|
$error = mysqli_error($db);
|
|
if ($error) {
|
|
echo $error;
|
|
die;
|
|
}
|
|
$invoiceData = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
|
$invoiceDiscountQuery = <<<SQL
|
|
SELECT
|
|
invoices_discount.discount AS total_discount,
|
|
invoices_discount_details.services_id AS service_id,
|
|
invoices_discount_details.reason AS reason,
|
|
invoices_discount_details.discount AS discount
|
|
FROM `invoices_discount_details`
|
|
INNER JOIN
|
|
invoices_discount
|
|
ON invoices_discount.id = invoices_discount_details.invoices_discount_id
|
|
INNER JOIN
|
|
invoices_details
|
|
ON invoices_details.id = invoices_discount.invoices_details_id
|
|
WHERE
|
|
(invoices_discount_details.services_id = ? OR invoices_discount_details.services_id = 0) AND
|
|
invoices_discount.invoices_details_id = ?
|
|
GROUP BY invoices_discount_details.reason
|
|
SQL;
|
|
|
|
$finalInvoiceData = [];
|
|
|
|
$year = '23';
|
|
$letter = 'I';
|
|
|
|
$branchData = [
|
|
'2' => ['1501', 0],
|
|
'3' => ['0701', 0],
|
|
'4' => ['2901', 0],
|
|
'5' => ['0602', 0],
|
|
'6' => ['KM01', 0],
|
|
'7' => ['VS01', 0],
|
|
'8' => ['VS02', 0],
|
|
'9' => ['PT07', 0],
|
|
'12' => ['2902', 0],
|
|
'13' => ['1502', 0],
|
|
];
|
|
|
|
$countQuery = <<<SQL
|
|
SELECT COUNT(*) AS count FROM invoices_has_book WHERE invoices_id = ?
|
|
SQL;
|
|
|
|
|
|
function getDecimalsLength(float $val) : int {
|
|
return strcspn(strrev((string) $val), '.');
|
|
}
|
|
|
|
function roundMoney(float $val, int $precision = 2) : string {
|
|
$decimals = getDecimalsLength($val);
|
|
for ($i = $decimals - 1; $i > ($precision - 1); --$i) {
|
|
$val = round($val, $i);
|
|
}
|
|
return number_format($val, 2);
|
|
}
|
|
|
|
$bundleQuery = <<<SQL
|
|
SELECT
|
|
services.id AS services_id,
|
|
services.price AS price,
|
|
bundle_services_has_services.how_many AS how_many
|
|
FROM bundle_services_has_services
|
|
INNER JOIN services ON services.id = bundle_services_has_services.services_id
|
|
WHERE
|
|
bundle_services_has_services.bundle_services_id = (
|
|
SELECT
|
|
bundle_services_id
|
|
FROM book_details_has_bundle_services
|
|
WHERE
|
|
book_details_id = (
|
|
SELECT MIN(id)
|
|
FROM book_details
|
|
WHERE
|
|
book_id = ? AND
|
|
status_id = 4
|
|
)
|
|
)
|
|
SQL;
|
|
|
|
function getTotalDiscount(int $invoiceId) : float {
|
|
global $db;
|
|
$stmt = mysqli_prepare($db, <<<SQL
|
|
SELECT invoices_discount.discount AS discount
|
|
FROM invoices_discount
|
|
INNER JOIN invoices_details ON invoices_details.id = invoices_discount.invoices_details_id
|
|
INNER JOIN invoices ON invoices.id = invoices_details.invoices_id
|
|
WHERE invoices.id = ?
|
|
SQL);
|
|
$stmt->bind_param('i', $invoiceId);
|
|
$stmt->execute();
|
|
$error = mysqli_error($db);
|
|
if ($error) {
|
|
echo $error;
|
|
die;
|
|
}
|
|
$result = $stmt->get_result();
|
|
$result = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
|
if (count($result) == 0) {
|
|
return 0.0;
|
|
}
|
|
return $result[0]['discount'];
|
|
}
|
|
|
|
function processInvoice(array &$data, int $serviceCount) : array {
|
|
global $db;
|
|
global $invoiceDiscountQuery;
|
|
global $countQuery;
|
|
global $year;
|
|
global $letter;
|
|
global $finalInvoiceData;
|
|
global $branchData;
|
|
|
|
$detailsId = $data['invoice_details_id'];
|
|
$serviceId = $data['services_id'];
|
|
$data['discount'] = 0;
|
|
$stmt = mysqli_prepare($db, $invoiceDiscountQuery);
|
|
$stmt->bind_param('ii', $serviceId, $detailsId);
|
|
$stmt->execute();
|
|
$error = mysqli_error($db);
|
|
if ($error) {
|
|
echo $error;
|
|
die;
|
|
}
|
|
|
|
$result = $stmt->get_result();
|
|
|
|
$discountData = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
|
|
|
$invoiceDiscounts = [];
|
|
foreach ($discountData as &$discount) {
|
|
// NOTE: this is for home visit services
|
|
if ($discount['service_id'] == 0) {
|
|
$countStmt = mysqli_prepare($db, $countQuery);
|
|
$countStmt->bind_param('i', $data['invoices_id']);
|
|
$countStmt->execute();
|
|
$error = mysqli_error($db);
|
|
if ($error) {
|
|
echo $error;
|
|
die;
|
|
}
|
|
$countResult = $countStmt->get_result();
|
|
$countResult = mysqli_fetch_all($countResult, MYSQLI_ASSOC);
|
|
$data['discount'] += $discount['total_discount'] / floatval($countResult[0]['count']);
|
|
$discount['discount'] = $discount['total_discount'] / floatval($countResult[0]['count']);
|
|
} else {
|
|
$data['discount'] += $discount['discount'];
|
|
}
|
|
$invoiceDiscounts[] = [
|
|
'reason' => $discount['reason'],
|
|
'discount' => $discount['discount'],
|
|
];
|
|
}
|
|
|
|
$totalAfterDiscount = $data['price'] * $serviceCount - $data['discount'];
|
|
$vat = $data['branch_id'] == 9 ? 0.0 : 15.0;
|
|
$totalAfterDiscountVat = $totalAfterDiscount * ($vat / 100);
|
|
|
|
$bData = &$branchData[$data['branch_id']];
|
|
$branchCode = $bData[0];
|
|
$bData[1] += 1;
|
|
$invoiceNumber = $bData[1];
|
|
$number = "{$year}{$letter}{$branchCode}";
|
|
$number .= str_pad("$invoiceNumber", 7, '0', STR_PAD_LEFT);
|
|
|
|
$total = $totalAfterDiscount + $totalAfterDiscountVat;
|
|
$total = round($total, 2);
|
|
if ($total <= $data['pay']) {
|
|
$data['price_no_vat'] = roundMoney($data['price']);
|
|
$data['total_discount'] = roundMoney($data['discount']);
|
|
$data['total_after_discount'] = roundMoney($totalAfterDiscount);
|
|
$data['vat'] = roundMoney($totalAfterDiscountVat);
|
|
$total = $totalAfterDiscount + $totalAfterDiscountVat;
|
|
$data['total'] = roundMoney($total);
|
|
} else {
|
|
echo ("WELCOME TO HELL");
|
|
var_dump([
|
|
'total' => $totalAfterDiscount + $totalAfterDiscountVat,
|
|
'pay' => $data['pay'],
|
|
]);
|
|
var_dump($data);
|
|
die;
|
|
}
|
|
|
|
return [
|
|
'branch_id' => $data['branch_id'],
|
|
'invoices_id' => $data['invoices_id'],
|
|
'book_id' => $data['book_id'],
|
|
'tretment_id' => $data['tretment_id'],
|
|
'number' => $number,
|
|
'date_time' => $data['date_time'],
|
|
'service_id' => $data['services_id'],
|
|
'price_no_vat' => $data['price_no_vat'],
|
|
'total_discount' => $data['total_discount'],
|
|
'total_after_discount' => $data['total_after_discount'],
|
|
'vat_rate' => $vat,
|
|
'vat' => $data['vat'],
|
|
'total' => $data['total'],
|
|
'quantity' => $serviceCount,
|
|
'how_pay_id' => $data['how_pay_id'],
|
|
'discount_details' => $invoiceDiscounts,
|
|
];
|
|
}
|
|
|
|
$invoicesTotals = [];
|
|
|
|
foreach ($invoiceData as &$data) {
|
|
// TODO: fix service bundles (where service_id == 0)
|
|
if ($data['services_id'] == 0) {
|
|
$stmt = mysqli_prepare($db, $bundleQuery);
|
|
$stmt->bind_param('i', $data['book_id']);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$bundleData = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
|
|
|
foreach ($bundleData as $bundle) {
|
|
$c += 1;
|
|
$d = $data;
|
|
$serviceId = $bundle['services_id'];
|
|
$count = $bundle['how_many'];
|
|
$price = $bundle['price'];
|
|
$d['services_id'] = $serviceId;
|
|
$d['price'] = $price;
|
|
$dd = processInvoice($d, $count);
|
|
$id = $d['invoices_id'];
|
|
$invoicesTotals["{$id}"]['total'] += $dd['total_discount'];
|
|
$invoicesTotals["{$id}"]['service_count'] = $count;
|
|
$invoicesTotals["{$id}"]['indices'][] = count($finalInvoiceData);
|
|
$finalInvoiceData[] = $dd;
|
|
}
|
|
} else {
|
|
$id = $data['invoices_id'];
|
|
$dd = processInvoice($data, 1);
|
|
$invoicesTotals["{$id}"]['total'] += $dd['total_discount'];
|
|
$invoicesTotals["{$id}"]['service_count'] = 1;
|
|
$invoicesTotals["{$id}"]['indices'][] = count($finalInvoiceData);
|
|
$finalInvoiceData[] = $dd;
|
|
}
|
|
}
|
|
|
|
foreach ($invoicesTotals as $id => $d) {
|
|
$total = $d['total'];
|
|
$indices = $d['indices'];
|
|
$count = $d['service_count'];
|
|
$originalTotal = getTotalDiscount($id);
|
|
if ($originalTotal != $total) {
|
|
$diff = bcsub($originalTotal, $total, 2);
|
|
foreach ($indices as $index) {
|
|
$total = $finalInvoiceData[$index]['total'];
|
|
$mod = bcmod($total, 1, 2);
|
|
if ($mod == $diff) {
|
|
$discount = $finalInvoiceData[$index]['total_discount'];
|
|
$discount += $diff;
|
|
|
|
$price = $finalInvoiceData[$index]['price_no_vat'];
|
|
$totalAfterDiscount = $price * $count - $discount;
|
|
$totalAfterDiscountVat = $totalAfterDiscount * ($finalInvoiceData[$index]['vat_rate'] / 100);
|
|
|
|
$totalAfterDiscount = roundMoney($price - $discount);
|
|
$vat = roundMoney($totalAfterDiscountVat);
|
|
$total = roundMoney($totalAfterDiscount + $totalAfterDiscountVat);
|
|
|
|
|
|
$finalInvoiceData[$index]['total_discount'] = $discount;
|
|
$finalInvoiceData[$index]['total_after_discount'] = $totalAfterDiscount;
|
|
$finalInvoiceData[$index]['vat'] = $vat;
|
|
$finalInvoiceData[$index]['total'] = $total;
|
|
$discountDetails = $finalInvoiceData[$index]['discount_details'];
|
|
if ($discountDetails && count($discountDetails) > 0) {
|
|
$discountDetails[0]['discount'] = $discount;
|
|
$finalInvoiceData[$index]['discount_details'] = $discountDetails;
|
|
}
|
|
break;
|
|
} else {
|
|
echo "WTH";
|
|
die;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var_dump($finalInvoiceData);
|
|
die;
|
|
|
|
$sum = 0.0;
|
|
$desired = 4695115.53;
|
|
|
|
$subset = [];
|
|
|
|
$reached_desired = false;
|
|
|
|
foreach ($invoiceData as &$data) {
|
|
if ($sum == $desired) {
|
|
$reached_desired = true;
|
|
break;
|
|
} else if ($sum < $desired) {
|
|
$sum += $data['pay'];
|
|
$subset[$key] = $bond;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
$sahabiInvoicesTables = <<<SQL
|
|
CREATE TABLE IF NOT EXISTS `sahabi_invoices` (
|
|
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
|
branch_id INT NOT NULL,
|
|
invoices_id INT NOT NULL,
|
|
book_id INT NOT NULL,
|
|
tretment_id INT NOT NULL,
|
|
number VARCHAR(14) NOT NULL,
|
|
date_time DATETIME NOT NULL,
|
|
service_id INT NOT NULL,
|
|
price_no_vat DECIMAL(10, 2) NOT NULL,
|
|
total_discount DECIMAL(10, 2) NOT NULL,
|
|
total_after_discount DECIMAL(10, 2) NOT NULL,
|
|
vat_rate DECIMAL(10, 2) DEFAULT NULL,
|
|
vat DECIMAL(10, 2) DEFAULT NULL,
|
|
total DECIMAL(10, 2) NOT NULL,
|
|
quantity INT NOT NULL,
|
|
how_pay_id INT NOT NULL
|
|
) ENGINE=INNODB;
|
|
|
|
CREATE TABLE IF NOT EXISTS `sahabi_invoices_discount_details` (
|
|
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
|
reason VARCHAR(255) NOT NULL,
|
|
discount DECIMAL(10,2) NOT NULL,
|
|
sahabi_invoice_id INT NOT NULL,
|
|
FOREIGN KEY (sahabi_invoice_id)
|
|
REFERENCES sahabi_invoices(id)
|
|
ON DELETE RESTRICT ON UPDATE CASCADE
|
|
) ENGINE=INNODB;
|
|
SQL;
|
|
// $result = mysqli_query($db, $sahabiBonds);
|
|
echo mysqli_error($db);
|
|
|
|
foreach ($subset as $id => $bond) {
|
|
$bData = &$branchData[$bond['branch_id']];
|
|
$branchCode = $bData[0];
|
|
$bData[1] += 1;
|
|
$invoiceNumber = $bData[1];
|
|
$number = "{$year}{$letter}{$branchCode}";
|
|
$number .= str_pad("$invoiceNumber", 7, '0', STR_PAD_LEFT);
|
|
$noVat = $bond['pay'] / 1.15;
|
|
$vat = $bond['pay'] - $noVat;
|
|
|
|
$params = [
|
|
$bond['bonds_id'],
|
|
$bond['branch_id'],
|
|
$bond['tretment_id'],
|
|
$bond['bonds_type_type_id'],
|
|
$number,
|
|
$bond['date_time'],
|
|
$noVat,
|
|
$vat,
|
|
$bond['pay'],
|
|
$bond['how_pay_id'],
|
|
];
|
|
|
|
$insertQuery = <<<SQL
|
|
INSERT INTO `sahabi_bonds` (
|
|
bonds_id,
|
|
branch_id,
|
|
tretment_id,
|
|
bonds_type_type_id,
|
|
number,
|
|
date_time,
|
|
price_no_vat,
|
|
vat,
|
|
total,
|
|
how_pay_id
|
|
) VALUES (
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?,
|
|
?
|
|
);
|
|
SQL;
|
|
|
|
$stmt = mysqli_prepare($db, $insertQuery);
|
|
$stmt->bind_param('ssiissdddi', ...$params);
|
|
// $stmt->execute();
|
|
}
|
|
|
|
// $desired = 655476.19;
|
|
// $subset = subsetSum($bonds, $desired);
|
|
// echo "done";
|
|
//
|
|
// $subsetSum = array_sum($subset);
|
|
|
|
// echo "<br>subset sum: $subsetSum";
|
|
|
|
echo "</pre>"; |