Ergaenze Chargenformular um Lagerbewegungen
This commit is contained in:
1 parent
1e5ededa00
commit
5908f71a39
3 files changed
+147
-5
No files matched your search
@@ -192,7 +192,10 @@ function update_stock_lot_traceability(
|
||||
?string $mfgDate,
|
||||
?string $expiryDate,
|
||||
?string $purchaseDate,
|
||||
string $changedBy
|
||||
string $changedBy,
|
||||
float $receiptQty = 0.0,
|
||||
float $adjustmentQty = 0.0,
|
||||
float $outQty = 0.0
|
||||
): array {
|
||||
if ($lotId <= 0) {
|
||||
throw new InvalidArgumentException('Chargen-ID fehlt');
|
||||
@@ -203,6 +206,16 @@ function update_stock_lot_traceability(
|
||||
$manufacturerLotNumber = null;
|
||||
}
|
||||
|
||||
if (!is_finite($receiptQty) || !is_finite($adjustmentQty) || !is_finite($outQty)) {
|
||||
throw new InvalidArgumentException('Ungueltige Bewegungsmenge');
|
||||
}
|
||||
if ($receiptQty < 0 || $outQty < 0) {
|
||||
throw new InvalidArgumentException('Zugang und Abgang duerfen nicht negativ sein');
|
||||
}
|
||||
if ($adjustmentQty !== 0.0 && abs($adjustmentQty) < 0.0001) {
|
||||
$adjustmentQty = 0.0;
|
||||
}
|
||||
|
||||
$dates = [
|
||||
'mfg_date' => $mfgDate,
|
||||
'expiry_date' => $expiryDate,
|
||||
@@ -261,6 +274,9 @@ function update_stock_lot_traceability(
|
||||
if ($manufacturerPartyId !== null && $manufacturerLotNumber === null && (string) $before['status'] !== 'open') {
|
||||
throw new InvalidArgumentException('Hersteller-Chargennummer fehlt');
|
||||
}
|
||||
if (($receiptQty > 0 || $adjustmentQty !== 0.0 || $outQty > 0) && (string) $before['status'] !== 'current') {
|
||||
throw new InvalidArgumentException('Lagerbewegungen koennen nur auf der aktiven Charge gebucht werden');
|
||||
}
|
||||
|
||||
$updateStmt = $pdo->prepare(
|
||||
"UPDATE stock_lot
|
||||
@@ -291,6 +307,10 @@ function update_stock_lot_traceability(
|
||||
'module' => 'erp.lager',
|
||||
]);
|
||||
|
||||
if ($receiptQty > 0 || $adjustmentQty !== 0.0 || $outQty > 0) {
|
||||
book_stock_lot_movements($pdo, (int) $before['product_id'], $lotId, $receiptQty, $adjustmentQty, $outQty);
|
||||
}
|
||||
|
||||
if ($startedTransaction) {
|
||||
$pdo->commit();
|
||||
}
|
||||
@@ -333,6 +353,30 @@ function get_current_lot_balance_for_update(PDO $pdo, int $productId): array
|
||||
];
|
||||
}
|
||||
|
||||
function get_stock_lot_balance(PDO $pdo, int $lotId): array
|
||||
{
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT
|
||||
COALESCE(v.qty_net, 0) AS qty_net,
|
||||
COALESCE(v.qty_in, 0) AS qty_in,
|
||||
COALESCE(v.qty_out, 0) AS qty_out
|
||||
FROM stock_lot sl
|
||||
LEFT JOIN v_stock_lot_balance v ON v.stock_lot_id = sl.id
|
||||
WHERE sl.id = :lot_id"
|
||||
);
|
||||
$stmt->execute([':lot_id' => $lotId]);
|
||||
$row = $stmt->fetch();
|
||||
if (!is_array($row)) {
|
||||
throw new RuntimeException('Charge nicht gefunden');
|
||||
}
|
||||
|
||||
return [
|
||||
'qty_net' => (float) $row['qty_net'],
|
||||
'qty_in' => (float) $row['qty_in'],
|
||||
'qty_out' => (float) $row['qty_out'],
|
||||
];
|
||||
}
|
||||
|
||||
function insert_stock_move_out(
|
||||
PDO $pdo,
|
||||
int $productId,
|
||||
@@ -401,6 +445,91 @@ function insert_stock_move_in(
|
||||
return (int) $id;
|
||||
}
|
||||
|
||||
function insert_stock_move_adjustment(
|
||||
PDO $pdo,
|
||||
int $productId,
|
||||
int $lotId,
|
||||
float $qty,
|
||||
?int $fromLocationId,
|
||||
?int $toLocationId,
|
||||
string $note
|
||||
): int {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO stock_move (
|
||||
product_id, lot_id, from_location_id, to_location_id, qty, move_type, move_date, note, created_at, updated_at
|
||||
) VALUES (
|
||||
:product_id, :lot_id, :from_location_id, :to_location_id, :qty, 'adjustment', NOW(), :note, NOW(), NOW()
|
||||
)
|
||||
RETURNING id"
|
||||
);
|
||||
$stmt->execute([
|
||||
':product_id' => $productId,
|
||||
':lot_id' => $lotId,
|
||||
':from_location_id' => $fromLocationId,
|
||||
':to_location_id' => $toLocationId,
|
||||
':qty' => $qty,
|
||||
':note' => $note,
|
||||
]);
|
||||
|
||||
$id = $stmt->fetchColumn();
|
||||
if ($id === false) {
|
||||
throw new RuntimeException('Konnte Bestandskorrektur nicht schreiben');
|
||||
}
|
||||
|
||||
return (int) $id;
|
||||
}
|
||||
|
||||
function book_stock_lot_movements(
|
||||
PDO $pdo,
|
||||
int $productId,
|
||||
int $lotId,
|
||||
float $receiptQty,
|
||||
float $adjustmentQty,
|
||||
float $outQty
|
||||
): void {
|
||||
$locations = get_default_location_ids($pdo);
|
||||
$balanceStmt = $pdo->prepare(
|
||||
"SELECT COALESCE(
|
||||
SUM(CASE
|
||||
WHEN move_type = 'in' THEN qty
|
||||
WHEN move_type = 'out' THEN -qty
|
||||
WHEN move_type = 'adjustment' AND to_location_id IS NOT NULL AND from_location_id IS NULL THEN qty
|
||||
WHEN move_type = 'adjustment' AND from_location_id IS NOT NULL AND to_location_id IS NULL THEN -qty
|
||||
ELSE 0
|
||||
END), 0
|
||||
)
|
||||
FROM stock_move
|
||||
WHERE lot_id = :lot_id"
|
||||
);
|
||||
$balanceStmt->execute([':lot_id' => $lotId]);
|
||||
$balance = (float) $balanceStmt->fetchColumn();
|
||||
|
||||
if ($receiptQty > 0) {
|
||||
insert_stock_move_in($pdo, $productId, $lotId, $receiptQty, $locations['storage'], $locations['storage'], 'Manueller Lagerzugang via Chargenformular');
|
||||
$balance += $receiptQty;
|
||||
}
|
||||
|
||||
if ($adjustmentQty !== 0.0) {
|
||||
if ($adjustmentQty > 0) {
|
||||
insert_stock_move_adjustment($pdo, $productId, $lotId, $adjustmentQty, null, $locations['storage'], 'Manuelle Bestandskorrektur via Chargenformular');
|
||||
} else {
|
||||
$correctionQty = abs($adjustmentQty);
|
||||
if ($correctionQty > $balance) {
|
||||
throw new InvalidArgumentException('Bestandskorrektur wuerde den Chargensaldo negativ machen');
|
||||
}
|
||||
insert_stock_move_adjustment($pdo, $productId, $lotId, $correctionQty, $locations['storage'], null, 'Manuelle Bestandskorrektur via Chargenformular');
|
||||
}
|
||||
$balance += $adjustmentQty;
|
||||
}
|
||||
|
||||
if ($outQty > $balance) {
|
||||
throw new InvalidArgumentException('Lagerabgang ist groesser als der aktuelle Chargenbestand');
|
||||
}
|
||||
if ($outQty > 0) {
|
||||
insert_stock_move_out($pdo, $productId, $lotId, $outQty, $locations['storage'], $locations['dispatch'], 'Manueller Lagerabgang via Chargenformular');
|
||||
}
|
||||
}
|
||||
|
||||
function switch_current_lot(PDO $pdo, int $productId, int $oldCurrentLotId, int $storageLocationId): int
|
||||
{
|
||||
$closeStmt = $pdo->prepare(
|
||||
|
||||
Reference in new issue
Block a user