public ActionType(XE actionType)
        {
            if (actionType == null)
            {
                throw new ArgumentNullException(nameof(actionType));
            }

            var tidAttribute      = actionType.Attribute(C.tid);
            var tidAttributeValue = int.Parse(tidAttribute.Value);

            if (!Enum.IsDefined(typeof(TransactionId), tidAttributeValue))
            {
                throw new ArgumentException($"Unknown {nameof(C.tid)} '{tidAttributeValue}'");
            }
            Id = (TransactionId)int.Parse(tidAttribute.Value);

            var success = TidToString.TryGetValue(Id, out var value);

            if (!success)
            {
                throw new ArgumentException($"{nameof(TidToString)} mapping doesn't contain {nameof(TransactionId)} with value {tidAttribute.Value}");
            }
            if (value != actionType.Value)
            {
                throw new ArgumentException($"Expected Action Type element to have value '{value}'. Was '{actionType.Value}'");
            }

            // UNDOCUMENTED: type or length of Action/Type content. We can only
            // assume an Ax of sufficient length to represent every
            // TransactionId in textual form.
            FieldTypes.AssertA25(actionType.Value);
        }
예제 #2
0
        // If an error occurs and response code isn't "Approved", form of
        // response is
        //
        // <ResponseCode hostCode="20">D</ResponseCode>
        // <DisplayMessage>Missing SVAN Element</DisplayMessage>
        //
        // A successful response code has the form <ResponseCode>A</ResponseCode>
        // and sometimes, but not always, contains DisplayMessage element.
        public ResponseCode(XE responseCode)
        {
            // POS API spec, Page 19: according to DisplayMessage documentation,
            // additional response codes include E, V, and P. Those should be
            // shown to POS terminal user. We haven't encountered these codes
            // and thus doesn't parse those.
            var value = responseCode.Value;

            FieldTypes.AssertA1(value);

            if (value == "A")
            {
                Value = Kind.Approved;
            }
            else if (value == "D")
            {
                var hostCodeAttribute = ExpectAttribute(responseCode, C.hostCode);
                HostCode = hostCodeAttribute.Value;
                Value    = Kind.DataCenterInitiatedError;
            }
            else
            {
                throw new ArgumentException($"Unsupported {nameof(Kind)} value: '{value}'");
            }
        }
예제 #3
0
 public CheckNumber(string value)
 {
     // UNDOCUMENTED: CheckNumber element is missing from POS API spec,
     // Page 19, Element Definitions. We assume CheckNumber is identical
     // to the CheckNumber part of TraceID which is N4.
     Value = FieldTypes.AssertN4(value);
 }
예제 #4
0
 public ExchangeRate(string value)
 {
     Value = FieldTypes.AssertDecimal(value);
     if (Value <= 0)
     {
         throw new ArgumentException($"{nameof(ExchangeRate)} rate must be positive. Was {value}");
     }
 }
 public Points(string value)
 {
     Value = FieldTypes.AssertDecimal(value);
     if (Value < 0)
     {
         throw new ArgumentException($"{nameof(Points)} must be positive. Was {value}");
     }
 }
 public RequestCode(string value)
 {
     FieldTypes.AssertA100(value);
     if (!Enum.IsDefined(typeof(TransactionKind), value))
     {
         throw new ArgumentException($"Unknown value '{value}'");
     }
     Value = (TransactionKind)Enum.Parse(typeof(TransactionKind), value);
 }
예제 #7
0
 public Transmission(string value)
 {
     FieldTypes.AssertA1(value);
     Value = value switch
     {
         "n" => Kind.Normal,
         "y" => Kind.Retransmission,
         _ => throw new ArgumentException($"Unsupported {nameof(Kind)} value: '{value}'")
     };
 }
        public Language(string value)
        {
            FieldTypes.AssertA5(value);

            if (value != Kind.EnUs)
            {
                throw new ArgumentException($"Expected '{Kind.EnUs}'. Was {value}");
            }

            Value = value;
        }
예제 #9
0
        public Currency(string value)
        {
            FieldTypes.AssertA3(value);

            // Not only must value not be null or whitespace and satisfy A3,
            // only Kind is allowed.
            if (!Enum.IsDefined(typeof(Kind), value))
            {
                throw new ArgumentException($"Error parsing {nameof(Kind)}: {value}");
            }
            Value = (Kind)Enum.Parse(typeof(Kind), value);
        }
예제 #10
0
 public ItemType(string value)
 {
     // UNDOCUMENTED: according to POS API spec, Page 21, ItemType is of
     // type XML with no field type definition. We've yet to encounter
     // any XML beneath the ItemType element. In the responses we've
     // encountered, the format is <ItemType>T</ItemType>.
     FieldTypes.AssertA1(value);
     Value = value switch
     {
         "M" => Kind.MenuOrSalesItem,
         "D" => Kind.Discount,
         "S" => Kind.ServiceCharge,
         "T" => Kind.Tender,
         _ => throw new ArgumentException($"Unsupported {nameof(Kind)} value: '{value}'"),
     };
 }
예제 #11
0
        public HostVersion(string value)
        {
            // UNDOCUMENTED: POS API spec, Page 18, designates hostVersion
            // attribute as A8. "1.00.8" example in documentation supports this
            // field type, but time seems to have surpassed documentation.
            // Current hostVersion is "9.1.0000.2301" which doesn't fit in A8.
            // We assume field is A16.
            Value = FieldTypes.AssertA16(value);

            // UNDOCUMENTED: Oracle's versioning strategy is unclear. Which
            // component of the version number, if any, would change to signal a
            // breaking change? For now, we hardcode version to force an
            // expclit failure on Oracle update.
            const string hostVersion = "9.1.0000.2301";

            if (value != hostVersion)
            {
                throw new ArgumentException($"Oracle updated POS host version from '{hostVersion}' to '{value}'");
            }
        }
예제 #12
0
        public TraceId(string value)
        {
            // UNDOCUMENTED: while POS API spec, Page 23 designates TraceID as
            // A25, examples show it as A19. Possibly for Oracle to change
            // TraceID in the future without updating the schema.
            FieldTypes.AssertA25(value);

            // Date part of TraceID doesn't follow the pattern used with
            // LocalDate and BusinessDate. For TraceID, year is two characters
            // only. Since TraceID is an element on its own and not a field type
            // (Ax, Nx, ...), its regular expression is defined inline and not
            // with FieldTypes.
            const string pattern = @"^(?<year>\d{2})(?<month>\d{2})(?<day>\d{2})(?<hour>\d{2})(?<minute>\d{2})(?<second>\d{2})(?<retransmit>.{1})(?<sequence>\d{2})(?<checkNumber>\d{4})$";
            var          re      = new Regex(pattern);
            var          m       = re.Match(value);

            if (!m.Success)
            {
                throw new ArgumentException($"{nameof(value)} must match pattern: {pattern}. Was '{value}'");
            }

            var date = FieldTypes.AssertDate($"20{m.Groups["year"].Value}{m.Groups["month"].Value}{m.Groups["day"].Value}");
            var time = FieldTypes.AssertTime($"{m.Groups["hour"].Value}{m.Groups["minute"].Value}{m.Groups["second"].Value}");

            Timestamp = date.Add(time);

            var retransmit = m.Groups["retransmit"].Value;

            if (!(retransmit == "N" || retransmit == "R"))
            {
                throw new ArgumentException($"Retransmit must be either 'N' or 'R'. Was '{retransmit}'");
            }
            Kind = retransmit == "N" ? TransmissionKind.Normal : TransmissionKind.Retransmit;

            var sequence = int.Parse(m.Groups["sequence"].Value);

            Sequence = new SequenceNumber(sequence);
            var checkNumber = int.Parse(m.Groups["checkNumber"].Value);

            CheckNumber = new CheckNumber(checkNumber);
        }
 public TerminalId(string value)
 {
     FieldTypes.AssertN9(value);
     Value = int.Parse(value);
 }
 public TransactionEmployee(string value)
 {
     Value = FieldTypes.AssertN9(value);
 }
 public RevenueCenter(string value)
 {
     Value = FieldTypes.AssertN9(value);
 }