001 sub adjust{ 002 my $self = shift; 003 my $instructions = shift; # $instructi
ID: 3537110 • Letter: 0
Question
001 sub adjust{
002 my $self = shift;
003 my $instructions = shift; # $instructions = [{mode => *mode*,lot_id => XXX, location_id => XXX,quant => XXX, nlocation_id = XXX }, ...]
004 my $cust_id = shift;
005
006
007 return $self->_error('no instructions arrayref specified') unless ref($instructions) eq 'ARRAY';
008
009 my @lotids;
010 foreach my $inst (@{$instructions}){
011 return $self->_error('mode must be specified') unless $inst->{mode};
012 return $self->_error('location_id must be specified') unless $inst->{location_id};
013 return $self->_error('quant must be specified') unless $inst->{quant};
014 if($inst->{mode} eq 'move'){
015 return $self->_error('nlocation_id must be specified') unless $inst->{nlocation_id};
016 }elsif($inst->{mode} eq 'adjust'){
017 return $self->_error('reason_code must be specified') unless $inst->{reason_code};
018 }elsif($inst->{mode} eq 'sale'){
019 #
020 }else{
021 return $self->_error("invalid mode $inst->{mode}");
022 }
023 push @lotids, $inst->{lot_id};
024 }
025
026 my $dbh = $self->{dbr}->connect('esrp_main') || return $self->_error('failed to connect to esrp_main');
027
028 return $self->_error('failed to select tracking') unless
029 my $transactions = $dbh->select(
030 -table => 'tracking',
031 -fields => [qw(row_id lot_id location_id quantity)],
032 -where => {
033 status => ['d',1], # 1 = active, 2 = retired
034 lot_id => ['in d',@lotids],
035 }
036 );
037
038 my %lottrack;
039 foreach my $transaction (@{$transactions}){
040 my $lotid = $transaction->{lot_id};
041 my $locid = $transaction->{location_id};
042
043 my $ref = $lottrack{ $lotid }->{ $locid } ||= {};
044
045 $ref->{quantity} += $transaction->{quantity};
046 push @{$ref->{row_ids} ||= []}, $transaction->{row_id};
047 }
048
049 my @retire;
050 my @newtrans;
051
052 #Now loop through the instructions and figure out how to execute them
053 foreach my $inst (@{$instructions}){
054 my $track = $lottrack{ $inst->{lot_id} }->{ $inst->{location_id} }; # pre existing quantity
055
056 my $changequant = $inst->{quant};
057
058 if ($inst->{mode} eq 'move') {
059 return $self->_error("no pre-existing quantity found for lot $inst->{lot_id} loc $inst->{location_id}") unless $track;
060
061 if ($changequant > $track->{quantity}) {
062 $changequant = $track->{quantity};
063 }
064 if ($changequant > 0) {
065 next if $inst->{nlocation_id} == $inst->{location_id}; #skip if its the same place
066 my $remainder = $track->{quantity} - $changequant;
067
068
069 my $status;
070 if($remainder == 0){
071 # none are left in the old location, they no longer need to be status 1
072 push @retire, @{$track->{row_ids}};
073 $status = 2;
074 }else{
075 $status = 1;
076 }
077
078 push @newtrans,{
079 quant => 0 - $changequant,
080 loc_id => $inst->{location_id},
081 lot_id => $inst->{lot_id},
082 action => 6, #moveout
083 status => $status, # might be live or retired
084 };
085
086
087 push @newtrans,{
088 quant => $changequant,
089 loc_id => $inst->{nlocation_id},
090 lot_id => $inst->{lot_id},
091 action => 3, #movein
092 status => 1, # live
093 };
094
095 }
096 } elsif ($inst->{mode} eq 'adjust') {
097 if ($changequant > 0) {
098 my $reason = $inst->{reason_code};
099
100
101 my $status;
102 if($reason =~ s/^A//i){
103 #Add
104 # no existing track is needed
105 $status = 1;
106 }elsif($reason =~ s/^S//i){ # subtract
107 return $self->_error("no quantity found for lot $inst->{lot_id} loc $inst->{location_id}") unless $track;
108
109 #chop requested quantity down so we don't go negative
110 $changequant = $track->{quantity} if $changequant > $track->{quantity};
111
112 my $remainder = $track->{quantity} - $changequant;
113 if ($remainder == 0) {
114 # none are left in the old location, they no longer need to be status 1
115 push @retire, @{$track->{row_ids}};
116 $status = 2;
117 } else {
118 $status = 1;
119 }
120
121 $changequant *= -1;
122 }else{
123 return $self->_error('no reason type specified');
124 }
125 $reason =~ s/D//g;
126
127 push @newtrans,{
128 quant => $changequant,
129 loc_id => $inst->{location_id},
130 lot_id => $inst->{lot_id},
131 action => 4, #adjust
132 reason => $reason,
133 status => $status,
134 };
135 }
136 }elsif ($inst->{mode} eq 'sale') {
137 if ($changequant > 0) {
138 return $self->_error("sale quantity exceeds available amount ($inst->{lot_id},$inst->{location_id},$changequant)") if
139 $changequant > $track->{quantity};
140
141 my $remainder = $track->{quantity} - $changequant;
142
143 my $status;
144 if($remainder == 0){
145 # none are left in the old location, they no longer need to be status 1
146 push @retire, @{$track->{row_ids}};
147 $status = 2;
148 }else{
149 $status = 1;
150 }
151
152 push @newtrans,{
153 quant => 0 - $changequant,
154 loc_id => $inst->{location_id},
155 lot_id => $inst->{lot_id},
156 action => 5 #sale
157 status => $status
158 };
159 }
160 }
161 }
162
163
164 $dbh->begin();
165
166 if (@retire) {
167
168 return $self->_error('failed to update tracking') unless
169 $dbh->update(
170 -table => 'tracking',
171 -fields => {status => ['d',2]},
172 -where => {
173 status => ['d',1], # 1 = active, 2 = retired
174 row_id => ['in d',@retire],
175 }
176 );
177 }
178
179 my $time = time();
180 foreach my $new (@newtrans){
181 return $self->_error('failed to insert tracking') unless
182 $dbh->insert(
183 -table => 'tracking',
184 -fields => {
185 lot_id => ['d',$new->{lot_id}],
186 date => ['d',$time],
187 status => ['d',$new->{status}],
188 location_id => ['d',$new->{loc_id}],
189 quantity => ['d',$new->{quant}],
190 action => ['d',$new->{action}],
191 reason => ['d',$new->{reason} || 0],
192 cust_id => ['d',$cust_id || 0],
193 },
194 );
195 }
196
197 $dbh->commit();
198
199
200 return 1;
201
202 }
1. What are your impressions of the style of this code?
2. What coding methodology is being used here?
3. What do you think the variable $self represents?
4. Describe the purpose of the code on lines 10-24
5. Describe what is happening on line 46
6. Describe what is happening on line 121
7. What is the purpose of prepending a letter to the reason_code parameter in a given instruction?
8. In your own words, Describe in detail the purpose of lines 39-47
9. Describe why $status is specified on line 83 but not on line 92, and the resulting effect.
10. Given the question #8, what do you think would be a more appropriate name for the %lottrack hash?
11. Are there any other variable names that you would change if you were to write this software? If so what would you change them to?
12. Can you spot any syntax or logical errors in the code? if so, please list them.
13. Describe any concepts in this code that you consider to be novel or interesting.
14. Please give your general impression of the sample code.
15. Are there any parts of this code you might have done differently? If so, how would you have done it?
Explanation / Answer
1. What are your impressions of the style of this code?
The style of code is procedural using a single sub-routine.
2. What coding methodology is being used here?
the coding methodology is CRUD - Create Read Update Delete, though in a procedural manner.
3. What do you think the variable $self represents?
It refers to the current running instance of the program.
4. Describe the purpose of the code on lines 10-24
Its a series of checks to validate the input 'instructions', and return proper error messages when required.
It's basically doing Input Validation.
5. Describe what is happening on line 46
Its inserting the row_id of the current transaction, into a list of already referred row_ids ( that is being pointed to by the ref variable).
Hence, its keeping track of all rows modified till now..
6. Describe what is happening on line 121
Its changing the sign of the quantity (i.e, either from negative to positive )
7. What is the purpose of prepending a letter to the reason_code parameter in a given instruction?
Its to keep track of whether the reason_code is validated or not.
8. In your own words, Describe in detail the purpose of lines 39-47
For each transaction, add the quantity in that transaction to specified lot & location (by lot_id, location_id).
Also keep track of the rows affected by keeping a list of referred row_ids.
9. Describe why $status is specified on line 83 but not on line 92, and the resulting effect.
Because it 82, we are oving out data, so we need to check the data status (whether its live or dead,i.e, whether its still useful or not)
This check is got by the variable $status.
In 92, we are moving in data, so we status is always live,i.e, status=1.
10. Given the question #8, what do you think would be a more appropriate name for the %lottrack hash?
lotList would be more proper.
11. Are there any other variable names that you would change if you were to write this software? If so what would you change them to?
NO
12. Can you spot any syntax or logical errors in the code? if so, please list them.
Not any currently.
13. Describe any concepts in this code that you consider to be novel or interesting.
I find the checking of status via live or dead novel, as its keeps the transactions, hence the database hash (lottrack) in a consistent state throughout.
14. Please give your general impression of the sample code.
The code is good, however should have been made more modular, by adding more proper subroutines.(not just the one in sub adjust).
15. Are there any parts of this code you might have done differently? If so, how would you have done it?
I would have added more subroutines to to separate the of Updating, Reading,Writing and Creating the database hash.
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.