OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 149 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
144 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.erp.core.sales.pos.model;
15
 
149 ilm 16
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
144 ilm 17
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
149 ilm 18
import org.openconcerto.erp.utils.TM;
19
import org.openconcerto.sql.PropsConfiguration;
144 ilm 20
import org.openconcerto.sql.model.SQLRowAccessor;
21
import org.openconcerto.sql.model.SQLRowValues;
149 ilm 22
import org.openconcerto.ui.SwingThreadUtils;
144 ilm 23
import org.openconcerto.utils.CollectionUtils;
24
 
25
import java.text.ParseException;
149 ilm 26
import java.util.ArrayList;
27
import java.util.Collections;
28
import java.util.List;
29
import java.util.Map;
30
import java.util.concurrent.Callable;
31
import java.util.concurrent.ExecutionException;
32
import java.util.concurrent.FutureTask;
33
import java.util.logging.Level;
144 ilm 34
 
149 ilm 35
import javax.swing.JOptionPane;
36
 
144 ilm 37
import net.jcip.annotations.Immutable;
38
 
39
/**
40
 * Encapsulate all the data about a register in the DB at a point in time.
41
 *
42
 * @author sylvain
43
 */
44
@Immutable
45
public final class DBState {
46
 
149 ilm 47
    private static final Status getStatus(final SQLRowAccessor entry) {
48
        final Status res = Status.valueOf(entry.getString("EVT"));
49
        if (res != Status.OPEN && res != Status.CLOSED)
50
            throw new IllegalStateException("Invalid status : " + res);
51
        return res;
52
    }
53
 
144 ilm 54
    // used not for requests but for tables and paths
55
    private final RegisterDB registerDB;
56
    private final SQLRowValues registerVals;
57
    private final SQLRowValues lastReceiptVals;
58
    private final RegisterState registerState;
149 ilm 59
    // first is the latest
60
    private final List<SQLRowValues> lastEntries;
144 ilm 61
 
62
    protected DBState(final RegisterDB registerDB, final SQLRowValues registerR) {
63
        super();
64
        this.registerDB = registerDB;
65
        this.registerVals = registerR.toImmutable();
66
        if (this.getPosID() != registerDB.getPosID())
67
            throw new IllegalArgumentException("Not same register");
68
        this.lastReceiptVals = CollectionUtils.getSole(this.registerVals.getReferentRows(this.registerDB.getReceiptElement().getTable().getField("ID_CAISSE")));
149 ilm 69
        this.lastEntries = Collections.unmodifiableList(new ArrayList<>(this.registerVals.getReferentRows(this.registerDB.getLogElement().getTable().getField("ID_CAISSE"))));
144 ilm 70
 
71
        final SQLRowAccessor lastEntry = getLastEntry();
72
        if (lastEntry == null) {
73
            this.registerState = new RegisterState(Status.CLOSED, null);
74
        } else {
75
            if (lastEntry.getForeignID("ID_CAISSE") != this.getPosID())
76
                throw new IllegalStateException("Incoherent register IDs");
149 ilm 77
            final Status status = getStatus(lastEntry);
144 ilm 78
            this.registerState = new RegisterState(status, lastEntry.getDate("DATE").getTime());
79
        }
80
    }
81
 
82
    public final int getPosID() {
83
        return this.registerVals.getID();
84
    }
85
 
86
    public final RegisterState getRegisterState() {
87
        return this.registerState;
88
    }
89
 
90
    public SQLRowValues getRegisterRow() {
91
        return this.registerVals;
92
    }
93
 
149 ilm 94
    public final SQLRowValues getLastClosure() {
95
        return this.registerVals.followPath(this.registerDB.getRegisterToLastClosureEntry().minusLast());
96
    }
97
 
144 ilm 98
    public final SQLRowValues getLastClosureEntry() {
99
        return this.registerVals.followPath(this.registerDB.getRegisterToLastClosureEntry());
100
    }
101
 
149 ilm 102
    public final SQLRowValues getLastOpeningEntry() {
103
        final List<SQLRowValues> entries = this.getLastEntries();
104
        if (entries.isEmpty()) {
105
            // never opened
106
            assert !this.getRegisterState().hasDate();
107
            return null;
108
        } else if (getStatus(entries.get(0)).equals(Status.OPEN)) {
109
            return entries.get(0);
110
        } else if (entries.size() > 1 && getStatus(entries.get(1)).equals(Status.OPEN)) {
111
            return entries.get(1);
112
        } else {
113
            throw new IllegalStateException("Two consecutive non-open entries : " + entries);
114
        }
115
    }
116
 
144 ilm 117
    public final SQLRowValues getLastEntry() {
149 ilm 118
        return CollectionUtils.getFirst(this.getLastEntries());
144 ilm 119
    }
120
 
149 ilm 121
    public final List<SQLRowValues> getLastEntries() {
122
        return this.lastEntries;
123
    }
124
 
144 ilm 125
    public final SQLRowValues getLastReceiptRow() {
126
        return this.lastReceiptVals;
127
    }
128
 
129
    public final ReceiptCode getLastReceiptCode() throws ParseException {
130
        final SQLRowValues lastReceiptRow = this.getLastReceiptRow();
131
        return lastReceiptRow == null ? null : new ReceiptCode(lastReceiptRow.getString("NUMERO"));
132
    }
133
 
149 ilm 134
    public final SQLRowValues fillHostValues(final SQLRowValues logVals) {
135
        logVals.put("HOST_NAME", PropsConfiguration.getHostname());
136
        logVals.put("HOST_USER", System.getProperty("user.name"));
137
        return logVals;
138
    }
139
 
140
    // initial values for entries created before this version
141
    private static final Map<String, ?> NULL_VALUES = CollectionUtils.createMap("HOST_NAME", null, "HOST_USER", null);
142
 
143
    /**
144
     * Check if the register installation has moved and ask the user about it if it did. This can be
145
     * called from outside the EDT.
146
     *
177 ilm 147
     * @param erpTM UI locale
149 ilm 148
     * @return <code>true</code> if the user wants to quit.
149
     * @throws InterruptedException if this thread was interrupted while waiting on the EDT.
150
     * @throws ExecutionException if there was an error while asking the user.
151
     */
177 ilm 152
    public final boolean checkIfMoved(final TM erpTM) throws InterruptedException, ExecutionException {
149 ilm 153
        final SQLRowValues lastEntry = this.getLastEntry();
154
        if (lastEntry == null) {
155
            return false;
156
        }
157
 
158
        final Map<String, Object> currentValues = fillHostValues(new SQLRowValues(lastEntry.getTable())).getAbsolutelyAll();
159
        final Map<String, Object> dbValues = lastEntry.getValues(currentValues.keySet());
160
        if (dbValues.equals(currentValues) || NULL_VALUES.equals(dbValues)) {
161
            return false;
162
        } else {
177 ilm 163
            final String message = erpTM.translate("register.moved", getPosID());
164
            final String[] options = new String[] { erpTM.translate("register.moved.ignore"), erpTM.translate("register.moved.quit") };
149 ilm 165
            final FutureTask<Boolean> askUserCallable = new FutureTask<>(new Callable<Boolean>() {
166
                @Override
167
                public Boolean call() throws Exception {
168
                    // quit by default
177 ilm 169
                    final int ans = JOptionPane.showOptionDialog(null, message, erpTM.translate("register.moved.title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options,
170
                            options[1]);
149 ilm 171
                    // CLOSED_OPTION also means quit, only clicking "ignore" means don't quit
172
                    return ans != 0;
173
                }
174
            });
175
            SwingThreadUtils.invoke(askUserCallable);
176
            final boolean quit = askUserCallable.get();
177
            if (!quit)
178
                POSConfiguration.getLogger().log(Level.WARNING, "User choose to ignore changed host,\nDB values : {0}\ncurrent values : {1}", new Object[] { dbValues, currentValues });
179
            return quit;
180
        }
181
    }
182
 
144 ilm 183
    @Override
184
    public String toString() {
185
        return this.getClass().getSimpleName() + " for register " + this.getPosID() + " in state " + this.getRegisterState();
186
    }
187
}