if ($form->{"assembly_$i"}) {
# record assembly item as allocated
- &process_assembly($dbh, $form, $form->{"id_$i"}, $baseqty);
+ &process_assembly($dbh, $myconfig, $form, $form->{"id_$i"}, $baseqty);
} else {
- $allocated = &cogs($dbh, $form, $form->{"id_$i"}, $baseqty, $basefactor, $i);
+ $allocated = &cogs($dbh, $myconfig, $form, $form->{"id_$i"}, $baseqty, $basefactor, $i);
}
}
# record payments and offsetting AR
if (!$form->{storno}) {
for my $i (1 .. $form->{paidaccounts}) {
+
+ if ($form->{"acc_trans_id_$i"}
+ && $payments_only
+ && ($::lx_office_conf{features}->{payments_changeable} == 0)) {
+ next;
+ }
next if ($form->{"paid_$i"} == 0);
# record payment
$form->{"paid_$i"} *= -1;
+ my $gldate = (conv_date($form->{"gldate_$i"}))? conv_date($form->{"gldate_$i"}) : conv_date($form->current_date($myconfig));
$query =
- qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, source, memo, taxkey, project_id)
- VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, ?, ?,
+ qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, gldate, source, memo, taxkey, project_id)
+ VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, ?, ?, ?,
(SELECT taxkey_id FROM chart WHERE accno = ?), ?)|;
@values = (conv_i($form->{"id"}), $accno, $form->{"paid_$i"}, $form->{"datepaid_$i"},
- $form->{"source_$i"}, $form->{"memo_$i"}, $accno, $project_id);
+ $gldate, $form->{"source_$i"}, $form->{"memo_$i"}, $accno, $project_id);
do_query($form, $dbh, $query, @values);
# exchangerate difference
$old_form = save_form();
# Delete all entries in acc_trans from prior payments.
- $self->_delete_payments($form, $dbh);
+ if ($::lx_office_conf{features}->{payments_changeable} != 0) {
+ $self->_delete_payments($form, $dbh);
+ }
# Save the new payments the user made before cleaning up $form.
- map { $payments{$_} = $form->{$_} } grep m/^datepaid_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^AR_paid_\d+$|^paidaccounts$/, keys %{ $form };
+ map { $payments{$_} = $form->{$_} } grep m/^datepaid_\d+$|^gldate_\d+$|^acc_trans_id_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^AR_paid_\d+$|^paidaccounts$/, keys %{ $form };
# Clean up $form so that old content won't tamper the results.
%keep_vars = map { $_, 1 } qw(login password id);
sub process_assembly {
$main::lxdebug->enter_sub();
- my ($dbh, $form, $id, $totalqty) = @_;
+ my ($dbh, $myconfig, $form, $id, $totalqty) = @_;
my $query =
qq|SELECT a.parts_id, a.qty, p.assembly, p.partnumber, p.description, p.unit,
$ref->{qty} *= $totalqty;
if ($ref->{assembly}) {
- &process_assembly($dbh, $form, $ref->{parts_id}, $ref->{qty});
+ &process_assembly($dbh, $myconfig, $form, $ref->{parts_id}, $ref->{qty});
next;
} else {
if ($ref->{inventory_accno_id}) {
- $allocated = &cogs($dbh, $form, $ref->{parts_id}, $ref->{qty});
+ $allocated = &cogs($dbh, $myconfig, $form, $ref->{parts_id}, $ref->{qty});
}
}
sub cogs {
$main::lxdebug->enter_sub();
- my ($dbh, $form, $id, $totalqty, $basefactor, $row) = @_;
+ # adjust allocated in table invoice according to FIFO princicple
+ # for a certain part with part_id $id
+
+ my ($dbh, $myconfig, $form, $id, $totalqty, $basefactor, $row) = @_;
$basefactor ||= 1;
my $allocated = 0;
my $qty;
+# all invoice entries of an example part:
+
+# id | trans_id | base_qty | allocated | sellprice | inventory_accno | income_accno | expense_accno
+# ---+----------+----------+-----------+-----------+-----------------+--------------+---------------
+# 4 | 4 | -5 | 5 | 20.00000 | 1140 | 4400 | 5400 bought 5 for 20
+# 5 | 5 | 4 | -4 | 50.00000 | 1140 | 4400 | 5400 sold 4 for 50
+# 6 | 6 | 1 | -1 | 50.00000 | 1140 | 4400 | 5400 sold 1 for 50
+# 7 | 7 | -5 | 1 | 20.00000 | 1140 | 4400 | 5400 bought 5 for 20
+# 8 | 8 | 1 | -1 | 50.00000 | 1140 | 4400 | 5400 sold 1 for 50
+
+# AND ((i.base_qty + i.allocated) < 0) filters out all but line with id=7, elsewhere i.base_qty + i.allocated has already reached 0
+# and all parts have been allocated
+
+# so transaction 8 only sees transaction 7 with unallocated parts and adjusts allocated for that transaction, before allocated was 0
+# 7 | 7 | -5 | 1 | 20.00000 | 1140 | 4400 | 5400 bought 5 for 20
+
+# in this example there are still 4 unsold articles
+
+
+ # search all invoice entries for the part in question, adjusting "allocated"
+ # until the total number of sold parts has been reached
+
+ # ORDER BY trans_id ensures FIFO
+
+
while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
if (($qty = (($ref->{base_qty} * -1) - $ref->{allocated})) > $totalqty) {
$qty = $totalqty;
}
+ # update allocated in invoice
$form->update_balance($dbh, "invoice", "allocated", qq|id = $ref->{id}|, $qty);
# total expenses and inventory
# sellprice is the cost of the item
my $linetotal = $form->round_amount(($ref->{sellprice} * $qty) / ( ($ref->{price_factor} || 1) * ( $basefactor || 1 )), 2);
- if (!$::lx_office_conf{system}->{eur}) {
+ if ( $::instance_conf->get_inventory_system eq 'perpetual' ) {
+ # Bestandsmethode: when selling parts, deduct their purchase value from the inventory account
$ref->{expense_accno} = ($form->{"expense_accno_$row"}) ? $form->{"expense_accno_$row"} : $ref->{expense_accno};
# add to expense
$form->{amount_cogs}{ $form->{id} }{ $ref->{expense_accno} } += -$linetotal;
i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.discount, i.parts_id AS id, i.unit, i.deliverydate AS reqdate,
i.project_id, i.serialnumber, i.id AS invoice_pos, i.pricegroup_id, i.ordnumber, i.transdate, i.cusordnumber, i.subtotal, i.lastcost,
i.price_factor_id, i.price_factor, i.marge_price_factor,
- p.partnumber, p.assembly, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel,
+ p.partnumber, p.assembly, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel, p.listprice,
pr.projectnumber, pg.partsgroup, prg.pricegroup
FROM invoice i
push @values, $form->{"partnumber_$i"};
}
+ # Search for part ID overrides all other criteria.
if ($form->{"id_${i}"}) {
- $where .= qq| AND p.id = ?|;
- push @values, $form->{"id_${i}"};
+ $where = qq|p.id = ?|;
+ @values = ($form->{"id_${i}"});
}
if ($form->{"description_$i"}) {