if (!empty($writeOffsForecast[$productId][$week]['writeOffs'])) {
$writeOffs = $writeOffsForecast[$productId][$week]['writeOffs'];
- $details['writeOffs']['groups'] = $writeOffs;
+ $details['writeOffs']['quantity'] = $writeOffs;
$total += is_array($writeOffs) ? array_sum($writeOffs) : (float)$writeOffs;
}
foreach (['offline', 'online', 'marketplace'] as $type) {
- $data = $salesForecast[$productId][$week][$type] ?? null;
- if ($data) {
- $details[$type]['groups'] = [];
- if (isset($data['share'])) {
- $share = (float)$data['share'];
- $details[$type]['groups']['share'] = $share;
- $details[$type]['groups']['quantity'] = round($quantity * $share, 2);
- $total += $details[$type]['groups']['quantity'];
- unset($data['share']);
- }
- if (!empty($data)) {
- $details[$type]['groups'] = array_merge($details[$type]['groups'], $data);
- $total += is_array($data) ? array_sum($data) : (float)$data;
- }
+ if (!isset($salesForecast[$store->id][$productId][$type])) {
+ $details[$type] = ['share' => 0, 'quantity' => 0, 'groups' => []];
+ continue;
}
+ $data = $salesForecast[$store->id][$productId][$type];
+ if (!is_array($data)) {
+ $details[$type] = ['share' => 0, 'quantity' => 0, 'groups' => []];
+ continue;
+ }
+ $block = [];
+ $groups = [];
+ $share = isset($salesForecast[$store->id][$type]['share']) ? (float)$salesForecast[$store->id][$type]['share'] : 0;
+ $block['share'] = $share;
+ $block['quantity'] = (float) sprintf('%.2f', round($quantity * $share, 2)); // Нормализует -0 до 0
+ $total += $block['quantity'];
+ foreach ($data as $k => $v) {
+ $val = (float)$v;
+ $groups[$k] = $val;
+ $total += $val;
+ }
+ $block['groups'] = !empty($groups) ? $groups : [];
+ $details[$type] = $block;
}
+ $total = (float) sprintf('%.2f', $total); // Нормализует -0 до 0 для $total
+
$needsUpdate = !$model->isNewRecord && (
$model->calculate !== $quantity ||
ceil((float)$model->total) !== ceil($total) ||
const parts = Object.entries(titleObj)
.map(([typeKey, typeValue]) => {
const title = typeTitles[typeKey] || typeKey;
- if (
- typeof typeValue === 'object' &&
- typeValue !== null &&
- typeof typeValue.groups === 'object'
- ) {
- const lines = Object.entries(typeValue.groups)
- .map(([key, val]) => `- ${key.replace(/_/g, ' ')}: ${parseFloat(val).toFixed(2)}`);
- return `${title}:\n${lines.join('\n')}`;
+
+ if (typeof typeValue !== 'object' || typeValue === null) {
+ return '';
+ }
+
+ const quantity = typeof typeValue.quantity === 'number'
+ ? parseFloat(typeValue.quantity).toFixed(2)
+ : '0.00';
+
+ let result = `${title}: ${quantity}`;
+
+ if (typeKey === 'writeOffs') {
+ if (typeof typeValue.quantity === 'number') {
+ result += `\n- Количество: ${parseFloat(typeValue.quantity).toFixed(2)}`;
+ }
}
- return '';
+ else if (typeof typeValue.groups === 'object' && typeValue.groups !== null) {
+ const groupEntries = Object.entries(typeValue.groups);
+ if (groupEntries.length > 0) {
+ const lines = groupEntries.map(
+ ([key, val]) => `- ${key.replace(/_/g, ' ')}: ${parseFloat(val).toFixed(2)}`
+ );
+ result += `\n${lines.join('\n')}`;
+ }
+ }
+
+ return result;
})
.filter(Boolean);
return parts.join('\n\n');
-};
+};
\ No newline at end of file